mirror of
https://github.com/steveicarus/iverilog.git
synced 2026-08-24 23:06:56 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3d14281e0d | ||
|
|
2564554178 | ||
|
|
8cd697fd24 | ||
|
|
306d2fb53b | ||
|
|
52b497f74c | ||
|
|
ce7f28202a | ||
|
|
49bea6a01a | ||
|
|
8ab100c1c7 | ||
|
|
177ae7c220 | ||
|
|
b04d5a9068 | ||
|
|
b8c8f03037 | ||
|
|
38013f7a34 | ||
|
|
561638a31f | ||
|
|
bb91512e75 | ||
|
|
09ff851483 | ||
|
|
19d8f43e9b | ||
|
|
ce88deaa97 | ||
|
|
1a8b19baf2 | ||
|
|
b3cf533b3c | ||
|
|
ba3856ebb0 | ||
|
|
c06e2790a7 | ||
|
|
6e460a6a3f | ||
|
|
dbc536c4fb | ||
|
|
5e41c86d01 | ||
|
|
572124e1e9 | ||
|
|
37ecdb4cfb | ||
|
|
a11dc8b472 | ||
|
|
e7852f8f9c | ||
|
|
9449c46865 | ||
|
|
8a780ece56 | ||
|
|
8bb4777789 | ||
|
|
3b705d95a6 | ||
|
|
f9559853f1 | ||
|
|
cda95c1554 | ||
|
|
4066031add | ||
|
|
d6d50e9b68 | ||
|
|
0ffbb2b1de | ||
|
|
9b55a3d67f | ||
|
|
07623bef2e | ||
|
|
73d688c313 | ||
|
|
6155986d1c | ||
|
|
face462cc2 | ||
|
|
a5f6329500 | ||
|
|
3e13594816 | ||
|
|
99138eafb1 | ||
|
|
86968e3752 | ||
|
|
27a46f4afe | ||
|
|
d770199550 | ||
|
|
06f6a72770 | ||
|
|
30257e0914 | ||
|
|
b2281b0e65 | ||
|
|
161cebb178 | ||
|
|
b46d8b8389 | ||
|
|
2689ebacfe | ||
|
|
5bbb054173 | ||
|
|
7d2eeb0137 | ||
|
|
4aef636559 | ||
|
|
72fc3d712d | ||
|
|
3f75f6b155 | ||
|
|
9be3fc3a56 | ||
|
|
aa2260f4fa | ||
|
|
6974613bff | ||
|
|
8bd4e9d481 | ||
|
|
04ae07f03c | ||
|
|
d9be5318f9 | ||
|
|
88cd5534c4 | ||
|
|
3b577340ad | ||
|
|
583a31c121 | ||
|
|
a391c3ae28 | ||
|
|
b551a783e8 | ||
|
|
33db07ab8d | ||
|
|
e2aae72880 | ||
|
|
ec9897af5a | ||
|
|
2771abf86a | ||
|
|
b0461787c8 | ||
|
|
6f41576930 | ||
|
|
cc7516eab3 | ||
|
|
1a5ae96540 | ||
|
|
1ea8a13bf8 | ||
|
|
490884cf7b | ||
|
|
ca1d7ccffe | ||
|
|
faf9bfe158 | ||
|
|
086ce04cf5 | ||
|
|
7b7231c417 | ||
|
|
d7b919f6d0 | ||
|
|
9b34a96cb9 | ||
|
|
90cf0e5794 | ||
|
|
818379b9bc | ||
|
|
9fbb7f84e6 | ||
|
|
ed7d6c1002 | ||
|
|
a4306dbac1 | ||
|
|
a682e13d82 | ||
|
|
643e0a984e | ||
|
|
63d2059b85 | ||
|
|
d9e09ceb59 | ||
|
|
6d0ab9978f | ||
|
|
e25cdf86ac | ||
|
|
13bff8c50d | ||
|
|
b1b017251a | ||
|
|
e13a52637a | ||
|
|
4803f0d12b | ||
|
|
be44289fc0 | ||
|
|
e682166253 | ||
|
|
e2a1f21896 | ||
|
|
cb73accd84 | ||
|
|
a66361a4f2 | ||
|
|
1159de0482 | ||
|
|
ac5d4114ad | ||
|
|
85f796fda2 | ||
|
|
8612ec5452 | ||
|
|
870a351944 | ||
|
|
434bf0fe46 | ||
|
|
5147105042 | ||
|
|
fc2139f01c | ||
|
|
775904ab0f | ||
|
|
0ae3414ec5 | ||
|
|
f3321126ed | ||
|
|
428f059c58 | ||
|
|
e98bcb61bb | ||
|
|
5facf243cd | ||
|
|
853f119d83 | ||
|
|
3e2196651a | ||
|
|
64b72cf7e1 | ||
|
|
d766e82aa1 | ||
|
|
c35f2f8334 | ||
|
|
afd225a44d | ||
|
|
b36a0a2c54 | ||
|
|
a3728dcf20 | ||
|
|
4cf4cdabcd | ||
|
|
5f906369b5 | ||
|
|
12f4d29df3 | ||
|
|
5e931b7e89 | ||
|
|
11d7cbd3e2 | ||
|
|
7aff1adf99 | ||
|
|
093e7eb2c8 | ||
|
|
82d46a5e1a | ||
|
|
fc976bdb97 | ||
|
|
9f7995f648 | ||
|
|
9bcafe39c6 | ||
|
|
9635f031a1 | ||
|
|
e6be9dec08 | ||
|
|
97c6339241 | ||
|
|
8d2149f5aa | ||
|
|
e8225bd39e | ||
|
|
935ee6137d | ||
|
|
586e415d96 | ||
|
|
637fc40dd9 | ||
|
|
05a52e55e9 | ||
|
|
59c211d20c | ||
|
|
dad223316e | ||
|
|
df597e19cb | ||
|
|
7597270939 | ||
|
|
5509b3c7a5 | ||
|
|
49253c43ba | ||
|
|
311ffb27f2 | ||
|
|
f0fd73e146 | ||
|
|
5858e1bbac | ||
|
|
95044d9ac7 | ||
|
|
c6f934964f | ||
|
|
6f867d6f01 | ||
|
|
e6b57910a4 | ||
|
|
cc9b182eb6 | ||
|
|
d39f692cfd | ||
|
|
b666b9c0bf | ||
|
|
b3c1fa3e85 | ||
|
|
169228ad0f | ||
|
|
356a09d295 | ||
|
|
47c5ce0ab6 | ||
|
|
3c437874e2 | ||
|
|
c28000c55f | ||
|
|
5a0d967682 | ||
|
|
49efe6573c | ||
|
|
ea12c0fe23 | ||
|
|
44dfc41004 | ||
|
|
bdd0657140 | ||
|
|
1d279798d8 | ||
|
|
0e66e9781a | ||
|
|
b23faff27c | ||
|
|
b242663cae | ||
|
|
d39c284055 | ||
|
|
6a73de0c43 | ||
|
|
e0cdd71984 | ||
|
|
81e1735959 | ||
|
|
3fb65eb51a | ||
|
|
3080f5730d | ||
|
|
29ddd5208f | ||
|
|
4a31f36646 | ||
|
|
1f1d47887e | ||
|
|
80403d2ade | ||
|
|
cd3180d1c2 | ||
|
|
68f8007fc4 | ||
|
|
d6ff1946f9 | ||
|
|
4068c172f4 | ||
|
|
9ac9f1c9f2 | ||
|
|
2739f83702 | ||
|
|
7af3280215 | ||
|
|
05d591ccd6 | ||
|
|
fbedf4ae22 | ||
|
|
e6c6f6c81e | ||
|
|
33c651aa00 | ||
|
|
358bb4d5d9 | ||
|
|
d5b41853fd | ||
|
|
0fc10e3e70 | ||
|
|
ab688613cc | ||
|
|
79042e38ad | ||
|
|
ced9759c65 | ||
|
|
8f22998447 | ||
|
|
51d7237d52 | ||
|
|
7aab315ce5 | ||
|
|
bc83d2914a | ||
|
|
bb2e6782fa | ||
|
|
9231ad51a4 | ||
|
|
25458b8cc2 | ||
|
|
515ab40ffe | ||
|
|
ddc204391e | ||
|
|
a33bbecc98 | ||
|
|
61ace52f31 | ||
|
|
71b1546a7d | ||
|
|
578a2543f7 | ||
|
|
a479bd6b16 | ||
|
|
c75498b1d4 | ||
|
|
b6304129fa | ||
|
|
bb444b6178 | ||
|
|
7442c14689 | ||
|
|
0082795967 | ||
|
|
ac4f4cf1a0 | ||
|
|
676d23f973 | ||
|
|
6069cbfc3c | ||
|
|
cfbc90812b | ||
|
|
e530b4e642 | ||
|
|
6a3edc63d5 | ||
|
|
3069b8dd51 | ||
|
|
7db01d8ded | ||
|
|
e4694cb6cb | ||
|
|
08e5aa021a | ||
|
|
4304fd503e | ||
|
|
5438464d67 | ||
|
|
6df2979998 | ||
|
|
9de4ced133 | ||
|
|
45dc13e496 | ||
|
|
9e3f1ef1ff | ||
|
|
1b3e321d35 | ||
|
|
a27274aa04 | ||
|
|
f1be16be7c | ||
|
|
9ac374501c | ||
|
|
250b278d0e | ||
|
|
52275deb0e | ||
|
|
120ad59017 | ||
|
|
2ac8a555e1 | ||
|
|
8d845ae49f | ||
|
|
352175d921 | ||
|
|
e78205eacf | ||
|
|
c6e618350d | ||
|
|
301a7e587b | ||
|
|
3cee5d4567 | ||
|
|
e1ae5020c4 | ||
|
|
22d15f9ca9 | ||
|
|
19d966e235 | ||
|
|
c8fe897446 | ||
|
|
5101b3b64b | ||
|
|
bed5ee4529 | ||
|
|
7c0a191626 | ||
|
|
cfa43c7742 | ||
|
|
a5138e238f | ||
|
|
d352d8ead3 | ||
|
|
02ee3874e7 | ||
|
|
f9fef5d00b | ||
|
|
891399185f | ||
|
|
5dc1396eea | ||
|
|
ccf7c042c9 | ||
|
|
560b9530fd | ||
|
|
b89c059153 | ||
|
|
8326fe843b | ||
|
|
1cbc38100e | ||
|
|
ba31252226 | ||
|
|
008affe557 | ||
|
|
0ca856d4e8 | ||
|
|
2a210dfee1 | ||
|
|
83d721232d | ||
|
|
d5ffb55bfd | ||
|
|
ab9a8ccbf3 | ||
|
|
e6525ec35f | ||
|
|
afaedbd06d | ||
|
|
d4237774a5 | ||
|
|
2f2539e557 | ||
|
|
11a86794d9 | ||
|
|
3b14797075 | ||
|
|
e006f9e132 | ||
|
|
437dc10341 | ||
|
|
102d2d534f | ||
|
|
5e437145bf | ||
|
|
d1dc98b7f7 | ||
|
|
50b45dac7b | ||
|
|
295e4e7dfb | ||
|
|
807ad8002d | ||
|
|
d3229b9068 | ||
|
|
099bb427bc | ||
|
|
d406545331 | ||
|
|
1de3fb1625 | ||
|
|
e33b8b4dde | ||
|
|
9128eb67b9 | ||
|
|
afbda099fb | ||
|
|
4b0d220671 | ||
|
|
a42b056b24 | ||
|
|
1852c5ab9d | ||
|
|
24be13d825 | ||
|
|
bddfcac823 | ||
|
|
ea1c07e234 | ||
|
|
8e0ae733ca | ||
|
|
feb710a186 | ||
|
|
62abb199d7 | ||
|
|
7373bf2224 | ||
|
|
ae629f8c41 | ||
|
|
03e0e96832 | ||
|
|
3c38b2972d | ||
|
|
4f1fc6e302 | ||
|
|
f1436fbe62 | ||
|
|
a79533ddc9 | ||
|
|
d47afb588b | ||
|
|
386774ac19 | ||
|
|
9ca754b6db | ||
|
|
0f0bef32f2 | ||
|
|
cd55f30a27 | ||
|
|
5884879b02 | ||
|
|
a1a4f47894 | ||
|
|
e569e07d4e | ||
|
|
ee840391d6 | ||
|
|
0046e9eca0 | ||
|
|
f51c037432 | ||
|
|
763c6fe3c9 | ||
|
|
49b6ddf93c | ||
|
|
12b4914b63 | ||
|
|
fc0728ab6f | ||
|
|
46c41f9be2 | ||
|
|
cdf18de10e | ||
|
|
19ff6a434b | ||
|
|
5349ca9a55 | ||
|
|
5b7b980ead | ||
|
|
a1c2a8e605 | ||
|
|
8777cd8e7c | ||
|
|
11bb7ac348 | ||
|
|
9de69f2f24 | ||
|
|
dae3410dcd | ||
|
|
1a367c84b6 | ||
|
|
8a854affa6 | ||
|
|
60077f4f06 | ||
|
|
51ce9f1a60 | ||
|
|
48265ecd9b | ||
|
|
abbcea64d0 | ||
|
|
25c3798248 | ||
|
|
90293d8e0a | ||
|
|
621cf37339 | ||
|
|
6d75af86e6 | ||
|
|
5d26f0e28d | ||
|
|
774609fbbb | ||
|
|
9ba7694484 | ||
|
|
870a826225 | ||
|
|
2ecfed0baa | ||
|
|
56e410f386 | ||
|
|
d4dd635bf6 | ||
|
|
c287281bbe | ||
|
|
962330f20a | ||
|
|
777e7e0a3d | ||
|
|
839f9cd7ae | ||
|
|
b8b2f53027 | ||
|
|
9b3bd039bb | ||
|
|
51b9191021 | ||
|
|
756c9ceccf | ||
|
|
8b3667f76e | ||
|
|
a52242745a | ||
|
|
ff5b696569 | ||
|
|
b05a19dffc | ||
|
|
e6b22a2bea | ||
|
|
a02ebc3114 | ||
|
|
0592ba042e | ||
|
|
bcca3cf395 | ||
|
|
01ba41afd8 | ||
|
|
84c592b068 | ||
|
|
bb93a585b6 | ||
|
|
47688d234b | ||
|
|
b3425d6cf3 | ||
|
|
40ae1051d4 | ||
|
|
21c60b38e1 | ||
|
|
78c6b3cad2 | ||
|
|
a04104077f | ||
|
|
0e3a758894 | ||
|
|
d682029240 | ||
|
|
1ffcd40336 | ||
|
|
09439c55ab | ||
|
|
c858dea2d5 | ||
|
|
228a3f123a | ||
|
|
074f7a7a49 | ||
|
|
f642313e1b | ||
|
|
dd9d96eb07 | ||
|
|
35401f0e2c | ||
|
|
b6e16aea6b | ||
|
|
eeaf23041b | ||
|
|
e8096eda80 | ||
|
|
961d6a8f3b | ||
|
|
288ebf011c | ||
|
|
0ae304b6a8 | ||
|
|
5e61bb64b7 | ||
|
|
3f847fd927 | ||
|
|
4a41a53b42 | ||
|
|
a1630e1d30 | ||
|
|
bca84d9dbb | ||
|
|
e61ed48914 | ||
|
|
d29a6d134f | ||
|
|
6310b47538 | ||
|
|
9c75a4b96b | ||
|
|
c57e68292c | ||
|
|
0fecdcbeda | ||
|
|
23ad62f317 | ||
|
|
ac20008606 | ||
|
|
96d181efed | ||
|
|
18bfe7d497 | ||
|
|
86562e60ba | ||
|
|
b400532169 | ||
|
|
6fd10dedb6 | ||
|
|
c8255952a3 | ||
|
|
71c4ea36e8 | ||
|
|
5df179cd5f | ||
|
|
ce5c4ca8ba | ||
|
|
6aa8e49b09 | ||
|
|
f29f4ff4e3 | ||
|
|
3ccc59eaa3 | ||
|
|
0282b8450c | ||
|
|
43841af2f3 | ||
|
|
b2d8d41e3f | ||
|
|
0e38843ae9 | ||
|
|
96472e5537 | ||
|
|
48b0fed29e | ||
|
|
1efa220773 | ||
|
|
2d6622e543 | ||
|
|
edf112b900 | ||
|
|
f0a0ab100f | ||
|
|
c28188618b | ||
|
|
0d7daf5862 | ||
|
|
60ab1daa1f | ||
|
|
105521b547 | ||
|
|
fd3086f0a9 | ||
|
|
77ebfcacb9 | ||
|
|
d62a307c34 | ||
|
|
011519cb5b | ||
|
|
77d1671d8f | ||
|
|
409f8c5823 | ||
|
|
03198356a5 | ||
|
|
b1d2393789 | ||
|
|
0f740289e9 | ||
|
|
46ce236cfb | ||
|
|
86139c855d | ||
|
|
eb070b061b | ||
|
|
2b1393e7b9 | ||
|
|
85c7b07a9b | ||
|
|
0c5ed2b60f | ||
|
|
3bd307db85 | ||
|
|
35db02d35d | ||
|
|
f287546f49 | ||
|
|
1645e682f4 | ||
|
|
a57e0a1e3f | ||
|
|
b83144c552 | ||
|
|
58fb80aec4 | ||
|
|
38f277d81b | ||
|
|
fb5ae48b18 | ||
|
|
82ca4cf641 | ||
|
|
679021a1b5 | ||
|
|
f3392561ed | ||
|
|
7a9a022744 | ||
|
|
c222b3b6a4 | ||
|
|
663c79d4af | ||
|
|
bea03db25d | ||
|
|
b96f04ccce | ||
|
|
a9db765f98 | ||
|
|
c71ab5869a | ||
|
|
04bdfbccee | ||
|
|
2acc9fbdee | ||
|
|
725ed869ba | ||
|
|
301edf69d3 | ||
|
|
1612c6d638 | ||
|
|
aadd67cd3b | ||
|
|
c2ca9c3b73 | ||
|
|
0601b4e43b | ||
|
|
8aca66b109 | ||
|
|
2aeb3871ed | ||
|
|
ea21fb856e | ||
|
|
d5123011b3 | ||
|
|
8ac06fb63f | ||
|
|
4e727adc25 | ||
|
|
702a8c3a05 | ||
|
|
48d3972299 | ||
|
|
62fce50f8c | ||
|
|
e4b862f3d1 | ||
|
|
09d3a5de59 | ||
|
|
97bde47c31 | ||
|
|
1c80c6e37a | ||
|
|
4588f7c615 | ||
|
|
24b8752475 | ||
|
|
3ddcf03764 | ||
|
|
35f5d51028 | ||
|
|
87c019c65c | ||
|
|
69a1fecd2e | ||
|
|
9964d67e5e | ||
|
|
a98f21aa65 | ||
|
|
88e4938074 | ||
|
|
e932c7a637 | ||
|
|
b5e0099f28 | ||
|
|
1afe7476e3 | ||
|
|
4068570f43 | ||
|
|
7ceb18fb37 | ||
|
|
d2ff77d56c | ||
|
|
91b7c6ab55 | ||
|
|
ebed793dec | ||
|
|
be5bfeb172 | ||
|
|
801e795112 | ||
|
|
e66fc7e5cc | ||
|
|
1d63875e5d | ||
|
|
554fb7ebdd | ||
|
|
c9e8392dc7 | ||
|
|
60d37e1f53 | ||
|
|
401fccdf6e | ||
|
|
f5564a195f | ||
|
|
c7e61f3aa4 | ||
|
|
1805598eae | ||
|
|
0eca210722 | ||
|
|
fdc9e8590d | ||
|
|
e497f63e29 | ||
|
|
75233a9bca | ||
|
|
11197baf86 | ||
|
|
23ba0bc019 | ||
|
|
9cfb15a302 | ||
|
|
8bebe59e20 | ||
|
|
20d415463a | ||
|
|
9c1dcad994 | ||
|
|
0e13726e83 | ||
|
|
54346d7095 | ||
|
|
0121fbc88c | ||
|
|
f1855eed0e | ||
|
|
0f9828f179 | ||
|
|
d2c2d6d8dc | ||
|
|
f94a655121 | ||
|
|
078a3fd409 | ||
|
|
dfaed128c0 | ||
|
|
1fc4093191 | ||
|
|
ae1f8be277 | ||
|
|
d8533104b0 | ||
|
|
c6c697bdb7 | ||
|
|
660d59a7a9 | ||
|
|
92a5e6a698 | ||
|
|
aaa054a932 | ||
|
|
079065ea73 | ||
|
|
1905264061 | ||
|
|
b0a9430e98 | ||
|
|
6a93b6a7e4 | ||
|
|
ec6009dd8f | ||
|
|
4820d46353 | ||
|
|
a2845cee70 | ||
|
|
c897ca017c | ||
|
|
aee540d8bb | ||
|
|
19402aeef2 | ||
|
|
fcc0a6a203 | ||
|
|
e5eb754150 | ||
|
|
063c6d6065 | ||
|
|
2fc8ce8a16 | ||
|
|
1a3adbe9cd | ||
|
|
63fa44fa4a | ||
|
|
f89dbd48c8 | ||
|
|
9fc3e84e93 | ||
|
|
e708a5b59d | ||
|
|
d55e4c0552 | ||
|
|
54926840e6 | ||
|
|
5ef077fdf6 |
@@ -0,0 +1,2 @@
|
||||
# gperf in MSYS chokes on DOS line endings
|
||||
*.gperf text eol=lf
|
||||
@@ -40,7 +40,7 @@ hname_t::hname_t(perm_string text, int num)
|
||||
number_[0] = num;
|
||||
}
|
||||
|
||||
hname_t::hname_t(perm_string text, vector<int>&nums)
|
||||
hname_t::hname_t(perm_string text, const vector<int>&nums)
|
||||
: name_(text), number_(nums)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ class hname_t {
|
||||
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);
|
||||
explicit hname_t (perm_string text, const std::vector<int>&nums);
|
||||
hname_t (const hname_t&that);
|
||||
~hname_t();
|
||||
|
||||
@@ -56,12 +56,12 @@ class hname_t {
|
||||
|
||||
size_t has_numbers() const;
|
||||
int peek_number(size_t idx) const;
|
||||
const std::vector<int>&peek_numbers() 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.
|
||||
// If this vector has size, then the numbers all together make
|
||||
// up part of the hierarchical name.
|
||||
std::vector<int> number_;
|
||||
|
||||
private: // not implemented
|
||||
@@ -82,6 +82,11 @@ inline int hname_t::peek_number(size_t idx) const
|
||||
return number_[idx];
|
||||
}
|
||||
|
||||
inline const std::vector<int>& hname_t::peek_numbers(void) const
|
||||
{
|
||||
return number_;
|
||||
}
|
||||
|
||||
inline size_t hname_t::has_numbers() const
|
||||
{
|
||||
return number_.size();
|
||||
|
||||
+3
-3
@@ -118,8 +118,8 @@ O = main.o async.o design_dump.o discipline.o dup_expr.o elaborate.o \
|
||||
pform_class_type.o pform_string_type.o pform_struct_type.o pform_types.o \
|
||||
symbol_search.o sync.o sys_funcs.o verinum.o verireal.o target.o \
|
||||
Attrib.o HName.o Module.o PClass.o PDelays.o PEvent.o PExpr.o PGate.o \
|
||||
PGenerate.o PPackage.o PScope.o PSpec.o PTask.o PUdp.o PFunction.o PWire.o \
|
||||
Statement.o AStatement.o $M $(FF) $(TT)
|
||||
PGenerate.o PModport.o PPackage.o PScope.o PSpec.o PTask.o PUdp.o \
|
||||
PFunction.o PWire.o Statement.o AStatement.o $M $(FF) $(TT)
|
||||
|
||||
all: dep config.h _pli_types.h version_tag.h ivl@EXEEXT@ version.exe iverilog-vpi.man
|
||||
$(foreach dir,$(SUBDIRS),$(MAKE) -C $(dir) $@ && ) true
|
||||
@@ -292,7 +292,7 @@ endif
|
||||
version_tag.h version:
|
||||
@if $(GIT_PRESENT) && test -d $(srcdir)/.git; then \
|
||||
echo "Using git-describe for VERSION_TAG"; \
|
||||
tmp=`$(GIT) --git-dir $(srcdir)/.git describe --always --dirty \
|
||||
tmp=`(cd $(srcdir) && $(GIT) describe --always --dirty) \
|
||||
| sed -e 's;\(.*\);#define VERSION_TAG "\1";'`; \
|
||||
echo "$$tmp" | diff - version_tag.h > /dev/null 2>&1 || echo "$$tmp" > version_tag.h || exit 1; \
|
||||
elif test -r $(srcdir)/version_tag.h; then \
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998-2010 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2016 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
|
||||
@@ -35,9 +35,6 @@ Module::Module(LexicalScope*parent, perm_string n)
|
||||
program_block = false;
|
||||
uc_drive = UCD_NONE;
|
||||
timescale_warn_done = false;
|
||||
time_unit = 0;
|
||||
time_precision = 0;
|
||||
time_from_timescale = false;
|
||||
}
|
||||
|
||||
Module::~Module()
|
||||
@@ -94,13 +91,15 @@ perm_string Module::get_port_name(unsigned idx) const
|
||||
{
|
||||
|
||||
assert(idx < ports.size());
|
||||
if (ports[idx] == 0) {
|
||||
if (ports[idx] == 0 || ports[idx]->name.str() == 0) {
|
||||
/* It is possible to have undeclared ports. These
|
||||
are ports that are skipped in the declaration,
|
||||
for example like so: module foo(x ,, y); The
|
||||
port between x and y is unnamed and thus
|
||||
inaccessible to binding by name. */
|
||||
return perm_string::literal("");
|
||||
inaccessible to binding by name. Port references
|
||||
that aren't simple or escaped identifiers are
|
||||
also inaccessible to binding by name. */
|
||||
return perm_string::literal("unnamed");
|
||||
}
|
||||
return ports[idx]->name;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef IVL_Module_H
|
||||
#define IVL_Module_H
|
||||
/*
|
||||
* Copyright (c) 1998-2014 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2016 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
|
||||
@@ -35,6 +35,7 @@ class PExpr;
|
||||
class PEIdent;
|
||||
class PGate;
|
||||
class PGenerate;
|
||||
class PModport;
|
||||
class PSpecPath;
|
||||
class PTask;
|
||||
class PFunction;
|
||||
@@ -47,6 +48,10 @@ class NetScope;
|
||||
* A module is a named container and scope. A module holds a bunch of
|
||||
* semantic quantities such as wires and gates. The module is
|
||||
* therefore the handle for grasping the described circuit.
|
||||
*
|
||||
* SystemVerilog introduces program blocks and interfaces. These have
|
||||
* much in common with modules, so the Module class is used to represent
|
||||
* these containers as well.
|
||||
*/
|
||||
|
||||
class Module : public PScopeExtra, public LineInfo {
|
||||
@@ -64,7 +69,7 @@ class Module : public PScopeExtra, public LineInfo {
|
||||
|
||||
public:
|
||||
/* The name passed here is the module name, not the instance
|
||||
name. This make must be a permallocated string. */
|
||||
name. This name must be a permallocated string. */
|
||||
explicit Module(LexicalScope*parent, perm_string name);
|
||||
~Module();
|
||||
|
||||
@@ -81,6 +86,11 @@ class Module : public PScopeExtra, public LineInfo {
|
||||
restrictions and slightly modify scheduling semantics. */
|
||||
bool program_block;
|
||||
|
||||
/* This is true if the module represents a interface
|
||||
instead of a module/cell. Interfaces have different
|
||||
content restrictions and some extra allowed items. */
|
||||
bool is_interface;
|
||||
|
||||
enum UCDriveType { UCD_NONE, UCD_PULL0, UCD_PULL1 };
|
||||
UCDriveType uc_drive;
|
||||
|
||||
@@ -111,10 +121,6 @@ class Module : public PScopeExtra, public LineInfo {
|
||||
|
||||
map<perm_string,PExpr*> attributes;
|
||||
|
||||
/* These are the timescale for this module. The default is
|
||||
set by the `timescale directive. */
|
||||
int time_unit, time_precision;
|
||||
bool time_from_timescale;
|
||||
bool timescale_warn_done;
|
||||
|
||||
/* The module has a list of generate schemes that appear in
|
||||
@@ -125,6 +131,11 @@ class Module : public PScopeExtra, public LineInfo {
|
||||
unless they are instantiated, implicitly or explicitly. */
|
||||
std::map<perm_string,Module*> nested_modules;
|
||||
|
||||
/* An interface can contain one or more named modport lists.
|
||||
The parser will ensure these don't appear in modules or
|
||||
program blocks. */
|
||||
map<perm_string,PModport*> modports;
|
||||
|
||||
list<PSpecPath*> specify_paths;
|
||||
|
||||
// The mod_name() is the name of the module type.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998-2012 Stephen Williams <[email protected]>
|
||||
* Copyright (c) 1998-2016 Stephen Williams <[email protected]>
|
||||
* Copyright CERN 2013 / Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
@@ -137,7 +137,7 @@ bool PEBinary::has_aa_term(Design*des, NetScope*scope) const
|
||||
return left_->has_aa_term(des, scope) || right_->has_aa_term(des, scope);
|
||||
}
|
||||
|
||||
PECastSize::PECastSize(unsigned si, PExpr*b)
|
||||
PECastSize::PECastSize(PExpr*si, PExpr*b)
|
||||
: size_(si), base_(b)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef IVL_PExpr_H
|
||||
#define IVL_PExpr_H
|
||||
/*
|
||||
* Copyright (c) 1998-2014 Stephen Williams <[email protected]>
|
||||
* Copyright (c) 1998-2016 Stephen Williams <[email protected]>
|
||||
* Copyright CERN 2013 / Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
@@ -436,7 +436,7 @@ class PEIdent : public PExpr {
|
||||
const perm_string&) const;
|
||||
bool elaborate_lval_net_packed_member_(Design*, NetScope*,
|
||||
NetAssign_*,
|
||||
const perm_string&) const;
|
||||
const name_component_t&) const;
|
||||
bool elaborate_lval_darray_bit_(Design*, NetScope*,
|
||||
NetAssign_*) const;
|
||||
|
||||
@@ -917,8 +917,10 @@ class PECallFunction : public PExpr {
|
||||
virtual bool has_aa_term(Design*des, NetScope*scope) const;
|
||||
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
||||
unsigned expr_wid,
|
||||
unsigned flags) const;
|
||||
ivl_type_t type, unsigned flags) 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);
|
||||
@@ -969,7 +971,7 @@ class PECallFunction : public PExpr {
|
||||
class PECastSize : public PExpr {
|
||||
|
||||
public:
|
||||
explicit PECastSize(unsigned expr_wid, PExpr*base);
|
||||
explicit PECastSize(PExpr*size, PExpr*base);
|
||||
~PECastSize();
|
||||
|
||||
void dump(ostream &out) const;
|
||||
@@ -982,7 +984,7 @@ class PECastSize : public PExpr {
|
||||
width_mode_t&mode);
|
||||
|
||||
private:
|
||||
unsigned size_;
|
||||
PExpr* size_;
|
||||
PExpr* base_;
|
||||
};
|
||||
|
||||
@@ -997,6 +999,9 @@ class PECastType : public PExpr {
|
||||
|
||||
void dump(ostream &out) const;
|
||||
|
||||
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;
|
||||
|
||||
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include "PModport.h"
|
||||
|
||||
PModport::PModport(perm_string n)
|
||||
: name_(n)
|
||||
{
|
||||
}
|
||||
|
||||
PModport::~PModport()
|
||||
{
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
#ifndef IVL_PModport_H
|
||||
#define IVL_PModport_H
|
||||
/*
|
||||
* Copyright (c) 2015 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
# include "LineInfo.h"
|
||||
# include "PScope.h"
|
||||
# include "StringHeap.h"
|
||||
# include "netlist.h"
|
||||
# include <vector>
|
||||
|
||||
/*
|
||||
* The PModport class represents a parsed SystemVerilog modport list.
|
||||
*/
|
||||
class PModport : public LineInfo {
|
||||
|
||||
public:
|
||||
// The name is a perm-allocated string. It is the simple name
|
||||
// of the modport, without any scope.
|
||||
explicit PModport(perm_string name);
|
||||
~PModport();
|
||||
|
||||
perm_string name() const { return name_; }
|
||||
|
||||
typedef pair <NetNet::PortType,PExpr*> simple_port_t;
|
||||
map<perm_string,simple_port_t> simple_ports;
|
||||
|
||||
private:
|
||||
perm_string name_;
|
||||
|
||||
private: // not implemented
|
||||
PModport(const PModport&);
|
||||
PModport& operator= (const PModport&);
|
||||
};
|
||||
|
||||
#endif /* IVL_PModport_H */
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008,2010 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2008,2016 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,21 +19,9 @@
|
||||
|
||||
# include "PScope.h"
|
||||
|
||||
PScope::PScope(perm_string n, LexicalScope*parent)
|
||||
: LexicalScope(parent), name_(n)
|
||||
bool LexicalScope::var_init_needs_explicit_lifetime() const
|
||||
{
|
||||
}
|
||||
|
||||
PScope::PScope(perm_string n)
|
||||
: LexicalScope(0), name_(n)
|
||||
{
|
||||
}
|
||||
|
||||
PScope::~PScope()
|
||||
{
|
||||
for(map<perm_string, data_type_t*>::iterator it = typedefs.begin();
|
||||
it != typedefs.end(); ++it)
|
||||
delete it->second;
|
||||
return false;
|
||||
}
|
||||
|
||||
PWire* LexicalScope::wires_find(perm_string name)
|
||||
@@ -45,17 +33,26 @@ PWire* LexicalScope::wires_find(perm_string name)
|
||||
return (*cur).second;
|
||||
}
|
||||
|
||||
PScopeExtra::PScopeExtra(perm_string n, LexicalScope*parent)
|
||||
: PScope(n, parent)
|
||||
PScope::PScope(perm_string n, LexicalScope*parent)
|
||||
: LexicalScope(parent), name_(n)
|
||||
{
|
||||
time_unit = 0;
|
||||
time_precision = 0;
|
||||
time_from_timescale = false;
|
||||
}
|
||||
|
||||
PScopeExtra::PScopeExtra(perm_string n)
|
||||
: PScope(n)
|
||||
PScope::~PScope()
|
||||
{
|
||||
for(map<perm_string, data_type_t*>::iterator it = typedefs.begin();
|
||||
it != typedefs.end(); ++it)
|
||||
delete it->second;
|
||||
}
|
||||
|
||||
PScopeExtra::PScopeExtra(perm_string n, LexicalScope*parent)
|
||||
: PScope(n, parent)
|
||||
{
|
||||
}
|
||||
|
||||
PScopeExtra::~PScopeExtra()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef IVL_PScope_H
|
||||
#define IVL_PScope_H
|
||||
/*
|
||||
* Copyright (c) 2008-2014 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2008-2016 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,7 @@ class PProcess;
|
||||
class PClass;
|
||||
class PTask;
|
||||
class PWire;
|
||||
class Statement;
|
||||
|
||||
class Design;
|
||||
class NetScope;
|
||||
@@ -52,10 +53,14 @@ class NetScope;
|
||||
class LexicalScope {
|
||||
|
||||
public:
|
||||
explicit LexicalScope(LexicalScope*parent) : parent_(parent) { }
|
||||
enum lifetime_t { INHERITED, STATIC, AUTOMATIC };
|
||||
|
||||
explicit LexicalScope(LexicalScope*parent) : default_lifetime(INHERITED), parent_(parent) { }
|
||||
// A virtual destructor is so that dynamic_cast can work.
|
||||
virtual ~LexicalScope() { }
|
||||
|
||||
lifetime_t default_lifetime;
|
||||
|
||||
struct range_t {
|
||||
// True if this is an exclude
|
||||
bool exclude_flag;
|
||||
@@ -108,6 +113,9 @@ class LexicalScope {
|
||||
// creating implicit nets.
|
||||
map<perm_string,LineInfo*> genvars;
|
||||
|
||||
// Variable initializations in this scope
|
||||
vector<Statement*> var_inits;
|
||||
|
||||
// Behaviors (processes) in this scope
|
||||
list<PProcess*> behaviors;
|
||||
list<AProcess*> analog_behaviors;
|
||||
@@ -117,6 +125,8 @@ class LexicalScope {
|
||||
|
||||
LexicalScope* parent_scope() const { return parent_; }
|
||||
|
||||
virtual bool var_init_needs_explicit_lifetime() const;
|
||||
|
||||
protected:
|
||||
void dump_typedefs_(ostream&out, unsigned indent) const;
|
||||
|
||||
@@ -130,6 +140,10 @@ class LexicalScope {
|
||||
|
||||
void dump_wires_(ostream&out, unsigned indent) const;
|
||||
|
||||
void dump_var_inits_(ostream&out, unsigned indent) const;
|
||||
|
||||
bool elaborate_var_inits_(Design*des, NetScope*scope) const;
|
||||
|
||||
private:
|
||||
LexicalScope*parent_;
|
||||
};
|
||||
@@ -145,12 +159,17 @@ class PScope : public LexicalScope {
|
||||
// modules do not nest in Verilog, the parent must be nil for
|
||||
// modules. Scopes for tasks and functions point to their
|
||||
// containing module.
|
||||
PScope(perm_string name, LexicalScope*parent);
|
||||
PScope(perm_string name);
|
||||
explicit PScope(perm_string name, LexicalScope*parent =0);
|
||||
virtual ~PScope();
|
||||
|
||||
perm_string pscope_name() const { return name_; }
|
||||
|
||||
/* These are the timescale for this scope. The default is
|
||||
set by the `timescale directive or, in SystemVerilog,
|
||||
by timeunit and timeprecision statements. */
|
||||
int time_unit, time_precision;
|
||||
bool time_from_timescale;
|
||||
|
||||
protected:
|
||||
bool elaborate_sig_wires_(Design*des, NetScope*scope) const;
|
||||
|
||||
@@ -168,14 +187,13 @@ class PScope : public LexicalScope {
|
||||
class PScopeExtra : public PScope {
|
||||
|
||||
public:
|
||||
PScopeExtra(perm_string, LexicalScope*parent);
|
||||
PScopeExtra(perm_string);
|
||||
explicit PScopeExtra(perm_string, LexicalScope*parent =0);
|
||||
~PScopeExtra();
|
||||
|
||||
/* Task definitions within this module */
|
||||
std::map<perm_string,PTask*> tasks;
|
||||
std::map<perm_string,PFunction*> funcs;
|
||||
/* class definitions within this module. */
|
||||
/* 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. */
|
||||
|
||||
@@ -30,6 +30,11 @@ PTaskFunc::~PTaskFunc()
|
||||
{
|
||||
}
|
||||
|
||||
bool PTaskFunc::var_init_needs_explicit_lifetime() const
|
||||
{
|
||||
return default_lifetime == STATIC;
|
||||
}
|
||||
|
||||
void PTaskFunc::set_ports(vector<pform_tf_port_t>*p)
|
||||
{
|
||||
assert(ports_ == 0);
|
||||
@@ -41,7 +46,7 @@ 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.
|
||||
// Push a synthesis argument that is the "this" value.
|
||||
if (ports_==0)
|
||||
ports_ = new vector<pform_tf_port_t>;
|
||||
|
||||
|
||||
@@ -41,6 +41,8 @@ class PTaskFunc : public PScope, public LineInfo {
|
||||
PTaskFunc(perm_string name, LexicalScope*parent);
|
||||
~PTaskFunc();
|
||||
|
||||
bool var_init_needs_explicit_lifetime() const;
|
||||
|
||||
void set_ports(std::vector<pform_tf_port_t>*p);
|
||||
|
||||
void set_this(class_type_t*use_type, PWire*this_wire);
|
||||
|
||||
@@ -115,6 +115,11 @@ PBlock::~PBlock()
|
||||
delete list_[idx];
|
||||
}
|
||||
|
||||
bool PBlock::var_init_needs_explicit_lifetime() const
|
||||
{
|
||||
return default_lifetime == STATIC;
|
||||
}
|
||||
|
||||
PChainConstructor* PBlock::extract_chain_constructor()
|
||||
{
|
||||
if (list_.empty())
|
||||
|
||||
+4
-1
@@ -108,7 +108,8 @@ class PAssign_ : public Statement {
|
||||
NetAssign_* elaborate_lval(Design*, NetScope*scope) const;
|
||||
NetExpr* elaborate_rval_(Design*, NetScope*, ivl_type_t lv_net_type,
|
||||
ivl_variable_type_t lv_type,
|
||||
unsigned lv_width) const;
|
||||
unsigned lv_width,
|
||||
bool force_unsigned =false) const;
|
||||
NetExpr* elaborate_rval_(Design*, NetScope*, ivl_type_t ntype) const;
|
||||
|
||||
NetExpr* elaborate_rval_obj_(Design*, NetScope*,
|
||||
@@ -182,6 +183,8 @@ class PBlock : public PScope, public Statement {
|
||||
|
||||
BL_TYPE bl_type() const { return bl_type_; }
|
||||
|
||||
bool var_init_needs_explicit_lifetime() const;
|
||||
|
||||
// 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.
|
||||
|
||||
Vendored
+2
-1
@@ -223,8 +223,9 @@ AC_SUBST(strip_dynamic)
|
||||
# -------------
|
||||
AC_DEFUN([AX_C99_STRTOD],
|
||||
[# On MinGW we need to jump through hoops to get a C99 compliant strtod().
|
||||
# mingw-w64 doesn't need this, and the 64-bit version doesn't support it.
|
||||
case "${host}" in
|
||||
*-*-mingw*)
|
||||
*-*-mingw32)
|
||||
LDFLAGS+=" -Wl,--undefined=___strtod,--wrap,strtod,--defsym,___wrap_strtod=___strtod"
|
||||
;;
|
||||
esac
|
||||
|
||||
+19
-15
@@ -1,7 +1,7 @@
|
||||
#ifndef IVL_compiler_H
|
||||
#define IVL_compiler_H
|
||||
/*
|
||||
* Copyright (c) 1999-2014 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1999-2016 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
|
||||
@@ -80,6 +80,10 @@ extern unsigned recursive_mod_limit;
|
||||
/* Implicit definitions of wires. */
|
||||
extern bool warn_implicit;
|
||||
|
||||
/* Warn if dimensions of port or var/net are implicitly taken from
|
||||
the input/output/inout declaration. */
|
||||
extern bool warn_implicit_dimensions;
|
||||
|
||||
/* inherit timescales across files. */
|
||||
extern bool warn_timescale;
|
||||
|
||||
@@ -138,7 +142,8 @@ extern int build_library_index(const char*path, bool key_case_sensitive);
|
||||
|
||||
/* This is the generation of Verilog that the compiler is asked to
|
||||
support. Then there are also more detailed controls for more
|
||||
specific language features. */
|
||||
specific language features. Note that the compiler often assumes
|
||||
this is an ordered list. */
|
||||
enum generation_t {
|
||||
GN_VER1995 = 1,
|
||||
GN_VER2001_NOCONFIG = 2,
|
||||
@@ -182,25 +187,24 @@ extern bool gn_strict_ca_eval_flag;
|
||||
standard expression width rules. */
|
||||
extern bool gn_strict_expr_width_flag;
|
||||
|
||||
/* If variables can be converted to uwires by a continuous assignment
|
||||
(assuming no procedural assign, then return true. This will be true
|
||||
for SystemVerilog */
|
||||
static inline bool gn_var_can_be_uwire(void)
|
||||
/* If this flag is true, then don't add a for-loop control variable
|
||||
to an implicit event_expression list if it is only used inside the
|
||||
loop. */
|
||||
extern bool gn_shared_loop_index_flag;
|
||||
|
||||
static inline bool gn_system_verilog(void)
|
||||
{
|
||||
if (generation_flag == GN_VER2005_SV ||
|
||||
generation_flag == GN_VER2009 ||
|
||||
generation_flag == GN_VER2012)
|
||||
if (generation_flag >= GN_VER2005_SV)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool gn_system_verilog(void)
|
||||
/* If variables can be converted to uwires by a continuous assignment
|
||||
(assuming no procedural assign), then return true. This will be true
|
||||
for SystemVerilog */
|
||||
static inline bool gn_var_can_be_uwire(void)
|
||||
{
|
||||
if (generation_flag == GN_VER2005_SV ||
|
||||
generation_flag == GN_VER2009 ||
|
||||
generation_flag == GN_VER2012)
|
||||
return true;
|
||||
return false;
|
||||
return gn_system_verilog();
|
||||
}
|
||||
|
||||
static inline bool gn_modules_nest(void)
|
||||
|
||||
Vendored
+324
-447
File diff suppressed because it is too large
Load Diff
+2
-1
@@ -1,7 +1,7 @@
|
||||
#ifndef IVL_config_H /* -*- c++ -*- */
|
||||
#define IVL_config_H
|
||||
/*
|
||||
* Copyright (c) 2001-2014 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2001-2015 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
|
||||
@@ -55,6 +55,7 @@
|
||||
# undef HAVE_FSEEKO
|
||||
/* And this is needed by the fst files (copied from GTKWave). */
|
||||
# undef HAVE_LIBPTHREAD
|
||||
# undef HAVE_REALPATH
|
||||
|
||||
/*
|
||||
* Define this if you want to compile vvp with memory freeing and
|
||||
|
||||
Vendored
+225
-101
@@ -1,44 +1,40 @@
|
||||
#! /bin/sh
|
||||
# Configuration validation subroutine script.
|
||||
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
|
||||
# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
|
||||
# Free Software Foundation, Inc.
|
||||
# Copyright 1992-2015 Free Software Foundation, Inc.
|
||||
|
||||
timestamp='2009-04-17'
|
||||
timestamp='2015-03-08'
|
||||
|
||||
# This file is (in principle) common to ALL GNU software.
|
||||
# The presence of a machine in this file suggests that SOME GNU software
|
||||
# can handle that machine. It does not imply ALL GNU software can.
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# This file is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
|
||||
# 02110-1301, USA.
|
||||
# along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
# the same distribution terms that you use for the rest of that
|
||||
# program. This Exception is an additional permission under section 7
|
||||
# of the GNU General Public License, version 3 ("GPLv3").
|
||||
|
||||
|
||||
# Please send patches to <[email protected]>. Submit a context
|
||||
# diff and a properly formatted ChangeLog entry.
|
||||
# Please send patches to <[email protected]>.
|
||||
#
|
||||
# Configuration subroutine to validate and canonicalize a configuration type.
|
||||
# Supply the specified configuration type as an argument.
|
||||
# If it is invalid, we print an error message on stderr and exit with code 1.
|
||||
# Otherwise, we print the canonical config type on stdout and succeed.
|
||||
|
||||
# You can get the latest version of this script from:
|
||||
# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
|
||||
|
||||
# This file is supposed to be the same for all GNU packages
|
||||
# and recognize all the CPU types, system types and aliases
|
||||
# that are meaningful with *any* GNU software.
|
||||
@@ -72,8 +68,7 @@ Report bugs and patches to <[email protected]>."
|
||||
version="\
|
||||
GNU config.sub ($timestamp)
|
||||
|
||||
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
|
||||
2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
Copyright 1992-2015 Free Software Foundation, Inc.
|
||||
|
||||
This is free software; see the source for copying conditions. There is NO
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
|
||||
@@ -120,13 +115,18 @@ esac
|
||||
# Here we must recognize all the valid KERNEL-OS combinations.
|
||||
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
|
||||
case $maybe_os in
|
||||
nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
|
||||
uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
|
||||
nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
|
||||
linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
|
||||
knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \
|
||||
kopensolaris*-gnu* | \
|
||||
storm-chaos* | os2-emx* | rtmk-nova*)
|
||||
os=-$maybe_os
|
||||
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
|
||||
;;
|
||||
android-linux)
|
||||
os=-linux-android
|
||||
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
|
||||
;;
|
||||
*)
|
||||
basic_machine=`echo $1 | sed 's/-[^-]*$//'`
|
||||
if [ $basic_machine != $1 ]
|
||||
@@ -149,10 +149,13 @@ case $os in
|
||||
-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
|
||||
-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
|
||||
-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
|
||||
-apple | -axis | -knuth | -cray)
|
||||
-apple | -axis | -knuth | -cray | -microblaze*)
|
||||
os=
|
||||
basic_machine=$1
|
||||
;;
|
||||
-bluegene*)
|
||||
os=-cnk
|
||||
;;
|
||||
-sim | -cisco | -oki | -wec | -winbond)
|
||||
os=
|
||||
basic_machine=$1
|
||||
@@ -167,10 +170,10 @@ case $os in
|
||||
os=-chorusos
|
||||
basic_machine=$1
|
||||
;;
|
||||
-chorusrdb)
|
||||
os=-chorusrdb
|
||||
-chorusrdb)
|
||||
os=-chorusrdb
|
||||
basic_machine=$1
|
||||
;;
|
||||
;;
|
||||
-hiux*)
|
||||
os=-hiuxwe2
|
||||
;;
|
||||
@@ -215,6 +218,12 @@ case $os in
|
||||
-isc*)
|
||||
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
|
||||
;;
|
||||
-lynx*178)
|
||||
os=-lynxos178
|
||||
;;
|
||||
-lynx*5)
|
||||
os=-lynxos5
|
||||
;;
|
||||
-lynx*)
|
||||
os=-lynxos
|
||||
;;
|
||||
@@ -239,20 +248,28 @@ case $basic_machine in
|
||||
# Some are omitted here because they have special meanings below.
|
||||
1750a | 580 \
|
||||
| a29k \
|
||||
| aarch64 | aarch64_be \
|
||||
| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
|
||||
| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
|
||||
| am33_2.0 \
|
||||
| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
|
||||
| arc | arceb \
|
||||
| arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
|
||||
| avr | avr32 \
|
||||
| be32 | be64 \
|
||||
| bfin \
|
||||
| c4x | clipper \
|
||||
| c4x | c8051 | clipper \
|
||||
| d10v | d30v | dlx | dsp16xx \
|
||||
| fido | fr30 | frv \
|
||||
| e2k | epiphany \
|
||||
| fido | fr30 | frv | ft32 \
|
||||
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
|
||||
| hexagon \
|
||||
| i370 | i860 | i960 | ia64 \
|
||||
| ip2k | iq2000 \
|
||||
| k1om \
|
||||
| le32 | le64 \
|
||||
| lm32 \
|
||||
| m32c | m32r | m32rle | m68000 | m68k | m88k \
|
||||
| maxq | mb | microblaze | mcore | mep | metag \
|
||||
| maxq | mb | microblaze | microblazeel | mcore | mep | metag \
|
||||
| mips | mipsbe | mipseb | mipsel | mipsle \
|
||||
| mips16 \
|
||||
| mips64 | mips64el \
|
||||
@@ -266,36 +283,55 @@ case $basic_machine in
|
||||
| mips64vr5900 | mips64vr5900el \
|
||||
| mipsisa32 | mipsisa32el \
|
||||
| mipsisa32r2 | mipsisa32r2el \
|
||||
| mipsisa32r6 | mipsisa32r6el \
|
||||
| mipsisa64 | mipsisa64el \
|
||||
| mipsisa64r2 | mipsisa64r2el \
|
||||
| mipsisa64r6 | mipsisa64r6el \
|
||||
| mipsisa64sb1 | mipsisa64sb1el \
|
||||
| mipsisa64sr71k | mipsisa64sr71kel \
|
||||
| mipsr5900 | mipsr5900el \
|
||||
| mipstx39 | mipstx39el \
|
||||
| mn10200 | mn10300 \
|
||||
| moxie \
|
||||
| mt \
|
||||
| msp430 \
|
||||
| nios | nios2 \
|
||||
| nds32 | nds32le | nds32be \
|
||||
| nios | nios2 | nios2eb | nios2el \
|
||||
| ns16k | ns32k \
|
||||
| or32 \
|
||||
| open8 | or1k | or1knd | or32 \
|
||||
| pdp10 | pdp11 | pj | pjl \
|
||||
| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
|
||||
| powerpc | powerpc64 | powerpc64le | powerpcle \
|
||||
| pyramid \
|
||||
| riscv32 | riscv64 \
|
||||
| rl78 | rx \
|
||||
| score \
|
||||
| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
|
||||
| sh64 | sh64le \
|
||||
| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
|
||||
| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
|
||||
| spu | strongarm \
|
||||
| tahoe | thumb | tic4x | tic80 | tron \
|
||||
| v850 | v850e \
|
||||
| spu \
|
||||
| tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
|
||||
| ubicom32 \
|
||||
| v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
|
||||
| visium \
|
||||
| we32k \
|
||||
| x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
|
||||
| x86 | xc16x | xstormy16 | xtensa \
|
||||
| z8k | z80)
|
||||
basic_machine=$basic_machine-unknown
|
||||
;;
|
||||
m6811 | m68hc11 | m6812 | m68hc12)
|
||||
# Motorola 68HC11/12.
|
||||
c54x)
|
||||
basic_machine=tic54x-unknown
|
||||
;;
|
||||
c55x)
|
||||
basic_machine=tic55x-unknown
|
||||
;;
|
||||
c6x)
|
||||
basic_machine=tic6x-unknown
|
||||
;;
|
||||
leon|leon[3-9])
|
||||
basic_machine=sparc-$basic_machine
|
||||
;;
|
||||
m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)
|
||||
basic_machine=$basic_machine-unknown
|
||||
os=-none
|
||||
;;
|
||||
@@ -305,6 +341,21 @@ case $basic_machine in
|
||||
basic_machine=mt-unknown
|
||||
;;
|
||||
|
||||
strongarm | thumb | xscale)
|
||||
basic_machine=arm-unknown
|
||||
;;
|
||||
xgate)
|
||||
basic_machine=$basic_machine-unknown
|
||||
os=-none
|
||||
;;
|
||||
xscaleeb)
|
||||
basic_machine=armeb-unknown
|
||||
;;
|
||||
|
||||
xscaleel)
|
||||
basic_machine=armel-unknown
|
||||
;;
|
||||
|
||||
# We use `pc' rather than `unknown'
|
||||
# because (1) that's what they normally are, and
|
||||
# (2) the word "unknown" tends to confuse beginning users.
|
||||
@@ -319,25 +370,31 @@ case $basic_machine in
|
||||
# Recognize the basic CPU types with company name.
|
||||
580-* \
|
||||
| a29k-* \
|
||||
| aarch64-* | aarch64_be-* \
|
||||
| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
|
||||
| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
|
||||
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
|
||||
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
|
||||
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
|
||||
| avr-* | avr32-* \
|
||||
| be32-* | be64-* \
|
||||
| bfin-* | bs2000-* \
|
||||
| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
|
||||
| clipper-* | craynv-* | cydra-* \
|
||||
| c[123]* | c30-* | [cjt]90-* | c4x-* \
|
||||
| c8051-* | clipper-* | craynv-* | cydra-* \
|
||||
| d10v-* | d30v-* | dlx-* \
|
||||
| elxsi-* \
|
||||
| e2k-* | elxsi-* \
|
||||
| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
|
||||
| h8300-* | h8500-* \
|
||||
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
|
||||
| hexagon-* \
|
||||
| i*86-* | i860-* | i960-* | ia64-* \
|
||||
| ip2k-* | iq2000-* \
|
||||
| k1om-* \
|
||||
| le32-* | le64-* \
|
||||
| lm32-* \
|
||||
| m32c-* | m32r-* | m32rle-* \
|
||||
| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
|
||||
| m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
|
||||
| microblaze-* | microblazeel-* \
|
||||
| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
|
||||
| mips16-* \
|
||||
| mips64-* | mips64el-* \
|
||||
@@ -351,32 +408,42 @@ case $basic_machine in
|
||||
| mips64vr5900-* | mips64vr5900el-* \
|
||||
| mipsisa32-* | mipsisa32el-* \
|
||||
| mipsisa32r2-* | mipsisa32r2el-* \
|
||||
| mipsisa32r6-* | mipsisa32r6el-* \
|
||||
| mipsisa64-* | mipsisa64el-* \
|
||||
| mipsisa64r2-* | mipsisa64r2el-* \
|
||||
| mipsisa64r6-* | mipsisa64r6el-* \
|
||||
| mipsisa64sb1-* | mipsisa64sb1el-* \
|
||||
| mipsisa64sr71k-* | mipsisa64sr71kel-* \
|
||||
| mipsr5900-* | mipsr5900el-* \
|
||||
| mipstx39-* | mipstx39el-* \
|
||||
| mmix-* \
|
||||
| mt-* \
|
||||
| msp430-* \
|
||||
| nios-* | nios2-* \
|
||||
| nds32-* | nds32le-* | nds32be-* \
|
||||
| nios-* | nios2-* | nios2eb-* | nios2el-* \
|
||||
| none-* | np1-* | ns16k-* | ns32k-* \
|
||||
| open8-* \
|
||||
| or1k*-* \
|
||||
| orion-* \
|
||||
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
|
||||
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
|
||||
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
|
||||
| pyramid-* \
|
||||
| romp-* | rs6000-* \
|
||||
| rl78-* | romp-* | rs6000-* | rx-* \
|
||||
| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
|
||||
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
|
||||
| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
|
||||
| sparclite-* \
|
||||
| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
|
||||
| tahoe-* | thumb-* \
|
||||
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* | tile-* \
|
||||
| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \
|
||||
| tahoe-* \
|
||||
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
|
||||
| tile*-* \
|
||||
| tron-* \
|
||||
| v850-* | v850e-* | vax-* \
|
||||
| ubicom32-* \
|
||||
| v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
|
||||
| vax-* \
|
||||
| visium-* \
|
||||
| we32k-* \
|
||||
| x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
|
||||
| x86-* | x86_64-* | xc16x-* | xps100-* \
|
||||
| xstormy16-* | xtensa*-* \
|
||||
| ymp-* \
|
||||
| z8k-* | z80-*)
|
||||
@@ -401,7 +468,7 @@ case $basic_machine in
|
||||
basic_machine=a29k-amd
|
||||
os=-udi
|
||||
;;
|
||||
abacus)
|
||||
abacus)
|
||||
basic_machine=abacus-unknown
|
||||
;;
|
||||
adobe68k)
|
||||
@@ -451,6 +518,9 @@ case $basic_machine in
|
||||
basic_machine=i386-pc
|
||||
os=-aros
|
||||
;;
|
||||
asmjs)
|
||||
basic_machine=asmjs-unknown
|
||||
;;
|
||||
aux)
|
||||
basic_machine=m68k-apple
|
||||
os=-aux
|
||||
@@ -467,11 +537,24 @@ case $basic_machine in
|
||||
basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
os=-linux
|
||||
;;
|
||||
bluegene*)
|
||||
basic_machine=powerpc-ibm
|
||||
os=-cnk
|
||||
;;
|
||||
c54x-*)
|
||||
basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
c55x-*)
|
||||
basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
c6x-*)
|
||||
basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
c90)
|
||||
basic_machine=c90-cray
|
||||
os=-unicos
|
||||
;;
|
||||
cegcc)
|
||||
cegcc)
|
||||
basic_machine=arm-unknown
|
||||
os=-cegcc
|
||||
;;
|
||||
@@ -503,7 +586,7 @@ case $basic_machine in
|
||||
basic_machine=craynv-cray
|
||||
os=-unicosmp
|
||||
;;
|
||||
cr16)
|
||||
cr16 | cr16-*)
|
||||
basic_machine=cr16-unknown
|
||||
os=-elf
|
||||
;;
|
||||
@@ -661,7 +744,6 @@ case $basic_machine in
|
||||
i370-ibm* | ibm*)
|
||||
basic_machine=i370-ibm
|
||||
;;
|
||||
# I'm not sure what "Sysv32" means. Should this be sysv3.2?
|
||||
i*86v32)
|
||||
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
|
||||
os=-sysv32
|
||||
@@ -700,6 +782,9 @@ case $basic_machine in
|
||||
basic_machine=m68k-isi
|
||||
os=-sysv
|
||||
;;
|
||||
leon-*|leon[3-9]-*)
|
||||
basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'`
|
||||
;;
|
||||
m68knommu)
|
||||
basic_machine=m68k-unknown
|
||||
os=-linux
|
||||
@@ -719,8 +804,15 @@ case $basic_machine in
|
||||
basic_machine=ns32k-utek
|
||||
os=-sysv
|
||||
;;
|
||||
microblaze*)
|
||||
basic_machine=microblaze-xilinx
|
||||
;;
|
||||
mingw64)
|
||||
basic_machine=x86_64-pc
|
||||
os=-mingw64
|
||||
;;
|
||||
mingw32)
|
||||
basic_machine=i386-pc
|
||||
basic_machine=i686-pc
|
||||
os=-mingw32
|
||||
;;
|
||||
mingw32ce)
|
||||
@@ -748,6 +840,10 @@ case $basic_machine in
|
||||
basic_machine=powerpc-unknown
|
||||
os=-morphos
|
||||
;;
|
||||
moxiebox)
|
||||
basic_machine=moxie-unknown
|
||||
os=-moxiebox
|
||||
;;
|
||||
msdos)
|
||||
basic_machine=i386-pc
|
||||
os=-msdos
|
||||
@@ -755,10 +851,18 @@ case $basic_machine in
|
||||
ms1-*)
|
||||
basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
|
||||
;;
|
||||
msys)
|
||||
basic_machine=i686-pc
|
||||
os=-msys
|
||||
;;
|
||||
mvs)
|
||||
basic_machine=i370-ibm
|
||||
os=-mvs
|
||||
;;
|
||||
nacl)
|
||||
basic_machine=le32-unknown
|
||||
os=-nacl
|
||||
;;
|
||||
ncr3000)
|
||||
basic_machine=i486-ncr
|
||||
os=-sysv4
|
||||
@@ -823,6 +927,12 @@ case $basic_machine in
|
||||
np1)
|
||||
basic_machine=np1-gould
|
||||
;;
|
||||
neo-tandem)
|
||||
basic_machine=neo-tandem
|
||||
;;
|
||||
nse-tandem)
|
||||
basic_machine=nse-tandem
|
||||
;;
|
||||
nsr-tandem)
|
||||
basic_machine=nsr-tandem
|
||||
;;
|
||||
@@ -905,9 +1015,10 @@ case $basic_machine in
|
||||
;;
|
||||
power) basic_machine=power-ibm
|
||||
;;
|
||||
ppc) basic_machine=powerpc-unknown
|
||||
ppc | ppcbe) basic_machine=powerpc-unknown
|
||||
;;
|
||||
ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
ppc-* | ppcbe-*)
|
||||
basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
ppcle | powerpclittle | ppc-le | powerpc-little)
|
||||
basic_machine=powerpcle-unknown
|
||||
@@ -932,7 +1043,11 @@ case $basic_machine in
|
||||
basic_machine=i586-unknown
|
||||
os=-pw32
|
||||
;;
|
||||
rdos)
|
||||
rdos | rdos64)
|
||||
basic_machine=x86_64-pc
|
||||
os=-rdos
|
||||
;;
|
||||
rdos32)
|
||||
basic_machine=i386-pc
|
||||
os=-rdos
|
||||
;;
|
||||
@@ -1001,6 +1116,9 @@ case $basic_machine in
|
||||
basic_machine=i860-stratus
|
||||
os=-sysv4
|
||||
;;
|
||||
strongarm-* | thumb-*)
|
||||
basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`
|
||||
;;
|
||||
sun2)
|
||||
basic_machine=m68000-sun
|
||||
;;
|
||||
@@ -1057,20 +1175,8 @@ case $basic_machine in
|
||||
basic_machine=t90-cray
|
||||
os=-unicos
|
||||
;;
|
||||
tic54x | c54x*)
|
||||
basic_machine=tic54x-unknown
|
||||
os=-coff
|
||||
;;
|
||||
tic55x | c55x*)
|
||||
basic_machine=tic55x-unknown
|
||||
os=-coff
|
||||
;;
|
||||
tic6x | c6x*)
|
||||
basic_machine=tic6x-unknown
|
||||
os=-coff
|
||||
;;
|
||||
tile*)
|
||||
basic_machine=tile-unknown
|
||||
basic_machine=$basic_machine-unknown
|
||||
os=-linux-gnu
|
||||
;;
|
||||
tx39)
|
||||
@@ -1140,6 +1246,9 @@ case $basic_machine in
|
||||
xps | xps100)
|
||||
basic_machine=xps100-honeywell
|
||||
;;
|
||||
xscale-* | xscalee[bl]-*)
|
||||
basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`
|
||||
;;
|
||||
ymp)
|
||||
basic_machine=ymp-cray
|
||||
os=-unicos
|
||||
@@ -1237,9 +1346,12 @@ esac
|
||||
if [ x"$os" != x"" ]
|
||||
then
|
||||
case $os in
|
||||
# First match some system type aliases
|
||||
# that might get confused with valid system types.
|
||||
# First match some system type aliases
|
||||
# that might get confused with valid system types.
|
||||
# -solaris* is a basic system type, with this one exception.
|
||||
-auroraux)
|
||||
os=-auroraux
|
||||
;;
|
||||
-solaris1 | -solaris1.*)
|
||||
os=`echo $os | sed -e 's|solaris1|sunos4|'`
|
||||
;;
|
||||
@@ -1260,30 +1372,31 @@ case $os in
|
||||
# Each alternative MUST END IN A *, to match a version number.
|
||||
# -sysv* is not here because it comes later, after sysvr4.
|
||||
-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
|
||||
| -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
|
||||
| -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
|
||||
| -kopensolaris* \
|
||||
| -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
|
||||
| -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
|
||||
| -sym* | -kopensolaris* | -plan9* \
|
||||
| -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
|
||||
| -aos* | -aros* \
|
||||
| -aos* | -aros* | -cloudabi* \
|
||||
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
|
||||
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
|
||||
| -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
|
||||
| -openbsd* | -solidbsd* \
|
||||
| -bitrig* | -openbsd* | -solidbsd* \
|
||||
| -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
|
||||
| -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
|
||||
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
|
||||
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
|
||||
| -chorusos* | -chorusrdb* | -cegcc* \
|
||||
| -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
|
||||
| -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
|
||||
| -uxpv* | -beos* | -mpeix* | -udk* \
|
||||
| -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
|
||||
| -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
|
||||
| -linux-newlib* | -linux-musl* | -linux-uclibc* \
|
||||
| -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \
|
||||
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
|
||||
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
|
||||
| -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
|
||||
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
|
||||
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
|
||||
| -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
|
||||
| -skyos* | -haiku* | -rdos* | -toppers* | -drops*)
|
||||
| -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*)
|
||||
# Remember, each alternative MUST END IN *, to match a version number.
|
||||
;;
|
||||
-qnx*)
|
||||
@@ -1322,7 +1435,7 @@ case $os in
|
||||
-opened*)
|
||||
os=-openedition
|
||||
;;
|
||||
-os400*)
|
||||
-os400*)
|
||||
os=-os400
|
||||
;;
|
||||
-wince*)
|
||||
@@ -1371,7 +1484,7 @@ case $os in
|
||||
-sinix*)
|
||||
os=-sysv4
|
||||
;;
|
||||
-tpf*)
|
||||
-tpf*)
|
||||
os=-tpf
|
||||
;;
|
||||
-triton*)
|
||||
@@ -1407,15 +1520,14 @@ case $os in
|
||||
-aros*)
|
||||
os=-aros
|
||||
;;
|
||||
-kaos*)
|
||||
os=-kaos
|
||||
;;
|
||||
-zvmoe)
|
||||
os=-zvmoe
|
||||
;;
|
||||
-dicos*)
|
||||
os=-dicos
|
||||
;;
|
||||
-nacl*)
|
||||
;;
|
||||
-none)
|
||||
;;
|
||||
*)
|
||||
@@ -1438,10 +1550,10 @@ else
|
||||
# system, and we'll never get to this point.
|
||||
|
||||
case $basic_machine in
|
||||
score-*)
|
||||
score-*)
|
||||
os=-elf
|
||||
;;
|
||||
spu-*)
|
||||
spu-*)
|
||||
os=-elf
|
||||
;;
|
||||
*-acorn)
|
||||
@@ -1453,8 +1565,23 @@ case $basic_machine in
|
||||
arm*-semi)
|
||||
os=-aout
|
||||
;;
|
||||
c4x-* | tic4x-*)
|
||||
os=-coff
|
||||
c4x-* | tic4x-*)
|
||||
os=-coff
|
||||
;;
|
||||
c8051-*)
|
||||
os=-elf
|
||||
;;
|
||||
hexagon-*)
|
||||
os=-elf
|
||||
;;
|
||||
tic54x-*)
|
||||
os=-coff
|
||||
;;
|
||||
tic55x-*)
|
||||
os=-coff
|
||||
;;
|
||||
tic6x-*)
|
||||
os=-coff
|
||||
;;
|
||||
# This must come before the *-dec entry.
|
||||
pdp10-*)
|
||||
@@ -1474,14 +1601,11 @@ case $basic_machine in
|
||||
;;
|
||||
m68000-sun)
|
||||
os=-sunos3
|
||||
# This also exists in the configure program, but was not the
|
||||
# default.
|
||||
# os=-sunos4
|
||||
;;
|
||||
m68*-cisco)
|
||||
os=-aout
|
||||
;;
|
||||
mep-*)
|
||||
mep-*)
|
||||
os=-elf
|
||||
;;
|
||||
mips*-cisco)
|
||||
@@ -1508,7 +1632,7 @@ case $basic_machine in
|
||||
*-ibm)
|
||||
os=-aix
|
||||
;;
|
||||
*-knuth)
|
||||
*-knuth)
|
||||
os=-mmixware
|
||||
;;
|
||||
*-wec)
|
||||
@@ -1613,7 +1737,7 @@ case $basic_machine in
|
||||
-sunos*)
|
||||
vendor=sun
|
||||
;;
|
||||
-aix*)
|
||||
-cnk*|-aix*)
|
||||
vendor=ibm
|
||||
;;
|
||||
-beos*)
|
||||
|
||||
+8
-1
@@ -82,7 +82,7 @@ CFLAGS="$iverilog_temp_cflags"
|
||||
|
||||
AC_SUBST(DEPENDENCY_FLAG, [-MD])
|
||||
AC_SUBST(WARNING_FLAGS, ["-Wall $iverilog_wextra_flag -Wshadow"])
|
||||
AC_SUBST(WARNING_FLAGS_CC, [""])
|
||||
AC_SUBST(WARNING_FLAGS_CC, ["-Wstrict-prototypes"])
|
||||
AC_SUBST(WARNING_FLAGS_CXX, [""])
|
||||
fi
|
||||
|
||||
@@ -223,6 +223,10 @@ case "${host}" in
|
||||
CPPFLAGS="-mieee $CPPFLAGS"
|
||||
CFLAGS="-mieee $CFLAGS"
|
||||
;;
|
||||
*-*-mingw*)
|
||||
CXXFLAGS="-D__USE_MINGW_ANSI_STDIO=1 $CXXFLAGS"
|
||||
CFLAGS="-D__USE_MINGW_ANSI_STDIO=1 $CFLAGS"
|
||||
;;
|
||||
esac
|
||||
|
||||
# Do some more operating system specific setup. We put the file64_support
|
||||
@@ -238,6 +242,9 @@ case "${host}" in
|
||||
esac
|
||||
AC_SUBST(file64_support)
|
||||
|
||||
# fstapi.c (from GTKWave) needs this define.
|
||||
AC_CHECK_FUNCS(realpath)
|
||||
|
||||
# Check that these functions exist. They are mostly C99
|
||||
# functions that older compilers may not yet support.
|
||||
AC_CHECK_FUNCS(fopen64)
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
// These are correct and are used to find the base (zero) pin.
|
||||
thisSubtraction:netlist.h:4938
|
||||
thisSubtraction:netlist.h:4947
|
||||
thisSubtraction:netlist.h:4976
|
||||
thisSubtraction:netlist.h:4985
|
||||
|
||||
+19
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998-2014 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2015 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
|
||||
@@ -677,8 +677,12 @@ void NetConst::dump_node(ostream&o, unsigned ind) const
|
||||
void NetFF::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "LPM_FF: " << name()
|
||||
<< " scope=" << scope_path(scope())
|
||||
<< " aset_value=" << aset_value_ << endl;
|
||||
<< " scope=" << scope_path(scope());
|
||||
if (negedge_)
|
||||
o << " negedge";
|
||||
else
|
||||
o << " posedge";
|
||||
o << " aset_value=" << aset_value_ << endl;
|
||||
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
@@ -1375,6 +1379,7 @@ void NetScope::dump(ostream&o) const
|
||||
if (is_cell()) o << " (cell)";
|
||||
if (nested_module()) o << " (nested)";
|
||||
if (program_block()) o << " (program)";
|
||||
if (is_interface()) o << " (interface)";
|
||||
o << " " << children_.size() << " children, "
|
||||
<< classes_.size() << " classes" << endl;
|
||||
|
||||
@@ -1661,6 +1666,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)
|
||||
@@ -1879,7 +1894,7 @@ void Design::dump(ostream&o) const
|
||||
cur->second->dump(o);
|
||||
}
|
||||
|
||||
o << "$ROOT CLASSESS:" << endl;
|
||||
o << "$ROOT CLASSES:" << endl;
|
||||
for (map<perm_string,netclass_t*>::const_iterator cur = classes_.begin()
|
||||
; cur != classes_.end() ; ++cur) {
|
||||
cur->second->dump_scope(o);
|
||||
|
||||
@@ -49,6 +49,7 @@ endif
|
||||
|
||||
CPPFLAGS = $(INCLUDE_PATH) @CPPFLAGS@ @DEFS@
|
||||
CFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CC@ @CFLAGS@
|
||||
CXXFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CXX@ @CXXFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
|
||||
O = main.o res.o
|
||||
@@ -80,11 +81,12 @@ config.h: $(srcdir)/config.h.in Makefile
|
||||
sed -e 's;@IVLCC@;@CC@;' -e 's;@IVLCXX@;@CXX@;' \
|
||||
-e 's;@SUFFIX@;$(suffix);g' \
|
||||
-e 's;@IVLCFLAGS@;$(CFLAGS);' \
|
||||
-e 's;@IVLCXXFLAGS@;$(CXXFLAGS);' \
|
||||
-e 's;@SHARED@;@shared@;' $< > $@
|
||||
|
||||
# Windows specific...
|
||||
res.rc: $(srcdir)/res.rc.in ../version.exe
|
||||
sed -e 's;@PRODUCTVERSION@;'`../version.exe '%M,%m,%n,0'`';' \
|
||||
sed -e 's;@PRODUCTVERSION@;'`../version.exe '%M,%n,0,0'`';' \
|
||||
$(srcdir)/res.rc.in > $@
|
||||
|
||||
res.o: res.rc
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#define IVERILOG_VPI_CC "@IVLCC@"
|
||||
#define IVERILOG_VPI_CXX "@IVLCXX@"
|
||||
#define IVERILOG_VPI_CFLAGS " @IVLCFLAGS@"
|
||||
#define IVERILOG_VPI_CXXFLAGS " @IVLCXXFLAGS@"
|
||||
#define IVERILOG_VPI_LDFLAGS "@SHARED@"
|
||||
#define IVERILOG_VPI_LDLIBS "-lveriuser@SUFFIX@ -lvpi@SUFFIX@"
|
||||
#define IVERILOG_SUFFIX "@SUFFIX@"
|
||||
|
||||
+169
-164
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2002 Gus Baldauf (gus@picturel.com)
|
||||
* Copyright (c) 2015 Martin Whitaker
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -20,7 +21,7 @@
|
||||
/*
|
||||
* iverilog-vpi.c
|
||||
*
|
||||
* this program provides the functionality of iverilog-vpi.sh under Win32
|
||||
* this program provides the functionality of iverilog-vpi.sh under Windows
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
@@ -32,7 +33,7 @@
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
static void setup_ivl_environment();
|
||||
static void setup_ivl_environment(void);
|
||||
static void assign(char **ptr, char *str);
|
||||
|
||||
/* The compile options: compiler, flags, etc. are in here */
|
||||
@@ -43,16 +44,17 @@ static void assign(char **ptr, char *str);
|
||||
static struct global_strings {
|
||||
char *pCCSRC; /* list of C source files (*.c) */
|
||||
char *pCXSRC; /* list of C++ source files (*.cc, *.cpp) */
|
||||
char *pOBJ; /* list of object files */
|
||||
char *pLIB; /* list of library files */
|
||||
char *pINCS; /* list of include directories */
|
||||
char *pDEFS; /* list of definitions */
|
||||
char *pOUT; /* output file name (.vpi extension), if 0 length then no source files specified */
|
||||
char *pOBJ; /* list of object files */
|
||||
char *pLIB; /* list of library files */
|
||||
char *pINCS; /* list of include directories */
|
||||
char *pDEFS; /* list of definitions */
|
||||
char *pOUT; /* output file name (.vpi extension), if 0 length then no source files specified */
|
||||
char *pMINGW; /* path to MinGW directory */
|
||||
char *pIVL; /* path to IVL directory */
|
||||
char *pCFLAGS; /* CFLAGS option */
|
||||
char *pLDLIBS; /* LDLIBS option */
|
||||
char *pNewPath; /* new PATH environment variable setting */
|
||||
char *pIVL; /* path to IVL directory */
|
||||
char *pCCFLAGS; /* compiler flags for compiling C source files */
|
||||
char *pCXFLAGS; /* compiler flags for compiling C++ source files */
|
||||
char *pLDLIBS; /* linker flags for final linking stage */
|
||||
char *pCCNAME; /* base name of compiler */
|
||||
char *pLD; /* what to use for a linker */
|
||||
} gstr;
|
||||
|
||||
@@ -75,21 +77,21 @@ static void myExit(int exitVal)
|
||||
deInitDynString(gstr.pOUT);
|
||||
deInitDynString(gstr.pMINGW);
|
||||
deInitDynString(gstr.pIVL);
|
||||
deInitDynString(gstr.pCFLAGS);
|
||||
deInitDynString(gstr.pCCFLAGS);
|
||||
deInitDynString(gstr.pCXFLAGS);
|
||||
deInitDynString(gstr.pLDLIBS);
|
||||
deInitDynString(gstr.pNewPath);
|
||||
free(gstr.pLD);
|
||||
deInitDynString(gstr.pCCNAME);
|
||||
deInitDynString(gstr.pLD);
|
||||
|
||||
exit(exitVal);
|
||||
}
|
||||
|
||||
/* display usage summary and exit */
|
||||
|
||||
static void usage()
|
||||
static void usage(void)
|
||||
{
|
||||
fprintf(stderr,"usage: iverilog-vpi" IVERILOG_SUFFIX " [src and obj files]...\n");
|
||||
fprintf(stderr," or iverilog-vpi" IVERILOG_SUFFIX " -mingw=dir\n");
|
||||
fprintf(stderr," or iverilog-vpi" IVERILOG_SUFFIX " -ivl=dir\n");
|
||||
fprintf(stderr, "usage: iverilog-vpi" IVERILOG_SUFFIX " [options] [src and obj files]...\n");
|
||||
fprintf(stderr, " or iverilog-vpi" IVERILOG_SUFFIX " -mingw=dir\n");
|
||||
myExit(1);
|
||||
}
|
||||
|
||||
@@ -98,7 +100,7 @@ static void initDynString(char **str)
|
||||
*str = (char *) malloc(1);
|
||||
|
||||
if (!*str) {
|
||||
fprintf(stderr,"error: out of memory\n");
|
||||
fprintf(stderr, "error: out of memory\n");
|
||||
myExit(4);
|
||||
}
|
||||
|
||||
@@ -107,8 +109,10 @@ static void initDynString(char **str)
|
||||
|
||||
/* initialize dynamic memory buffers */
|
||||
|
||||
static void init()
|
||||
static void init(void)
|
||||
{
|
||||
char *ptr;
|
||||
|
||||
initDynString(&gstr.pCCSRC);
|
||||
initDynString(&gstr.pCXSRC);
|
||||
initDynString(&gstr.pOBJ);
|
||||
@@ -118,9 +122,17 @@ static void init()
|
||||
initDynString(&gstr.pOUT);
|
||||
initDynString(&gstr.pMINGW);
|
||||
initDynString(&gstr.pIVL);
|
||||
initDynString(&gstr.pCFLAGS);
|
||||
initDynString(&gstr.pCCFLAGS);
|
||||
initDynString(&gstr.pCXFLAGS);
|
||||
initDynString(&gstr.pLDLIBS);
|
||||
initDynString(&gstr.pNewPath);
|
||||
initDynString(&gstr.pCCNAME);
|
||||
initDynString(&gstr.pLD);
|
||||
|
||||
/* Get the base name of the C compiler. */
|
||||
assign(&gstr.pCCNAME, IVERILOG_VPI_CC);
|
||||
ptr = strchr(gstr.pCCNAME, ' ');
|
||||
if (ptr != NULL) *ptr = '\0';
|
||||
|
||||
/* By default use the C compiler to link the programs. */
|
||||
assign(&gstr.pLD, IVERILOG_VPI_CC);
|
||||
}
|
||||
@@ -136,7 +148,7 @@ static int endsIn (char *end, char *str)
|
||||
|
||||
ext = str + (strlen(str) - strlen(end));
|
||||
|
||||
return stricmp(end,ext) ? 0 : 1;
|
||||
return stricmp(end, ext) ? 0 : 1;
|
||||
}
|
||||
|
||||
/* return true if "str" begins with "prefix", case insensitive */
|
||||
@@ -146,35 +158,35 @@ static int startsWith (char *prefix, char *str)
|
||||
if (strlen(prefix) >= strlen(str))
|
||||
return 0;
|
||||
|
||||
return strnicmp(prefix,str,strlen(prefix)) ? 0 : 1;
|
||||
return strnicmp(prefix, str, strlen(prefix)) ? 0 : 1;
|
||||
}
|
||||
|
||||
/* append "app" to "ptr", allocating memory as needed */
|
||||
/* if count is zero, then copy all characters of "app" */
|
||||
|
||||
static void appendn (char **ptr, char *app, int count)
|
||||
static void appendn (char **ptr, char *app, size_t count)
|
||||
{
|
||||
char *nptr = (char *) realloc(*ptr, strlen(*ptr) +
|
||||
(count?count:strlen(app)) + 1);
|
||||
(count ? count : strlen(app)) + 1);
|
||||
|
||||
if (nptr == NULL) {
|
||||
fprintf(stderr,"error: out of memory\n");
|
||||
fprintf(stderr, "error: out of memory\n");
|
||||
free(*ptr);
|
||||
myExit(4);
|
||||
}
|
||||
*ptr = nptr;
|
||||
|
||||
if (count)
|
||||
strncat(*ptr,app,count);
|
||||
strncat(*ptr, app, count);
|
||||
else
|
||||
strcat(*ptr,app);
|
||||
strcat(*ptr, app);
|
||||
}
|
||||
|
||||
/* append "app" to "ptr", allocating memory as needed */
|
||||
|
||||
static void append (char **ptr, char *app)
|
||||
{
|
||||
appendn(ptr,app,0);
|
||||
appendn(ptr, app, 0);
|
||||
}
|
||||
|
||||
/* if the string does not end with a backslash, add one */
|
||||
@@ -182,36 +194,36 @@ static void append (char **ptr, char *app)
|
||||
static void appendBackSlash(char **str)
|
||||
{
|
||||
if ((*str)[strlen(*str)-1] != '\\')
|
||||
append(str,"\\");
|
||||
append(str, "\\");
|
||||
}
|
||||
|
||||
/* copy count characters of "str" to "ptr", allocating memory as needed */
|
||||
/* if count is zero, then copy all characters of "str" */
|
||||
|
||||
static void assignn (char **ptr, char *str, int count)
|
||||
static void assignn (char **ptr, char *str, size_t count)
|
||||
{
|
||||
char *nptr = (char *) realloc(*ptr, (count?count:strlen(str)) + 1);
|
||||
char *nptr = (char *) realloc(*ptr, (count ? count : strlen(str)) + 1);
|
||||
|
||||
if (nptr == NULL) {
|
||||
fprintf(stderr,"error: out of memory\n");
|
||||
fprintf(stderr, "error: out of memory\n");
|
||||
free(*ptr);
|
||||
myExit(4);
|
||||
}
|
||||
*ptr = nptr;
|
||||
|
||||
if (count) {
|
||||
strncpy(*ptr,str,count);
|
||||
strncpy(*ptr, str, count);
|
||||
(*ptr)[count] = 0;
|
||||
}
|
||||
else
|
||||
strcpy(*ptr,str);
|
||||
strcpy(*ptr, str);
|
||||
}
|
||||
|
||||
/* copy count characters of "str" to "ptr", allocating memory as needed */
|
||||
|
||||
static void assign (char **ptr, char *str)
|
||||
{
|
||||
assignn(ptr,str,0);
|
||||
assignn(ptr, str, 0);
|
||||
}
|
||||
|
||||
/* get a copy of a Icarus Verilog registry string key */
|
||||
@@ -223,11 +235,11 @@ static int GetRegistryKey(char *key, char **value)
|
||||
char *regKeyBuffer;
|
||||
DWORD regKeyType, regKeySize;
|
||||
|
||||
lrv = RegOpenKeyEx(HKEY_LOCAL_MACHINE,"Software\\Icarus Verilog",0,KEY_QUERY_VALUE,&hkKey);
|
||||
lrv = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Icarus Verilog", 0, KEY_QUERY_VALUE, &hkKey);
|
||||
if (lrv != ERROR_SUCCESS)
|
||||
return 0;
|
||||
|
||||
lrv = RegQueryValueEx(hkKey,key,NULL,®KeyType,NULL,®KeySize);
|
||||
lrv = RegQueryValueEx(hkKey, key, NULL, ®KeyType, NULL, ®KeySize);
|
||||
if ((lrv != ERROR_SUCCESS) || (regKeyType != REG_SZ) || (!regKeySize)) {
|
||||
lrv = RegCloseKey(hkKey);
|
||||
return 0;
|
||||
@@ -236,7 +248,7 @@ static int GetRegistryKey(char *key, char **value)
|
||||
regKeyBuffer = (char *) malloc(regKeySize+1);
|
||||
if (!regKeyBuffer) {
|
||||
lrv = RegCloseKey(hkKey);
|
||||
fprintf(stderr,"error: out of memory\n");
|
||||
fprintf(stderr, "error: out of memory\n");
|
||||
myExit(4);
|
||||
}
|
||||
regKeyBuffer[regKeySize] = 0; /* makes sure there is a trailing NULL */
|
||||
@@ -252,7 +264,7 @@ static int GetRegistryKey(char *key, char **value)
|
||||
|
||||
RegCloseKey(hkKey);
|
||||
|
||||
assign(value,regKeyBuffer);
|
||||
assign(value, regKeyBuffer);
|
||||
free(regKeyBuffer);
|
||||
|
||||
return 1;
|
||||
@@ -262,27 +274,30 @@ static int GetRegistryKey(char *key, char **value)
|
||||
|
||||
static void SetRegistryKey(char *key, char *value)
|
||||
{
|
||||
long lrv;
|
||||
HKEY hkKey;
|
||||
DWORD res;
|
||||
|
||||
if (RegCreateKeyEx(
|
||||
HKEY_LOCAL_MACHINE,
|
||||
"Software\\Icarus Verilog",
|
||||
0,
|
||||
"",
|
||||
REG_OPTION_NON_VOLATILE,
|
||||
KEY_ALL_ACCESS,NULL,
|
||||
&hkKey,
|
||||
&res) != ERROR_SUCCESS)
|
||||
return;
|
||||
lrv = RegCreateKeyEx(HKEY_LOCAL_MACHINE, "Software\\Icarus Verilog", 0, "",
|
||||
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkKey, &res);
|
||||
if (lrv != ERROR_SUCCESS) {
|
||||
char message[1024];
|
||||
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, lrv, LANG_USER_DEFAULT,
|
||||
message, sizeof(message), NULL);
|
||||
fprintf(stderr, "error: couldn't write to registry - %s\n", message);
|
||||
if (lrv == ERROR_ACCESS_DENIED) {
|
||||
fprintf(stderr, " try running as administrator\n");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* This needs an unsigned char *, but for MinGW the char is signed. */
|
||||
RegSetValueEx(hkKey, key, 0, REG_SZ, (unsigned char *) value,
|
||||
strlen(value)+1);
|
||||
RegCloseKey(hkKey);
|
||||
|
||||
printf("info: storing %s in Windows' registry entry\n",value);
|
||||
printf(" HKEY_LOCAL_MACHINE\\Software\\Icarus Verilog\\%s\n",key);
|
||||
printf("info: storing %s in Windows' registry entry\n", value);
|
||||
printf(" HKEY_LOCAL_MACHINE\\Software\\Icarus Verilog\\%s\n", key);
|
||||
}
|
||||
|
||||
/* parse the command line, assign results to global variable strings */
|
||||
@@ -299,7 +314,6 @@ static int parse(int argc, char *argv[])
|
||||
char lib_option[] = "-l";
|
||||
char inc_option[] = "-I";
|
||||
char mingw_option[] = "-mingw=";
|
||||
char ivl_option[] = "-ivl=";
|
||||
char def_option[] = "-D";
|
||||
|
||||
if (argc == 1) return 0;
|
||||
@@ -339,7 +353,7 @@ static int parse(int argc, char *argv[])
|
||||
/* Check for compiled object files */
|
||||
else if (endsIn(dot_o_ext, argv[idx])) {
|
||||
++srcFileCnt;
|
||||
append(&gstr.pOBJ," ");
|
||||
append(&gstr.pOBJ, " ");
|
||||
append(&gstr.pOBJ, argv[idx]);
|
||||
if (!*gstr.pOUT)
|
||||
assignn(&gstr.pOUT, argv[idx],
|
||||
@@ -349,10 +363,6 @@ static int parse(int argc, char *argv[])
|
||||
else if (startsWith(mingw_option, argv[idx]))
|
||||
assignn(&gstr.pMINGW, argv[idx]+sizeof(mingw_option)-1,
|
||||
strlen(argv[idx])-(sizeof(mingw_option)-1));
|
||||
/* Check for the -ivl option */
|
||||
else if (startsWith(ivl_option, argv[idx]))
|
||||
assignn(&gstr.pIVL, argv[idx]+sizeof(ivl_option)-1,
|
||||
strlen(argv[idx])-(sizeof(ivl_option)-1));
|
||||
/* Check for the --name option */
|
||||
else if (startsWith(name_option, argv[idx])) {
|
||||
assignn(&gstr.pOUT, argv[idx]+sizeof(name_option)-1,
|
||||
@@ -376,7 +386,7 @@ static int parse(int argc, char *argv[])
|
||||
/* Check for the --cflags option */
|
||||
else if (stricmp("--cflags", argv[idx]) == 0) {
|
||||
setup_ivl_environment();
|
||||
printf("%s\n", gstr.pCFLAGS);
|
||||
printf("%s\n", gstr.pCCFLAGS);
|
||||
myExit(0);
|
||||
}
|
||||
/* Check for the --ldflags option */
|
||||
@@ -393,7 +403,7 @@ static int parse(int argc, char *argv[])
|
||||
/* Check for the --install-dir option */
|
||||
else if (stricmp("--install-dir", argv[idx]) == 0) {
|
||||
setup_ivl_environment();
|
||||
printf("%s\\\\lib\\\\ivl" IVERILOG_SUFFIX "\\\\.\n", gstr.pIVL);
|
||||
printf("%s\\lib\\ivl" IVERILOG_SUFFIX "\\.\n", gstr.pIVL);
|
||||
myExit(0);
|
||||
}
|
||||
/* This is different than iverilog-vpi.sh, we don't
|
||||
@@ -402,15 +412,16 @@ static int parse(int argc, char *argv[])
|
||||
}
|
||||
|
||||
/* In case there is a --name without source/object files */
|
||||
if (0 == srcFileCnt) assign(&gstr.pOUT,"");
|
||||
if (0 == srcFileCnt) assign(&gstr.pOUT, "");
|
||||
|
||||
/* Normally it's an error if there are no source or object files */
|
||||
/* Unless we are setting the IVL or MinGW registry entries */
|
||||
if (!*gstr.pOUT) {
|
||||
if (!*gstr.pMINGW && !*gstr.pIVL) return 0;
|
||||
} else
|
||||
if (*gstr.pOUT) {
|
||||
/* We have a valid result file so add the .vpi extension */
|
||||
append(&gstr.pOUT, ".vpi");
|
||||
} else {
|
||||
/* Unless we are setting the MinGW registry entry, it's
|
||||
an error if there are no source or object files */
|
||||
if (!*gstr.pMINGW) return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -421,58 +432,27 @@ static void checkMingwDir(char *root)
|
||||
{
|
||||
int irv;
|
||||
struct _stat stat_buf;
|
||||
|
||||
char *path, *comp, *cp;
|
||||
initDynString(&path);
|
||||
assign(&path,gstr.pMINGW);
|
||||
appendBackSlash(&path);
|
||||
append(&path,"bin\\");
|
||||
/* Get just the compiler name (the first word) */
|
||||
comp = strdup(IVERILOG_VPI_CC);
|
||||
cp = strchr(comp, ' ');
|
||||
if (cp != NULL) *cp = '\0';
|
||||
append(&path, comp);
|
||||
append(&path,".exe");
|
||||
free(comp);
|
||||
|
||||
irv = _stat(path,&stat_buf);
|
||||
deInitDynString(path);
|
||||
|
||||
if (irv) {
|
||||
fprintf(stderr,"error: %s does not appear to be the valid root directory\n",root);
|
||||
fprintf(stderr," of MinGW. Use the -mingw option of iverilog-vpi.exe to\n");
|
||||
fprintf(stderr," point to the MinGW root directory. For a Windows command\n");
|
||||
fprintf(stderr," shell the option would be something like -mingw=c:\\mingw\n");
|
||||
fprintf(stderr," For a Cygwin shell the option would be something like\n");
|
||||
fprintf(stderr," -mingw=c:\\\\mingw\n");
|
||||
myExit(5);
|
||||
}
|
||||
}
|
||||
|
||||
/* do minimal check that the Icarus Verilog root directory looks valid */
|
||||
|
||||
static void checkIvlDir(char *root)
|
||||
{
|
||||
int irv;
|
||||
struct _stat stat_buf;
|
||||
|
||||
char *path;
|
||||
|
||||
initDynString(&path);
|
||||
assign(&path,gstr.pIVL);
|
||||
assign(&path, gstr.pMINGW);
|
||||
appendBackSlash(&path);
|
||||
append(&path,"bin\\vvp" IVERILOG_SUFFIX ".exe");
|
||||
append(&path, "bin\\");
|
||||
append(&path, gstr.pCCNAME);
|
||||
append(&path, ".exe");
|
||||
|
||||
irv = _stat(path,&stat_buf);
|
||||
deInitDynString(path);
|
||||
|
||||
if (irv) {
|
||||
fprintf(stderr,"error: %s does not appear to be the valid root directory of\n",root);
|
||||
fprintf(stderr," Icarus Verilog. Use the -ivl option of iverilog-vpi" IVERILOG_SUFFIX " to\n");
|
||||
fprintf(stderr," point to the Icarus Verilog root directory. For a Windows\n");
|
||||
fprintf(stderr," command shell the option would be something like -ivl=c:\\iverilog\n");
|
||||
fprintf(stderr," For a Cygwin shell the option would be something like\n");
|
||||
fprintf(stderr," -ivl=c:\\\\iverilog\n");
|
||||
myExit(6);
|
||||
fprintf(stderr, "error: %s\n", root);
|
||||
fprintf(stderr, " does not appear to be the valid root directory of\n");
|
||||
fprintf(stderr, " MinGW. Use the -mingw option of iverilog-vpi.exe to\n");
|
||||
fprintf(stderr, " point to the MinGW root directory. For a Windows command\n");
|
||||
fprintf(stderr, " shell the option would be something like -mingw=c:\\mingw\n");
|
||||
fprintf(stderr, " For a Cygwin shell the option would be something like\n");
|
||||
fprintf(stderr, " -mingw=c:\\\\mingw\n");
|
||||
myExit(5);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -480,68 +460,98 @@ static void checkIvlDir(char *root)
|
||||
|
||||
#define IVL_REGKEY_MINGW "MingwDir"
|
||||
|
||||
static void setup_mingw_environment()
|
||||
static void setup_mingw_environment(void)
|
||||
{
|
||||
char *pOldPATH = getenv("PATH"); /* get current path */
|
||||
char buffer[1]; /* doesn't matter how big this is, as we don't use the result */
|
||||
char *path;
|
||||
|
||||
if (*gstr.pMINGW) {
|
||||
checkMingwDir(gstr.pMINGW);
|
||||
SetRegistryKey(IVL_REGKEY_MINGW,gstr.pMINGW);
|
||||
} else if (!GetRegistryKey(IVL_REGKEY_MINGW,&gstr.pMINGW)) {
|
||||
fprintf(stderr,"error: can not locate the MinGW root directory, use the -mingw option of\n");
|
||||
fprintf(stderr," iverilog-vpi.exe to point to the MinGW root directory. For\n");
|
||||
fprintf(stderr," a Windows command shell the option would be something like\n");
|
||||
fprintf(stderr," -mingw=c:\\mingw For a Cygwin shell the option would be\n");
|
||||
fprintf(stderr," something like -mingw=c:\\\\mingw\n");
|
||||
myExit(5);
|
||||
}
|
||||
if (!*gstr.pOUT) SetRegistryKey(IVL_REGKEY_MINGW, gstr.pMINGW);
|
||||
|
||||
} else if (GetRegistryKey(IVL_REGKEY_MINGW, &gstr.pMINGW)) {
|
||||
checkMingwDir(gstr.pMINGW);
|
||||
|
||||
} else if (SearchPath(NULL, gstr.pCCNAME, ".exe", sizeof(buffer), buffer, NULL)) {
|
||||
return;
|
||||
|
||||
} else {
|
||||
fprintf(stderr, "error: cannot locate the MinGW C compiler - either add its location\n");
|
||||
fprintf(stderr, " to the PATH environment variable or use the -mingw option of\n");
|
||||
fprintf(stderr, " iverilog-vpi.exe to point to the MinGW root directory. For\n");
|
||||
fprintf(stderr, " a Windows command shell the option would be something like\n");
|
||||
fprintf(stderr, " -mingw=c:\\mingw For a Cygwin shell the option would be\n");
|
||||
fprintf(stderr, " something like -mingw=c:\\\\mingw\n");
|
||||
myExit(5);
|
||||
}
|
||||
|
||||
/* Create new path with MinGW in it */
|
||||
assign(&gstr.pNewPath,"PATH=");
|
||||
append(&gstr.pNewPath,gstr.pMINGW);
|
||||
appendBackSlash(&gstr.pNewPath);
|
||||
append(&gstr.pNewPath, "\\");
|
||||
append(&gstr.pNewPath,"bin;");
|
||||
append(&gstr.pNewPath,pOldPATH);
|
||||
initDynString(&path);
|
||||
assign(&path, "PATH=");
|
||||
append(&path, gstr.pMINGW);
|
||||
appendBackSlash(&path);
|
||||
append(&path, "bin;");
|
||||
append(&path, getenv("PATH"));
|
||||
|
||||
/* Place new path in environment */
|
||||
_putenv(gstr.pNewPath);
|
||||
_putenv(path);
|
||||
deInitDynString(path);
|
||||
}
|
||||
|
||||
/* see if we can find iverilog root */
|
||||
/* find the iverilog root and initialise the compiler options */
|
||||
|
||||
#define IVL_REGKEY_IVL "InstallDir"
|
||||
|
||||
static void setup_ivl_environment()
|
||||
static void setup_ivl_environment(void)
|
||||
{
|
||||
if (*gstr.pIVL) {
|
||||
checkIvlDir(gstr.pIVL);
|
||||
SetRegistryKey(IVL_REGKEY_IVL,gstr.pIVL);
|
||||
} else if (!GetRegistryKey(IVL_REGKEY_IVL,&gstr.pIVL)) {
|
||||
fprintf(stderr,"error: can not locate the Icarus Verilog root directory, use the -ivl option\n");
|
||||
fprintf(stderr," of iverilog-vpi" IVERILOG_SUFFIX " to point to the Icarus Verilog root directory.\n");
|
||||
fprintf(stderr," For a Windows command shell the option would be something like\n");
|
||||
fprintf(stderr," -ivl=c:\\iverilog For a Cygwin shell the option would be something\n");
|
||||
fprintf(stderr," like -ivl=c:\\\\iverilog\n");
|
||||
myExit(6);
|
||||
}
|
||||
char path[4096];
|
||||
char *ptr;
|
||||
|
||||
/* Build up the CFLAGS option string */
|
||||
assign(&gstr.pCFLAGS,IVERILOG_VPI_CFLAGS " -I\"");
|
||||
append(&gstr.pCFLAGS,gstr.pIVL);
|
||||
appendBackSlash(&gstr.pCFLAGS);
|
||||
append(&gstr.pCFLAGS,"\\include\\\\iverilog\"" IVERILOG_SUFFIX);
|
||||
/* Extract the Icarus Verilog root directory from the path to the
|
||||
command. The command path will look something like this:
|
||||
|
||||
C:\iverilog\bin\iverilog-vpi.exe
|
||||
|
||||
The corresponding root directory is
|
||||
|
||||
C:\iverilog
|
||||
|
||||
so we chop off the file name and the last directory. */
|
||||
GetModuleFileName(NULL, path, sizeof(path));
|
||||
ptr = strrchr(path, '\\');
|
||||
if (!ptr) {
|
||||
fprintf(stderr, "error: couldn't find start of program name in command path '%s'\n", path);
|
||||
myExit(6);
|
||||
}
|
||||
*ptr = 0;
|
||||
ptr = strrchr(path, '\\');
|
||||
if (!ptr) {
|
||||
fprintf(stderr, "error: couldn't find start of bin directory in command path '%s'\n", path);
|
||||
myExit(6);
|
||||
}
|
||||
*ptr = 0;
|
||||
assign(&gstr.pIVL, path);
|
||||
|
||||
/* Build up the CCFLAGS option string */
|
||||
assign(&gstr.pCCFLAGS, IVERILOG_VPI_CFLAGS " -I\"");
|
||||
append(&gstr.pCCFLAGS, gstr.pIVL);
|
||||
appendBackSlash(&gstr.pCCFLAGS);
|
||||
append(&gstr.pCCFLAGS, "include\\iverilog\"" IVERILOG_SUFFIX);
|
||||
|
||||
/* Build up the CXFLAGS option string */
|
||||
assign(&gstr.pCXFLAGS, IVERILOG_VPI_CXXFLAGS " -I\"");
|
||||
append(&gstr.pCXFLAGS, gstr.pIVL);
|
||||
appendBackSlash(&gstr.pCXFLAGS);
|
||||
append(&gstr.pCXFLAGS, "include\\iverilog\"" IVERILOG_SUFFIX);
|
||||
|
||||
/* Build up the LDFLAGS option string */
|
||||
assign(&gstr.pLDLIBS,"-L\"");
|
||||
append(&gstr.pLDLIBS,gstr.pIVL);
|
||||
assign(&gstr.pLDLIBS, "-L\"");
|
||||
append(&gstr.pLDLIBS, gstr.pIVL);
|
||||
appendBackSlash(&gstr.pLDLIBS);
|
||||
append(&gstr.pLDLIBS,"\\lib\" " IVERILOG_VPI_LDLIBS);
|
||||
append(&gstr.pLDLIBS, "lib\" " IVERILOG_VPI_LDLIBS);
|
||||
}
|
||||
|
||||
/* compile source modules */
|
||||
|
||||
static void compile(char *pSource, char **pObject, int *compile_errors, char *compiler)
|
||||
static void compile(char *pSource, char *pFlags, char **pObject, int *compile_errors, char *compiler)
|
||||
{
|
||||
char *ptr1 = pSource;
|
||||
char *ptr2 = strchr(ptr1, ' ');
|
||||
@@ -568,7 +578,7 @@ static void compile(char *pSource, char **pObject, int *compile_errors, char *co
|
||||
append(&buf, " ");
|
||||
append(&buf, gstr.pDEFS);
|
||||
append(&buf, " ");
|
||||
append(&buf, gstr.pCFLAGS);
|
||||
append(&buf, pFlags);
|
||||
append(&buf, " ");
|
||||
append(&buf, gstr.pINCS);
|
||||
append(&buf, " ");
|
||||
@@ -593,27 +603,22 @@ static void compile(char *pSource, char **pObject, int *compile_errors, char *co
|
||||
|
||||
/* using the global strings, compile and link */
|
||||
|
||||
static void compile_and_link()
|
||||
static void compile_and_link(void)
|
||||
{
|
||||
char *buf=0;
|
||||
int iRet, compile_errors = 0;
|
||||
|
||||
/* To make the output match iverilog-vpi.sh do not print out the
|
||||
* root directories */
|
||||
|
||||
// printf("MinGW root directory: %s.\n", gstr.pMINGW);
|
||||
checkMingwDir(gstr.pMINGW);
|
||||
|
||||
// printf("Icarus Verilog root directory: %s.\n", gstr.pIVL);
|
||||
checkIvlDir(gstr.pIVL);
|
||||
|
||||
/* compile the C source files (*.c) */
|
||||
compile(gstr.pCCSRC, &gstr.pOBJ, &compile_errors, IVERILOG_VPI_CC );
|
||||
compile(gstr.pCCSRC, gstr.pCCFLAGS, &gstr.pOBJ, &compile_errors, IVERILOG_VPI_CC );
|
||||
/* compile the C++ source files (*.cc, *.cpp) */
|
||||
compile(gstr.pCXSRC, &gstr.pOBJ, &compile_errors, IVERILOG_VPI_CXX);
|
||||
compile(gstr.pCXSRC, gstr.pCXFLAGS, &gstr.pOBJ, &compile_errors, IVERILOG_VPI_CXX);
|
||||
|
||||
if (compile_errors) {
|
||||
fprintf(stderr,"iverilog-vpi: %d file(s) failed to compile.\n",
|
||||
fprintf(stderr, "iverilog-vpi: %d file(s) failed to compile.\n",
|
||||
compile_errors);
|
||||
myExit(2);
|
||||
}
|
||||
@@ -644,7 +649,7 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
init();
|
||||
|
||||
if (!parse(argc,argv)) usage();
|
||||
if (!parse(argc, argv)) usage();
|
||||
|
||||
setup_mingw_environment();
|
||||
setup_ivl_environment();
|
||||
|
||||
+3
-2
@@ -4,7 +4,7 @@
|
||||
|
||||
%{
|
||||
/*
|
||||
* Copyright (c) 2001-2014 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2001-2016 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,7 +124,8 @@ int cmdfile_stack_ptr = 0;
|
||||
"-c" { return TOK_Dc; }
|
||||
"-f" { return TOK_Dc; }
|
||||
|
||||
/* Notice the -v flag. */
|
||||
/* Notice the -l or -v flag. */
|
||||
"-l" { return TOK_Dv; }
|
||||
"-v" { return TOK_Dv; }
|
||||
|
||||
/* Notice the -y flag. */
|
||||
|
||||
+47
-9
@@ -1,14 +1,15 @@
|
||||
.TH iverilog 1 "February 26th, 2014" "" "Version %M.%m.%n %E"
|
||||
.TH iverilog 1 "Oct 2nd, 2016" "" "Version %M.%n%E"
|
||||
.SH NAME
|
||||
iverilog - Icarus Verilog compiler
|
||||
|
||||
.SH SYNOPSIS
|
||||
.B iverilog
|
||||
[\-ESVv] [\-Bpath] [\-ccmdfile|\-fcmdfile] [\-Dmacro[=defn]]
|
||||
[\-Pparameter=value] [\-pflag=value]
|
||||
[\-dname] [\-g1995|\-g2001|\-g2005|\-g2005-sv|\-g2009|\-g2012|\-g<feature>]
|
||||
[\-Pparameter=value] [\-pflag=value] [\-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
|
||||
[\-stopmodule] [\-ttype] [\-Tmin/typ/max] [\-Wclass] [\-ypath] [\-lfile]
|
||||
sourcefile
|
||||
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
@@ -30,7 +31,7 @@ different set of programs. The path given is used to locate
|
||||
\fIivlpp\fP, \fIivl\fP, code generators and the VPI modules.
|
||||
.TP 8
|
||||
.B -c\fIfile\fP -f\fIfile\fP
|
||||
These flags specifies an input file that contains a list of Verilog
|
||||
These flags specify an input file that contains a list of Verilog
|
||||
source files. This is similar to the \fIcommand file\fP of other
|
||||
Verilog simulators, in that it is a file that contains the file names
|
||||
instead of taking them on the command line. See \fBCommand Files\fP below.
|
||||
@@ -133,12 +134,29 @@ 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 -gshared-loop-index\fI|\fP-gno-shared-loop-index
|
||||
Enable or disable (default) the exclusion of for-loop control variables
|
||||
from implicit event_expression lists. When enabled, if a for-loop control
|
||||
variable (loop index) is only used inside the for-loop statement, the
|
||||
compiler will not include it in an implicit event_expression list it
|
||||
calculates for that statement or any enclosing statement. This allows
|
||||
the same control variable to be used in multiple processes without risk
|
||||
of entering an infinite loop caused by each process triggering all other
|
||||
processes that use the same varaible. For strict compliance with the
|
||||
standards, this behaviour should be disabled.
|
||||
.TP 8
|
||||
.B -I\fIincludedir\fP
|
||||
Append directory \fIincludedir\fP to list of directories searched
|
||||
for Verilog include files. The \fB\-I\fP switch may be used many times
|
||||
to specify several directories to search, the directories are searched
|
||||
in the order they appear on the command line.
|
||||
.TP 8
|
||||
.B -l\fIfile\fP
|
||||
Add the specified file to the list of source files to be compiled,
|
||||
but mark it as a library file. All modules contained within that
|
||||
file will be treated as library modules, and only elaborated if
|
||||
they are instantiated by other modules in the design.
|
||||
.TP 8
|
||||
.B -M\fIpath\fP
|
||||
This is equivalent to \fB\-Mall=path\fP. Preserved for backwards
|
||||
compatibility.
|
||||
@@ -213,6 +231,12 @@ a reference to a key temporary file that passes information to the
|
||||
compiler proper. To keep that file from being deleted at the end
|
||||
of the process, provide a file name of your own in the environment
|
||||
variable \fBIVERILOG_ICONFIG\fP.
|
||||
|
||||
If the selected target is \fIvvp\fP, the \fB\-v\fP switch is appended
|
||||
to the shebang line in the compiler output file, so directly executing
|
||||
the compiler output file will turn on verbose messages in \fIvvp\fP.
|
||||
This extra verbosity can be avoided by using the \fIvvp\fP command to
|
||||
indirectly execute the compiler output file.
|
||||
.TP 8
|
||||
.B -V
|
||||
Print the version of the compiler, and exit.
|
||||
@@ -286,8 +310,13 @@ after a \fB\-Wall\fP argument to suppress isolated warning types.
|
||||
|
||||
.TP 8
|
||||
.B all
|
||||
This enables the implicit, portbind, select\-range, timescale, and
|
||||
sensitivity\-entire\-array warning categories.
|
||||
This enables the anachronisms, implicit, portbind, select\-range,
|
||||
timescale, and sensitivity\-entire\-array warning categories.
|
||||
|
||||
.TP 8
|
||||
.B anachronisms
|
||||
This enables warnings for use of features that have been deprecated
|
||||
or removed in the selected generation of the Verilog language.
|
||||
|
||||
.TP 8
|
||||
.B implicit
|
||||
@@ -391,6 +420,15 @@ A \fB\-c\fP or \fB\-f\fP token prefixes a command file, exactly like it
|
||||
does on the command line. The cmdfile may be on the same line or the
|
||||
next non-comment line.
|
||||
|
||||
.TP 8
|
||||
.B -l\ \fIfile\fP -v\ \fIfile\fP
|
||||
A \fB\-l\fP token prefixes a library file in the command file,
|
||||
exactly like it does on the command line. The parameter to the \fB\-l\fP
|
||||
flag may be on the same line or the next non-comment line. \fB\-v\fP is
|
||||
an alias for \fB\-l\fP, provided for compatibility with other simulators.
|
||||
|
||||
Variables in the \fIfile\fP are substituted.
|
||||
|
||||
.TP 8
|
||||
.B -y\ \fIlibdir\fP
|
||||
A \fB\-y\fP token prefixes a library directory in the command file,
|
||||
@@ -514,14 +552,14 @@ Steve Williams ([email protected])
|
||||
|
||||
.SH SEE ALSO
|
||||
vvp(1),
|
||||
.BR "<http://www.icarus.com/eda/verilog/>"
|
||||
.BR "<http://iverilog.icarus.com/>"
|
||||
|
||||
Tips on using, debugging, and developing the compiler can be found at
|
||||
.BR "<http://iverilog.wikia.com/>"
|
||||
|
||||
.SH COPYRIGHT
|
||||
.nf
|
||||
Copyright \(co 2002\-2014 Stephen Williams
|
||||
Copyright \(co 2002\-2016 Stephen Williams
|
||||
|
||||
This document can be freely redistributed according to the terms of the
|
||||
GNU General Public License version 2.0
|
||||
|
||||
+31
-14
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2016 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,7 +44,7 @@ const char HELP[] =
|
||||
" [-M [mode=]depfile] [-m module]\n"
|
||||
" [-N file] [-o filename] [-p flag=value]\n"
|
||||
" [-s topmodule] [-t target] [-T min|typ|max]\n"
|
||||
" [-W class] [-y dir] [-Y suf] source_file(s)\n"
|
||||
" [-W class] [-y dir] [-Y suf] [-l file] source_file(s)\n"
|
||||
"\n"
|
||||
"See the man page for details.";
|
||||
|
||||
@@ -128,6 +128,7 @@ const char*gen_icarus = "icarus-misc";
|
||||
const char*gen_io_range_error = "io-range-error";
|
||||
const char*gen_strict_ca_eval = "no-strict-ca-eval";
|
||||
const char*gen_strict_expr_width = "no-strict-expr-width";
|
||||
const char*gen_shared_loop_index = "no-shared-loop-index";
|
||||
const char*gen_verilog_ams = "no-verilog-ams";
|
||||
|
||||
/* Boolean: true means use a default include dir, false means don't */
|
||||
@@ -496,6 +497,7 @@ static void process_warning_switch(const char*name)
|
||||
if (strcmp(name,"all") == 0) {
|
||||
process_warning_switch("anachronisms");
|
||||
process_warning_switch("implicit");
|
||||
process_warning_switch("implicit-dimensions");
|
||||
process_warning_switch("portbind");
|
||||
process_warning_switch("select-range");
|
||||
process_warning_switch("timescale");
|
||||
@@ -506,6 +508,9 @@ static void process_warning_switch(const char*name)
|
||||
} else if (strcmp(name,"implicit") == 0) {
|
||||
if (! strchr(warning_flags, 'i'))
|
||||
strcat(warning_flags, "i");
|
||||
} else if (strcmp(name,"implicit-dimensions") == 0) {
|
||||
if (! strchr(warning_flags, 'd'))
|
||||
strcat(warning_flags, "d");
|
||||
} else if (strcmp(name,"portbind") == 0) {
|
||||
if (! strchr(warning_flags, 'p'))
|
||||
strcat(warning_flags, "p");
|
||||
@@ -538,6 +543,12 @@ static void process_warning_switch(const char*name)
|
||||
cp[0] = cp[1];
|
||||
cp += 1;
|
||||
}
|
||||
} else if (strcmp(name,"no-implicit-dimensions") == 0) {
|
||||
char*cp = strchr(warning_flags, 'd');
|
||||
if (cp) while (*cp) {
|
||||
cp[0] = cp[1];
|
||||
cp += 1;
|
||||
}
|
||||
} else if (strcmp(name,"no-portbind") == 0) {
|
||||
char*cp = strchr(warning_flags, 'p');
|
||||
if (cp) while (*cp) {
|
||||
@@ -568,6 +579,9 @@ static void process_warning_switch(const char*name)
|
||||
cp[0] = cp[1];
|
||||
cp += 1;
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Ignoring unknown warning class "
|
||||
"%s\n", name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -717,6 +731,12 @@ static int process_generation(const char*name)
|
||||
else if (strcmp(name,"no-strict-expr-width") == 0)
|
||||
gen_strict_expr_width = "no-strict-expr-width";
|
||||
|
||||
else if (strcmp(name,"shared-loop-index") == 0)
|
||||
gen_shared_loop_index = "shared-loop-index";
|
||||
|
||||
else if (strcmp(name,"no-shared-loop-index") == 0)
|
||||
gen_shared_loop_index = "no-shared-loop-index";
|
||||
|
||||
else if (strcmp(name,"verilog-ams") == 0)
|
||||
gen_verilog_ams = "verilog-ams";
|
||||
|
||||
@@ -742,7 +762,8 @@ static int process_generation(const char*name)
|
||||
" icarus-misc | no-icarus-misc\n"
|
||||
" io-range-error | no-io-range-error\n"
|
||||
" strict-ca-eval | no-strict-ca-eval\n"
|
||||
" strict-expr-width | no-strict-expr-width\n");
|
||||
" strict-expr-width | no-strict-expr-width\n"
|
||||
" shared-loop-index | no-shared-loop-index\n");
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -907,7 +928,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:hl:I:M:m:N:o:P:p:Ss:T:t:vVW:y:Y:")) != EOF) {
|
||||
|
||||
switch (opt) {
|
||||
case 'B':
|
||||
@@ -962,6 +983,10 @@ int main(int argc, char **argv)
|
||||
process_include_dir(optarg);
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
process_file_name(optarg, 1);
|
||||
break;
|
||||
|
||||
case 'M':
|
||||
if (process_depfile(optarg) != 0)
|
||||
return -1;
|
||||
@@ -1044,19 +1069,10 @@ int main(int argc, char **argv)
|
||||
|
||||
if (version_flag || verbose_flag) {
|
||||
printf("Icarus Verilog version " VERSION " (" VERSION_TAG ")\n\n");
|
||||
printf("Copyright 1998-2013 Stephen Williams\n\n");
|
||||
printf("Copyright 1998-2015 Stephen Williams\n\n");
|
||||
puts(NOTICE);
|
||||
}
|
||||
|
||||
if (synth_flag) {
|
||||
fprintf(stderr, "Warning: Synthesis is not currently being "
|
||||
"maintained and may not\n");
|
||||
fprintf(stderr, " function correctly. V0.8 was the "
|
||||
"last release branch to\n");
|
||||
fprintf(stderr, " have active synthesis development "
|
||||
"and support!\n");
|
||||
}
|
||||
|
||||
/* Make a common conf file path to reflect the target. */
|
||||
snprintf(iconfig_common_path, sizeof iconfig_common_path, "%s%c%s%s.conf",
|
||||
base, sep, targ, synth_flag? "-s" : "");
|
||||
@@ -1104,6 +1120,7 @@ int main(int argc, char **argv)
|
||||
fprintf(iconfig_file, "generation:%s\n", gen_io_range_error);
|
||||
fprintf(iconfig_file, "generation:%s\n", gen_strict_ca_eval);
|
||||
fprintf(iconfig_file, "generation:%s\n", gen_strict_expr_width);
|
||||
fprintf(iconfig_file, "generation:%s\n", gen_shared_loop_index);
|
||||
fprintf(iconfig_file, "generation:%s\n", gen_verilog_ams);
|
||||
fprintf(iconfig_file, "generation:%s\n", gen_icarus);
|
||||
fprintf(iconfig_file, "warnings:%s\n", warning_flags);
|
||||
|
||||
+260
-94
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2016 Stephen Williams (steve@icarus.com)
|
||||
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
@@ -90,7 +90,7 @@ static NetBranch* find_existing_implicit_branch(NetNet*sig, NetNet*gnd)
|
||||
|
||||
NetExpr* elaborate_rval_expr(Design*des, NetScope*scope, ivl_type_t lv_net_type,
|
||||
ivl_variable_type_t lv_type, unsigned lv_width,
|
||||
PExpr*expr, bool need_const)
|
||||
PExpr*expr, bool need_const, bool force_unsigned)
|
||||
{
|
||||
if (debug_elaborate) {
|
||||
cerr << expr->get_fileline() << ": elaborate_rval_expr: "
|
||||
@@ -135,7 +135,7 @@ NetExpr* elaborate_rval_expr(Design*des, NetScope*scope, ivl_type_t lv_net_type,
|
||||
}
|
||||
|
||||
return elab_and_eval(des, scope, expr, context_wid, need_const,
|
||||
false, lv_type);
|
||||
false, lv_type, force_unsigned);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -267,6 +267,13 @@ unsigned PEBinary::test_width(Design*des, NetScope*scope, width_mode_t&mode)
|
||||
|
||||
unsigned l_width = left_->test_width(des, scope, mode);
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PEBinary::test_width: "
|
||||
<< "op_=" << op_ << ", l_width=" << l_width
|
||||
<< ", r_width=" << r_width
|
||||
<< ", saved_mode=" << saved_mode << endl;
|
||||
}
|
||||
|
||||
// If the width mode changed, retest the right operand, as it
|
||||
// may choose a different width if it is in a lossless context.
|
||||
if ((mode >= LOSSLESS) && (saved_mode < LOSSLESS))
|
||||
@@ -650,10 +657,13 @@ NetExpr* PEBComp::elaborate_expr(Design*des, NetScope*scope,
|
||||
case 'E': /* === */
|
||||
case 'N': /* !== */
|
||||
if (lp->expr_type() == IVL_VT_REAL ||
|
||||
rp->expr_type() == IVL_VT_REAL) {
|
||||
lp->expr_type() == IVL_VT_STRING ||
|
||||
rp->expr_type() == IVL_VT_REAL ||
|
||||
rp->expr_type() == IVL_VT_STRING) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< human_readable_op(op_)
|
||||
<< " operator may not have REAL operands." << endl;
|
||||
<< " operator may not have REAL or STRING operands."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
@@ -665,10 +675,7 @@ NetExpr* PEBComp::elaborate_expr(Design*des, NetScope*scope,
|
||||
NetExpr*tmp = new NetEBComp(op_, lp, rp);
|
||||
tmp->set_line(*this);
|
||||
|
||||
tmp = pad_to_width(tmp, expr_wid, *this);
|
||||
tmp->cast_signed(signed_flag_);
|
||||
|
||||
return tmp;
|
||||
return pad_to_width(tmp, expr_wid, signed_flag_, *this);
|
||||
}
|
||||
|
||||
unsigned PEBLogic::test_width(Design*, NetScope*, width_mode_t&)
|
||||
@@ -706,10 +713,7 @@ NetExpr*PEBLogic::elaborate_expr(Design*des, NetScope*scope,
|
||||
NetExpr*tmp = new NetEBLogic(op_, lp, rp);
|
||||
tmp->set_line(*this);
|
||||
|
||||
tmp = pad_to_width(tmp, expr_wid, *this);
|
||||
tmp->cast_signed(signed_flag_);
|
||||
|
||||
return tmp;
|
||||
return pad_to_width(tmp, expr_wid, signed_flag_, *this);
|
||||
}
|
||||
|
||||
unsigned PEBLeftWidth::test_width(Design*des, NetScope*scope, width_mode_t&mode)
|
||||
@@ -717,6 +721,14 @@ unsigned PEBLeftWidth::test_width(Design*des, NetScope*scope, width_mode_t&mode)
|
||||
ivl_assert(*this, left_);
|
||||
ivl_assert(*this, right_);
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PEBLeftWidth::test_width: "
|
||||
<< "op_=" << op_
|
||||
<< ", left_=" << *left_
|
||||
<< ", right_=" << *right_
|
||||
<< ", mode=" << width_mode_name(mode) << endl;
|
||||
}
|
||||
|
||||
// The right operand is self determined. Test its type and
|
||||
// width for use later. We only need to know its width now
|
||||
// if the left operand is unsized and we need to calculate
|
||||
@@ -724,11 +736,26 @@ unsigned PEBLeftWidth::test_width(Design*des, NetScope*scope, width_mode_t&mode)
|
||||
width_mode_t r_mode = SIZED;
|
||||
unsigned r_width = right_->test_width(des, scope, r_mode);
|
||||
|
||||
expr_width_ = left_->test_width(des, scope, mode);
|
||||
// The left operand is what will determine the size of the
|
||||
// expression. The l_mode will be converted to UNSIZED if the
|
||||
// expression does not have a well-determined size.
|
||||
width_mode_t l_mode = SIZED;
|
||||
expr_width_ = left_->test_width(des, scope, l_mode);
|
||||
expr_type_ = left_->expr_type();
|
||||
signed_flag_ = left_->has_sign();
|
||||
|
||||
if (mode==SIZED)
|
||||
mode = l_mode;
|
||||
|
||||
// The left operand width defines the size of the
|
||||
// expression. If the expression has a well-defined size, the
|
||||
// left_->test_width() above would have set mode==SIZED and we
|
||||
// can skip a lot of stuff. But if the mode is an undetermined
|
||||
// size, we need to figure out what we really want to keep a
|
||||
// lossless value. That's what the following if(...) {...} is
|
||||
// all about.
|
||||
if ((mode >= EXPAND) && type_is_vectorable(expr_type_)) {
|
||||
|
||||
// We need to make our best guess at the right operand
|
||||
// value, to minimize the calculated width. This is
|
||||
// particularly important for the power operator...
|
||||
@@ -755,8 +782,18 @@ unsigned PEBLeftWidth::test_width(Design*des, NetScope*scope, width_mode_t&mode)
|
||||
right_ = tmp;
|
||||
}
|
||||
NetEConst*rc = dynamic_cast<NetEConst*> (rp);
|
||||
if (rc && (r_width < sizeof(long)*8))
|
||||
r_val = rc->value().as_long();
|
||||
// Adjust the expression width that can be converter depending
|
||||
// on if the R-value is signed or not.
|
||||
unsigned c_width = sizeof(long)*8;
|
||||
if (! right_->has_sign()) c_width -= 1;
|
||||
if (rc && (r_width <= c_width)) r_val = rc->value().as_long();
|
||||
|
||||
if (debug_elaborate && rc) {
|
||||
cerr << get_fileline() << ": PEBLeftWidth::test_width: "
|
||||
<< "Evaluated rc=" << *rc
|
||||
<< ", r_val=" << r_val
|
||||
<< ", width_cap=" << width_cap << endl;
|
||||
}
|
||||
|
||||
// Clip to a sensible range to avoid underflow/overflow
|
||||
// in the following calculations.
|
||||
@@ -774,7 +811,8 @@ unsigned PEBLeftWidth::test_width(Design*des, NetScope*scope, width_mode_t&mode)
|
||||
unsigned use_width = expr_width_;
|
||||
switch (op_) {
|
||||
case 'l': // <<
|
||||
use_width += (unsigned)r_val;
|
||||
if (l_mode != SIZED)
|
||||
use_width += (unsigned)r_val;
|
||||
break;
|
||||
|
||||
case 'r': // >>
|
||||
@@ -812,6 +850,12 @@ unsigned PEBLeftWidth::test_width(Design*des, NetScope*scope, width_mode_t&mode)
|
||||
if ((rc == 0) && (use_width > expr_width_) && (use_width > integer_width))
|
||||
use_width = integer_width;
|
||||
|
||||
if (use_width >= width_cap) {
|
||||
cerr << get_fileline() << ": warning: "
|
||||
<< "Unsized expression (" << *this << ")"
|
||||
<< " expanded beyond and was clipped to " << use_width
|
||||
<< " bits. Try using sized operands." << endl;
|
||||
}
|
||||
expr_width_ = use_width;
|
||||
}
|
||||
|
||||
@@ -820,6 +864,13 @@ unsigned PEBLeftWidth::test_width(Design*des, NetScope*scope, width_mode_t&mode)
|
||||
else
|
||||
min_width_ = UINT_MAX; // disable width pruning
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PEBLeftWidth::test_width: "
|
||||
<< "Done calculating expr_width_=" << expr_width_
|
||||
<< ", min_width_=" << min_width_
|
||||
<< ", mode=" << width_mode_name(mode) << endl;
|
||||
}
|
||||
|
||||
return fix_width_(mode);
|
||||
}
|
||||
|
||||
@@ -978,8 +1029,7 @@ NetExpr*PEBShift::elaborate_expr_leaf(Design*des, NetExpr*lp, NetExpr*rp,
|
||||
tmp->set_line(*this);
|
||||
tmp = new NetESelect(lp, tmp, 1);
|
||||
tmp->set_line(*this);
|
||||
tmp = pad_to_width(tmp, expr_wid, *this);
|
||||
tmp->cast_signed(true);
|
||||
tmp = pad_to_width(tmp, expr_wid, true, *this);
|
||||
|
||||
delete rp;
|
||||
return tmp;
|
||||
@@ -1021,7 +1071,7 @@ unsigned PECallFunction::test_width_sfunc_(Design*des, NetScope*scope,
|
||||
|
||||
if (name=="$ivlh_to_unsigned") {
|
||||
ivl_assert(*this, parms_.size() == 2);
|
||||
// The Icarus Verilog specific $ivl_unsigned() system
|
||||
// The Icarus Verilog specific $ivlh_to_unsigned() system
|
||||
// task takes a second argument which is the output
|
||||
// size. This can be an arbitrary constant function.
|
||||
PExpr*pexpr = parms_[1];
|
||||
@@ -1043,6 +1093,11 @@ unsigned PECallFunction::test_width_sfunc_(Design*des, NetScope*scope,
|
||||
bool rc = eval_as_long(value, nexpr);
|
||||
ivl_assert(*this, rc && value>=0);
|
||||
|
||||
// The argument type/width is self-determined and doesn't
|
||||
// affect the result type/width.
|
||||
width_mode_t arg_mode = SIZED;
|
||||
parms_[0]->test_width(des, scope, arg_mode);
|
||||
|
||||
expr_width_ = value;
|
||||
signed_flag_= false;
|
||||
return expr_width_;
|
||||
@@ -1273,6 +1328,18 @@ unsigned PECallFunction::test_width_method_(Design*des, NetScope*scope,
|
||||
if (net == 0)
|
||||
return 0;
|
||||
|
||||
// Look for built in string attributes.
|
||||
if (net->data_type()==IVL_VT_STRING) {
|
||||
|
||||
if (method_name == "len") {
|
||||
expr_type_ = IVL_VT_BOOL;
|
||||
expr_width_ = 32;
|
||||
min_width_ = 32;
|
||||
signed_flag_= true;
|
||||
return expr_width_;
|
||||
}
|
||||
}
|
||||
|
||||
// function int size()
|
||||
if (use_darray && method_name == "size") {
|
||||
if (debug_elaborate) {
|
||||
@@ -1333,27 +1400,14 @@ unsigned PECallFunction::test_width_method_(Design*des, NetScope*scope,
|
||||
|
||||
NetExpr*PECallFunction::cast_to_width_(NetExpr*expr, unsigned wid) const
|
||||
{
|
||||
/* If the expression is a const, then replace it with a new
|
||||
const. This is a more efficient result. */
|
||||
if (NetEConst*tmp = dynamic_cast<NetEConst*>(expr)) {
|
||||
tmp->cast_signed(signed_flag_);
|
||||
if (wid > tmp->expr_width()) {
|
||||
tmp = new NetEConst(verinum(tmp->value(), wid));
|
||||
tmp->set_line(*this);
|
||||
delete expr;
|
||||
}
|
||||
return tmp;
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PECallFunction::cast_to_width_: "
|
||||
<< "cast to " << wid
|
||||
<< " bits " << (signed_flag_?"signed":"unsigned")
|
||||
<< " from expr_width()=" << expr->expr_width() << endl;
|
||||
}
|
||||
|
||||
if (debug_elaborate)
|
||||
cerr << get_fileline() << ": debug: cast to " << wid
|
||||
<< " bits " << (signed_flag_?"signed":"unsigned") << endl;
|
||||
|
||||
NetESelect*tmp = new NetESelect(expr, 0, wid);
|
||||
tmp->cast_signed(signed_flag_);
|
||||
tmp->set_line(*this);
|
||||
|
||||
return tmp;
|
||||
return cast_to_width(expr, wid, signed_flag_, *this);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1377,7 +1431,7 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope,
|
||||
|
||||
PExpr*expr = parms_[0];
|
||||
ivl_assert(*this, expr);
|
||||
NetExpr*sub = expr->elaborate_expr(des, scope, expr_width_, flags);
|
||||
NetExpr*sub = expr->elaborate_expr(des, scope, expr->expr_width(), flags);
|
||||
return cast_to_width_(sub, expr_wid);
|
||||
}
|
||||
|
||||
@@ -1392,6 +1446,10 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PECallFunction::elaborate_sfunc_: "
|
||||
<< name << " expression is the argument cast to expr_wid=" << expr_wid << endl;
|
||||
}
|
||||
PExpr*expr = parms_[0];
|
||||
NetExpr*sub = expr->elaborate_expr(des, scope, expr_width_, flags);
|
||||
|
||||
@@ -1516,7 +1574,7 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope,
|
||||
|
||||
if (missing_parms > 0) {
|
||||
cerr << get_fileline() << ": error: The function " << name
|
||||
<< " has been called with empty parameters." << endl;
|
||||
<< " has been called with missing/empty parameters." << endl;
|
||||
cerr << get_fileline() << ": : Verilog doesn't allow "
|
||||
<< "passing empty parameters to functions." << endl;
|
||||
des->errors += 1;
|
||||
@@ -1525,10 +1583,7 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope,
|
||||
if (missing_parms || parm_errors)
|
||||
return 0;
|
||||
|
||||
NetExpr*tmp = pad_to_width(fun, expr_wid, *this);
|
||||
tmp->cast_signed(signed_flag_);
|
||||
|
||||
return tmp;
|
||||
return pad_to_width(fun, expr_wid, signed_flag_, *this);
|
||||
}
|
||||
|
||||
NetExpr* PECallFunction::elaborate_access_func_(Design*des, NetScope*scope,
|
||||
@@ -1585,10 +1640,7 @@ NetExpr* PECallFunction::elaborate_access_func_(Design*des, NetScope*scope,
|
||||
NetExpr*tmp = new NetEAccess(branch, nature);
|
||||
tmp->set_line(*this);
|
||||
|
||||
tmp = pad_to_width(tmp, expr_wid, *this);
|
||||
tmp->cast_signed(signed_flag_);
|
||||
|
||||
return tmp;
|
||||
return pad_to_width(tmp, expr_wid, signed_flag_, *this);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2108,6 +2160,14 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
|
||||
return elaborate_base_(des, scope, dscope, expr_wid, flags);
|
||||
}
|
||||
|
||||
NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
|
||||
ivl_type_t type, unsigned flags) const
|
||||
{
|
||||
const netdarray_t*darray = dynamic_cast<const netdarray_t*>(type);
|
||||
assert(darray);
|
||||
return elaborate_expr(des, scope, darray->element_type()->packed_width(), flags);
|
||||
}
|
||||
|
||||
NetExpr* PECallFunction::elaborate_base_(Design*des, NetScope*scope, NetScope*dscope,
|
||||
unsigned expr_wid, unsigned flags) const
|
||||
{
|
||||
@@ -2189,10 +2249,10 @@ NetExpr* PECallFunction::elaborate_base_(Design*des, NetScope*scope, NetScope*ds
|
||||
NetEUFunc*func = new NetEUFunc(scope, dscope, eres, parms, need_const);
|
||||
func->set_line(*this);
|
||||
|
||||
NetExpr*tmp = pad_to_width(func, expr_wid, *this);
|
||||
tmp->cast_signed(signed_flag_);
|
||||
if(res->darray_type())
|
||||
return func;
|
||||
|
||||
return tmp;
|
||||
return pad_to_width(func, expr_wid, signed_flag_, *this);
|
||||
}
|
||||
|
||||
cerr << get_fileline() << ": internal error: Unable to locate "
|
||||
@@ -2221,6 +2281,21 @@ unsigned PECallFunction::elaborate_arguments_(Design*des, NetScope*scope,
|
||||
const unsigned parm_count = parms.size() - parm_off;
|
||||
const unsigned actual_count = parms_.size();
|
||||
|
||||
/* The parser can't distinguish between a function call with
|
||||
no arguments and a function call with one empty argument,
|
||||
and always supplies one empty argument. Handle the no
|
||||
argument case here. */
|
||||
if ((parm_count == 0) && (actual_count == 1) && (parms_[0] == 0))
|
||||
return 0;
|
||||
|
||||
if (actual_count > parm_count) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "Too many arguments (" << actual_count
|
||||
<< ", expecting " << parm_count << ")"
|
||||
<< " in call to function." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
for (unsigned idx = 0 ; idx < parm_count ; idx += 1) {
|
||||
unsigned pidx = idx + parm_off;
|
||||
PExpr*tmp = (idx < actual_count) ? parms_[idx] : 0;
|
||||
@@ -2251,7 +2326,7 @@ unsigned PECallFunction::elaborate_arguments_(Design*des, NetScope*scope,
|
||||
} else if (def->port_defe(pidx)) {
|
||||
if (! gn_system_verilog()) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<<"Found (and using) default function argument "
|
||||
<< "Found (and using) default function argument "
|
||||
<< "requires SystemVerilog." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
@@ -2265,7 +2340,7 @@ unsigned PECallFunction::elaborate_arguments_(Design*des, NetScope*scope,
|
||||
|
||||
if (missing_parms > 0) {
|
||||
cerr << get_fileline() << ": error: The function " << path_
|
||||
<< " has been called with empty parameters." << endl;
|
||||
<< " has been called with missing/empty parameters." << endl;
|
||||
cerr << get_fileline() << ": : Verilog doesn't allow "
|
||||
<< "passing empty parameters to functions." << endl;
|
||||
parm_errors += 1;
|
||||
@@ -2414,22 +2489,54 @@ NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope,
|
||||
|
||||
unsigned PECastSize::test_width(Design*des, NetScope*scope, width_mode_t&)
|
||||
{
|
||||
expr_width_ = size_;
|
||||
ivl_assert(*this, size_);
|
||||
ivl_assert(*this, base_);
|
||||
|
||||
NetExpr*size_ex = elab_and_eval(des, scope, size_, -1, true);
|
||||
NetEConst*size_ce = dynamic_cast<NetEConst*>(size_ex);
|
||||
expr_width_ = size_ce ? size_ce->value().as_ulong() : 0;
|
||||
delete size_ex;
|
||||
if (expr_width_ == 0) {
|
||||
cerr << get_fileline() << ": error: Cast size expression "
|
||||
"must be constant and greater than zero." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
width_mode_t tmp_mode = PExpr::SIZED;
|
||||
base_->test_width(des, scope, tmp_mode);
|
||||
|
||||
return size_;
|
||||
if (!type_is_vectorable(base_->expr_type())) {
|
||||
cerr << get_fileline() << ": error: Cast base expression "
|
||||
"must be a vector type." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
expr_type_ = base_->expr_type();
|
||||
min_width_ = expr_width_;
|
||||
signed_flag_ = base_->has_sign();
|
||||
|
||||
return expr_width_;
|
||||
}
|
||||
|
||||
NetExpr* PECastSize::elaborate_expr(Design*des, NetScope*scope,
|
||||
unsigned, unsigned) const
|
||||
unsigned expr_wid, unsigned flags) const
|
||||
{
|
||||
NetExpr*sub = base_->elaborate_expr(des, scope, base_->expr_width(), NO_FLAGS);
|
||||
NetESelect*sel = new NetESelect(sub, 0, size_);
|
||||
sel->set_line(*this);
|
||||
flags &= ~SYS_TASK_ARG; // don't propagate the SYS_TASK_ARG flag
|
||||
|
||||
return sel;
|
||||
ivl_assert(*this, size_);
|
||||
ivl_assert(*this, base_);
|
||||
|
||||
NetExpr*sub = base_->elaborate_expr(des, scope, base_->expr_width(), flags);
|
||||
|
||||
// Perform the cast. The extension method (zero/sign), if needed,
|
||||
// depends on the type of the base expression.
|
||||
NetExpr*tmp = cast_to_width(sub, expr_width_, base_->has_sign(), *this);
|
||||
|
||||
// Pad up to the expression width. The extension method (zero/sign)
|
||||
// depends on the type of enclosing expression.
|
||||
return pad_to_width(tmp, expr_wid, signed_flag_, *this);
|
||||
}
|
||||
|
||||
unsigned PECastType::test_width(Design*des, NetScope*scope, width_mode_t&wid)
|
||||
@@ -2452,11 +2559,44 @@ unsigned PECastType::test_width(Design*des, NetScope*scope, width_mode_t&wid)
|
||||
expr_width_ = t->packed_width();
|
||||
}
|
||||
|
||||
signed_flag_= t->get_signed();
|
||||
signed_flag_ = t->get_signed();
|
||||
min_width_ = expr_width_;
|
||||
return expr_width_;
|
||||
}
|
||||
|
||||
NetExpr* PECastType::elaborate_expr(Design*des, NetScope*scope,
|
||||
ivl_type_t type, unsigned) const
|
||||
{
|
||||
const netdarray_t*darray = NULL;
|
||||
const netvector_t*vector = NULL;
|
||||
|
||||
// Casting array of vectors to dynamic array type
|
||||
if((darray = dynamic_cast<const netdarray_t*>(type)) &&
|
||||
(vector = dynamic_cast<const netvector_t*>(darray->element_type()))) {
|
||||
PExpr::width_mode_t mode = PExpr::SIZED;
|
||||
unsigned use_wid = base_->test_width(des, scope, mode);
|
||||
NetExpr*base = base_->elaborate_expr(des, scope, use_wid, NO_FLAGS);
|
||||
|
||||
assert(vector->packed_width() > 0);
|
||||
assert(base->expr_width() > 0);
|
||||
|
||||
// Find rounded up length that can fit the whole casted array of vectors
|
||||
int len = base->expr_width() + vector->packed_width() - 1;
|
||||
if(base->expr_width() > vector->packed_width()) {
|
||||
len /= vector->packed_width();
|
||||
} else {
|
||||
len /= base->expr_width();
|
||||
}
|
||||
|
||||
// Number of words in the created dynamic array
|
||||
NetEConst*len_expr = new NetEConst(verinum(len));
|
||||
return new NetENew(type, len_expr, base);
|
||||
}
|
||||
|
||||
// Fallback
|
||||
return elaborate_expr(des, scope, (unsigned) 0, 0);
|
||||
}
|
||||
|
||||
NetExpr* PECastType::elaborate_expr(Design*des, NetScope*scope,
|
||||
unsigned, unsigned) const
|
||||
{
|
||||
@@ -2500,17 +2640,15 @@ NetExpr* PECastType::elaborate_expr(Design*des, NetScope*scope,
|
||||
|
||||
if((base_->expr_type() != IVL_VT_BOOL) &&
|
||||
(base_->expr_type() != IVL_VT_LOGIC)) {
|
||||
cerr << get_fileline() << ": cannot be casted to string." << endl;
|
||||
cerr << get_fileline() << ": cannot be cast to a string." << endl;
|
||||
ivl_assert(*this, false);
|
||||
}
|
||||
|
||||
return expr;
|
||||
}
|
||||
|
||||
cerr << get_fileline() << ": sorry: I don't know how to cast expression." << endl;
|
||||
ivl_assert(*this, false);
|
||||
|
||||
return expr;
|
||||
cerr << get_fileline() << ": sorry: This cast operation is not yet supported." << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned PEConcat::test_width(Design*des, NetScope*scope, width_mode_t&)
|
||||
@@ -2702,17 +2840,16 @@ NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope,
|
||||
concat->set(idx, parms[off+idx]);
|
||||
}
|
||||
|
||||
if (wid_sum == 0 && concat_depth < 2) {
|
||||
cerr << get_fileline() << ": error: Concatenation may not "
|
||||
<< "have zero width in this context." << endl;
|
||||
if (wid_sum == 0) {
|
||||
cerr << get_fileline() << ": error: Concatenation/replication "
|
||||
<< "may not have zero width in this context." << endl;
|
||||
des->errors += 1;
|
||||
concat_depth -= 1;
|
||||
delete concat;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetExpr*tmp = pad_to_width(concat, expr_wid, *this);
|
||||
tmp->cast_signed(signed_flag_);
|
||||
NetExpr*tmp = pad_to_width(concat, expr_wid, signed_flag_, *this);
|
||||
|
||||
concat_depth -= 1;
|
||||
return tmp;
|
||||
@@ -2752,6 +2889,25 @@ NetExpr* PEFNumber::elaborate_expr(Design*, NetScope*, unsigned, unsigned) const
|
||||
bool PEIdent::calculate_packed_indices_(Design*des, NetScope*scope, NetNet*net,
|
||||
list<long>&prefix_indices) const
|
||||
{
|
||||
unsigned dimensions = net->unpacked_dimensions() + net->packed_dimensions();
|
||||
switch (net->data_type()) {
|
||||
case IVL_VT_STRING:
|
||||
case IVL_VT_DARRAY:
|
||||
case IVL_VT_QUEUE:
|
||||
dimensions += 1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (path_.back().index.size() > dimensions) {
|
||||
cerr << get_fileline() << ": error: the number of indices ("
|
||||
<< path_.back().index.size()
|
||||
<< ") is greater than the number of dimensions ("
|
||||
<< dimensions
|
||||
<< ")." << endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
list<index_component_t> index;
|
||||
index = path_.back().index;
|
||||
ivl_assert(*this, index.size() >= net->unpacked_dimensions());
|
||||
@@ -2780,7 +2936,7 @@ bool PEIdent::calculate_bits_(Design*des, NetScope*scope,
|
||||
NetEConst*msb_c = dynamic_cast<NetEConst*>(msb_ex);
|
||||
if (msb_c == 0) {
|
||||
cerr << index_tail.msb->get_fileline() << ": error: "
|
||||
"Bit select expressionsmust be constant."
|
||||
"Bit select expressions must be constant."
|
||||
<< endl;
|
||||
cerr << index_tail.msb->get_fileline() << ": : "
|
||||
"This msb expression violates the rule: "
|
||||
@@ -3610,10 +3766,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
||||
|
||||
if (!tmp) return 0;
|
||||
|
||||
tmp = pad_to_width(tmp, expr_wid, *this);
|
||||
tmp->cast_signed(signed_flag_);
|
||||
|
||||
return tmp;
|
||||
return pad_to_width(tmp, expr_wid, signed_flag_, *this);
|
||||
}
|
||||
|
||||
// If the identifier names a signal (a register or wire)
|
||||
@@ -3649,10 +3802,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
||||
<< ", tmp=" << *tmp << endl;
|
||||
}
|
||||
|
||||
tmp = pad_to_width(tmp, expr_wid, *this);
|
||||
tmp->cast_signed(signed_flag_);
|
||||
|
||||
return tmp;
|
||||
return pad_to_width(tmp, expr_wid, signed_flag_, *this);
|
||||
}
|
||||
|
||||
// If the identifier is a named event
|
||||
@@ -3699,7 +3849,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
||||
}
|
||||
|
||||
// Maybe this is a method attached to an enumeration name? If
|
||||
// this is system verilog, then test to see if the name is
|
||||
// this is SystemVerilog, then test to see if the name is
|
||||
// really a method attached to an object.
|
||||
if (gn_system_verilog() && found_in==0 && path_.size() >= 2) {
|
||||
pform_name_t use_path = path_;
|
||||
@@ -3752,9 +3902,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
||||
member_comp);
|
||||
if (!tmp) return 0;
|
||||
|
||||
tmp = pad_to_width(tmp, expr_wid, *this);
|
||||
tmp->cast_signed(signed_flag_);
|
||||
return tmp;
|
||||
return pad_to_width(tmp, expr_wid, signed_flag_, *this);
|
||||
}
|
||||
|
||||
if (net->class_type() != 0) {
|
||||
@@ -4333,7 +4481,7 @@ NetExpr* PEIdent::elaborate_expr_param_(Design*des,
|
||||
<< "Elaborate parameter <" << path_
|
||||
<< "> as enumeration constant." << *etmp << endl;
|
||||
tmp = etmp->dup_expr();
|
||||
tmp = pad_to_width(tmp, expr_wid, *this);
|
||||
tmp = pad_to_width(tmp, expr_wid, signed_flag_, *this);
|
||||
|
||||
} else {
|
||||
perm_string name = peek_tail_name(path_);
|
||||
@@ -4508,7 +4656,8 @@ NetExpr* PEIdent::elaborate_expr_net_part_(Design*des, NetScope*scope,
|
||||
{
|
||||
list<long> prefix_indices;
|
||||
bool rc = calculate_packed_indices_(des, scope, net->sig(), prefix_indices);
|
||||
ivl_assert(*this, rc);
|
||||
if (!rc)
|
||||
return 0;
|
||||
|
||||
long msv, lsv;
|
||||
bool parts_defined_flag;
|
||||
@@ -4648,7 +4797,8 @@ NetExpr* PEIdent::elaborate_expr_net_idx_up_(Design*des, NetScope*scope,
|
||||
{
|
||||
list<long>prefix_indices;
|
||||
bool rc = calculate_packed_indices_(des, scope, net->sig(), prefix_indices);
|
||||
ivl_assert(*this, rc);
|
||||
if (!rc)
|
||||
return 0;
|
||||
|
||||
NetExpr*base = calculate_up_do_base_(des, scope, need_const);
|
||||
|
||||
@@ -4750,7 +4900,8 @@ NetExpr* PEIdent::elaborate_expr_net_idx_do_(Design*des, NetScope*scope,
|
||||
{
|
||||
list<long>prefix_indices;
|
||||
bool rc = calculate_packed_indices_(des, scope, net->sig(), prefix_indices);
|
||||
ivl_assert(*this, rc);
|
||||
if (!rc)
|
||||
return 0;
|
||||
|
||||
NetExpr*base = calculate_up_do_base_(des, scope, need_const);
|
||||
|
||||
@@ -4838,7 +4989,8 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
|
||||
{
|
||||
list<long>prefix_indices;
|
||||
bool rc = calculate_packed_indices_(des, scope, net->sig(), prefix_indices);
|
||||
ivl_assert(*this, rc);
|
||||
if (!rc)
|
||||
return 0;
|
||||
|
||||
const name_component_t&name_tail = path_.back();
|
||||
ivl_assert(*this, !name_tail.index.empty());
|
||||
@@ -4848,6 +5000,8 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
|
||||
ivl_assert(*this, index_tail.lsb == 0);
|
||||
|
||||
NetExpr*mux = elab_and_eval(des, scope, index_tail.msb, -1, need_const);
|
||||
if (!mux)
|
||||
return 0;
|
||||
|
||||
if (const netdarray_t*darray = net->sig()->darray_type()) {
|
||||
// Special case: This is a select of a dynamic
|
||||
@@ -5395,10 +5549,23 @@ unsigned PENumber::test_width(Design*, NetScope*, width_mode_t&mode)
|
||||
expr_width_ = integer_width;
|
||||
mode = UNSIZED;
|
||||
} else if (mode < LOSSLESS) {
|
||||
mode = LOSSLESS;
|
||||
if (expr_width_ < integer_width) {
|
||||
expr_width_ = integer_width;
|
||||
if (mode < UNSIZED)
|
||||
mode = UNSIZED;
|
||||
} else {
|
||||
mode = LOSSLESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PENumber::test_width: "
|
||||
<< "Value=" << *value_
|
||||
<< ", width=" << expr_width_
|
||||
<< ", output mode=" << width_mode_name(mode) << endl;
|
||||
}
|
||||
|
||||
return expr_width_;
|
||||
}
|
||||
|
||||
@@ -5510,7 +5677,6 @@ unsigned PETernary::test_width(Design*des, NetScope*scope, width_mode_t&mode)
|
||||
} else if (tru_type == IVL_VT_LOGIC || fal_type == IVL_VT_LOGIC) {
|
||||
expr_type_ = IVL_VT_LOGIC;
|
||||
} else {
|
||||
ivl_assert(*this, tru_type == fal_type);
|
||||
expr_type_ = tru_type;
|
||||
}
|
||||
if (expr_type_ == IVL_VT_REAL) {
|
||||
@@ -5906,7 +6072,7 @@ NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope,
|
||||
}
|
||||
tmp->set_line(*this);
|
||||
}
|
||||
tmp = pad_to_width(tmp, expr_wid, *this);
|
||||
tmp = pad_to_width(tmp, expr_wid, signed_flag_, *this);
|
||||
break;
|
||||
|
||||
case '&': // Reduction AND
|
||||
@@ -5924,7 +6090,7 @@ NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope,
|
||||
}
|
||||
tmp = new NetEUReduce(op_, ip);
|
||||
tmp->set_line(*this);
|
||||
tmp = pad_to_width(tmp, expr_wid, *this);
|
||||
tmp = pad_to_width(tmp, expr_wid, signed_flag_, *this);
|
||||
break;
|
||||
|
||||
case '~':
|
||||
|
||||
+73
-32
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2016 Stephen Williams (steve@icarus.com)
|
||||
* Copyright CERN 2012-2013 / Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
@@ -138,6 +138,9 @@ NetAssign_* PEConcat::elaborate_lval(Design*des,
|
||||
continue;
|
||||
}
|
||||
|
||||
/* A concatenation is always unsigned. */
|
||||
tmp->set_signed(false);
|
||||
|
||||
/* Link the new l-value to the previous one. */
|
||||
NetAssign_*last = tmp;
|
||||
while (last->more)
|
||||
@@ -157,7 +160,7 @@ NetAssign_*PEIdent::scan_lname_for_nested_members_(Design*des, NetScope*scope,
|
||||
return 0;
|
||||
|
||||
pform_name_t use_path = cur_path;
|
||||
perm_string tmp_name = peek_tail_name(use_path);
|
||||
name_component_t tail = use_path.back();
|
||||
use_path.pop_back();
|
||||
|
||||
NetNet* reg = 0;
|
||||
@@ -171,18 +174,32 @@ NetAssign_*PEIdent::scan_lname_for_nested_members_(Design*des, NetScope*scope,
|
||||
return 0;
|
||||
|
||||
tmp = new NetAssign_(tmp);
|
||||
tmp->set_property(tmp_name);
|
||||
tmp->set_property(tail.name);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
if (reg->struct_type()) {
|
||||
if (reg->struct_type() && reg->struct_type()->packed()) {
|
||||
NetAssign_*tmp = new NetAssign_(reg);
|
||||
elaborate_lval_net_packed_member_(des, scope, tmp, tail);
|
||||
return tmp;
|
||||
}
|
||||
#if 0
|
||||
if (reg->struct_type() && reg->struct_type()->packed()) {
|
||||
cerr << get_fileline() << ": sorry: "
|
||||
<< "I don't know what to do with struct " << use_path << endl;
|
||||
<< "I don't know what to do with packed struct " << use_path
|
||||
<< " with member " << tail << "." << endl;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
if (reg->struct_type() && !reg->struct_type()->packed()) {
|
||||
cerr << get_fileline() << ": sorry: "
|
||||
<< "I don't know what to do with unpacked struct " << use_path
|
||||
<< " with member " << tail << "." << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (reg->class_type()) {
|
||||
return elaborate_lval_net_class_member_(des, scope, reg, tmp_name);
|
||||
return elaborate_lval_net_class_member_(des, scope, reg, tail.name);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -202,6 +219,11 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
||||
NetEvent* eve = 0;
|
||||
perm_string method_name;
|
||||
|
||||
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))
|
||||
@@ -263,17 +285,18 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PEIdent::elaborate_lval: "
|
||||
<< "Lval reg = " << reg->name() << endl;
|
||||
<< "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
|
||||
// example, the Verilog may be "a.b.c", so we are processing
|
||||
// "c" at this point. (Note that if method_name is not nil,
|
||||
// then this is "a.b.c.method" and "a.b.c" is a struct or class.)
|
||||
const name_component_t&name_tail = path_.back();
|
||||
|
||||
// Use the last index to determine what kind of select
|
||||
// (bit/part/etc) we are processing. For example, the verilog
|
||||
// (bit/part/etc) we are processing. For example, the Verilog
|
||||
// may be "a.b.c[1][2][<index>]". All but the last index must
|
||||
// be simple expressions, only the <index> may be a part
|
||||
// select etc., so look at it to determine how we will be
|
||||
@@ -310,7 +333,8 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
||||
|
||||
if (reg->struct_type() && !method_name.nil()) {
|
||||
NetAssign_*lv = new NetAssign_(reg);
|
||||
elaborate_lval_net_packed_member_(des, use_scope, lv, method_name);
|
||||
name_component_t tmp_name (method_name);
|
||||
elaborate_lval_net_packed_member_(des, use_scope, lv, tmp_name);
|
||||
return lv;
|
||||
}
|
||||
|
||||
@@ -378,6 +402,7 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
||||
/* No select expressions. */
|
||||
|
||||
NetAssign_*lv = new NetAssign_(reg);
|
||||
lv->set_signed(reg->get_signed());
|
||||
|
||||
return lv;
|
||||
}
|
||||
@@ -464,7 +489,7 @@ NetAssign_* PEIdent::elaborate_lval_method_class_member_(Design*des,
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PEIdent::elaborate_lval_method_class_member_: "
|
||||
<< "Found initialzers for property " << class_type->get_prop_name(pidx) << endl;
|
||||
<< "Found initializers for property " << class_type->get_prop_name(pidx) << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -509,6 +534,11 @@ NetAssign_* PEIdent::elaborate_lval_net_word_(Design*des,
|
||||
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,"
|
||||
@@ -576,6 +606,11 @@ NetAssign_* PEIdent::elaborate_lval_net_word_(Design*des,
|
||||
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;
|
||||
@@ -656,20 +691,24 @@ bool PEIdent::elaborate_lval_net_bit_(Design*des,
|
||||
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;
|
||||
|
||||
if (warn_ob_select) {
|
||||
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;
|
||||
|
||||
if (warn_ob_select) {
|
||||
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;
|
||||
}
|
||||
@@ -766,12 +805,10 @@ bool PEIdent::elaborate_lval_net_bit_(Design*des,
|
||||
// Constant bit select that does something useful.
|
||||
long loff = reg->sb_to_idx(prefix_indices,lsb);
|
||||
|
||||
if (loff < 0 || loff >= (long)reg->vector_width()) {
|
||||
cerr << get_fileline() << ": error: bit select "
|
||||
if (warn_ob_select && (loff < 0 || loff >= (long)reg->vector_width())) {
|
||||
cerr << get_fileline() << ": warning: bit select "
|
||||
<< reg->name() << "[" <<lsb<<"]"
|
||||
<< " is out of range." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (reg->type()==NetNet::UNRESOLVED_WIRE) {
|
||||
@@ -837,10 +874,13 @@ bool PEIdent::elaborate_lval_net_part_(Design*des,
|
||||
ivl_assert(*this, reg);
|
||||
|
||||
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;
|
||||
if (warn_ob_select) {
|
||||
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);
|
||||
@@ -903,11 +943,11 @@ bool PEIdent::elaborate_lval_net_part_(Design*des,
|
||||
}
|
||||
|
||||
/* If the part select extends beyond the extremes of the
|
||||
variable, then report an error. Note that loff is
|
||||
variable, then output a warning. Note that loff is
|
||||
converted to normalized form so is relative the
|
||||
variable pins. */
|
||||
|
||||
if (loff < 0 || moff >= (long)reg->vector_width()) {
|
||||
if (warn_ob_select && (loff < 0 || moff >= (long)reg->vector_width())) {
|
||||
cerr << get_fileline() << ": warning: Part select "
|
||||
<< reg->name() << "[" << msb<<":"<<lsb<<"]"
|
||||
<< " is out of range." << endl;
|
||||
@@ -1099,8 +1139,9 @@ NetAssign_* PEIdent::elaborate_lval_net_class_member_(Design*des, NetScope*scope
|
||||
|
||||
bool PEIdent::elaborate_lval_net_packed_member_(Design*des, NetScope*scope,
|
||||
NetAssign_*lv,
|
||||
const perm_string&member_name) const
|
||||
const name_component_t&member_comp) const
|
||||
{
|
||||
const perm_string&member_name = member_comp.name;
|
||||
NetNet*reg = lv->sig();
|
||||
ivl_assert(*this, reg);
|
||||
|
||||
|
||||
+57
-30
@@ -328,39 +328,66 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
|
||||
return false;
|
||||
}
|
||||
|
||||
long lidx_tmp = sig->sb_to_idx(prefix_indices, lsb);
|
||||
long midx_tmp = sig->sb_to_idx(prefix_indices, msb);
|
||||
/* Detect reversed indices of a part select. */
|
||||
if (lidx_tmp > midx_tmp) {
|
||||
cerr << get_fileline() << ": error: Part select "
|
||||
<< sig->name() << "[" << msb << ":"
|
||||
<< lsb << "] indices reversed." << endl;
|
||||
cerr << get_fileline() << ": : Did you mean "
|
||||
<< sig->name() << "[" << lsb << ":"
|
||||
<< msb << "]?" << endl;
|
||||
long tmp = midx_tmp;
|
||||
midx_tmp = lidx_tmp;
|
||||
lidx_tmp = tmp;
|
||||
des->errors += 1;
|
||||
}
|
||||
if (prefix_indices.size()+1 < sig->packed_dims().size()) {
|
||||
// Here we have a slice that doesn't have enough indices
|
||||
// to get to a single slice. For example:
|
||||
// wire [9:0][5:1] foo
|
||||
// ... foo[4:3] ...
|
||||
// Make this work by finding the indexed slices and
|
||||
// creating a generated slice that spans the whole
|
||||
// range.
|
||||
long loff, moff;
|
||||
unsigned long lwid, mwid;
|
||||
bool lrc;
|
||||
lrc = sig->sb_to_slice(prefix_indices, lsb, loff, lwid);
|
||||
ivl_assert(*this, lrc);
|
||||
lrc = sig->sb_to_slice(prefix_indices, msb, moff, mwid);
|
||||
ivl_assert(*this, lrc);
|
||||
ivl_assert(*this, lwid == mwid);
|
||||
|
||||
/* Warn about a part select that is out of range. */
|
||||
if (midx_tmp >= (long)sig->vector_width() || lidx_tmp < 0) {
|
||||
cerr << get_fileline() << ": warning: Part select "
|
||||
<< sig->name();
|
||||
if (sig->unpacked_dimensions() > 0) {
|
||||
cerr << "[]";
|
||||
if (moff > loff) {
|
||||
lidx = loff;
|
||||
midx = moff + mwid - 1;
|
||||
} else {
|
||||
lidx = moff;
|
||||
midx = loff + lwid - 1;
|
||||
}
|
||||
cerr << "[" << msb << ":" << lsb
|
||||
<< "] is out of range." << endl;
|
||||
}
|
||||
/* This is completely out side the signal so just skip it. */
|
||||
if (lidx_tmp >= (long)sig->vector_width() || midx_tmp < 0) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
long lidx_tmp = sig->sb_to_idx(prefix_indices, lsb);
|
||||
long midx_tmp = sig->sb_to_idx(prefix_indices, msb);
|
||||
|
||||
midx = midx_tmp;
|
||||
lidx = lidx_tmp;
|
||||
/* Detect reversed indices of a part select. */
|
||||
if (lidx_tmp > midx_tmp) {
|
||||
cerr << get_fileline() << ": error: Part select "
|
||||
<< sig->name() << "[" << msb << ":"
|
||||
<< lsb << "] indices reversed." << endl;
|
||||
cerr << get_fileline() << ": : Did you mean "
|
||||
<< sig->name() << "[" << lsb << ":"
|
||||
<< msb << "]?" << endl;
|
||||
long tmp = midx_tmp;
|
||||
midx_tmp = lidx_tmp;
|
||||
lidx_tmp = tmp;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
/* Warn about a part select that is out of range. */
|
||||
if (midx_tmp >= (long)sig->vector_width() || lidx_tmp < 0) {
|
||||
cerr << get_fileline() << ": warning: Part select "
|
||||
<< sig->name();
|
||||
if (sig->unpacked_dimensions() > 0) {
|
||||
cerr << "[]";
|
||||
}
|
||||
cerr << "[" << msb << ":" << lsb
|
||||
<< "] is out of range." << endl;
|
||||
}
|
||||
/* This is completely out side the signal so just skip it. */
|
||||
if (lidx_tmp >= (long)sig->vector_width() || midx_tmp < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
midx = midx_tmp;
|
||||
lidx = lidx_tmp;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
+27
-12
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2016 Stephen Williams (steve@icarus.com)
|
||||
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
@@ -54,6 +54,15 @@
|
||||
# include <cassert>
|
||||
# include "ivl_assert.h"
|
||||
|
||||
|
||||
void set_scope_timescale(Design*des, NetScope*scope, PScope*pscope)
|
||||
{
|
||||
scope->time_unit(pscope->time_unit);
|
||||
scope->time_precision(pscope->time_precision);
|
||||
scope->time_from_timescale(pscope->time_from_timescale);
|
||||
des->set_precision(pscope->time_precision);
|
||||
}
|
||||
|
||||
typedef map<perm_string,LexicalScope::param_expr_t>::const_iterator mparm_it_t;
|
||||
|
||||
static void collect_parm_item_(Design*des, NetScope*scope, perm_string name,
|
||||
@@ -523,6 +532,7 @@ static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass)
|
||||
class_scope->set_class_def(use_class);
|
||||
use_class->set_class_scope(class_scope);
|
||||
use_class->set_definition_scope(scope);
|
||||
set_scope_timescale(des, class_scope, pclass);
|
||||
|
||||
// Collect the properties, elaborate them, and add them to the
|
||||
// elaborated class definition.
|
||||
@@ -654,8 +664,10 @@ static void elaborate_scope_task(Design*des, NetScope*scope, PTask*task)
|
||||
task_scope->is_auto(task->is_auto());
|
||||
task_scope->set_line(task);
|
||||
|
||||
if (scope==0)
|
||||
if (scope==0) {
|
||||
set_scope_timescale(des, task_scope, task);
|
||||
des->add_root_task(task_scope, task);
|
||||
}
|
||||
|
||||
if (debug_scopes) {
|
||||
cerr << task->get_fileline() << ": elaborate_scope_task: "
|
||||
@@ -719,8 +731,10 @@ static void elaborate_scope_func(Design*des, NetScope*scope, PFunction*task)
|
||||
task_scope->is_auto(task->is_auto());
|
||||
task_scope->set_line(task);
|
||||
|
||||
if (scope==0)
|
||||
if (scope==0) {
|
||||
set_scope_timescale(des, task_scope, task);
|
||||
des->add_root_task(task_scope, task);
|
||||
}
|
||||
|
||||
if (debug_scopes) {
|
||||
cerr << task->get_fileline() << ": elaborate_scope_func: "
|
||||
@@ -793,7 +807,7 @@ void elaborate_rootscope_tasks(Design*des)
|
||||
}
|
||||
|
||||
cerr << cur->second->get_fileline() << ": internal error: "
|
||||
<< "elabortae_rootscope_tasks does not understand "
|
||||
<< "elaborate_rootscope_tasks does not understand "
|
||||
<< "this object," << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
@@ -1742,18 +1756,15 @@ void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*s
|
||||
// scope searches will continue into the parent scope.
|
||||
NetScope*my_scope = new NetScope(sc, use_name, NetScope::MODULE,
|
||||
bound_type_? true : false,
|
||||
mod->program_block);
|
||||
mod->program_block,
|
||||
mod->is_interface);
|
||||
my_scope->set_line(get_file(), mod->get_file(),
|
||||
get_lineno(), mod->get_lineno());
|
||||
my_scope->set_module_name(mod->mod_name());
|
||||
|
||||
instances[idx] = my_scope;
|
||||
|
||||
// Set time units and precision.
|
||||
my_scope->time_unit(mod->time_unit);
|
||||
my_scope->time_precision(mod->time_precision);
|
||||
my_scope->time_from_timescale(mod->time_from_timescale);
|
||||
des->set_precision(mod->time_precision);
|
||||
set_scope_timescale(des, my_scope, mod);
|
||||
|
||||
// Look for module parameter replacements. The "replace" map
|
||||
// maps parameter name to replacement expression that is
|
||||
@@ -1792,8 +1803,12 @@ void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*s
|
||||
// so the mapping into the replace list is much easier.
|
||||
if (parms_) {
|
||||
assert(overrides_ == 0);
|
||||
for (unsigned jdx = 0 ; jdx < nparms_ ; jdx += 1)
|
||||
replace[parms_[jdx].name] = parms_[jdx].parm;
|
||||
for (unsigned jdx = 0 ; jdx < nparms_ ; jdx += 1) {
|
||||
// No expression means that the parameter is not
|
||||
// replaced.
|
||||
if (parms_[jdx].parm)
|
||||
replace[parms_[jdx].name] = parms_[jdx].parm;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
+60
-20
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2016 Stephen Williams (steve@icarus.com)
|
||||
* Copyright CERN 2012 / Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
@@ -715,16 +715,23 @@ void PTaskFunc::elaborate_sig_ports_(Design*des, NetScope*scope,
|
||||
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 the port has a default expression, elaborate
|
||||
// that expression here.
|
||||
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;
|
||||
if (tmp->port_type() == NetNet::PINPUT) {
|
||||
tmp_def = elab_and_eval(des, scope, ports_->at(idx).defe,
|
||||
-1, scope->need_const_func());
|
||||
if (tmp_def == 0) {
|
||||
cerr << get_fileline()
|
||||
<< ": error: Unable to evaluate "
|
||||
<< *ports_->at(idx).defe
|
||||
<< " as a port default expression." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
} else {
|
||||
cerr << get_fileline() << ": sorry: Default arguments "
|
||||
"for subroutine output or inout ports are not "
|
||||
"yet supported." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
}
|
||||
@@ -909,6 +916,11 @@ bool test_ranges_eeq(const vector<netrange_t>&lef, const vector<netrange_t>&rig)
|
||||
*/
|
||||
NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
// This sets the vector or array dimension size that will
|
||||
// cause a warning. For now, these warnings are permanently
|
||||
// enabled.
|
||||
const long warn_dimension_size = 1 << 30;
|
||||
|
||||
NetNet::Type wtype = type_;
|
||||
bool is_implicit_scalar = false;
|
||||
if (wtype == NetNet::IMPLICIT) {
|
||||
@@ -964,6 +976,23 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
}
|
||||
|
||||
if (port_set_ || net_set_) {
|
||||
|
||||
if (warn_implicit_dimensions
|
||||
&& port_set_ && net_set_
|
||||
&& net_.empty() && !port_.empty()) {
|
||||
cerr << get_fileline() << ": warning: "
|
||||
<< "var/net declaration of " << basename()
|
||||
<< " inherits dimensions from port declaration." << endl;
|
||||
}
|
||||
|
||||
if (warn_implicit_dimensions
|
||||
&& port_set_ && net_set_
|
||||
&& port_.empty() && !net_.empty()) {
|
||||
cerr << get_fileline() << ": warning: "
|
||||
<< "Port declaration of " << basename()
|
||||
<< " inherits dimensions from var/net." << endl;
|
||||
}
|
||||
|
||||
bool bad_range = false;
|
||||
vector<netrange_t> plist, nlist;
|
||||
/* If they exist get the port definition MSB and LSB */
|
||||
@@ -1042,7 +1071,11 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
|
||||
packed_dimensions = nlist;
|
||||
wid = netrange_width(packed_dimensions);
|
||||
|
||||
if (wid > warn_dimension_size) {
|
||||
cerr << get_fileline() << ": warning: Vector size "
|
||||
"is greater than " << warn_dimension_size
|
||||
<< "." << endl;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned nattrib = 0;
|
||||
@@ -1063,6 +1096,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
// put all the packed dimensions there.
|
||||
if (use_lidx==0 && use_ridx==0) {
|
||||
netvector_t*vec = new netvector_t(packed_dimensions, data_type_);
|
||||
vec->set_signed(get_signed());
|
||||
packed_dimensions.clear();
|
||||
ivl_assert(*this, netdarray==0);
|
||||
netdarray = new netdarray_t(vec);
|
||||
@@ -1073,6 +1107,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
// 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_);
|
||||
vec->set_signed(get_signed());
|
||||
packed_dimensions.clear();
|
||||
ivl_assert(*this, netdarray==0);
|
||||
netdarray = new netqueue_t(vec);
|
||||
@@ -1114,6 +1149,11 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
index_l = lval.as_long();
|
||||
index_r = rval.as_long();
|
||||
}
|
||||
if (abs(index_r - index_l) > warn_dimension_size) {
|
||||
cerr << get_fileline() << ": warning: Array dimension "
|
||||
"is greater than " << warn_dimension_size
|
||||
<< "." << endl;
|
||||
}
|
||||
|
||||
unpacked_dimensions.push_back(netrange_t(index_l, index_r));
|
||||
}
|
||||
@@ -1145,6 +1185,14 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
|
||||
NetLogic*pull = 0;
|
||||
if (wtype == NetNet::SUPPLY0 || wtype == NetNet::SUPPLY1) {
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: "
|
||||
<< "Generate a SUPPLY pull for the ";
|
||||
if (wtype == NetNet::SUPPLY0) cerr << "supply0";
|
||||
else cerr << "supply1";
|
||||
cerr << " net." << endl;
|
||||
}
|
||||
|
||||
NetLogic::TYPE pull_type = (wtype==NetNet::SUPPLY1)
|
||||
? NetLogic::PULLUP
|
||||
: NetLogic::PULLDOWN;
|
||||
@@ -1155,14 +1203,6 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
pull->pin(0).drive1(IVL_DR_SUPPLY);
|
||||
des->add_node(pull);
|
||||
wtype = NetNet::WIRE;
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: "
|
||||
<< "Generate a SUPPLY pull for the ";
|
||||
if (wtype == NetNet::SUPPLY0) cerr << "supply0";
|
||||
else cerr << "supply1";
|
||||
cerr << " net." << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1194,7 +1234,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
cerr << " in scope " << scope_path(scope) << endl;
|
||||
}
|
||||
|
||||
sig = new NetNet(scope, name_, wtype, use_type);
|
||||
sig = new NetNet(scope, name_, wtype, unpacked_dimensions, use_type);
|
||||
|
||||
} else if (enum_type_t*enum_type = dynamic_cast<enum_type_t*>(set_data_type_)) {
|
||||
list<named_pexpr_t>::const_iterator sample_name = enum_type->names->begin();
|
||||
|
||||
+61
-36
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2012-2016 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,11 +17,13 @@
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
# include "PExpr.h"
|
||||
# include "pform_types.h"
|
||||
# include "netlist.h"
|
||||
# include "netclass.h"
|
||||
# include "netdarray.h"
|
||||
# include "netenum.h"
|
||||
# include "netqueue.h"
|
||||
# include "netparray.h"
|
||||
# include "netscalar.h"
|
||||
# include "netstruct.h"
|
||||
@@ -32,6 +34,44 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
/*
|
||||
* Some types have a list of ranges that need to be elaborated. This
|
||||
* function elaborates the ranges referenced by "dims" into the vector
|
||||
* "ranges".
|
||||
*/
|
||||
static void elaborate_array_ranges(Design*des, NetScope*scope,
|
||||
vector<netrange_t>&ranges,
|
||||
const list<pform_range_t>*dims)
|
||||
{
|
||||
if (dims == 0)
|
||||
return;
|
||||
|
||||
for (list<pform_range_t>::const_iterator cur = dims->begin()
|
||||
; cur != dims->end() ; ++ cur) {
|
||||
|
||||
NetExpr*me = elab_and_eval(des, scope, cur->first, 0, true);
|
||||
|
||||
NetExpr*le = elab_and_eval(des, scope, cur->second, 0, true);
|
||||
|
||||
/* If elaboration failed for either expression, we
|
||||
should have already reported the error, so just
|
||||
skip the following evaluation to recover. */
|
||||
|
||||
long mnum = 0, lnum = 0;
|
||||
if ( me && ! eval_as_long(mnum, me) ) {
|
||||
assert(0);
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
if ( le && ! eval_as_long(lnum, le) ) {
|
||||
assert(0);
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
ranges.push_back(netrange_t(mnum, lnum));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Elaborations of types may vary depending on the scope that it is
|
||||
* done in, so keep a per-scope cache of the results.
|
||||
@@ -43,8 +83,8 @@ ivl_type_s* data_type_t::elaborate_type(Design*des, NetScope*scope)
|
||||
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;
|
||||
if (pos != cache_type_elaborate_.end() && pos->first == use_definitions)
|
||||
return pos->second;
|
||||
|
||||
ivl_type_s*tmp = elaborate_type_raw(des, scope);
|
||||
cache_type_elaborate_.insert(pos, pair<NetScope*,ivl_type_s*>(scope, tmp));
|
||||
@@ -120,33 +160,7 @@ ivl_type_s* enum_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
|
||||
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));
|
||||
}
|
||||
}
|
||||
elaborate_array_ranges(des, scope, packed, pdims.get());
|
||||
|
||||
netvector_t*tmp = new netvector_t(packed, base_type);
|
||||
tmp->set_signed(signed_flag);
|
||||
@@ -171,13 +185,14 @@ 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
|
||||
ivl_type_s* parray_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
|
||||
{
|
||||
cerr << get_fileline() << " : sorry: "
|
||||
<< "Packed arrays are not currently supported in this context."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
vector<netrange_t>packed;
|
||||
elaborate_array_ranges(des, scope, packed, dims.get());
|
||||
|
||||
ivl_type_t etype = base_type->elaborate_type(des, scope);
|
||||
|
||||
return new netparray_t(packed, etype);
|
||||
}
|
||||
|
||||
netstruct_t* struct_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
|
||||
@@ -232,6 +247,16 @@ ivl_type_s* uarray_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
|
||||
return res;
|
||||
}
|
||||
|
||||
// Special case: if the dimension is null:nil. this is a queue.
|
||||
if (cur->second==0 && dynamic_cast<PENull*>(cur->first)) {
|
||||
cerr << get_fileline() << ": sorry: "
|
||||
<< "SV queues inside classes are not yet supported." << endl;
|
||||
des->errors += 1;
|
||||
|
||||
ivl_type_s*res = new netqueue_t(btype);
|
||||
return res;
|
||||
}
|
||||
|
||||
vector<netrange_t> dimensions;
|
||||
bool bad_range = evaluate_ranges(des, scope, dimensions, *dims);
|
||||
|
||||
|
||||
+301
-102
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2016 Stephen Williams (steve@icarus.com)
|
||||
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
@@ -36,6 +36,7 @@
|
||||
# include "PEvent.h"
|
||||
# include "PGenerate.h"
|
||||
# include "PPackage.h"
|
||||
# include "PScope.h"
|
||||
# include "PSpec.h"
|
||||
# include "netlist.h"
|
||||
# include "netenum.h"
|
||||
@@ -50,6 +51,9 @@
|
||||
# include "ivl_assert.h"
|
||||
|
||||
|
||||
// Implemented in elab_scope.cc
|
||||
extern void set_scope_timescale(Design*des, NetScope*scope, PScope*pscope);
|
||||
|
||||
void PGate::elaborate(Design*, NetScope*) const
|
||||
{
|
||||
cerr << "internal error: what kind of gate? " <<
|
||||
@@ -787,7 +791,7 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
|
||||
|
||||
if (check_delay_count(des)) return;
|
||||
NetExpr* rise_time, *fall_time, *decay_time;
|
||||
eval_delays(des, scope, rise_time, fall_time, decay_time);
|
||||
eval_delays(des, scope, rise_time, fall_time, decay_time, true);
|
||||
|
||||
struct attrib_list_t*attrib_list;
|
||||
unsigned attrib_list_n = 0;
|
||||
@@ -1287,15 +1291,18 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
||||
for (unsigned idx = 0 ; idx < pins.size() ; idx += 1) {
|
||||
bool unconnected_port = false;
|
||||
|
||||
perm_string port_name = rmod->get_port_name(idx);
|
||||
|
||||
// Skip unconnected module ports. This happens when a
|
||||
// null parameter is passed in.
|
||||
|
||||
if (pins[idx] == 0) {
|
||||
|
||||
if (pins_fromwc[idx]) {
|
||||
cerr << get_fileline() << ": error: Wildcard named port " <<
|
||||
"connection (.*) did not find a matching identifier " <<
|
||||
"for port '" << rmod->ports[idx]->name << "'." << endl;
|
||||
cerr << get_fileline() << ": error: Wildcard named "
|
||||
"port connection (.*) did not find a matching "
|
||||
"identifier for port " << (idx+1) << " ("
|
||||
<< port_name << ")." << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
}
|
||||
@@ -1330,22 +1337,22 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
||||
break;
|
||||
}
|
||||
|
||||
// Print a waring for an unconnected input.
|
||||
// Print a warning for an unconnected input.
|
||||
if (warn_portbinding) {
|
||||
cerr << get_fileline() << ": warning: "
|
||||
<< "Instantiating module "
|
||||
<< rmod->mod_name()
|
||||
<< " with dangling input port '"
|
||||
<< rmod->ports[idx]->name;
|
||||
<< " with dangling input port "
|
||||
<< (idx+1) << " (" << port_name;
|
||||
switch (rmod->uc_drive) {
|
||||
case Module::UCD_PULL0:
|
||||
cerr << "' (pulled low)." << endl;
|
||||
cerr << ") pulled low." << endl;
|
||||
break;
|
||||
case Module::UCD_PULL1:
|
||||
cerr << "' (pulled high)." << endl;
|
||||
cerr << ") pulled high." << endl;
|
||||
break;
|
||||
case Module::UCD_NONE:
|
||||
cerr << "' (floating)." << endl;
|
||||
cerr << ") floating." << endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1361,8 +1368,8 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: " << get_name()
|
||||
<< ": Port " << (idx+1) << " has " << prts.size()
|
||||
<< " sub-ports." << endl;
|
||||
<< ": Port " << (idx+1) << " (" << port_name
|
||||
<< ") has " << prts.size() << " sub-ports." << endl;
|
||||
}
|
||||
|
||||
// Count the internal vector bits of the port.
|
||||
@@ -1394,7 +1401,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
||||
prt_vector_width += port_width;
|
||||
ptype = PortType::merged(netnet->port_type(), ptype);
|
||||
}
|
||||
inst_scope->add_module_port_info(idx, rmod->get_port_name(idx), ptype, prt_vector_width );
|
||||
inst_scope->add_module_port_info(idx, port_name, ptype, prt_vector_width );
|
||||
}
|
||||
|
||||
// If I find that the port is unconnected inside the
|
||||
@@ -1418,6 +1425,16 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
||||
<< prts[0]->name() << " is coerced to inout." << endl;
|
||||
}
|
||||
|
||||
if (!prts.empty() && (prts[0]->port_type() == NetNet::POUTPUT)
|
||||
&& (prts[0]->type() != NetNet::REG)
|
||||
&& prts[0]->pin(0).nexus()->has_floating_input()
|
||||
&& pins[idx]->is_collapsible_net(des, scope)) {
|
||||
prts[0]->port_type(NetNet::PINOUT);
|
||||
|
||||
cerr << pins[idx]->get_fileline() << ": warning: output port "
|
||||
<< prts[0]->name() << " is coerced to inout." << endl;
|
||||
}
|
||||
|
||||
// Elaborate the expression that connects to the
|
||||
// module[s] port. sig is the thing outside the module
|
||||
// that connects to the port.
|
||||
@@ -1454,8 +1471,9 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
||||
NetExpr*tmp_expr = elab_and_eval(des, scope, pins[idx], -1);
|
||||
if (tmp_expr == 0) {
|
||||
cerr << pins[idx]->get_fileline()
|
||||
<< ": internal error: Port expression "
|
||||
<< "too complicated for elaboration." << endl;
|
||||
<< ": error: Failed to elaborate port expression."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1541,8 +1559,8 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
||||
cerr << pins[idx]->get_fileline() << ": error: "
|
||||
<< "Inout port expression must support "
|
||||
<< "continuous assignment." << endl;
|
||||
cerr << pins[idx]->get_fileline() << ": : "
|
||||
<< "Port " << rmod->ports[idx]->name << " of "
|
||||
cerr << pins[idx]->get_fileline() << ": : Port "
|
||||
<< (idx+1) << " (" << port_name << ") of "
|
||||
<< rmod->mod_name() << " is connected to "
|
||||
<< *pins[idx] << endl;
|
||||
des->errors += 1;
|
||||
@@ -1555,9 +1573,9 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
||||
!prts.empty() && (prts[0]->data_type() != IVL_VT_REAL )) {
|
||||
cerr << pins[idx]->get_fileline() << ": error: "
|
||||
<< "Cannot automatically connect bit based "
|
||||
"inout port " << rmod->ports[idx]->name
|
||||
<< " of module " << rmod->mod_name() << " to real "
|
||||
"signal " << sig->name() << "." << endl;
|
||||
"inout port " << (idx+1) << " (" << port_name
|
||||
<< ") of module " << rmod->mod_name()
|
||||
<< " to real signal " << sig->name() << "." << endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
@@ -1566,9 +1584,8 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
||||
if (!prts.empty() && (prts[0]->data_type() == IVL_VT_REAL )) {
|
||||
cerr << pins[idx]->get_fileline() << ": error: "
|
||||
<< "No support for connecting real inout ports ("
|
||||
"port "
|
||||
<< rmod->ports[idx]->name << " of module "
|
||||
<< rmod->mod_name() << ")." << endl;
|
||||
"port " << (idx+1) << " (" << port_name
|
||||
<< ") of module " << rmod->mod_name() << ")." << endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
@@ -1581,7 +1598,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
||||
|
||||
// Special case: If the output port is an unpacked
|
||||
// array, then there should be no sub-ports and
|
||||
// the passed pexxpression is processed
|
||||
// the passed port expression is processed
|
||||
// differently. Note that we are calling it the
|
||||
// "r-value" expression, but since this is an
|
||||
// output port, we assign to it from the internal object.
|
||||
@@ -1611,8 +1628,8 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
||||
cerr << pins[idx]->get_fileline() << ": error: "
|
||||
<< "Output port expression must support "
|
||||
<< "continuous assignment." << endl;
|
||||
cerr << pins[idx]->get_fileline() << ": : "
|
||||
<< "Port " << rmod->ports[idx]->name << " of "
|
||||
cerr << pins[idx]->get_fileline() << ": : Port "
|
||||
<< (idx+1) << " (" << port_name << ") of "
|
||||
<< rmod->mod_name() << " is connected to "
|
||||
<< *pins[idx] << endl;
|
||||
des->errors += 1;
|
||||
@@ -1687,8 +1704,8 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
||||
instance.size() != 1) {
|
||||
cerr << pins[idx]->get_fileline() << ": error: "
|
||||
<< "An arrayed instance of " << rmod->mod_name()
|
||||
<< " cannot have a real port ("
|
||||
<< rmod->ports[idx]->name << ") connected to a "
|
||||
<< " cannot have a real port (port " << (idx+1)
|
||||
<< " : " << port_name << ") connected to a "
|
||||
"real signal (" << sig->name() << ")." << endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
@@ -1721,8 +1738,9 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: " << get_name()
|
||||
<< ": Port " << (idx+1) << " has vector width of "
|
||||
<< prts_vector_width << "." << endl;
|
||||
<< ": Port " << (idx+1) << " (" << port_name
|
||||
<< ") has vector width of " << prts_vector_width
|
||||
<< "." << endl;
|
||||
}
|
||||
|
||||
// Check that the parts have matching pin counts. If
|
||||
@@ -1730,11 +1748,8 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
||||
// based, but users count parameter positions from 1.
|
||||
if ((instance.size() == 1)
|
||||
&& (prts_vector_width != sig->vector_width())) {
|
||||
const char *tmp3 = rmod->ports[idx]->name.str();
|
||||
bool as_signed = false;
|
||||
|
||||
if (tmp3 == 0) tmp3 = "???";
|
||||
|
||||
switch (prts[0]->port_type()) {
|
||||
case NetNet::POUTPUT:
|
||||
as_signed = prts[0]->get_signed();
|
||||
@@ -1754,7 +1769,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
||||
}
|
||||
|
||||
cerr << get_fileline() << ": warning: Port " << (idx+1)
|
||||
<< " (" << tmp3 << ") of "
|
||||
<< " (" << port_name << ") of "
|
||||
<< type_ << " expects " << prts_vector_width <<
|
||||
" bits, got " << sig->vector_width() << "." << endl;
|
||||
|
||||
@@ -1999,7 +2014,7 @@ void PGModule::elaborate_udp_(Design*des, PUdp*udp, NetScope*scope) const
|
||||
PDelays tmp_del;
|
||||
tmp_del.set_delays(overrides_, false);
|
||||
tmp_del.eval_delays(des, scope, rise_expr, fall_expr,
|
||||
decay_expr);
|
||||
decay_expr, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2282,11 +2297,18 @@ NetAssign_* PAssign_::elaborate_lval(Design*des, NetScope*scope) const
|
||||
PExpr::width_mode_t mode = PExpr::SIZED;
|
||||
rval_->test_width(des, scope, mode);
|
||||
// Create a L-value that matches the function return type.
|
||||
NetNet*tmp;
|
||||
netvector_t*tmp_vec = new netvector_t(rval_->expr_type(),
|
||||
rval_->expr_width()-1, 0,
|
||||
rval_->has_sign());
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::REG, tmp_vec);
|
||||
|
||||
if(rval_->expr_type() == IVL_VT_DARRAY) {
|
||||
netdarray_t*darray = new netdarray_t(tmp_vec);
|
||||
tmp = new NetNet(scope, scope->local_symbol(), NetNet::REG, darray);
|
||||
} else {
|
||||
tmp = new NetNet(scope, scope->local_symbol(), NetNet::REG, tmp_vec);
|
||||
}
|
||||
|
||||
tmp->set_file(rval_->get_file());
|
||||
tmp->set_lineno(rval_->get_lineno());
|
||||
NetAssign_*lv = new NetAssign_(tmp);
|
||||
@@ -2317,7 +2339,8 @@ NetExpr* PAssign_::elaborate_rval_(Design*des, NetScope*scope,
|
||||
NetExpr* PAssign_::elaborate_rval_(Design*des, NetScope*scope,
|
||||
ivl_type_t lv_net_type,
|
||||
ivl_variable_type_t lv_type,
|
||||
unsigned lv_width) const
|
||||
unsigned lv_width,
|
||||
bool force_unsigned) const
|
||||
{
|
||||
ivl_assert(*this, rval_);
|
||||
|
||||
@@ -2326,7 +2349,7 @@ NetExpr* PAssign_::elaborate_rval_(Design*des, NetScope*scope,
|
||||
// should look into fixing calls to this method to pass a
|
||||
// net_type instead of the separate lv_width/lv_type values.
|
||||
NetExpr*rv = elaborate_rval_expr(des, scope, lv_net_type, lv_type, lv_width,
|
||||
rval(), is_constant_);
|
||||
rval(), is_constant_, force_unsigned);
|
||||
|
||||
if (!is_constant_ || !rv) return rv;
|
||||
|
||||
@@ -2444,10 +2467,35 @@ NetProc* PAssign::elaborate_compressed_(Design*des, NetScope*scope) const
|
||||
NetAssign_*lv = elaborate_lval(des, scope);
|
||||
if (lv == 0) return 0;
|
||||
|
||||
NetExpr*rv = elaborate_rval_(des, scope, 0, lv->expr_type(), count_lval_width(lv));
|
||||
// Compressed assignments should behave identically to the
|
||||
// equivalent uncompressed assignments. This means we need
|
||||
// to take the type of the LHS into account when determining
|
||||
// the type of the RHS expression.
|
||||
bool force_unsigned;
|
||||
switch (op_) {
|
||||
case 'l':
|
||||
case 'r':
|
||||
case 'R':
|
||||
// The right-hand operand of shift operations is
|
||||
// self-determined.
|
||||
force_unsigned = false;
|
||||
break;
|
||||
default:
|
||||
force_unsigned = !lv->get_signed();
|
||||
break;
|
||||
}
|
||||
NetExpr*rv = elaborate_rval_(des, scope, 0, lv->expr_type(),
|
||||
count_lval_width(lv), force_unsigned);
|
||||
if (rv == 0) return 0;
|
||||
|
||||
NetAssign*cur = new NetAssign(lv, op_, rv);
|
||||
// The ivl_target API doesn't support signalling the type
|
||||
// of a lval, so convert arithmetic shifts into logical
|
||||
// shifts now if the lval is unsigned.
|
||||
char op = op_;
|
||||
if ((op == 'R') && !lv->get_signed())
|
||||
op = 'r';
|
||||
|
||||
NetAssign*cur = new NetAssign(lv, op, rv);
|
||||
cur->set_line(*this);
|
||||
|
||||
return cur;
|
||||
@@ -2669,11 +2717,16 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
|
||||
return bl;
|
||||
}
|
||||
|
||||
if (lv->enumeration() &&
|
||||
! lv->enumeration()->matches(rv->enumeration())) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "Enumeration type mismatch in assignment." << endl;
|
||||
des->errors += 1;
|
||||
if (lv->enumeration()) {
|
||||
if (! rv->enumeration()) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
"This assignment requires an explicit cast." << endl;
|
||||
des->errors += 1;
|
||||
} else if (! lv->enumeration()->matches(rv->enumeration())) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
"Enumeration type mismatch in assignment." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
}
|
||||
|
||||
NetAssign*cur = new NetAssign(lv, rv);
|
||||
@@ -2860,14 +2913,27 @@ NetProc* PBlock::elaborate(Design*des, NetScope*scope) const
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(nscope);
|
||||
|
||||
elaborate_behaviors_(des, nscope);
|
||||
}
|
||||
|
||||
NetBlock*cur = new NetBlock(type, nscope);
|
||||
|
||||
if (nscope) {
|
||||
// Handle any variable initialization statements in this scope.
|
||||
// For automatic scopes these statements need to be executed
|
||||
// each time the block is entered, so add them to the main
|
||||
// block. For static scopes, put them in a separate process
|
||||
// that will be executed at the start of simulation.
|
||||
if (nscope->is_auto()) {
|
||||
for (unsigned idx = 0; idx < var_inits.size(); idx += 1) {
|
||||
NetProc*tmp = var_inits[idx]->elaborate(des, nscope);
|
||||
if (tmp) cur->append(tmp);
|
||||
}
|
||||
} else {
|
||||
elaborate_var_inits_(des, nscope);
|
||||
}
|
||||
}
|
||||
|
||||
if (nscope == 0)
|
||||
nscope = scope;
|
||||
|
||||
@@ -3720,7 +3786,7 @@ NetProc* PCallTask::elaborate_build_call_(Design*des, NetScope*scope,
|
||||
|
||||
NetExpr*rv = 0;
|
||||
|
||||
if (parms_idx<parms_.size() && parms_[parms_idx]) {
|
||||
if (parms_idx < parms_.size() && parms_[parms_idx]) {
|
||||
rv = elaborate_rval_expr(des, scope, port->net_type(),
|
||||
lv_type, wid, parms_ [parms_idx]);
|
||||
if (NetEEvent*evt = dynamic_cast<NetEEvent*> (rv)) {
|
||||
@@ -3735,7 +3801,7 @@ NetProc* PCallTask::elaborate_build_call_(Design*des, NetScope*scope,
|
||||
if (! gn_system_verilog()) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "Found (and using) default task expression "
|
||||
<< " requires SystemVerilog." << endl;
|
||||
"requires SystemVerilog." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
rv = def->port_defe(idx);
|
||||
@@ -3770,7 +3836,9 @@ NetProc* PCallTask::elaborate_build_call_(Design*des, NetScope*scope,
|
||||
expression that can be a target to a procedural
|
||||
assignment, including a memory word. */
|
||||
|
||||
for (unsigned idx = 0 ; idx < parm_count ; idx += 1) {
|
||||
for (unsigned idx = use_this?1:0 ; idx < parm_count ; idx += 1) {
|
||||
|
||||
size_t parms_idx = use_this? idx-1 : idx;
|
||||
|
||||
NetNet*port = def->port(idx);
|
||||
|
||||
@@ -3782,20 +3850,24 @@ NetProc* PCallTask::elaborate_build_call_(Design*des, NetScope*scope,
|
||||
|
||||
/* Elaborate an l-value version of the port expression
|
||||
for output and inout ports. If the expression does
|
||||
not exist then quietly skip it, but if the expression
|
||||
is not a valid l-value print an error message. Note
|
||||
that the elaborate_lval method already printed a
|
||||
detailed message. */
|
||||
NetAssign_*lv;
|
||||
if (parms_[idx]) {
|
||||
lv = parms_[idx]->elaborate_lval(des, scope, false, false);
|
||||
not exist or is not a valid l-value print an error
|
||||
message. Note that the elaborate_lval method already
|
||||
printed a detailed message for the latter case. */
|
||||
NetAssign_*lv = 0;
|
||||
if (parms_idx < parms_.size() && parms_[parms_idx]) {
|
||||
lv = parms_[parms_idx]->elaborate_lval(des, scope, false, false);
|
||||
if (lv == 0) {
|
||||
cerr << parms_[idx]->get_fileline() << ": error: "
|
||||
cerr << parms_[parms_idx]->get_fileline() << ": error: "
|
||||
<< "I give up on task port " << (idx+1)
|
||||
<< " expression: " << *parms_[idx] << endl;
|
||||
<< " expression: " << *parms_[parms_idx] << endl;
|
||||
}
|
||||
} else {
|
||||
lv = 0;
|
||||
} else if (port->port_type() == NetNet::POUTPUT) {
|
||||
// Output ports were skipped earlier, so
|
||||
// report the error now.
|
||||
cerr << get_fileline() << ": error: "
|
||||
<< "Missing argument " << (idx+1)
|
||||
<< " of call to task." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
if (lv == 0)
|
||||
@@ -4027,9 +4099,18 @@ NetProc* PDisable::elaborate(Design*des, NetScope*scope) const
|
||||
*/
|
||||
NetProc* PDoWhile::elaborate(Design*des, NetScope*scope) const
|
||||
{
|
||||
NetExpr*tmp = elab_and_eval(des, scope, cond_, -1);
|
||||
tmp->set_line(*this);
|
||||
NetDoWhile*loop = new NetDoWhile(tmp, statement_->elaborate(des, scope));
|
||||
NetExpr*ce = elab_and_eval(des, scope, cond_, -1);
|
||||
NetProc*sub;
|
||||
if (statement_)
|
||||
sub = statement_->elaborate(des, scope);
|
||||
else
|
||||
sub = new NetBlock(NetBlock::SEQU, 0);
|
||||
if (ce == 0 || sub == 0) {
|
||||
delete ce;
|
||||
delete sub;
|
||||
return 0;
|
||||
}
|
||||
NetDoWhile*loop = new NetDoWhile(ce, sub);
|
||||
loop->set_line(*this);
|
||||
return loop;
|
||||
}
|
||||
@@ -4560,7 +4641,11 @@ NetProc* PEventStatement::elaborate(Design*des, NetScope*scope) const
|
||||
*/
|
||||
NetProc* PForever::elaborate(Design*des, NetScope*scope) const
|
||||
{
|
||||
NetProc*stat = statement_->elaborate(des, scope);
|
||||
NetProc*stat;
|
||||
if (statement_)
|
||||
stat = statement_->elaborate(des, scope);
|
||||
else
|
||||
stat = new NetBlock(NetBlock::SEQU, 0);
|
||||
if (stat == 0) return 0;
|
||||
|
||||
NetForever*proc = new NetForever(stat);
|
||||
@@ -4766,7 +4851,11 @@ NetProc* PForeach::elaborate(Design*des, NetScope*scope) const
|
||||
|
||||
/* Elaborate the statement that is contained in the foreach
|
||||
loop. */
|
||||
NetProc*sub = statement_->elaborate(des, scope);
|
||||
NetProc*sub;
|
||||
if (statement_)
|
||||
sub = statement_->elaborate(des, scope);
|
||||
else
|
||||
sub = new NetBlock(NetBlock::SEQU, 0);
|
||||
|
||||
/* Make a step statement: idx += 1 */
|
||||
NetAssign_*idx_lv = new NetAssign_(idx_sig);
|
||||
@@ -4797,7 +4886,11 @@ NetProc* PForeach::elaborate_static_array_(Design*des, NetScope*scope,
|
||||
ivl_assert(*this, index_vars_.size() > 0);
|
||||
ivl_assert(*this, dims.size() == index_vars_.size());
|
||||
|
||||
NetProc*sub = statement_->elaborate(des, scope);
|
||||
NetProc*sub;
|
||||
if (statement_)
|
||||
sub = statement_->elaborate(des, scope);
|
||||
else
|
||||
sub = new NetBlock(NetBlock::SEQU, 0);
|
||||
NetForLoop*stmt = 0;
|
||||
|
||||
for (int idx_idx = index_vars_.size()-1 ; idx_idx >= 0 ; idx_idx -= 1) {
|
||||
@@ -4882,7 +4975,7 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const
|
||||
sig->data_type(), sig->vector_width(),
|
||||
expr1_);
|
||||
|
||||
if (debug_elaborate) {
|
||||
if (debug_elaborate && initial_expr) {
|
||||
cerr << get_fileline() << ": debug: FOR initial assign: "
|
||||
<< sig->name() << " = " << *initial_expr << endl;
|
||||
}
|
||||
@@ -4891,36 +4984,35 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const
|
||||
loop. If there is an error, this will return 0 and I should
|
||||
skip the append. No need to worry, the error has been
|
||||
reported so it's OK that the netlist is bogus. */
|
||||
NetProc*sub = statement_->elaborate(des, scope);
|
||||
|
||||
NetProc*sub;
|
||||
if (statement_)
|
||||
sub = statement_->elaborate(des, scope);
|
||||
else
|
||||
sub = new NetBlock(NetBlock::SEQU, 0);
|
||||
|
||||
/* Now elaborate the for_step statement. I really should do
|
||||
some error checking here to make sure the step statement
|
||||
really does step the variable. */
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": debug: Elaborate for_step statement "
|
||||
<< sig->name() << " = " << *initial_expr << endl;
|
||||
}
|
||||
|
||||
NetProc*step = step_->elaborate(des, scope);
|
||||
|
||||
|
||||
/* Elaborate the condition expression. Try to evaluate it too,
|
||||
in case it is a constant. This is an interesting case
|
||||
worthy of a warning. */
|
||||
NetExpr*ce = elab_and_eval(des, scope, cond_, -1);
|
||||
if (ce == 0) {
|
||||
delete sub;
|
||||
delete step;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dynamic_cast<NetEConst*>(ce)) {
|
||||
cerr << get_fileline() << ": warning: condition expression "
|
||||
"of for-loop is constant." << endl;
|
||||
}
|
||||
|
||||
|
||||
/* Error recovery - if we failed to elaborate any of the loop
|
||||
expressions, give up now. */
|
||||
if (initial_expr == 0 || ce == 0 || step == 0 || sub == 0) {
|
||||
delete initial_expr;
|
||||
delete ce;
|
||||
delete step;
|
||||
delete sub;
|
||||
return 0;
|
||||
}
|
||||
/* All done, build up the loop. */
|
||||
|
||||
NetForLoop*loop = new NetForLoop(sig, initial_expr, ce, sub, step);
|
||||
@@ -4965,7 +5057,6 @@ void PFunction::elaborate(Design*des, NetScope*scope) const
|
||||
des->errors += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
assert(def);
|
||||
|
||||
ivl_assert(*this, statement_);
|
||||
@@ -4978,6 +5069,31 @@ void PFunction::elaborate(Design*des, NetScope*scope) const
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle any variable initialization statements in this scope.
|
||||
// For automatic functions, these statements need to be executed
|
||||
// each time the function is called, so insert them at the start
|
||||
// of the elaborated definition. For static functions, put them
|
||||
// in a separate process that will be executed before the start
|
||||
// of simulation.
|
||||
if (is_auto_) {
|
||||
// Get the NetBlock of the statement. If it is not a
|
||||
// NetBlock then create one to wrap the initialization
|
||||
// statements and the original statement.
|
||||
NetBlock*blk = dynamic_cast<NetBlock*> (st);
|
||||
if ((blk == 0) && (var_inits.size() > 0)) {
|
||||
blk = new NetBlock(NetBlock::SEQU, scope);
|
||||
blk->set_line(*this);
|
||||
blk->append(st);
|
||||
st = blk;
|
||||
}
|
||||
for (unsigned idx = var_inits.size(); idx > 0; idx -= 1) {
|
||||
NetProc*tmp = var_inits[idx-1]->elaborate(des, scope);
|
||||
if (tmp) blk->prepend(tmp);
|
||||
}
|
||||
} else {
|
||||
elaborate_var_inits_(des, scope);
|
||||
}
|
||||
|
||||
def->set_proc(st);
|
||||
}
|
||||
|
||||
@@ -5013,8 +5129,16 @@ NetProc* PRepeat::elaborate(Design*des, NetScope*scope) const
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
// If the expression is real, convert to an integer. 64 bits
|
||||
// should be more enough for any real use case.
|
||||
if (expr->expr_type() == IVL_VT_REAL)
|
||||
expr = cast_to_int4(expr, 64);
|
||||
|
||||
NetProc*stat = statement_->elaborate(des, scope);
|
||||
NetProc*stat;
|
||||
if (statement_)
|
||||
stat = statement_->elaborate(des, scope);
|
||||
else
|
||||
stat = new NetBlock(NetBlock::SEQU, 0);
|
||||
if (stat == 0) return 0;
|
||||
|
||||
// If the expression is a constant, handle certain special
|
||||
@@ -5132,11 +5256,6 @@ NetProc* PReturn::elaborate(Design*des, NetScope*scope) const
|
||||
|
||||
void PTask::elaborate(Design*des, NetScope*task) const
|
||||
{
|
||||
// Elaborate any processes that are part of this scope that
|
||||
// aren't the definition itself. This can happen, for example,
|
||||
// with variable initialization statements in this scope.
|
||||
elaborate_behaviors_(des, task);
|
||||
|
||||
NetTaskDef*def = task->task_def();
|
||||
assert(def);
|
||||
|
||||
@@ -5155,6 +5274,31 @@ void PTask::elaborate(Design*des, NetScope*task) const
|
||||
}
|
||||
}
|
||||
|
||||
// Handle any variable initialization statements in this scope.
|
||||
// For automatic tasks , these statements need to be executed
|
||||
// each time the task is called, so insert them at the start
|
||||
// of the elaborated definition. For static tasks, put them
|
||||
// in a separate process that will be executed before the start
|
||||
// of simulation.
|
||||
if (is_auto_) {
|
||||
// Get the NetBlock of the statement. If it is not a
|
||||
// NetBlock then create one to wrap the initialization
|
||||
// statements and the original statement.
|
||||
NetBlock*blk = dynamic_cast<NetBlock*> (st);
|
||||
if ((blk == 0) && (var_inits.size() > 0)) {
|
||||
blk = new NetBlock(NetBlock::SEQU, task);
|
||||
blk->set_line(*this);
|
||||
blk->append(st);
|
||||
st = blk;
|
||||
}
|
||||
for (unsigned idx = var_inits.size(); idx > 0; idx -= 1) {
|
||||
NetProc*tmp = var_inits[idx-1]->elaborate(des, task);
|
||||
if (tmp) blk->prepend(tmp);
|
||||
}
|
||||
} else {
|
||||
elaborate_var_inits_(des, task);
|
||||
}
|
||||
|
||||
def->set_proc(st);
|
||||
}
|
||||
|
||||
@@ -5193,9 +5337,18 @@ NetProc* PTrigger::elaborate(Design*des, NetScope*scope) const
|
||||
*/
|
||||
NetProc* PWhile::elaborate(Design*des, NetScope*scope) const
|
||||
{
|
||||
NetExpr*tmp = elab_and_eval(des, scope, cond_, -1);
|
||||
tmp->set_line(*this);
|
||||
NetWhile*loop = new NetWhile(tmp, statement_->elaborate(des, scope));
|
||||
NetExpr*ce = elab_and_eval(des, scope, cond_, -1);
|
||||
NetProc*sub;
|
||||
if (statement_)
|
||||
sub = statement_->elaborate(des, scope);
|
||||
else
|
||||
sub = new NetBlock(NetBlock::SEQU, 0);
|
||||
if (ce == 0 || sub == 0) {
|
||||
delete ce;
|
||||
delete sub;
|
||||
return 0;
|
||||
}
|
||||
NetWhile*loop = new NetWhile(ce, sub);
|
||||
loop->set_line(*this);
|
||||
return loop;
|
||||
}
|
||||
@@ -5602,6 +5755,10 @@ bool Module::elaborate(Design*des, NetScope*scope) const
|
||||
(*gt)->elaborate(des, scope);
|
||||
}
|
||||
|
||||
// Elaborate the variable initialization statements, making a
|
||||
// single initial process out of them.
|
||||
result_flag &= elaborate_var_inits_(des, scope);
|
||||
|
||||
// Elaborate the behaviors, making processes out of them. This
|
||||
// involves scanning the PProcess* list, creating a NetProcTop
|
||||
// for each process.
|
||||
@@ -5679,6 +5836,9 @@ bool PGenerate::elaborate(Design*des, NetScope*container) const
|
||||
"generate " << scheme_type
|
||||
<< " elaborating in scope " << scope_path(container)
|
||||
<< "." << endl;
|
||||
cerr << get_fileline() << ": PGenerate::elaborate: "
|
||||
"generate scope_name=" << scope_name
|
||||
<< ", id_number=" << id_number << endl;
|
||||
}
|
||||
|
||||
// Handle the special case that this is a CASE scheme. In this
|
||||
@@ -5713,6 +5873,7 @@ bool PGenerate::elaborate(Design*des, NetScope*container) const
|
||||
// scheme defined in the Verilog-2005 standard.
|
||||
const char*name = scope_name.str();
|
||||
if (name[0] == '$') {
|
||||
|
||||
if (!scope->auto_name("genblk", '0', name + 4)) {
|
||||
cerr << get_fileline() << ": warning: Couldn't build"
|
||||
<< " unique name for unnamed generate block"
|
||||
@@ -5788,6 +5949,8 @@ bool PGenerate::elaborate_(Design*des, NetScope*scope) const
|
||||
for (gates_it_t cur = gates.begin() ; cur != gates.end() ; ++ cur )
|
||||
(*cur)->elaborate(des, scope);
|
||||
|
||||
elaborate_var_inits_(des, scope);
|
||||
|
||||
typedef list<PProcess*>::const_iterator proc_it_t;
|
||||
for (proc_it_t cur = behaviors.begin(); cur != behaviors.end(); ++ cur )
|
||||
(*cur)->elaborate(des, scope);
|
||||
@@ -5823,6 +5986,44 @@ bool PScope::elaborate_behaviors_(Design*des, NetScope*scope) const
|
||||
return result_flag;
|
||||
}
|
||||
|
||||
bool LexicalScope::elaborate_var_inits_(Design*des, NetScope*scope) const
|
||||
{
|
||||
if (var_inits.size() == 0)
|
||||
return true;
|
||||
|
||||
NetProc*proc = 0;
|
||||
if (var_inits.size() == 1) {
|
||||
proc = var_inits[0]->elaborate(des, scope);
|
||||
} else {
|
||||
NetBlock*blk = new NetBlock(NetBlock::SEQU, 0);
|
||||
bool flag = true;
|
||||
for (unsigned idx = 0; idx < var_inits.size(); idx += 1) {
|
||||
NetProc*tmp = var_inits[idx]->elaborate(des, scope);
|
||||
if (tmp)
|
||||
blk->append(tmp);
|
||||
else
|
||||
flag = false;
|
||||
}
|
||||
if (flag) proc = blk;
|
||||
}
|
||||
if (proc == 0)
|
||||
return false;
|
||||
|
||||
NetProcTop*top = new NetProcTop(scope, IVL_PR_INITIAL, proc);
|
||||
if (const LineInfo*li = dynamic_cast<const LineInfo*>(this)) {
|
||||
top->set_line(*li);
|
||||
}
|
||||
if (gn_system_verilog()) {
|
||||
top->attribute(perm_string::literal("_ivl_schedule_init"),
|
||||
verinum(1));
|
||||
}
|
||||
des->add_process(top);
|
||||
|
||||
scope->set_var_init(proc);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
class elaborate_package_t : public elaborator_work_item_t {
|
||||
public:
|
||||
elaborate_package_t(Design*d, NetScope*scope, PPackage*p)
|
||||
@@ -6056,6 +6257,7 @@ Design* elaborate(list<perm_string>roots)
|
||||
ivl_assert(*pac->second, pac->first == pac->second->pscope_name());
|
||||
NetScope*scope = des->make_package_scope(pac->first);
|
||||
scope->set_line(pac->second);
|
||||
set_scope_timescale(des, scope, pac->second);
|
||||
|
||||
elaborator_work_item_t*es = new elaborate_package_t(des, scope, pac->second);
|
||||
des->elaboration_work_list.push_back(es);
|
||||
@@ -6086,16 +6288,13 @@ Design* elaborate(list<perm_string>roots)
|
||||
|
||||
// Make the root scope. This makes a NetScope object and
|
||||
// pushes it into the list of root scopes in the Design.
|
||||
NetScope*scope = des->make_root_scope(*root, rmod->program_block);
|
||||
NetScope*scope = des->make_root_scope(*root, rmod->program_block,
|
||||
rmod->is_interface);
|
||||
|
||||
// Collect some basic properties of this scope from the
|
||||
// Module definition.
|
||||
scope->set_line(rmod);
|
||||
scope->time_unit(rmod->time_unit);
|
||||
scope->time_precision(rmod->time_precision);
|
||||
scope->time_from_timescale(rmod->time_from_timescale);
|
||||
des->set_precision(rmod->time_precision);
|
||||
|
||||
set_scope_timescale(des, scope, rmod);
|
||||
|
||||
// Save this scope, along with its definition, in the
|
||||
// "root_elems" list for later passes.
|
||||
|
||||
@@ -507,7 +507,6 @@ int Design::emit(struct target_t*tgt) const
|
||||
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
|
||||
@@ -521,7 +520,6 @@ int Design::emit(struct target_t*tgt) const
|
||||
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
|
||||
@@ -548,6 +546,12 @@ int Design::emit(struct target_t*tgt) const
|
||||
|
||||
// emit task and function definitions
|
||||
bool tasks_rc = true;
|
||||
for (map<NetScope*,PTaskFunc*>::const_iterator scope = root_tasks_.begin()
|
||||
; scope != root_tasks_.end() ; ++ scope)
|
||||
tasks_rc &= scope->first->emit_defs(tgt);
|
||||
for (map<perm_string,netclass_t*>::const_iterator cur = classes_.begin()
|
||||
; cur != classes_.end() ; ++cur)
|
||||
tasks_rc &= cur->second->emit_defs(tgt);
|
||||
for (map<perm_string,NetScope*>::const_iterator scope = packages_.begin()
|
||||
; scope != packages_.end() ; ++ scope )
|
||||
tasks_rc &= scope->second->emit_defs(tgt);
|
||||
|
||||
+14
-3
@@ -697,7 +697,9 @@ NetEConst* NetEBComp::eval_eqeqeq_(bool ne_flag, const NetExpr*le, const NetExpr
|
||||
// If the left value is longer check it against the pad bit.
|
||||
if (res == verinum::V1) {
|
||||
verinum::V pad = verinum::V0;
|
||||
if (is_signed) pad = rv.get(rv.len()-1);
|
||||
if (is_signed)
|
||||
pad = rv.get(rv.len()-1);
|
||||
|
||||
for (unsigned idx = cnt ; idx < lv.len() ; idx += 1)
|
||||
if (lv.get(idx) != pad) {
|
||||
res = verinum::V0;
|
||||
@@ -708,12 +710,15 @@ NetEConst* NetEBComp::eval_eqeqeq_(bool ne_flag, const NetExpr*le, const NetExpr
|
||||
// If the right value is longer check it against the pad bit.
|
||||
if (res == verinum::V1) {
|
||||
verinum::V pad = verinum::V0;
|
||||
if (is_signed) pad = lv.get(lv.len()-1);
|
||||
if (is_signed)
|
||||
pad = lv.get(lv.len()-1);
|
||||
|
||||
for (unsigned idx = cnt ; idx < rv.len() ; idx += 1) {
|
||||
if (rv.get(idx) != pad)
|
||||
if (rv.get(idx) != pad) {
|
||||
res = verinum::V0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ne_flag) {
|
||||
@@ -2009,6 +2014,12 @@ static bool check_dimension(const NetExpr*dim_expr, long &dim)
|
||||
static bool get_array_info(const NetExpr*arg, long dim,
|
||||
long &left, long &right, bool&defer)
|
||||
{
|
||||
if (const NetEConstParam*param = dynamic_cast<const NetEConstParam*>(arg)) {
|
||||
assert(dim == 1);
|
||||
left = param->expr_width() - 1;
|
||||
right = 0;
|
||||
return false;
|
||||
}
|
||||
/* The argument must be a signal that has enough dimensions. */
|
||||
const NetESignal*esig = dynamic_cast<const NetESignal*>(arg);
|
||||
if (esig == 0) return true;
|
||||
|
||||
+20
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2013 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2015 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
|
||||
@@ -1138,18 +1138,29 @@ NetNet* NetESelect::synthesize(Design *des, NetScope*scope, NetExpr*root)
|
||||
if (sub->vector_width() == expr_width())
|
||||
return sub;
|
||||
|
||||
// The vector_width is not exactly right, so the source is
|
||||
// probably asking for padding. Create nodes to do sign
|
||||
// extension or 0 extension, depending on the has_sign() mode
|
||||
// of the expression.
|
||||
|
||||
netvector_t*net_vec = new netvector_t(expr_type(), expr_width()-1, 0);
|
||||
net_vec->set_signed(has_sign());
|
||||
NetNet*net = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, net_vec);
|
||||
net->set_line(*this);
|
||||
net->local_flag(true);
|
||||
if (has_sign()) {
|
||||
|
||||
// It may still happen that the expression is wider than the selection,
|
||||
// and there was no part select created earlier (size casting).
|
||||
if(expr_width() < sub->vector_width()) {
|
||||
NetPartSelect*sel = new NetPartSelect(sub, 0, expr_width(),
|
||||
NetPartSelect::VP, has_sign());
|
||||
sel->set_line(*this);
|
||||
des->add_node(sel);
|
||||
|
||||
connect(net->pin(0), sel->pin(0));
|
||||
|
||||
// The vector_width is not exactly right, so the source is
|
||||
// probably asking for padding. Create nodes to do sign
|
||||
// extension or 0 extension, depending on the has_sign() mode
|
||||
// of the expression.
|
||||
|
||||
} else if (has_sign()) {
|
||||
NetSignExtend*pad = new NetSignExtend(scope,
|
||||
scope->local_symbol(),
|
||||
expr_width());
|
||||
@@ -1166,7 +1177,6 @@ NetNet* NetESelect::synthesize(Design *des, NetScope*scope, NetExpr*root)
|
||||
cat->set_line(*this);
|
||||
des->add_node(cat);
|
||||
|
||||
assert(expr_width() > sub->vector_width());
|
||||
unsigned pad_width = expr_width() - sub->vector_width();
|
||||
verinum pad((uint64_t)0, pad_width);
|
||||
NetConst*con = new NetConst(scope, scope->local_symbol(),
|
||||
@@ -1278,6 +1288,8 @@ NetNet* NetESignal::synthesize(Design*des, NetScope*scope, NetExpr*root)
|
||||
net_->vector_width()-1, 0);
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, tmp_vec);
|
||||
tmp->set_line(*this);
|
||||
tmp->local_flag(true);
|
||||
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);
|
||||
|
||||
+39
-47
@@ -1,10 +1,10 @@
|
||||
.TH iverilog-vpi 1 "April 17th, 2009" "" "Version %M.%m.%n %E"
|
||||
.TH iverilog-vpi 1 "Jan 29th, 2017" "" "Version %M.%n%E"
|
||||
.SH NAME
|
||||
iverilog-vpi - Compile front end for VPI modules
|
||||
|
||||
.SH SYNOPSIS
|
||||
.B iverilog-vpi
|
||||
[\-\-name=\fIname\fP]
|
||||
[options]
|
||||
\fIsourcefile\fP...
|
||||
|
||||
.SH DESCRIPTION
|
||||
@@ -15,9 +15,9 @@ list of C or C++ source files, and generates as output a linked VPI
|
||||
module. See the \fBvvp\fP(1) man page for a description of how the
|
||||
linked module is loaded by a simulation.
|
||||
|
||||
The output is named after the first source file. For example, if the
|
||||
first source file is named \fIfoo.c\fP, the output becomes
|
||||
\fIfoo.vpi\fP.
|
||||
By default the output is named after the first source file. For
|
||||
example, if the first source file is named \fIfoo.c\fP, the output
|
||||
becomes \fIfoo.vpi\fP.
|
||||
|
||||
.SH OPTIONS
|
||||
\fIiverilog\-vpi\fP accepts the following options:
|
||||
@@ -26,10 +26,15 @@ first source file is named \fIfoo.c\fP, the output becomes
|
||||
Include the named library in the link of the VPI module. This allows
|
||||
VPI modules to further reference external libraries.
|
||||
|
||||
.TP 8
|
||||
.B -L\fIdirectory\fP
|
||||
Add \fIdirectory\fP to the list of directories that will be searched
|
||||
for library files.
|
||||
|
||||
.TP 8
|
||||
.B -I\fIdirectory\fP
|
||||
Add \fIdirectory\fP to the list of directories that will be search for
|
||||
header files.
|
||||
Add \fIdirectory\fP to the list of directories that will be searched
|
||||
for header files.
|
||||
|
||||
.TP 8
|
||||
.B -D\fIdefine\fP
|
||||
@@ -41,46 +46,38 @@ Normally, the output VPI module will be named after the first source
|
||||
file passed to the command. This flag sets the name (without the .vpi
|
||||
suffix) of the output vpi module.
|
||||
|
||||
.TP 8
|
||||
.B --install-dir
|
||||
This flag causes the program to print the install directory for VPI
|
||||
modules, then exit. It is a convenience for makefiles or automated
|
||||
plug-in installers.
|
||||
|
||||
.TP 8
|
||||
.B --cflags, --ldflags and --ldlibs
|
||||
These flags provide compile time information.
|
||||
|
||||
.SH "PC-ONLY OPTIONS"
|
||||
|
||||
The PC port of \fIiverilog\-vpi\fP includes two special flags needed to
|
||||
support the more intractable development environment. These flags help
|
||||
the program locate parts that it needs.
|
||||
When built as a native Windows program (using the MinGW toolchain),
|
||||
by default \fIiverilog\-vpi\fP will attempt to locate the MinGW tools
|
||||
needed to compile a VPI module on the system path (as set by the PATH
|
||||
environment variable). As an alternative, the user may specify the
|
||||
location of the MinGW tools via the following option.
|
||||
|
||||
.TP 8
|
||||
.B -mingw=\fIpath\fP
|
||||
Tell the program the root of the Mingw compiler tool suite. The
|
||||
Tell the program the root of the MinGW compiler tool suite. The
|
||||
\fBvvp\fP runtime is compiled with this compiler, and this is the
|
||||
compiler that \fIiverilog\-vpi\fP expects to use to compile your source
|
||||
code. This is normally not needed, and if you do use it, it is only
|
||||
needed once. The compiler will save the \fIpath\fP in the registry for
|
||||
use later.
|
||||
compiler that \fIiverilog\-vpi\fP expects to use to compile your
|
||||
source code. If this option accompanies a list of files, it will
|
||||
apply to the current build only. If this option is provided on its
|
||||
own, \fIiverilog\-vpi\fP will save the \fIpath\fP in the registry
|
||||
and use that path in preference to the system path for subsequent
|
||||
operations, avoiding the need to specify it on the command line
|
||||
every time.
|
||||
|
||||
.SH "INFORMATIONAL OPTIONS"
|
||||
|
||||
\fIiverilog\-vpi\fP includes additional flags to let Makefile gurus
|
||||
peek at the configuration of the \fIiverilog\fP installation. This way,
|
||||
Makefiles can be written that handle complex VPI builds natively, and
|
||||
without hard-coding values that depend on the system and installation.
|
||||
If used at all, these options must be used one at a time, and without
|
||||
any other options or directives.
|
||||
|
||||
.TP 8
|
||||
.B -ivl=\fIpath\fP
|
||||
Set for the use during compilation the root if the Icarus Verilog
|
||||
install. This is the place where you installed Icarus Verilog when you
|
||||
ran the installer. This flag is also only needed once, and the path is
|
||||
stored in the registry for future use.
|
||||
|
||||
.SH "UNIX-ONLY OPTIONS"
|
||||
|
||||
The UNIX version of \fIiverilog\-vpi\fP includes additional flags to
|
||||
let Makefile gurus peek at the configuration of the \fIiverilog\fP
|
||||
installation. This way, Makefiles can be written that handle complex VPI
|
||||
builds natively, and without hard-coding values that depend on the
|
||||
system and installation. If used at all, these options must be
|
||||
used one at a time, and without any other options or directives.
|
||||
.B --install-dir
|
||||
Print the install directory for VPI modules.
|
||||
|
||||
.TP 8
|
||||
.B --cflags
|
||||
@@ -95,11 +92,6 @@ Print the linker flags (LDFLAGS) needed to link a VPI module.
|
||||
.B --ldlibs
|
||||
Print the libraries (LDLIBS) needed to link a VPI module.
|
||||
|
||||
.TP 8
|
||||
.B -m32
|
||||
On 64bit systems that support it (and support vvp32) this flag
|
||||
requests a 32bit vpi binary instead of the default 64bit binary.
|
||||
|
||||
.P
|
||||
Example GNU makefile that takes advantage of these flags:
|
||||
.IP "" 4
|
||||
@@ -123,12 +115,12 @@ Steve Williams ([email protected])
|
||||
|
||||
.SH SEE ALSO
|
||||
iverilog(1), vvp(1),
|
||||
.BR "<http://www.icarus.com/eda/verilog/>",
|
||||
.BR "<http://www.mingw.org>",
|
||||
.BR "<http://iverilog.icarus.com/>",
|
||||
.BR "<http://mingw-w64.yaxm.org/>",
|
||||
|
||||
.SH COPYRIGHT
|
||||
.nf
|
||||
Copyright \(co 2002\-2009 Stephen Williams
|
||||
Copyright \(co 2002\-2017 Stephen Williams
|
||||
|
||||
This document can be freely redistributed according to the terms of the
|
||||
GNU General Public License version 2.0
|
||||
|
||||
+5
-1
@@ -35,6 +35,7 @@ CCSRC=
|
||||
CXSRC=
|
||||
OBJ=
|
||||
LIB=
|
||||
LIBDIR=
|
||||
OUT=
|
||||
INCOPT=
|
||||
DEFS=
|
||||
@@ -81,6 +82,9 @@ do
|
||||
-l*) LIB="$LIB $parm"
|
||||
;;
|
||||
|
||||
-L*) LIBDIR="$LIBDIR $parm"
|
||||
;;
|
||||
|
||||
-I*) INCOPT="$INCOPT $parm"
|
||||
;;
|
||||
|
||||
@@ -148,4 +152,4 @@ then
|
||||
fi
|
||||
|
||||
echo "Making $OUT from $OBJ..."
|
||||
exec $LD -o $OUT $LDFLAGS $OBJ $LIB $LDLIBS
|
||||
exec $LD -o $OUT $LDFLAGS $LIBDIR $OBJ $LIB $LDLIBS
|
||||
|
||||
@@ -125,6 +125,7 @@ ivl_lpm_enable
|
||||
ivl_lpm_file
|
||||
ivl_lpm_lineno
|
||||
ivl_lpm_name
|
||||
ivl_lpm_negedge
|
||||
ivl_lpm_q
|
||||
ivl_lpm_scope
|
||||
ivl_lpm_select
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
# include <stdio.h>
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__)
|
||||
/*
|
||||
* Define a safer version of malloc().
|
||||
*/
|
||||
@@ -82,5 +83,6 @@
|
||||
} \
|
||||
__ivl_rtn; \
|
||||
})
|
||||
#endif
|
||||
|
||||
#endif /* IVL_ivl_alloc_H */
|
||||
|
||||
+17
-8
@@ -1,7 +1,7 @@
|
||||
#ifndef IVL_ivl_target_H
|
||||
#define IVL_ivl_target_H
|
||||
/*
|
||||
* Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2015 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
|
||||
@@ -41,6 +41,12 @@
|
||||
# define __attribute__(x)
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus) && defined(_MSC_VER)
|
||||
# define ENUM_UNSIGNED_INT : unsigned int
|
||||
#else
|
||||
# define ENUM_UNSIGNED_INT
|
||||
#endif
|
||||
|
||||
_BEGIN_DECL
|
||||
|
||||
/*
|
||||
@@ -201,7 +207,7 @@ typedef enum ivl_dis_domain_e {
|
||||
IVL_DIS_CONTINUOUS = 2
|
||||
} ivl_dis_domain_t;
|
||||
|
||||
typedef enum ivl_drive_e {
|
||||
typedef enum ivl_drive_e ENUM_UNSIGNED_INT {
|
||||
IVL_DR_HiZ = 0,
|
||||
IVL_DR_SMALL = 1,
|
||||
IVL_DR_MEDIUM = 2,
|
||||
@@ -243,7 +249,7 @@ typedef enum ivl_expr_type_e {
|
||||
IVL_EX_UNARY = 14
|
||||
} ivl_expr_type_t;
|
||||
|
||||
typedef enum ivl_select_type_e {
|
||||
typedef enum ivl_select_type_e ENUM_UNSIGNED_INT {
|
||||
IVL_SEL_OTHER = 0,
|
||||
IVL_SEL_IDX_UP = 1,
|
||||
IVL_SEL_IDX_DOWN = 2
|
||||
@@ -300,7 +306,7 @@ typedef enum ivl_lpm_type_e {
|
||||
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_EQX= 37, /* Wildcard EQ (==?) */
|
||||
IVL_LPM_CMP_EQZ= 38, /* casez EQ */
|
||||
IVL_LPM_CMP_EQ = 10,
|
||||
IVL_LPM_CMP_GE = 1,
|
||||
@@ -345,7 +351,7 @@ typedef enum ivl_path_edge_e {
|
||||
|
||||
/* Processes are initial, always, or final blocks with a statement. This is
|
||||
the type of the ivl_process_t object. */
|
||||
typedef enum ivl_process_type_e {
|
||||
typedef enum ivl_process_type_e ENUM_UNSIGNED_INT {
|
||||
IVL_PR_INITIAL = 0,
|
||||
IVL_PR_ALWAYS = 1,
|
||||
IVL_PR_FINAL = 2
|
||||
@@ -431,7 +437,7 @@ typedef enum ivl_sfunc_as_task_e {
|
||||
|
||||
/* This is the type of a variable, and also used as the type for an
|
||||
expression. */
|
||||
typedef enum ivl_variable_type_e {
|
||||
typedef enum ivl_variable_type_e ENUM_UNSIGNED_INT {
|
||||
IVL_VT_VOID = 0, /* Not used */
|
||||
IVL_VT_NO_TYPE = 1, /* Place holder for missing/unknown type. */
|
||||
IVL_VT_REAL = 2,
|
||||
@@ -1285,8 +1291,8 @@ 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
|
||||
* The EQX and EQZ nodes are wildcard compares, where xz bits (EQX) or
|
||||
* z bits (EQZ) in the data(1) operand are treated as wildcards. no
|
||||
* bits in the data(0) operand are wild. This matches the
|
||||
* SystemVerilog convention for the ==? operator.
|
||||
*
|
||||
@@ -1418,6 +1424,7 @@ extern ivl_signal_t ivl_lpm_array(ivl_lpm_t net);
|
||||
/* IVL_LPM_PART IVL_LPM_SUBSTITUTE */
|
||||
extern unsigned ivl_lpm_base(ivl_lpm_t net);
|
||||
/* IVL_LPM_FF */
|
||||
extern unsigned ivl_lpm_negedge(ivl_lpm_t net);
|
||||
extern ivl_nexus_t ivl_lpm_clk(ivl_lpm_t net);
|
||||
/* IVL_LPM_UFUNC */
|
||||
extern ivl_scope_t ivl_lpm_define(ivl_lpm_t net);
|
||||
@@ -2342,4 +2349,6 @@ typedef const char* (*target_query_f) (const char*key);
|
||||
|
||||
_END_DECL
|
||||
|
||||
#undef ENUM_UNSIGNED_INT
|
||||
|
||||
#endif /* IVL_ivl_target_H */
|
||||
|
||||
+1
-1
@@ -95,7 +95,7 @@ keys, with their corresponding values, are:
|
||||
This is exactly the same as the "-Dname=<value>" described above.
|
||||
|
||||
I:<dir>
|
||||
This is exctly the same as "-I<dir>".
|
||||
This is exactly the same as "-I<dir>".
|
||||
|
||||
relative include:<flag>
|
||||
The <flag> can be "true" or "false". This enables "relative
|
||||
|
||||
+240
-356
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -1,5 +1,5 @@
|
||||
const char COPYRIGHT[] =
|
||||
"Copyright (c) 1999-2011 Stephen Williams ([email protected])";
|
||||
"Copyright (c) 1999-2011,2015 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
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
%{
|
||||
/*
|
||||
* Copyright (c) 1998-2014 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2015 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
|
||||
@@ -432,18 +432,28 @@ TU [munpf]
|
||||
return SYSTEM_IDENTIFIER; }
|
||||
|
||||
|
||||
\'[sS]?[dD][ \t]*[0-9][0-9_]* { yylval.number = make_unsized_dec(yytext);
|
||||
return BASED_NUMBER; }
|
||||
\'[sS]?[dD][ \t]*[xzXZ?]_* { yylval.number = make_undef_highz_dec(yytext);
|
||||
return BASED_NUMBER; }
|
||||
\'[sS]?[bB][ \t]*[0-1xzXZ_\?]+ { yylval.number = make_unsized_binary(yytext);
|
||||
return BASED_NUMBER; }
|
||||
\'[sS]?[oO][ \t]*[0-7xzXZ_\?]+ { yylval.number = make_unsized_octal(yytext);
|
||||
return BASED_NUMBER; }
|
||||
\'[sS]?[hH][ \t]*[0-9a-fA-FxzXZ_\?]+ { yylval.number = make_unsized_hex(yytext);
|
||||
return BASED_NUMBER; }
|
||||
\'[sS]?[dD][ \t]*[0-9][0-9_]* {
|
||||
yylval.number = make_unsized_dec(yytext);
|
||||
return BASED_NUMBER;
|
||||
}
|
||||
\'[sS]?[dD][ \t]*[xzXZ?]_* {
|
||||
yylval.number = make_undef_highz_dec(yytext);
|
||||
return BASED_NUMBER;
|
||||
}
|
||||
\'[sS]?[bB][ \t]*[0-1xzXZ?][0-1xzXZ?_]* {
|
||||
yylval.number = make_unsized_binary(yytext);
|
||||
return BASED_NUMBER;
|
||||
}
|
||||
\'[sS]?[oO][ \t]*[0-7xzXZ?][0-7xzXZ?_]* {
|
||||
yylval.number = make_unsized_octal(yytext);
|
||||
return BASED_NUMBER;
|
||||
}
|
||||
\'[sS]?[hH][ \t]*[0-9a-fA-FxzXZ?][0-9a-fA-FxzXZ?_]* {
|
||||
yylval.number = make_unsized_hex(yytext);
|
||||
return BASED_NUMBER;
|
||||
}
|
||||
\'[01xzXZ] {
|
||||
if (generation_flag < GN_VER2005_SV) {
|
||||
if (!gn_system_verilog()) {
|
||||
cerr << yylloc.text << ":" << yylloc.first_line << ": warning: "
|
||||
<< "Using SystemVerilog 'N bit vector. Use at least "
|
||||
<< "-g2005-sv to remove this warning." << endl;
|
||||
@@ -469,7 +479,7 @@ TU [munpf]
|
||||
|
||||
/* 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 | GN_VER2012)) {
|
||||
if (gn_system_verilog()) {
|
||||
yylval.text = strdupnew(yytext);
|
||||
return TIME_LITERAL;
|
||||
} else REJECT; }
|
||||
@@ -847,7 +857,7 @@ verinum*make_unsized_binary(const char*txt)
|
||||
ptr += 1;
|
||||
}
|
||||
|
||||
assert((tolower(*ptr) == 'b') || (generation_flag >= GN_VER2005_SV));
|
||||
assert((tolower(*ptr) == 'b') || gn_system_verilog());
|
||||
if (tolower(*ptr) == 'b') {
|
||||
ptr += 1;
|
||||
} else {
|
||||
|
||||
@@ -27,6 +27,11 @@ LineInfo::LineInfo()
|
||||
{
|
||||
}
|
||||
|
||||
LineInfo::LineInfo(const LineInfo&that) :
|
||||
file_(that.file_), lineno_(that.lineno_)
|
||||
{
|
||||
}
|
||||
|
||||
LineInfo::~LineInfo()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ using namespace std;
|
||||
class LineInfo {
|
||||
public:
|
||||
LineInfo();
|
||||
LineInfo(const LineInfo&that);
|
||||
virtual ~LineInfo();
|
||||
|
||||
// Get a fully formatted file/lineno
|
||||
|
||||
@@ -36,7 +36,7 @@ double acc_fetch_paramval(handle object)
|
||||
fprintf(pli_trace, "acc_fetch_paramval(%s) --> \"%s\"\n",
|
||||
vpi_get_str(vpiName, object), val.value.str);
|
||||
}
|
||||
return (double) (long)val.value.str;
|
||||
return (double) (intptr_t)val.value.str;
|
||||
|
||||
default:
|
||||
vpi_printf("XXXX: parameter %s has type %d\n",
|
||||
|
||||
@@ -115,7 +115,7 @@ PLI_INT32 tf_getlongtime(PLI_INT32 *high)
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is not defined in the IEE standard, but is provided for
|
||||
* This function is not defined in the IEEE standard, but is provided for
|
||||
* compatibility with other simulators. On platforms that support this,
|
||||
* make it a weak symbol just in case the user has defined their own
|
||||
* function for this.
|
||||
|
||||
+20
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2013 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2015 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
|
||||
@@ -45,6 +45,14 @@ bool Nexus::drivers_constant() const
|
||||
return false;
|
||||
}
|
||||
|
||||
/* If we are connected to a tran, there may be a driver
|
||||
on the other side of the tran. We could try checking
|
||||
for this, but for now, be pessimistic. */
|
||||
if (dynamic_cast<const NetTran*>(cur->get_obj())) {
|
||||
driven_ = VAR;
|
||||
return false;
|
||||
}
|
||||
|
||||
Link::DIR cur_dir = cur->get_dir();
|
||||
if (cur_dir == Link::INPUT)
|
||||
continue;
|
||||
@@ -267,11 +275,17 @@ vector<bool> Nexus::driven_mask(void) const
|
||||
}
|
||||
|
||||
const NetPartSelect*obj_ps = dynamic_cast<const NetPartSelect*>(obj);
|
||||
if (obj_ps && obj_ps->dir()==NetPartSelect::VP)
|
||||
continue;
|
||||
if (obj_ps && cur->get_pin()!=1)
|
||||
continue;
|
||||
if (obj_ps) {
|
||||
if(obj_ps) {
|
||||
if (obj_ps->dir()==NetPartSelect::VP) {
|
||||
if(cur->get_pin() != 0)
|
||||
continue;
|
||||
for (size_t idx = 0 ; idx < mask.size() ; idx += 1)
|
||||
mask[idx] = true;
|
||||
return mask;
|
||||
} else {
|
||||
if (cur->get_pin() != 1)
|
||||
continue;
|
||||
}
|
||||
for (unsigned idx = 0 ; idx < obj_ps->width() ; idx += 1) {
|
||||
size_t bit = idx + obj_ps->base();
|
||||
ivl_assert(*obj, bit < mask.size());
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
const char COPYRIGHT[] =
|
||||
"Copyright (c) 1998-2014 Stephen Williams ([email protected])";
|
||||
"Copyright (c) 1998-2015 Stephen Williams ([email protected])";
|
||||
|
||||
/*
|
||||
* This source code is free software; you can redistribute it
|
||||
@@ -108,6 +108,7 @@ bool gn_assertions_flag = true;
|
||||
bool gn_io_range_error_flag = true;
|
||||
bool gn_strict_ca_eval_flag = false;
|
||||
bool gn_strict_expr_width_flag = false;
|
||||
bool gn_shared_loop_index_flag = false;
|
||||
bool gn_verilog_ams_flag = false;
|
||||
|
||||
/*
|
||||
@@ -153,6 +154,7 @@ FILE *depend_file = NULL;
|
||||
* These are the warning enable flags.
|
||||
*/
|
||||
bool warn_implicit = false;
|
||||
bool warn_implicit_dimensions = false;
|
||||
bool warn_timescale = false;
|
||||
bool warn_portbinding = false;
|
||||
bool warn_inf_loop = false;
|
||||
@@ -343,6 +345,12 @@ static void process_generation_flag(const char*gen)
|
||||
} else if (strcmp(gen,"no-strict-expr-width") == 0) {
|
||||
gn_strict_expr_width_flag = false;
|
||||
|
||||
} else if (strcmp(gen,"shared-loop-index") == 0) {
|
||||
gn_shared_loop_index_flag = true;
|
||||
|
||||
} else if (strcmp(gen,"no-shared-loop-index") == 0) {
|
||||
gn_shared_loop_index_flag = false;
|
||||
|
||||
} else {
|
||||
}
|
||||
}
|
||||
@@ -678,6 +686,9 @@ static void read_iconfig_file(const char*ipath)
|
||||
case 'i':
|
||||
warn_implicit = true;
|
||||
break;
|
||||
case 'd':
|
||||
warn_implicit_dimensions = true;
|
||||
break;
|
||||
case 'l':
|
||||
warn_inf_loop = true;
|
||||
break;
|
||||
@@ -859,6 +870,7 @@ int main(int argc, char*argv[])
|
||||
# if defined(HAVE_TIMES)
|
||||
times_flag = true;
|
||||
# endif
|
||||
flags["VVP_EXTRA_ARGS"] = strdup(" -v");
|
||||
break;
|
||||
case 'V':
|
||||
version_flag = true;
|
||||
@@ -1106,7 +1118,7 @@ int main(int argc, char*argv[])
|
||||
|
||||
/* Decide if we are going to allow system functions to be called
|
||||
* as tasks. */
|
||||
if (generation_flag >= GN_VER2005_SV) {
|
||||
if (gn_system_verilog()) {
|
||||
def_sfunc_as_task = IVL_SFUNC_AS_TASK_WARNING;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,282 +1,4 @@
|
||||
Please NOTE:
|
||||
Please see the Icarus Verilog Wiki for instruction on building and installing
|
||||
Icarus Verilog as a native Windows application using the MinGW tools:
|
||||
|
||||
These directions are slightly outdated and need to be updated.
|
||||
The plan is to rewrite all this using the latest MinGW at
|
||||
some time in the not too distant future (CR Aug. 2009)
|
||||
|
||||
|
||||
MINGW PORT OF ICARUS VERILOG
|
||||
|
||||
Copyright 2006 Stephen Williams <[email protected]>
|
||||
|
||||
|
||||
Icarus Verilog source can be compiled with the mingw C/C++ compilers
|
||||
to get a Windows binary that does not require the POSIX compatibility
|
||||
cruft of the Cygwin.dll library. The resulting program can be run with
|
||||
or without Cygwin, so this is the preferred Windows distribution form.
|
||||
The configure scripts automatically detect that the compilers in use
|
||||
are the mingw compilers and will configure the Makefiles appropriately.
|
||||
|
||||
The mingw patch doesn't contain tools beyond the compiler, but there
|
||||
is the "msys" package that the makers of Mingw publish that has enough
|
||||
extra tools to get most everything else working. There are a few extra
|
||||
packages needed beyond mingw and msys, and the following instructions
|
||||
explain how to get them and install them.
|
||||
|
||||
* Some Preliminary Comments -- PLEASE READ ME --
|
||||
|
||||
The Windows port of Icarus Verilog is the most difficult of all the
|
||||
ports. The Windows system off the shelf is completely stripped, devoid
|
||||
of any support for software development. Everything needed to compile
|
||||
Icarus Verilog must be collected from various sources and stitched
|
||||
together by hand. Normal human beings with a basic understanding of
|
||||
software development can do this, but some patience (and access to the
|
||||
Internet) is required. You may choose to print these instructions. FOR
|
||||
BEST RESULTS, FOLLOW THESE INSTRUCTIONS CAREFULLY.
|
||||
|
||||
NOTE that if you have Cygwin installed, it is best to not use a cygwin
|
||||
window to do the build, as the Cygwin tools will intermix with the
|
||||
mingw tools such that it is hard to be sure you are using the right
|
||||
compiler. Thus, it is recommended that these steps be *not* done in a
|
||||
Cygwin window. Use an MSYS window instead, and be careful that your
|
||||
msys/mingw tools are not masked by paths that point to Cygwin binaries.
|
||||
|
||||
I have no plans to intentionally support MSVC++ compilation. Don't ask.
|
||||
|
||||
* Summary of Prerequisites
|
||||
|
||||
This is a brief list of prerequisite packages, along with the URL
|
||||
where each can be found. In most cases, the specific version is not
|
||||
critical, but these are the versions I use.
|
||||
|
||||
msys-1.0 <http://www.mingw/org>
|
||||
msysDTK-1.0 <http://www.mingw.org>
|
||||
Mingw32-5.x <http://www.mingw.org>
|
||||
... including the sub-packages binutils, gcc-core and gcc-g++
|
||||
if you are given the option.
|
||||
readline-5.0-1 <http://gnuwin32.sourceforge.net>
|
||||
bzip2-1.0.3 <http://gnuwin32.sourceforge.net>
|
||||
zlib-1.2.3 <http://gnuwin32.sourceforge.net>
|
||||
gperf-3.0.1 <http://gnuwin32.sourceforge.net>
|
||||
bison-2.1 <http://gnuwin32.sourceforge.net>
|
||||
flex-2.5.4a <http://gnuwin32.sourceforge.net>
|
||||
|
||||
The above table lists the packages required. It is convenient to
|
||||
install them in the above order. Many of these packages are also
|
||||
collected into the directory:
|
||||
|
||||
<ftp://icarus.com/pub/eda/verilog/win32-build-parts>
|
||||
|
||||
Incidentally, besides Mingw32, none of these packages are needed after
|
||||
installation of Icarus Verilog is complete. These are only needed to
|
||||
build the compiler. The Mingw32 package can be used to compile VPI
|
||||
modules if you choose.
|
||||
|
||||
* Install MSYS and msysDTK
|
||||
|
||||
The msys package is available from the mingw download site. This is
|
||||
not the compiler but a collection of *nix tools ported to Windows and
|
||||
wrapped in a convenient installer. The msys package is all the various
|
||||
basic tools (shells, file utils, etc) and the msysDTK is extra
|
||||
developer tools other than the compiler.
|
||||
|
||||
Download the msys-1.x.x.exe and msysdtc-1.x.x.exe binaries. These are
|
||||
self-installing packages. Install msys first, and then msysDTC. Most
|
||||
likely, you want to install them in c:/msys. (The msysDTK is installed
|
||||
in the same location, as it is an add-on.)
|
||||
|
||||
This install should be easy and reliable.
|
||||
|
||||
The installation will leave an "msys" icon on your desktop and in the
|
||||
mingw sub-menu of your Start menu. This icon brings up a shell window
|
||||
(a command line) that has paths all set up for executing msys and
|
||||
mingw commands. This is what you will want to use while executing
|
||||
commands below.
|
||||
|
||||
* Install Mingw32
|
||||
|
||||
The obvious step 2, then, is install the mingw compilers. These can be
|
||||
found at the web page <http://www.mingw.org>. The Mingw-5.x.x package
|
||||
is a convenient remote installer. Download this program and run
|
||||
it. The installer will ask which components you want to install. You
|
||||
need only the base C compiler and the C++ compiler. (You may install
|
||||
other languages if you wish.)
|
||||
|
||||
When I install Mingw32 (using the installer) I typically set a
|
||||
destination directory of d:\mingw or the like. You will be using
|
||||
that path later.
|
||||
|
||||
NOTES:
|
||||
If you intend to compile VPI modules for Icarus Verilog, you
|
||||
need Mingw32, even if you are using a precompiled binary. VPI
|
||||
modules only require Mingw32, and none of the other libraries.
|
||||
|
||||
Finally, as part of installing the mingw32 compilers, remember to add
|
||||
the mingw/bin directory to your path. You will need that to be able to
|
||||
find the compilers later.
|
||||
|
||||
* Install GnuWin32 Packages
|
||||
|
||||
The GnuWin32 project is a collections of open source programs and
|
||||
libraries ported to Windows. These also work well with the Mingw
|
||||
compiler, and in fact Icarus Verilog uses a few pieces from this
|
||||
collection.
|
||||
|
||||
You will need these gnuwin32 packages to compile Icarus Verilog:
|
||||
|
||||
<http://gnuwin32.sourceforge.net>
|
||||
bzip2-1.0.3.exe
|
||||
zlib-1.2.3.exe
|
||||
gperf-3.0.1.exe
|
||||
bison-2.1.exe
|
||||
flex-2.5.4a.exe
|
||||
readline-5.0-1.exe
|
||||
|
||||
I suggest creating a common directory for holding all your gnuwin32
|
||||
packages. I use C:\gnuwin32. The download page at the gnuwin32 site
|
||||
has a "setup" link for each of these packages. Click the setup to
|
||||
download the installer for each of the desired programs, then execute
|
||||
the downloaded .exe files to invoke the installer. Install into the
|
||||
c:\gunwin32 directory.
|
||||
|
||||
NOTES:
|
||||
You need the binaries and the developer files, but you do not
|
||||
need the source to these packages. The installer gives you the
|
||||
choice.
|
||||
|
||||
After you are done installing the gnuwin32 tools, you should add the
|
||||
c:\gnuwin32\bin directory (assuming you installed in c:\gnuwin32) to
|
||||
your Windows path. The msys shell will pick up your Windows path.
|
||||
|
||||
* Unpack Icarus Verilog source
|
||||
|
||||
Unpack the compressed tar file (.tar.gz) of the source with a command
|
||||
like this:
|
||||
|
||||
$ gunzip -d verilog-xxxxxxxx.tar.gz | tar xvf -
|
||||
|
||||
This will create a directory "verilog-xxxxxxxx" that contains all the
|
||||
source for Icarus Verilog. Descend into that directory, as that is
|
||||
where we will work from now on.
|
||||
|
||||
$ cd verilog-xxxxxxxx
|
||||
|
||||
NOTES:
|
||||
The exact name of the file will vary according to the
|
||||
snapshot. The 20030303 name is only an example.
|
||||
|
||||
Unpack the source into a directory that has no spaces. The
|
||||
makefiles included in the source get confused by white space in
|
||||
directory names.
|
||||
|
||||
* Preconfigure Icarus Verilog (Not normally needed)
|
||||
|
||||
Under certain cases, you may need to "preconfigure" the Icarus Verilog
|
||||
source tree. You should only need to do this if you are getting the
|
||||
Icarus Verilog source tree from git, or you are using an existing
|
||||
source tree that you've patched to cause configure.in files to change.
|
||||
|
||||
NOTE: If you are building from a fresh, bundled source tree that
|
||||
you downloaded from an FTP site, then SKIP THIS STEP. Go on to
|
||||
the "Configure Icarus Verilog" step below.
|
||||
|
||||
First, remove any autom4te.cache directories that may exist in your
|
||||
source tree. These can make a mess of autoconf runs. Then, generate
|
||||
configure scripts with this command:
|
||||
|
||||
$ sh autoconf.sh
|
||||
|
||||
This script will run the "autoconf" command (part of the msysDTK) to
|
||||
generate all the necessary "configure" scripts. This will take a few
|
||||
minutes. This should go smoothly.
|
||||
|
||||
* Configure Icarus Verilog
|
||||
|
||||
Now we are all set to configure and compile Icarus Verilog. Choose a
|
||||
destination path where you will want to install the binaries. I chose
|
||||
on my system the directory "D:\iverilog". This choice is not
|
||||
permanent, so don't get too much angst over it. Just choose a name
|
||||
without white space.
|
||||
|
||||
Now, configure the source to make the makefiles and configuration
|
||||
details. Run these commands:
|
||||
|
||||
$ CPPFLAGS="-Ic:/gnuwin32/include
|
||||
$ LDFLAGS="-Lc:/gnuwin32/lib
|
||||
$ export CPPFLAGS LDFLAGS
|
||||
$ ./configure --prefix=c:/iverilog
|
||||
|
||||
NOTES:
|
||||
The CPPFLAGS and LDFLAGS variables tell configure where
|
||||
the gnuwin32 packages are. The configure program will
|
||||
write these values into the Makefiles, so you only need to
|
||||
keep these variables long enough for the configure program
|
||||
to work.
|
||||
|
||||
Your PATH variable was set in the previous step.
|
||||
|
||||
Use forward slashes as directory characters. All the various
|
||||
tools prefer the forward slash.
|
||||
|
||||
Substitute your chosen directory for the prefix. This will cause the
|
||||
makefiles to build and the source code to configure. The configure
|
||||
program will detect that this is a mingw environment and set things up
|
||||
to build properly.
|
||||
|
||||
(For a prefix, use the drive letter notation; the mingw compiled parts
|
||||
require it, and the Cygwin tools should be able to handle it. You may
|
||||
need to check or upgrade your Cygwin installation if this causes
|
||||
problems for you.)
|
||||
|
||||
|
||||
* Compile Icarus Verilog
|
||||
|
||||
This, believe it or not, should be the easy part:
|
||||
|
||||
$ make
|
||||
|
||||
It could take a while. Now is a good time to go get some coffee or
|
||||
take a tea break.
|
||||
|
||||
|
||||
* Install Icarus Verilog
|
||||
|
||||
If the compile ran OK, then next you install Icarus Verilog in the
|
||||
directory you have chosen. When you are ready, install like this:
|
||||
|
||||
$ make install
|
||||
|
||||
This is part of what the configure program did for you. The Makefiles
|
||||
now know to put the files under the D:\iverilog directory (or whatever
|
||||
directory you chose) and away you go.
|
||||
|
||||
You may find that you need to put some of the prerequisite DLLs into
|
||||
the d:\iverilog\bin directory. These include:
|
||||
|
||||
c:\mingw\bin\mingw10.dll
|
||||
c:\gnuwin32\bin\readline.dll
|
||||
c:\gnuwin32\bin\history.dll
|
||||
c:\gnuwin32\bin\bzip2.dll
|
||||
c:\gnuwin32\bin\zlib.dll
|
||||
|
||||
If you already have these in your Windows path (i.e. your system32
|
||||
directory) then you do not need to copy them into the iverilog
|
||||
directory. However, prepackaged Icarus Verilog binaries include these
|
||||
files.
|
||||
|
||||
* Running Icarus Verilog
|
||||
|
||||
Finally, put the C:\iverilog\bin directory in your Windows path, and
|
||||
you should be able to run the iverilog and vvp commands to your
|
||||
heart's content.
|
||||
|
||||
Currently, the iverilog.exe uses the path to itself to locate the
|
||||
libraries and modules associated with itself. In other words, if you
|
||||
execute the C:\iverilog\bin\iverilog.exe program, it will locate its
|
||||
subparts in the C:\iverilog directory and subdirectories below
|
||||
that. This means you can move the Icarus Verilog installation by
|
||||
simply moving the root directory and all its contents.
|
||||
|
||||
The vvp.pdf and iverilog.pdf files document the main commands. View
|
||||
these with Acrobat reader, or any other viewer capable of displaying
|
||||
PDF format files.
|
||||
http://iverilog.wikia.com/wiki/Installation_Guide#Compiling_on_MS_Windows_.28MinGW.29
|
||||
|
||||
@@ -43,6 +43,8 @@ NetAssign_::NetAssign_(NetAssign_*n)
|
||||
: nest_(n), sig_(0), word_(0), base_(0), sel_type_(IVL_SEL_OTHER)
|
||||
{
|
||||
more = 0;
|
||||
signed_ = false;
|
||||
turn_sig_to_wire_on_release_ = false;
|
||||
}
|
||||
|
||||
NetAssign_::NetAssign_(NetNet*s)
|
||||
@@ -51,6 +53,7 @@ NetAssign_::NetAssign_(NetNet*s)
|
||||
lwid_ = sig_->vector_width();
|
||||
sig_->incr_lref();
|
||||
more = 0;
|
||||
signed_ = false;
|
||||
turn_sig_to_wire_on_release_ = false;
|
||||
}
|
||||
|
||||
@@ -135,6 +138,9 @@ ivl_variable_type_t NetAssign_::expr_type() const
|
||||
return darray->element_base_type();
|
||||
}
|
||||
|
||||
if (sig_ && sig_->data_type()==IVL_VT_STRING && base_!=0)
|
||||
return IVL_VT_BOOL;
|
||||
|
||||
if (ntype) return ntype->base_type();
|
||||
|
||||
ivl_assert(*this, sig_);
|
||||
|
||||
+19
-12
@@ -101,11 +101,12 @@ uint64_t Design::scale_to_precision(uint64_t val,
|
||||
return val;
|
||||
}
|
||||
|
||||
NetScope* Design::make_root_scope(perm_string root, bool program_block)
|
||||
NetScope* Design::make_root_scope(perm_string root, bool program_block,
|
||||
bool is_interface)
|
||||
{
|
||||
NetScope *root_scope_;
|
||||
root_scope_ = new NetScope(0, hname_t(root), NetScope::MODULE,
|
||||
false, program_block);
|
||||
false, program_block, is_interface);
|
||||
/* This relies on the fact that the basename return value is
|
||||
permallocated. */
|
||||
root_scope_->set_module_name(root_scope_->basename());
|
||||
@@ -527,6 +528,20 @@ void NetScope::evaluate_parameter_logic_(Design*des, param_ref_t cur)
|
||||
des->errors += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
// If the parameter has type or range information, then
|
||||
// make sure the type is set right. Note that if the
|
||||
// parameter doesn't have an explicit type or range,
|
||||
// then it will get the signedness from the expression itself.
|
||||
if (cur->second.type != IVL_VT_NO_TYPE) {
|
||||
expr->cast_signed(cur->second.signed_flag);
|
||||
} else if (cur->second.signed_flag) {
|
||||
expr->cast_signed(true);
|
||||
}
|
||||
|
||||
if (!range_flag && !expr->has_width()) {
|
||||
expr = pad_to_width(expr, integer_width, *expr);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -536,17 +551,8 @@ void NetScope::evaluate_parameter_logic_(Design*des, param_ref_t cur)
|
||||
des->errors += 1;
|
||||
return;
|
||||
}
|
||||
(*cur).second.val = expr;
|
||||
|
||||
/* If the parameter has type or range information, then make
|
||||
sure the type is set right. Note that if the parameter
|
||||
doesn't have an explicit type or range, then it will get
|
||||
the signedness from the expression itself. */
|
||||
if ((*cur).second.type != IVL_VT_NO_TYPE) {
|
||||
(*cur).second.val->cast_signed((*cur).second.signed_flag);
|
||||
} else if ((*cur).second.signed_flag) {
|
||||
(*cur).second.val->cast_signed(true);
|
||||
}
|
||||
cur->second.val = expr;
|
||||
|
||||
// If there are no value ranges to test the value against,
|
||||
// then we are done.
|
||||
@@ -841,6 +847,7 @@ NetFuncDef* Design::find_function(NetScope*scope, const pform_name_t&name)
|
||||
// the function's signals have been elaborated. If this is
|
||||
// the case, elaborate them now.
|
||||
if (func->elab_stage() < 2) {
|
||||
func->need_const_func(true);
|
||||
const PFunction*pfunc = func->func_pform();
|
||||
assert(pfunc);
|
||||
pfunc->elaborate_sig(this, func);
|
||||
|
||||
+149
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012-2013 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2012-2016 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
|
||||
@@ -88,6 +88,10 @@ NetExpr* NetFuncDef::evaluate_function(const LineInfo&loc, const std::vector<Net
|
||||
// fills in the context_map with local variables held by the scope.
|
||||
scope()->evaluate_function_find_locals(loc, context_map);
|
||||
|
||||
// Execute any variable initialization statements.
|
||||
if (const NetProc*init_proc = scope()->var_init())
|
||||
init_proc->evaluate_function(loc, context_map);
|
||||
|
||||
if (debug_eval_tree && proc_==0) {
|
||||
cerr << loc.get_fileline() << ": NetFuncDef::evaluate_function: "
|
||||
<< "Function " << scope_path(scope())
|
||||
@@ -209,6 +213,98 @@ bool NetProc::evaluate_function(const LineInfo&,
|
||||
return false;
|
||||
}
|
||||
|
||||
void NetAssign::eval_func_lval_op_real_(const LineInfo&loc,
|
||||
verireal&lv, verireal&rv) const
|
||||
{
|
||||
switch (op_) {
|
||||
case '+':
|
||||
lv = lv + rv;
|
||||
break;
|
||||
case '-':
|
||||
lv = lv - rv;
|
||||
break;
|
||||
case '*':
|
||||
lv = lv * rv;
|
||||
break;
|
||||
case '/':
|
||||
lv = lv / rv;
|
||||
break;
|
||||
case '%':
|
||||
lv = lv % rv;
|
||||
break;
|
||||
default:
|
||||
cerr << "Illegal assignment operator: "
|
||||
<< human_readable_op(op_) << endl;
|
||||
ivl_assert(loc, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void NetAssign::eval_func_lval_op_(const LineInfo&loc,
|
||||
verinum&lv, verinum&rv) const
|
||||
{
|
||||
unsigned lv_width = lv.len();
|
||||
bool lv_sign = lv.has_sign();
|
||||
switch (op_) {
|
||||
case 'l':
|
||||
case 'R':
|
||||
// The left operand is self-determined.
|
||||
break;
|
||||
case 'r':
|
||||
// The left operand is self-determined, but we need to
|
||||
// cast it to unsigned to get a logical shift.
|
||||
lv.has_sign(false);
|
||||
break;
|
||||
default:
|
||||
// The left operand must be cast to the expression type/size
|
||||
lv.has_sign(rv.has_sign());
|
||||
lv = cast_to_width(lv, rv.len());
|
||||
}
|
||||
switch (op_) {
|
||||
case '+':
|
||||
lv = lv + rv;
|
||||
break;
|
||||
case '-':
|
||||
lv = lv - rv;
|
||||
break;
|
||||
case '*':
|
||||
lv = lv * rv;
|
||||
break;
|
||||
case '/':
|
||||
lv = lv / rv;
|
||||
break;
|
||||
case '%':
|
||||
lv = lv % rv;
|
||||
break;
|
||||
case '&':
|
||||
for (unsigned idx = 0 ; idx < lv.len() ; idx += 1)
|
||||
lv.set(idx, lv[idx] & rv[idx]);
|
||||
break;
|
||||
case '|':
|
||||
for (unsigned idx = 0 ; idx < lv.len() ; idx += 1)
|
||||
lv.set(idx, lv[idx] | rv[idx]);
|
||||
break;
|
||||
case '^':
|
||||
for (unsigned idx = 0 ; idx < lv.len() ; idx += 1)
|
||||
lv.set(idx, lv[idx] ^ rv[idx]);
|
||||
break;
|
||||
case 'l':
|
||||
lv = lv << rv.as_unsigned();
|
||||
break;
|
||||
case 'r':
|
||||
lv = lv >> rv.as_unsigned();
|
||||
break;
|
||||
case 'R':
|
||||
lv = lv >> rv.as_unsigned();
|
||||
break;
|
||||
default:
|
||||
cerr << "Illegal assignment operator: "
|
||||
<< human_readable_op(op_) << endl;
|
||||
ivl_assert(loc, 0);
|
||||
}
|
||||
lv = cast_to_width(lv, lv_width);
|
||||
lv.has_sign(lv_sign);
|
||||
}
|
||||
|
||||
bool NetAssign::eval_func_lval_(const LineInfo&loc,
|
||||
map<perm_string,LocalVar>&context_map,
|
||||
const NetAssign_*lval, NetExpr*rval_result) const
|
||||
@@ -269,18 +365,55 @@ bool NetAssign::eval_func_lval_(const LineInfo&loc,
|
||||
ivl_assert(loc, base + lval->lwidth() <= old_lval->expr_width());
|
||||
|
||||
NetEConst*lval_const = dynamic_cast<NetEConst*>(old_lval);
|
||||
ivl_assert(loc, lval_const);
|
||||
verinum lval_v = lval_const->value();
|
||||
NetEConst*rval_const = dynamic_cast<NetEConst*>(rval_result);
|
||||
verinum rval_v = cast_to_width(rval_const->value(), lval->lwidth());
|
||||
ivl_assert(loc, rval_const);
|
||||
verinum rval_v = rval_const->value();
|
||||
|
||||
for (unsigned idx = 0 ; idx < rval_v.len() ; idx += 1)
|
||||
lval_v.set(idx+base, rval_v[idx]);
|
||||
verinum lpart(verinum::Vx, lval->lwidth());
|
||||
if (op_) {
|
||||
for (unsigned idx = 0 ; idx < lpart.len() ; idx += 1)
|
||||
lpart.set(idx, lval_v[base+idx]);
|
||||
|
||||
eval_func_lval_op_(loc, lpart, rval_v);
|
||||
} else {
|
||||
lpart = cast_to_width(rval_v, lval->lwidth());
|
||||
}
|
||||
for (unsigned idx = 0 ; idx < lpart.len() ; idx += 1)
|
||||
lval_v.set(idx+base, lpart[idx]);
|
||||
|
||||
delete base_result;
|
||||
delete rval_result;
|
||||
rval_result = new NetEConst(lval_v);
|
||||
} else {
|
||||
rval_result = fix_assign_value(lval->sig(), rval_result);
|
||||
if (op_ == 0) {
|
||||
rval_result = fix_assign_value(lval->sig(), rval_result);
|
||||
} else if (dynamic_cast<NetECReal*>(rval_result)) {
|
||||
NetECReal*lval_const = dynamic_cast<NetECReal*>(old_lval);
|
||||
ivl_assert(loc, lval_const);
|
||||
verireal lval_r = lval_const->value();
|
||||
NetECReal*rval_const = dynamic_cast<NetECReal*>(rval_result);
|
||||
ivl_assert(loc, rval_const);
|
||||
verireal rval_r = rval_const->value();
|
||||
|
||||
eval_func_lval_op_real_(loc, lval_r, rval_r);
|
||||
|
||||
delete rval_result;
|
||||
rval_result = new NetECReal(lval_r);
|
||||
} else {
|
||||
NetEConst*lval_const = dynamic_cast<NetEConst*>(old_lval);
|
||||
ivl_assert(loc, lval_const);
|
||||
verinum lval_v = lval_const->value();
|
||||
NetEConst*rval_const = dynamic_cast<NetEConst*>(rval_result);
|
||||
ivl_assert(loc, rval_const);
|
||||
verinum rval_v = rval_const->value();
|
||||
|
||||
eval_func_lval_op_(loc, lval_v, rval_v);
|
||||
|
||||
delete rval_result;
|
||||
rval_result = new NetEConst(lval_v);
|
||||
}
|
||||
}
|
||||
|
||||
if (old_lval)
|
||||
@@ -318,6 +451,13 @@ bool NetAssign::evaluate_function(const LineInfo&loc,
|
||||
NetEConst*rval_const = dynamic_cast<NetEConst*>(rval_result);
|
||||
ivl_assert(*this, rval_const);
|
||||
|
||||
if (op_) {
|
||||
cerr << get_fileline() << ": sorry: Assignment operators "
|
||||
"inside a constant function are not currently "
|
||||
"supported if the LHS is a concatenation." << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
verinum rval_full = rval_const->value();
|
||||
delete rval_result;
|
||||
|
||||
@@ -369,6 +509,10 @@ bool NetBlock::evaluate_function(const LineInfo&loc,
|
||||
// Now collect the new locals.
|
||||
subscope_->evaluate_function_find_locals(loc, local_context_map);
|
||||
use_local_context_map = true;
|
||||
|
||||
// Execute any variable initialization statements.
|
||||
if (const NetProc*init_proc = subscope_->var_init())
|
||||
init_proc->evaluate_function(loc, local_context_map);
|
||||
}
|
||||
|
||||
// Now use the local context map if there is any local
|
||||
|
||||
+14
@@ -311,6 +311,20 @@ void Nexus::count_io(unsigned&inp, unsigned&out) const
|
||||
}
|
||||
}
|
||||
|
||||
bool Nexus::has_floating_input() const
|
||||
{
|
||||
bool found_input = false;
|
||||
for (const Link*cur = first_nlink() ; cur ; cur = cur->next_nlink()) {
|
||||
if (cur->get_dir() == Link::OUTPUT)
|
||||
return false;
|
||||
|
||||
if (cur->get_dir() == Link::INPUT)
|
||||
found_input = true;
|
||||
}
|
||||
|
||||
return found_input;
|
||||
}
|
||||
|
||||
bool Nexus::drivers_present() const
|
||||
{
|
||||
for (const Link*cur = first_nlink() ; cur ; cur = cur->next_nlink()) {
|
||||
|
||||
+21
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002-2013 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2002-2016 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
|
||||
@@ -404,6 +404,17 @@ NexusSet* NetDoWhile::nex_input(bool rem_out)
|
||||
return result;
|
||||
}
|
||||
|
||||
NexusSet* NetEvWait::nex_input(bool rem_out)
|
||||
{
|
||||
NexusSet*result;
|
||||
if (statement_)
|
||||
result = statement_->nex_input(rem_out);
|
||||
else
|
||||
result = new NexusSet;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
NexusSet* NetForce::nex_input(bool)
|
||||
{
|
||||
cerr << get_fileline() << ": internal warning: NetForce::nex_input()"
|
||||
@@ -427,6 +438,15 @@ NexusSet* NetForLoop::nex_input(bool rem_out)
|
||||
result->add(*tmp);
|
||||
delete tmp;
|
||||
|
||||
if (gn_shared_loop_index_flag) {
|
||||
tmp = new NexusSet();
|
||||
for (unsigned idx = 0 ; idx < index_->pin_count() ; idx += 1)
|
||||
tmp->add(index_->pin(idx).nexus(), 0, index_->vector_width());
|
||||
|
||||
result->rem(*tmp);
|
||||
delete tmp;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
+11
@@ -56,6 +56,17 @@ void NetBlock::append(NetProc*cur)
|
||||
}
|
||||
}
|
||||
|
||||
void NetBlock::prepend(NetProc*cur)
|
||||
{
|
||||
if (last_ == 0) {
|
||||
last_ = cur;
|
||||
cur->next_ = cur;
|
||||
} else {
|
||||
cur->next_ = last_->next_;
|
||||
last_->next_ = cur;
|
||||
}
|
||||
}
|
||||
|
||||
const NetProc* NetBlock::proc_first() const
|
||||
{
|
||||
if (last_ == 0)
|
||||
|
||||
+28
-20
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2017 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
|
||||
@@ -110,8 +110,10 @@ void Definitions::add_class(netclass_t*net_class)
|
||||
* in question.
|
||||
*/
|
||||
|
||||
NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t, bool nest, bool prog)
|
||||
: type_(t), name_(n), nested_module_(nest), program_block_(prog), up_(up)
|
||||
NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t, bool nest,
|
||||
bool program, bool interface)
|
||||
: type_(t), name_(n), nested_module_(nest), program_block_(program),
|
||||
is_interface_(interface), up_(up)
|
||||
{
|
||||
events_ = 0;
|
||||
lcounter_ = 0;
|
||||
@@ -137,6 +139,7 @@ NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t, bool nest, bo
|
||||
time_from_timescale_ = false;
|
||||
}
|
||||
|
||||
var_init_ = 0;
|
||||
switch (t) {
|
||||
case NetScope::TASK:
|
||||
task_ = 0;
|
||||
@@ -262,19 +265,20 @@ bool NetScope::auto_name(const char*prefix, char pad, const char* suffix)
|
||||
assert(self != up_->children_.end());
|
||||
assert(self->second == this);
|
||||
|
||||
char tmp[32];
|
||||
int pad_pos = strlen(prefix);
|
||||
int max_pos = sizeof(tmp) - strlen(suffix) - 1;
|
||||
strncpy(tmp, prefix, sizeof(tmp));
|
||||
tmp[31] = 0;
|
||||
// This is to keep the pad attempts from being stuck in some
|
||||
// sort of infinite loop. This should not be a practical
|
||||
// limit, but an extreme one.
|
||||
const size_t max_pad_attempts = 32 + strlen(prefix);
|
||||
|
||||
string use_prefix = prefix;
|
||||
|
||||
// Try a variety of potential new names. Make sure the new
|
||||
// name is not in the parent scope. Keep looking until we are
|
||||
// sure we have a unique name, or we run out of names to try.
|
||||
while (pad_pos <= max_pos) {
|
||||
while (use_prefix.size() <= max_pad_attempts) {
|
||||
// Try this name...
|
||||
strcat(tmp + pad_pos, suffix);
|
||||
hname_t new_name(lex_strings.make(tmp));
|
||||
string tmp = use_prefix + suffix;
|
||||
hname_t new_name(lex_strings.make(tmp.c_str()), name_.peek_numbers());
|
||||
if (!up_->child(new_name)) {
|
||||
// Ah, this name is unique. Rename myself, and
|
||||
// change my name in the parent scope.
|
||||
@@ -283,7 +287,9 @@ bool NetScope::auto_name(const char*prefix, char pad, const char* suffix)
|
||||
up_->children_[name_] = this;
|
||||
return true;
|
||||
}
|
||||
tmp[pad_pos++] = pad;
|
||||
|
||||
// Name collides, so try a different name.
|
||||
use_prefix = use_prefix + pad;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -294,16 +300,16 @@ bool NetScope::auto_name(const char*prefix, char pad, const char* suffix)
|
||||
*/
|
||||
bool NetScope::replace_parameter(perm_string key, PExpr*val, NetScope*scope)
|
||||
{
|
||||
bool flag = false;
|
||||
if (parameters.find(key) == parameters.end())
|
||||
return false;
|
||||
|
||||
if (parameters.find(key) != parameters.end()) {
|
||||
param_expr_t&ref = parameters[key];
|
||||
ref.val_expr = val;
|
||||
ref.val_scope = scope;
|
||||
flag = true;
|
||||
}
|
||||
param_expr_t&ref = parameters[key];
|
||||
if (ref.local_flag)
|
||||
return false;
|
||||
|
||||
return flag;
|
||||
ref.val_expr = val;
|
||||
ref.val_scope = scope;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetScope::make_parameter_unannotatable(perm_string key)
|
||||
@@ -372,6 +378,8 @@ NetScope::param_ref_t NetScope::find_parameter(perm_string key)
|
||||
// To get here the parameter must already exist, so we should
|
||||
// never get here.
|
||||
assert(0);
|
||||
// But return something to avoid a compiler warning.
|
||||
return idx;
|
||||
}
|
||||
|
||||
NetScope::TYPE NetScope::type() const
|
||||
|
||||
+4
-1
@@ -1,7 +1,7 @@
|
||||
#ifndef IVL_netdarray_H
|
||||
#define IVL_netdarray_H
|
||||
/*
|
||||
* Copyright (c) 2012-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2012-2015 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -33,6 +33,9 @@ class netdarray_t : public netarray_t {
|
||||
// IVL_VT_DARRAY for dynamic arrays?
|
||||
ivl_variable_type_t base_type() const;
|
||||
|
||||
// A dynamic array may have a type that is signed.
|
||||
inline bool get_signed() const { return element_type()->get_signed(); }
|
||||
|
||||
// This is the base_type() of the element of the array. We
|
||||
// need this in some cases in order to get the base type of
|
||||
// the element, and not the IVL_VT_DARRAY of the array itself.
|
||||
|
||||
+17
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998-2013 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2015 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
|
||||
@@ -557,7 +557,7 @@ void NetNet::calculate_slice_widths_from_packed_dims_(void)
|
||||
ivl_assert(*this, ! slice_wids_.empty());
|
||||
slice_wids_[0] = netrange_width(slice_dims_);
|
||||
vector<netrange_t>::const_iterator cur = slice_dims_.begin();
|
||||
for (size_t idx = 1 ; idx < slice_wids_.size() ; idx += 1) {
|
||||
for (size_t idx = 1 ; idx < slice_wids_.size() ; idx += 1, cur++) {
|
||||
slice_wids_[idx] = slice_wids_[idx-1] / cur->width();
|
||||
}
|
||||
}
|
||||
@@ -1153,8 +1153,8 @@ unsigned NetReplicate::repeat() const
|
||||
* ...
|
||||
*/
|
||||
|
||||
NetFF::NetFF(NetScope*s, perm_string n, unsigned width__)
|
||||
: NetNode(s, n, 8), width_(width__)
|
||||
NetFF::NetFF(NetScope*s, perm_string n, bool negedge__, unsigned width__)
|
||||
: NetNode(s, n, 8), negedge_(negedge__), width_(width__)
|
||||
{
|
||||
pin_Clock().set_dir(Link::INPUT);
|
||||
pin_Enable().set_dir(Link::INPUT);
|
||||
@@ -1170,6 +1170,11 @@ NetFF::~NetFF()
|
||||
{
|
||||
}
|
||||
|
||||
bool NetFF::is_negedge() const
|
||||
{
|
||||
return negedge_;
|
||||
}
|
||||
|
||||
unsigned NetFF::width() const
|
||||
{
|
||||
return width_;
|
||||
@@ -2738,10 +2743,11 @@ DelayType NetCase::delay_type() const
|
||||
|
||||
for (unsigned idx = 0; idx < nstmts; idx += 1) {
|
||||
if (!expr(idx)) def_stmt = true;
|
||||
DelayType dt = stat(idx) ? stat(idx)->delay_type() : NO_DELAY;
|
||||
if (idx == 0) {
|
||||
result = stat(idx)->delay_type();
|
||||
result = dt;
|
||||
} else {
|
||||
result = combine_delays(result, stat(idx)->delay_type());
|
||||
result = combine_delays(result, dt);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2764,6 +2770,7 @@ DelayType NetCondit::delay_type() const
|
||||
*/
|
||||
DelayType NetDoWhile::delay_type() const
|
||||
{
|
||||
ivl_assert(*this, proc_);
|
||||
return proc_->delay_type();
|
||||
}
|
||||
|
||||
@@ -2774,11 +2781,13 @@ DelayType NetEvWait::delay_type() const
|
||||
|
||||
DelayType NetForever::delay_type() const
|
||||
{
|
||||
ivl_assert(*this, statement_);
|
||||
return statement_->delay_type();
|
||||
}
|
||||
|
||||
DelayType NetForLoop::delay_type() const
|
||||
{
|
||||
ivl_assert(*this, statement_);
|
||||
return get_loop_delay_type(condition_, statement_);
|
||||
}
|
||||
|
||||
@@ -2801,6 +2810,7 @@ DelayType NetPDelay::delay_type() const
|
||||
|
||||
DelayType NetRepeat::delay_type() const
|
||||
{
|
||||
ivl_assert(*this, statement_);
|
||||
return get_loop_delay_type(expr_, statement_);
|
||||
}
|
||||
|
||||
@@ -2816,5 +2826,6 @@ DelayType NetUTask::delay_type() const
|
||||
|
||||
DelayType NetWhile::delay_type() const
|
||||
{
|
||||
ivl_assert(*this, proc_);
|
||||
return get_loop_delay_type(cond_, proc_);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef IVL_netlist_H
|
||||
#define IVL_netlist_H
|
||||
/*
|
||||
* Copyright (c) 1998-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2015 Stephen Williams (steve@icarus.com)
|
||||
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
@@ -90,6 +90,12 @@ class netvector_t;
|
||||
struct target;
|
||||
struct functor_t;
|
||||
|
||||
#if defined(__cplusplus) && defined(_MSC_VER)
|
||||
# define ENUM_UNSIGNED_INT : unsigned int
|
||||
#else
|
||||
# define ENUM_UNSIGNED_INT
|
||||
#endif
|
||||
|
||||
ostream& operator << (ostream&o, ivl_variable_type_t val);
|
||||
|
||||
extern void join_island(NetPins*obj);
|
||||
@@ -102,8 +108,7 @@ class Link {
|
||||
friend class NexusSet;
|
||||
|
||||
public:
|
||||
enum DIR { PASSIVE, INPUT, OUTPUT };
|
||||
|
||||
enum DIR ENUM_UNSIGNED_INT { PASSIVE, INPUT, OUTPUT };
|
||||
private: // Only NetPins can create/delete Link objects
|
||||
Link();
|
||||
~Link();
|
||||
@@ -383,6 +388,10 @@ class Nexus {
|
||||
is a variable, but also if this is a net with a force. */
|
||||
bool assign_lval() const;
|
||||
|
||||
/* This method returns true if there are any inputs
|
||||
attached to this nexus but no drivers. */
|
||||
bool has_floating_input() const;
|
||||
|
||||
/* This method returns true if there are any drivers
|
||||
(including variables) attached to this nexus. */
|
||||
bool drivers_present() const;
|
||||
@@ -619,7 +628,7 @@ class NetDelaySrc : public NetObj {
|
||||
class PortType
|
||||
{
|
||||
public:
|
||||
enum Enum { NOT_A_PORT, PIMPLICIT, PINPUT, POUTPUT, PINOUT, PREF };
|
||||
enum Enum ENUM_UNSIGNED_INT { NOT_A_PORT, PIMPLICIT, PINPUT, POUTPUT, PINOUT, PREF };
|
||||
|
||||
/*
|
||||
* Merge Port types (used to construct a sane combined port-type
|
||||
@@ -647,7 +656,7 @@ struct PortInfo
|
||||
class NetNet : public NetObj, public PortType {
|
||||
|
||||
public:
|
||||
enum Type { NONE, IMPLICIT, IMPLICIT_REG, INTEGER, WIRE, TRI, TRI1,
|
||||
enum Type ENUM_UNSIGNED_INT { NONE, IMPLICIT, IMPLICIT_REG, INTEGER, WIRE, TRI, TRI1,
|
||||
SUPPLY0, SUPPLY1, WAND, TRIAND, TRI0, WOR, TRIOR, REG,
|
||||
UNRESOLVED_WIRE };
|
||||
|
||||
@@ -708,7 +717,7 @@ class NetNet : public NetObj, public PortType {
|
||||
/* This method returns a reference to the packed dimensions
|
||||
for the vector. These are arranged as a list where the
|
||||
first range in the list (front) is the left-most range in
|
||||
the verilog declaration. These packed dims are compressed
|
||||
the Verilog declaration. These packed dims are compressed
|
||||
to represent the dimensions of all the subtypes. */
|
||||
const std::vector<netrange_t>& packed_dims() const { return slice_dims_; }
|
||||
|
||||
@@ -765,7 +774,7 @@ class NetNet : public NetObj, public PortType {
|
||||
unsigned peek_eref() const;
|
||||
|
||||
// Assignment statements count their lrefs here. And by
|
||||
// asignment statements, we mean BEHAVIORAL assignments.
|
||||
// assignment statements, we mean BEHAVIORAL assignments.
|
||||
void incr_lref();
|
||||
void decr_lref();
|
||||
unsigned peek_lref() const { return lref_count_; }
|
||||
@@ -918,7 +927,8 @@ class NetScope : public Definitions, public Attrib {
|
||||
|
||||
/* Create a new scope, and attach it to the given parent. The
|
||||
name is expected to have been permallocated. */
|
||||
NetScope(NetScope*up, const hname_t&name, TYPE t, bool nest=false, bool prog=false);
|
||||
NetScope(NetScope*up, const hname_t&name, TYPE t, bool nest=false,
|
||||
bool program=false, bool interface=false);
|
||||
~NetScope();
|
||||
|
||||
/* Rename the scope using the name generated by inserting as
|
||||
@@ -1008,11 +1018,19 @@ class NetScope : public Definitions, public Attrib {
|
||||
|
||||
// Nested modules have slightly different scope search rules.
|
||||
inline bool nested_module() const { return nested_module_; }
|
||||
// Program blocks have elaboration constraints.
|
||||
// Program blocks and interfaces have elaboration constraints.
|
||||
inline bool program_block() const { return program_block_; }
|
||||
inline bool is_interface() const { return is_interface_; }
|
||||
TYPE type() const;
|
||||
void print_type(ostream&) const;
|
||||
|
||||
// This provides a link to the variable initialisation process
|
||||
// for use when evaluating a constant function. Note this is
|
||||
// only used for static functions - the variable initialization
|
||||
// for automatic functions is included in the function definition.
|
||||
void set_var_init(const NetProc*proc) { var_init_ = proc; }
|
||||
const NetProc* var_init() const { return var_init_; }
|
||||
|
||||
void set_task_def(NetTaskDef*);
|
||||
void set_func_def(NetFuncDef*);
|
||||
void set_class_def(netclass_t*);
|
||||
@@ -1221,6 +1239,8 @@ class NetScope : public Definitions, public Attrib {
|
||||
bool nested_module_;
|
||||
// True if the scope is a program block
|
||||
bool program_block_;
|
||||
// True if the scope is an interface
|
||||
bool is_interface_;
|
||||
|
||||
perm_string file_;
|
||||
perm_string def_file_;
|
||||
@@ -1241,6 +1261,8 @@ class NetScope : public Definitions, public Attrib {
|
||||
|
||||
vector<PortInfo> ports_;
|
||||
|
||||
const NetProc*var_init_;
|
||||
|
||||
union {
|
||||
NetTaskDef*task_;
|
||||
NetFuncDef*func_;
|
||||
@@ -1618,9 +1640,10 @@ class NetModulo : public NetNode {
|
||||
class NetFF : public NetNode {
|
||||
|
||||
public:
|
||||
NetFF(NetScope*s, perm_string n, unsigned vector_width);
|
||||
NetFF(NetScope*s, perm_string n, bool negedge, unsigned vector_width);
|
||||
~NetFF();
|
||||
|
||||
bool is_negedge() const;
|
||||
unsigned width() const;
|
||||
|
||||
Link& pin_Clock();
|
||||
@@ -1652,6 +1675,7 @@ class NetFF : public NetNode {
|
||||
virtual void functor_node(Design*des, functor_t*fun);
|
||||
|
||||
private:
|
||||
bool negedge_;
|
||||
unsigned width_;
|
||||
verinum aset_value_;
|
||||
verinum sset_value_;
|
||||
@@ -2041,7 +2065,7 @@ class NetEConst : public NetExpr {
|
||||
/* This method allows the constant value to be converted
|
||||
to an unsized value. This is used after evaluating a
|
||||
unsized constant expression. */
|
||||
virtual void trim();
|
||||
void trim();
|
||||
|
||||
virtual void expr_scan(struct expr_scan_t*) const;
|
||||
virtual void dump(ostream&) const;
|
||||
@@ -2212,7 +2236,7 @@ class NetPartSelect : public NetNode {
|
||||
*
|
||||
* wire [7:0] foo = NetSubstitute(bar, bat, off);
|
||||
*
|
||||
* meaus that bar is a vector the same width as foo, bat is a narrower
|
||||
* means that bar is a vector the same width as foo, bat is a narrower
|
||||
* vector. The off is a constant offset into the bar vector. This
|
||||
* looks something like this:
|
||||
*
|
||||
@@ -2283,7 +2307,7 @@ class NetBUFZ : public NetNode {
|
||||
*
|
||||
* 0 -- Output (always returns 0 or 1)
|
||||
* 1 -- Input
|
||||
* 2 -- Input (windcard input for EQX and EQZ variants)
|
||||
* 2 -- Input (wildcard input for EQX and EQZ variants)
|
||||
*/
|
||||
class NetCaseCmp : public NetNode {
|
||||
|
||||
@@ -2614,8 +2638,10 @@ class NetProc : public virtual LineInfo {
|
||||
// picked off by e.g. condit statements as set/reset inputs to
|
||||
// the flipflop being generated.
|
||||
virtual bool synth_sync(Design*des, NetScope*scope,
|
||||
bool&ff_negedge,
|
||||
NetNet*ff_clock, NetBus&ff_ce,
|
||||
NetBus&ff_aclr, NetBus&ff_aset,
|
||||
vector<verinum>&ff_aset_value,
|
||||
NexusSet&nex_map, NetBus&nex_out,
|
||||
const std::vector<NetEvProbe*>&events);
|
||||
|
||||
@@ -2719,6 +2745,12 @@ class NetAssign_ {
|
||||
void set_property(const perm_string&name);
|
||||
inline perm_string get_property(void) const { return member_; }
|
||||
|
||||
// Determine if the assigned object is signed or unsigned.
|
||||
// This is used when determining the expression type for
|
||||
// a compressed assignment statement.
|
||||
bool get_signed() const { return signed_; }
|
||||
void set_signed(bool flag) { signed_ = flag; }
|
||||
|
||||
// Get the width of the r-value that this node expects. This
|
||||
// method accounts for the presence of the mux, so it is not
|
||||
// necessarily the same as the pin_count().
|
||||
@@ -2769,6 +2801,7 @@ class NetAssign_ {
|
||||
// member/property if signal is a class.
|
||||
perm_string member_;
|
||||
|
||||
bool signed_;
|
||||
bool turn_sig_to_wire_on_release_;
|
||||
// indexed part select base
|
||||
NetExpr*base_;
|
||||
@@ -2836,6 +2869,8 @@ class NetAssign : public NetAssignBase {
|
||||
map<perm_string,LocalVar>&ctx) const;
|
||||
|
||||
private:
|
||||
void eval_func_lval_op_real_(const LineInfo&loc, verireal&lv, verireal&rv) const;
|
||||
void eval_func_lval_op_(const LineInfo&loc, verinum&lv, verinum&rv) const;
|
||||
bool eval_func_lval_(const LineInfo&loc, map<perm_string,LocalVar>&ctx,
|
||||
const NetAssign_*lval, NetExpr*rval_result) const;
|
||||
|
||||
@@ -2882,6 +2917,7 @@ class NetBlock : public NetProc {
|
||||
NetScope* subscope() const { return subscope_; }
|
||||
|
||||
void append(NetProc*);
|
||||
void prepend(NetProc*);
|
||||
|
||||
const NetProc*proc_first() const;
|
||||
const NetProc*proc_next(const NetProc*cur) const;
|
||||
@@ -2895,8 +2931,10 @@ class NetBlock : public NetProc {
|
||||
NetBus&accumulated_nex_out);
|
||||
|
||||
bool synth_sync(Design*des, NetScope*scope,
|
||||
bool&ff_negedge,
|
||||
NetNet*ff_clk, NetBus&ff_ce,
|
||||
NetBus&ff_aclr,NetBus&ff_aset,
|
||||
vector<verinum>&ff_aset_value,
|
||||
NexusSet&nex_map, NetBus&nex_out,
|
||||
const std::vector<NetEvProbe*>&events);
|
||||
|
||||
@@ -3036,8 +3074,10 @@ class NetCondit : public NetProc {
|
||||
NetBus&accumulated_nex_out);
|
||||
|
||||
bool synth_sync(Design*des, NetScope*scope,
|
||||
bool&ff_negedge,
|
||||
NetNet*ff_clk, NetBus&ff_ce,
|
||||
NetBus&ff_aclr,NetBus&ff_aset,
|
||||
vector<verinum>&ff_aset_value,
|
||||
NexusSet&nex_map, NetBus&nex_out,
|
||||
const std::vector<NetEvProbe*>&events);
|
||||
|
||||
@@ -3306,6 +3346,7 @@ class NetEvWait : public NetProc {
|
||||
// process? This method checks.
|
||||
virtual bool is_synchronous();
|
||||
|
||||
virtual NexusSet* nex_input(bool rem_out = true);
|
||||
virtual void nex_output(NexusSet&out);
|
||||
|
||||
virtual bool synth_async(Design*des, NetScope*scope,
|
||||
@@ -3313,8 +3354,10 @@ class NetEvWait : public NetProc {
|
||||
NetBus&accumulated_nex_out);
|
||||
|
||||
virtual bool synth_sync(Design*des, NetScope*scope,
|
||||
bool&ff_negedge,
|
||||
NetNet*ff_clk, NetBus&ff_ce,
|
||||
NetBus&ff_aclr,NetBus&ff_aset,
|
||||
vector<verinum>&ff_aset_value,
|
||||
NexusSet&nex_map, NetBus&nex_out,
|
||||
const std::vector<NetEvProbe*>&events);
|
||||
|
||||
@@ -4650,6 +4693,7 @@ class NetECast : public NetEUnary {
|
||||
virtual NetNet* synthesize(Design*, NetScope*scope, NetExpr*root);
|
||||
virtual NetECast* dup_expr() const;
|
||||
virtual ivl_variable_type_t expr_type() const;
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
private:
|
||||
virtual NetExpr* eval_arguments_(const NetExpr*ex) const;
|
||||
@@ -4746,7 +4790,8 @@ class Design : public Definitions {
|
||||
|
||||
const char* get_flag(const string&key) const;
|
||||
|
||||
NetScope* make_root_scope(perm_string name, bool program_block);
|
||||
NetScope* make_root_scope(perm_string name, bool program_block,
|
||||
bool is_interface);
|
||||
NetScope* find_root_scope();
|
||||
std::list<NetScope*> find_root_scopes() const;
|
||||
|
||||
@@ -4989,4 +5034,5 @@ inline unsigned Link::get_pin() const
|
||||
return pin_;
|
||||
}
|
||||
|
||||
#undef ENUM_UNSIGNED_INT
|
||||
#endif /* IVL_netlist_H */
|
||||
|
||||
+125
-24
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2001-2016 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
|
||||
@@ -203,7 +203,7 @@ static NetExpr* make_add_expr(NetExpr*expr, long val)
|
||||
}
|
||||
|
||||
verinum val_v (val, expr->expr_width());
|
||||
val_v.has_sign(true);
|
||||
val_v.has_sign(expr->has_sign());
|
||||
|
||||
NetEConst*val_c = new NetEConst(val_v);
|
||||
val_c->set_line(*expr);
|
||||
@@ -236,7 +236,7 @@ static NetExpr* make_add_expr(const LineInfo*loc, NetExpr*expr1, NetExpr*expr2)
|
||||
static NetExpr* make_sub_expr(long val, NetExpr*expr)
|
||||
{
|
||||
verinum val_v (val, expr->expr_width());
|
||||
val_v.has_sign(true);
|
||||
val_v.has_sign(expr->has_sign());
|
||||
|
||||
NetEConst*val_c = new NetEConst(val_v);
|
||||
val_c->set_line(*expr);
|
||||
@@ -248,21 +248,50 @@ static NetExpr* make_sub_expr(long val, NetExpr*expr)
|
||||
return res;
|
||||
}
|
||||
|
||||
static NetExpr* make_mult_expr(NetExpr*expr, unsigned long val)
|
||||
/*
|
||||
* Subtract a signed constant from an existing expression.
|
||||
*/
|
||||
static NetExpr* make_sub_expr(NetExpr*expr, long val)
|
||||
{
|
||||
verinum val_v (val, expr->expr_width());
|
||||
val_v.has_sign(true);
|
||||
val_v.has_sign(expr->has_sign());
|
||||
|
||||
NetEConst*val_c = new NetEConst(val_v);
|
||||
val_c->set_line(*expr);
|
||||
|
||||
NetEBMult*res = new NetEBMult('*', expr, val_c, expr->expr_width(),
|
||||
NetEBAdd*res = new NetEBAdd('-', expr, val_c, expr->expr_width(),
|
||||
expr->has_sign());
|
||||
res->set_line(*expr);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Multiply an existing expression by a signed positive number.
|
||||
* This does a lossless multiply, so the arguments will need to be
|
||||
* sized to match the output size.
|
||||
*/
|
||||
static NetExpr* make_mult_expr(NetExpr*expr, unsigned long val)
|
||||
{
|
||||
const unsigned val_wid = ceil(log2((double)val)) ;
|
||||
unsigned use_wid = expr->expr_width() + val_wid;
|
||||
verinum val_v (val, use_wid);
|
||||
val_v.has_sign(expr->has_sign());
|
||||
|
||||
NetEConst*val_c = new NetEConst(val_v);
|
||||
val_c->set_line(*expr);
|
||||
|
||||
// We know by definitions that the expr argument needs to be
|
||||
// padded to be the right argument width for this lossless multiply.
|
||||
expr = pad_to_width(expr, use_wid, *expr);
|
||||
|
||||
NetEBMult*res = new NetEBMult('*', expr, val_c, use_wid, expr->has_sign());
|
||||
res->set_line(*expr);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* This routine is used to calculate the number of bits needed to
|
||||
* contain the given number.
|
||||
@@ -424,17 +453,41 @@ NetExpr *normalize_variable_slice_base(const list<long>&indices, NetExpr*base,
|
||||
-- pcur;
|
||||
}
|
||||
|
||||
long sb;
|
||||
if (pcur->get_msb() >= pcur->get_lsb())
|
||||
sb = pcur->get_lsb();
|
||||
else
|
||||
sb = pcur->get_msb();
|
||||
|
||||
long sb = min(pcur->get_lsb(), pcur->get_msb());
|
||||
long loff;
|
||||
reg->sb_to_slice(indices, sb, loff, lwid);
|
||||
|
||||
base = make_mult_expr(base, lwid);
|
||||
base = make_add_expr(base, loff);
|
||||
unsigned min_wid = base->expr_width();
|
||||
if ((sb < 0) && !base->has_sign()) min_wid += 1;
|
||||
if (min_wid < num_bits(pcur->get_lsb())) min_wid = pcur->get_lsb();
|
||||
if (min_wid < num_bits(pcur->get_msb())) min_wid = pcur->get_msb();
|
||||
base = pad_to_width(base, min_wid, *base);
|
||||
if ((sb < 0) && !base->has_sign()) {
|
||||
NetESelect *tmp = new NetESelect(base, 0 , min_wid);
|
||||
tmp->set_line(*base);
|
||||
tmp->cast_signed(true);
|
||||
base = tmp;
|
||||
}
|
||||
|
||||
if (pcur->get_msb() >= pcur->get_lsb()) {
|
||||
if (pcur->get_lsb() != 0)
|
||||
base = make_sub_expr(base, pcur->get_lsb());
|
||||
base = make_mult_expr(base, lwid);
|
||||
min_wid = base->expr_width();
|
||||
if (min_wid < num_bits(loff)) min_wid = num_bits(loff);
|
||||
if (loff != 0) min_wid += 1;
|
||||
base = pad_to_width(base, min_wid, *base);
|
||||
base = make_add_expr(base, loff);
|
||||
} else {
|
||||
if (pcur->get_msb() != 0)
|
||||
base = make_sub_expr(base, pcur->get_msb());
|
||||
base = make_mult_expr(base, lwid);
|
||||
min_wid = base->expr_width();
|
||||
if (min_wid < num_bits(loff)) min_wid = num_bits(loff);
|
||||
if (loff != 0) min_wid += 1;
|
||||
base = pad_to_width(base, min_wid, *base);
|
||||
base = make_sub_expr(loff, base);
|
||||
}
|
||||
return base;
|
||||
}
|
||||
|
||||
@@ -490,7 +543,7 @@ void indices_to_expressions(Design*des, NetScope*scope,
|
||||
}
|
||||
ivl_assert(*loc, cur->msb);
|
||||
|
||||
NetExpr*word_index = elab_and_eval(des, scope, cur->msb, -1, need_const);
|
||||
NetExpr*word_index = elab_and_eval_lossless(des, scope, cur->msb, -2, need_const);
|
||||
|
||||
if (word_index == 0)
|
||||
flags.invalid = true;
|
||||
@@ -680,7 +733,8 @@ NetExpr* make_canonical_index(Design*des, NetScope*scope,
|
||||
indices_flags flags;
|
||||
indices_to_expressions(des, scope, loc,
|
||||
src, src.size(),
|
||||
need_const, flags,
|
||||
need_const,
|
||||
flags,
|
||||
indices_expr, indices_const);
|
||||
|
||||
if (flags.undefined) {
|
||||
@@ -790,13 +844,17 @@ NetExpr* condition_reduce(NetExpr*expr)
|
||||
return cmp;
|
||||
}
|
||||
|
||||
NetExpr* elab_and_eval(Design*des, NetScope*scope, PExpr*pe,
|
||||
int context_width, bool need_const, bool annotatable,
|
||||
ivl_variable_type_t cast_type)
|
||||
static NetExpr* do_elab_and_eval(Design*des, NetScope*scope, PExpr*pe,
|
||||
int context_width, bool need_const,
|
||||
bool annotatable, bool force_expand,
|
||||
ivl_variable_type_t cast_type,
|
||||
bool force_unsigned)
|
||||
{
|
||||
PExpr::width_mode_t mode = PExpr::SIZED;
|
||||
if ((context_width == -2) && !gn_strict_expr_width_flag)
|
||||
mode = PExpr::EXPAND;
|
||||
if (force_expand)
|
||||
mode = PExpr::EXPAND;
|
||||
|
||||
pe->test_width(des, scope, mode);
|
||||
|
||||
@@ -810,13 +868,20 @@ NetExpr* elab_and_eval(Design*des, NetScope*scope, PExpr*pe,
|
||||
if ((pe->expr_type() != IVL_VT_REAL) && (expr_width < pos_context_width))
|
||||
expr_width = pos_context_width;
|
||||
|
||||
// If this is the RHS of a compressed assignment, the LHS also
|
||||
// affects the expression type (signed/unsigned).
|
||||
if (force_unsigned)
|
||||
pe->cast_signed(false);
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << pe->get_fileline() << ": elab_and_eval: test_width of "
|
||||
<< *pe << endl;
|
||||
cerr << pe->get_fileline() << ": : "
|
||||
<< "returns type=" << pe->expr_type()
|
||||
<< ", width=" << expr_width
|
||||
<< ", context_width=" << context_width
|
||||
<< ", signed=" << pe->has_sign()
|
||||
<< ", force_expand=" << force_expand
|
||||
<< ", expr_width=" << expr_width
|
||||
<< ", mode=" << PExpr::width_mode_name(mode) << endl;
|
||||
cerr << pe->get_fileline() << ": : "
|
||||
<< "cast_type=" << cast_type << endl;
|
||||
@@ -824,6 +889,7 @@ NetExpr* elab_and_eval(Design*des, NetScope*scope, PExpr*pe,
|
||||
|
||||
// If we can get the same result using a smaller expression
|
||||
// width, do so.
|
||||
|
||||
unsigned min_width = pe->min_width();
|
||||
if ((min_width != UINT_MAX) && (pe->expr_type() != IVL_VT_REAL)
|
||||
&& (pos_context_width > 0) && (expr_width > pos_context_width)) {
|
||||
@@ -850,6 +916,11 @@ NetExpr* elab_and_eval(Design*des, NetScope*scope, PExpr*pe,
|
||||
if (annotatable)
|
||||
flags |= PExpr::ANNOTATABLE;
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << pe->get_fileline() << ": elab_and_eval: "
|
||||
<< "Calculated width is " << expr_width << "." << endl;
|
||||
}
|
||||
|
||||
NetExpr*tmp = pe->elaborate_expr(des, scope, expr_width, flags);
|
||||
if (tmp == 0) return 0;
|
||||
|
||||
@@ -869,6 +940,13 @@ NetExpr* elab_and_eval(Design*des, NetScope*scope, PExpr*pe,
|
||||
}
|
||||
}
|
||||
|
||||
// If the context_width sent is is actually the minimum width,
|
||||
// then raise the context_width to be big enough for the
|
||||
// lossless expression.
|
||||
if (force_expand && context_width > 0) {
|
||||
context_width = max(context_width, (int)expr_width);
|
||||
}
|
||||
|
||||
eval_expr(tmp, context_width);
|
||||
|
||||
if (NetEConst*ce = dynamic_cast<NetEConst*>(tmp)) {
|
||||
@@ -879,6 +957,29 @@ NetExpr* elab_and_eval(Design*des, NetScope*scope, PExpr*pe,
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetExpr* elab_and_eval(Design*des, NetScope*scope, PExpr*pe,
|
||||
int context_width, bool need_const, bool annotatable,
|
||||
ivl_variable_type_t cast_type, bool force_unsigned)
|
||||
{
|
||||
return do_elab_and_eval(des, scope, pe, context_width,
|
||||
need_const, annotatable, false,
|
||||
cast_type, force_unsigned);
|
||||
}
|
||||
|
||||
/*
|
||||
* This variant of elab_and_eval does the expression losslessly, no
|
||||
* matter what the generation of Verilog. This is in support of
|
||||
* certain special contexts, notably index expressions.
|
||||
*/
|
||||
NetExpr* elab_and_eval_lossless(Design*des, NetScope*scope, PExpr*pe,
|
||||
int context_width, bool need_const, bool annotatable,
|
||||
ivl_variable_type_t cast_type)
|
||||
{
|
||||
return do_elab_and_eval(des, scope, pe, context_width,
|
||||
need_const, annotatable, true,
|
||||
cast_type, false);
|
||||
}
|
||||
|
||||
NetExpr* elab_and_eval(Design*des, NetScope*scope, PExpr*pe,
|
||||
ivl_type_t lv_net_type, bool need_const)
|
||||
{
|
||||
@@ -929,7 +1030,7 @@ NetExpr* elab_sys_task_arg(Design*des, NetScope*scope, perm_string name,
|
||||
// determine the exact width required to hold the result.
|
||||
// But leave literal numbers exactly as the user supplied
|
||||
// them.
|
||||
if ((mode >= PExpr::LOSSLESS) && !dynamic_cast<PENumber*>(pe))
|
||||
if ((mode >= PExpr::LOSSLESS) && !dynamic_cast<PENumber*>(pe) && tmp->expr_width()>32)
|
||||
ce->trim();
|
||||
}
|
||||
|
||||
@@ -1342,8 +1443,8 @@ bool evaluate_index_prefix(Design*des, NetScope*scope,
|
||||
{
|
||||
list<index_component_t>::const_iterator icur = indices.begin();
|
||||
for (size_t idx = 0 ; (idx+1) < indices.size() ; idx += 1, ++icur) {
|
||||
assert(icur != indices.end());
|
||||
assert(icur->sel == index_component_t::SEL_BIT);
|
||||
ivl_assert(*(icur->msb), icur != indices.end());
|
||||
ivl_assert(*(icur->msb), icur->sel == index_component_t::SEL_BIT);
|
||||
NetExpr*texpr = elab_and_eval(des, scope, icur->msb, -1, true);
|
||||
|
||||
long tmp;
|
||||
@@ -1354,7 +1455,7 @@ bool evaluate_index_prefix(Design*des, NetScope*scope,
|
||||
return false;
|
||||
}
|
||||
|
||||
prefix_indices .push_back(tmp);
|
||||
prefix_indices.push_back(tmp);
|
||||
delete texpr;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef IVL_netmisc_H
|
||||
#define IVL_netmisc_H
|
||||
/*
|
||||
* Copyright (c) 1999-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2016 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
|
||||
@@ -60,12 +60,32 @@ inline NetScope* symbol_search(const LineInfo*li,
|
||||
}
|
||||
|
||||
/*
|
||||
* This function transforms an expression by padding the high bits
|
||||
* with V0 until the expression has the desired width. This may mean
|
||||
* not transforming the expression at all, if it is already wide
|
||||
* enough.
|
||||
* This function transforms an expression by either zero or sign extending
|
||||
* the high bits until the expression has the desired width. This may mean
|
||||
* not transforming the expression at all, if it is already wide enough.
|
||||
* The extension method and the returned expression type is determined by
|
||||
* signed_flag.
|
||||
*/
|
||||
extern NetExpr*pad_to_width(NetExpr*expr, unsigned wid, const LineInfo&info);
|
||||
extern NetExpr*pad_to_width(NetExpr*expr, unsigned wid, bool signed_flag,
|
||||
const LineInfo&info);
|
||||
/*
|
||||
* This version determines the extension method from the base expression type.
|
||||
*/
|
||||
inline NetExpr*pad_to_width(NetExpr*expr, unsigned wid, const LineInfo&info)
|
||||
{
|
||||
return pad_to_width(expr, wid, expr->has_sign(), info);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function transforms an expression by either zero or sign extending
|
||||
* or discarding the high bits until the expression has the desired width.
|
||||
* This may mean not transforming the expression at all, if it is already
|
||||
* the correct width. The extension method (if needed) and the returned
|
||||
* expression type is determined by signed_flag.
|
||||
*/
|
||||
extern NetExpr*cast_to_width(NetExpr*expr, unsigned wid, bool signed_flag,
|
||||
const LineInfo&info);
|
||||
|
||||
extern NetNet*pad_to_width(Design*des, NetNet*n, unsigned w,
|
||||
const LineInfo&info);
|
||||
|
||||
@@ -255,6 +275,13 @@ extern unsigned count_lval_width(const class NetAssign_*first);
|
||||
class PExpr;
|
||||
|
||||
extern NetExpr* elab_and_eval(Design*des, NetScope*scope,
|
||||
PExpr*pe, int context_width,
|
||||
bool need_const =false,
|
||||
bool annotatable =false,
|
||||
ivl_variable_type_t cast_type =IVL_VT_NO_TYPE,
|
||||
bool force_unsigned =false);
|
||||
|
||||
extern NetExpr* elab_and_eval_lossless(Design*des, NetScope*scope,
|
||||
PExpr*pe, int context_width,
|
||||
bool need_const =false,
|
||||
bool annotatable =false,
|
||||
@@ -291,7 +318,8 @@ extern NetExpr* elaborate_rval_expr(Design*des, NetScope*scope,
|
||||
ivl_type_t lv_net_type,
|
||||
ivl_variable_type_t lv_type,
|
||||
unsigned lv_width, PExpr*expr,
|
||||
bool need_const =false);
|
||||
bool need_const =false,
|
||||
bool force_unsigned =false);
|
||||
|
||||
extern bool evaluate_ranges(Design*des, NetScope*scope,
|
||||
std::vector<netrange_t>&llist,
|
||||
|
||||
@@ -34,6 +34,12 @@ netparray_t::~netparray_t()
|
||||
* The packed width of a packed array is the packed width of the
|
||||
* element times the dimension width of the array itself.
|
||||
*/
|
||||
|
||||
bool netparray_t::packed(void) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
long netparray_t::packed_width(void) const
|
||||
{
|
||||
long cur_width = element_type()->packed_width();
|
||||
|
||||
@@ -64,6 +64,7 @@ class netparray_t : public netsarray_t {
|
||||
|
||||
public:
|
||||
// Virtual methods from the ivl_type_s type...
|
||||
bool packed(void) const;
|
||||
long packed_width(void) const;
|
||||
std::vector<netrange_t> slice_dimensions() const;
|
||||
|
||||
|
||||
+4
-1
@@ -1,7 +1,7 @@
|
||||
#ifndef IVL__netqueue_H
|
||||
#define IVL__netqueue_H
|
||||
/*
|
||||
* Copyright (c) 2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2014-2015 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
|
||||
@@ -38,6 +38,9 @@ class netqueue_t : public netdarray_t {
|
||||
// IVL_VT_QUEUE for queues.
|
||||
ivl_variable_type_t base_type() const;
|
||||
|
||||
// A queue may have a type that is signed.
|
||||
inline bool get_signed() const { return element_type()->get_signed(); }
|
||||
|
||||
std::ostream& debug_dump(std::ostream&) const;
|
||||
|
||||
private:
|
||||
|
||||
+3
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012-2013 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2012-2016 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
|
||||
@@ -141,19 +141,18 @@ bool prefix_to_slice(const std::vector<netrange_t>&dims,
|
||||
|
||||
// Now similarly go through the prefix numbers, working
|
||||
// through the dimensions until we run out. Accumulate a
|
||||
// growing slice width (acc_wid) that is used to caculate the
|
||||
// growing slice width (acc_wid) that is used to calculate the
|
||||
// growing offset (acc_off).
|
||||
list<long>::const_iterator icur = prefix.end();
|
||||
do {
|
||||
-- icur;
|
||||
acc_wid *= pcur->width();
|
||||
-- pcur;
|
||||
if (pcur->get_msb() >= pcur->get_lsb())
|
||||
acc_off += (*icur - pcur->get_lsb()) * acc_wid;
|
||||
else
|
||||
acc_off += (pcur->get_lsb() - *icur) * acc_wid;
|
||||
|
||||
-- pcur;
|
||||
|
||||
} while (icur != prefix.begin());
|
||||
|
||||
// Got our final offset.
|
||||
|
||||
+1
-1
@@ -94,7 +94,7 @@ class netrange_t {
|
||||
inline netrange_t() : msb_(LONG_MAX), lsb_(LONG_MAX) { }
|
||||
// Create a properly defined netrange
|
||||
inline netrange_t(long m, long l) : msb_(m), lsb_(l) { }
|
||||
// Copy constructure.
|
||||
// Copy constructor.
|
||||
inline netrange_t(const netrange_t&that)
|
||||
: msb_(that.msb_), lsb_(that.lsb_) { }
|
||||
|
||||
|
||||
+32
-11
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2011 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2016 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,21 +24,20 @@
|
||||
# include "netmisc.h"
|
||||
|
||||
|
||||
/*
|
||||
* This function transforms an expression by padding the high bits
|
||||
* with V0 until the expression has the desired width. This may mean
|
||||
* not transforming the expression at all, if it is already wide
|
||||
* enough.
|
||||
*/
|
||||
NetExpr*pad_to_width(NetExpr*expr, unsigned wid, const LineInfo&info)
|
||||
NetExpr*pad_to_width(NetExpr*expr, unsigned wid, bool signed_flag,
|
||||
const LineInfo&info)
|
||||
{
|
||||
if (wid <= expr->expr_width())
|
||||
if (wid <= expr->expr_width()) {
|
||||
expr->cast_signed(signed_flag);
|
||||
return expr;
|
||||
}
|
||||
|
||||
/* If the expression is a const, then replace it with a wider
|
||||
const. This is a more efficient result. */
|
||||
if (NetEConst*tmp = dynamic_cast<NetEConst*>(expr)) {
|
||||
verinum oval = pad_to_width(tmp->value(), wid);
|
||||
verinum oval = tmp->value();
|
||||
oval.has_sign(signed_flag);
|
||||
oval = pad_to_width(oval, wid);
|
||||
tmp = new NetEConst(oval);
|
||||
tmp->set_line(info);
|
||||
delete expr;
|
||||
@@ -46,8 +45,30 @@ NetExpr*pad_to_width(NetExpr*expr, unsigned wid, const LineInfo&info)
|
||||
}
|
||||
|
||||
NetESelect*tmp = new NetESelect(expr, 0, wid);
|
||||
tmp->cast_signed(signed_flag);
|
||||
tmp->set_line(info);
|
||||
tmp->cast_signed(expr->has_sign());
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetExpr*cast_to_width(NetExpr*expr, unsigned wid, bool signed_flag,
|
||||
const LineInfo&info)
|
||||
{
|
||||
/* If the expression is a const, then replace it with a new
|
||||
const. This is a more efficient result. */
|
||||
if (NetEConst*tmp = dynamic_cast<NetEConst*>(expr)) {
|
||||
tmp->cast_signed(signed_flag);
|
||||
if (wid != tmp->expr_width()) {
|
||||
tmp = new NetEConst(verinum(tmp->value(), wid));
|
||||
tmp->set_line(info);
|
||||
delete expr;
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetESelect*tmp = new NetESelect(expr, 0, wid);
|
||||
tmp->cast_signed(signed_flag);
|
||||
tmp->set_line(info);
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef IVL_pform_H
|
||||
#define IVL_pform_H
|
||||
/*
|
||||
* Copyright (c) 1998-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2016 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
|
||||
@@ -136,6 +136,10 @@ extern void pform_set_default_nettype(NetNet::Type net,
|
||||
used to reject statements that cannot exist in program blocks. */
|
||||
extern bool pform_in_program_block(void);
|
||||
|
||||
/* Return true if currently processing an interface. This can be
|
||||
used to reject statements that cannot exist in interfaces. */
|
||||
extern bool pform_in_interface(void);
|
||||
|
||||
/*
|
||||
* Look for the given wire in the current lexical scope. If the wire
|
||||
* (including variables of any type) cannot be found in the current
|
||||
@@ -152,23 +156,33 @@ extern PWire* pform_get_make_wire_in_scope(perm_string name, NetNet::Type net_ty
|
||||
* are to apply to the scope of that module. The endmodule causes the
|
||||
* pform to close up and finish the named module.
|
||||
*
|
||||
* The program_flag indicates that the module is actually a program
|
||||
* block. This has implications during parse and during
|
||||
* The program_block flag indicates that the module is actually a program
|
||||
* block. The is_interface flag indicates that the module is actually
|
||||
* an interface. These flags have implications during parse and during
|
||||
* elaboration/code generation.
|
||||
*/
|
||||
extern void pform_startmodule(const struct vlltype&loc, const char*name,
|
||||
bool program_block, list<named_pexpr_t>*attr);
|
||||
bool program_block, bool is_interface,
|
||||
LexicalScope::lifetime_t lifetime,
|
||||
list<named_pexpr_t>*attr);
|
||||
extern void pform_check_timeunit_prec();
|
||||
extern void pform_module_set_ports(vector<Module::port_t*>*);
|
||||
|
||||
/* This function is used to support the port definition in a
|
||||
port_definition_list. In this case, we have everything needed to
|
||||
define the port, all in one place. */
|
||||
/* These functions are used when we have a complete port definition, either
|
||||
in an ansi style or non-ansi style declaration. In this case, we have
|
||||
everything needed to define the port, all in one place. */
|
||||
extern void pform_module_define_port(const struct vlltype&li,
|
||||
perm_string name,
|
||||
NetNet::PortType,
|
||||
NetNet::Type type,
|
||||
data_type_t*vtype,
|
||||
list<named_pexpr_t>*attr,
|
||||
bool keep_attr =false);
|
||||
extern void pform_module_define_port(const struct vlltype&li,
|
||||
list<pform_port_t>*ports,
|
||||
NetNet::PortType,
|
||||
NetNet::Type type,
|
||||
data_type_t*vtype,
|
||||
list<named_pexpr_t>*attr);
|
||||
|
||||
extern Module::port_t* pform_module_port_reference(perm_string name,
|
||||
@@ -180,7 +194,8 @@ extern void pform_endmodule(const char*, bool inside_celldefine,
|
||||
extern void pform_start_class_declaration(const struct vlltype&loc,
|
||||
class_type_t*type,
|
||||
data_type_t*base_type,
|
||||
std::list<PExpr*>*base_exprs);
|
||||
std::list<PExpr*>*base_exprs,
|
||||
LexicalScope::lifetime_t lifetime);
|
||||
extern void pform_class_property(const struct vlltype&loc,
|
||||
property_qualifier_t pq,
|
||||
data_type_t*data_type,
|
||||
@@ -205,7 +220,8 @@ extern void pform_make_udp(perm_string name,
|
||||
* Package related functions.
|
||||
*/
|
||||
extern void pform_start_package_declaration(const struct vlltype&loc,
|
||||
const char*type);
|
||||
const char*type,
|
||||
LexicalScope::lifetime_t lifetime);
|
||||
extern void pform_end_package_declaration(const struct vlltype&loc);
|
||||
extern void pform_package_import(const struct vlltype&loc,
|
||||
PPackage*pkg, const char*ident);
|
||||
@@ -213,6 +229,15 @@ extern void pform_package_import(const struct vlltype&loc,
|
||||
extern PExpr* pform_package_ident(const struct vlltype&loc,
|
||||
PPackage*pkg, pform_name_t*ident);
|
||||
|
||||
/*
|
||||
* Interface related functions.
|
||||
*/
|
||||
extern void pform_start_modport_item(const struct vlltype&loc, const char*name);
|
||||
extern void pform_end_modport_item(const struct vlltype&loc);
|
||||
extern void pform_add_modport_port(const struct vlltype&loc,
|
||||
NetNet::PortType port_type,
|
||||
perm_string name, PExpr*expr);
|
||||
|
||||
/*
|
||||
* This creates an identifier aware of names that may have been
|
||||
* imported from other packages.
|
||||
@@ -231,13 +256,20 @@ extern void pform_pop_scope();
|
||||
*/
|
||||
extern LexicalScope* pform_peek_scope();
|
||||
|
||||
extern PClass* pform_push_class_scope(const struct vlltype&loc, perm_string name);
|
||||
extern PClass* pform_push_class_scope(const struct vlltype&loc, perm_string name,
|
||||
LexicalScope::lifetime_t lifetime);
|
||||
|
||||
extern PFunction*pform_push_constructor_scope(const struct vlltype&loc);
|
||||
extern PPackage* pform_push_package_scope(const struct vlltype&loc, perm_string name);
|
||||
|
||||
extern PPackage* pform_push_package_scope(const struct vlltype&loc, perm_string name,
|
||||
LexicalScope::lifetime_t lifetime);
|
||||
|
||||
extern PTask*pform_push_task_scope(const struct vlltype&loc, char*name,
|
||||
bool is_auto);
|
||||
LexicalScope::lifetime_t lifetime);
|
||||
|
||||
extern PFunction*pform_push_function_scope(const struct vlltype&loc, const char*name,
|
||||
bool is_auto);
|
||||
LexicalScope::lifetime_t lifetime);
|
||||
|
||||
extern PBlock*pform_push_block_scope(char*name, PBlock::BL_TYPE tt);
|
||||
|
||||
extern void pform_put_behavior_in_scope(AProcess*proc);
|
||||
@@ -272,7 +304,8 @@ extern void pform_endgenerate();
|
||||
*/
|
||||
extern PGenerate* pform_parent_generate(void);
|
||||
|
||||
extern void pform_set_typedef(perm_string name, data_type_t*data_type);
|
||||
extern void pform_set_typedef(perm_string name, data_type_t*data_type,
|
||||
std::list<pform_range_t>*unp_ranges);
|
||||
|
||||
/*
|
||||
* This function makes a PECallFunction of the named function. Decide
|
||||
@@ -335,17 +368,17 @@ extern void pform_makewire(const struct vlltype&li,
|
||||
list<perm_string>*names,
|
||||
list<named_pexpr_t>*attr);
|
||||
|
||||
extern void pform_make_reginit(const struct vlltype&li,
|
||||
perm_string name, PExpr*expr);
|
||||
extern void pform_make_var_init(const struct vlltype&li,
|
||||
perm_string name, PExpr*expr);
|
||||
|
||||
/* Look up the names of the wires, and set the port type,
|
||||
i.e. input, output or inout. If the wire does not exist, create
|
||||
it. The second form takes a single name. */
|
||||
/* This function is used when we have an incomplete port definition in
|
||||
a non-ansi style declaration. Look up the names of the wires, and set
|
||||
the port type, i.e. input, output or inout, and, if specified, the
|
||||
range and signedness. If the wire does not exist, create it. */
|
||||
extern void pform_set_port_type(const struct vlltype&li,
|
||||
list<perm_string>*names,
|
||||
list<pform_range_t>*range,
|
||||
bool signed_flag,
|
||||
list<pform_port_t>*ports,
|
||||
NetNet::PortType,
|
||||
data_type_t*dt,
|
||||
list<named_pexpr_t>*attr);
|
||||
|
||||
extern void pform_set_reg_idx(perm_string name,
|
||||
|
||||
+51
-10
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2016 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
|
||||
@@ -318,7 +318,7 @@ void PECallFunction::dump(ostream &out) const
|
||||
|
||||
void PECastSize::dump(ostream &out) const
|
||||
{
|
||||
out << size_ << "'(";
|
||||
out << *size_ << "'(";
|
||||
base_->dump(out);
|
||||
out << ")";
|
||||
}
|
||||
@@ -789,6 +789,8 @@ void PBlock::dump(ostream&out, unsigned ind) const
|
||||
dump_events_(out, ind+2);
|
||||
|
||||
dump_wires_(out, ind+2);
|
||||
|
||||
dump_var_inits_(out, ind+2);
|
||||
}
|
||||
|
||||
for (unsigned idx = 0 ; idx < list_.size() ; idx += 1) {
|
||||
@@ -926,7 +928,10 @@ void PDisable::dump(ostream&out, unsigned ind) const
|
||||
void PDoWhile::dump(ostream&out, unsigned ind) const
|
||||
{
|
||||
out << setw(ind) << "" << "do" << endl;
|
||||
statement_->dump(out, ind+3);
|
||||
if (statement_)
|
||||
statement_->dump(out, ind+3);
|
||||
else
|
||||
out << setw(ind+3) << "" << "/* NOOP */" << endl;
|
||||
out << setw(ind) << "" << "while (" << *cond_ << ");" << endl;
|
||||
}
|
||||
|
||||
@@ -989,13 +994,19 @@ void PForeach::dump(ostream&fd, unsigned ind) const
|
||||
}
|
||||
|
||||
fd << "] /* " << get_fileline() << " */" << endl;
|
||||
statement_->dump(fd, ind+3);
|
||||
if (statement_)
|
||||
statement_->dump(fd, ind+3);
|
||||
else
|
||||
fd << setw(ind+3) << "" << "/* NOOP */" << endl;
|
||||
}
|
||||
|
||||
void PForever::dump(ostream&out, unsigned ind) const
|
||||
{
|
||||
out << setw(ind) << "" << "forever /* " << get_fileline() << " */" << endl;
|
||||
statement_->dump(out, ind+3);
|
||||
if (statement_)
|
||||
statement_->dump(out, ind+3);
|
||||
else
|
||||
out << setw(ind+3) << "" << "/* NOOP */" << endl;
|
||||
}
|
||||
|
||||
void PForStatement::dump(ostream&out, unsigned ind) const
|
||||
@@ -1003,7 +1014,10 @@ void PForStatement::dump(ostream&out, unsigned ind) const
|
||||
out << setw(ind) << "" << "for (" << *name1_ << " = " << *expr1_
|
||||
<< "; " << *cond_ << "; <for_step>)" << endl;
|
||||
step_->dump(out, ind+6);
|
||||
statement_->dump(out, ind+3);
|
||||
if (statement_)
|
||||
statement_->dump(out, ind+3);
|
||||
else
|
||||
out << setw(ind+3) << "" << "/* NOOP */" << endl;
|
||||
}
|
||||
|
||||
void PFunction::dump(ostream&out, unsigned ind) const
|
||||
@@ -1030,6 +1044,8 @@ void PFunction::dump(ostream&out, unsigned ind) const
|
||||
|
||||
dump_wires_(out, ind+2);
|
||||
|
||||
dump_var_inits_(out, ind+2);
|
||||
|
||||
if (statement_)
|
||||
statement_->dump(out, ind+2);
|
||||
else
|
||||
@@ -1045,7 +1061,10 @@ void PRelease::dump(ostream&out, unsigned ind) const
|
||||
void PRepeat::dump(ostream&out, unsigned ind) const
|
||||
{
|
||||
out << setw(ind) << "" << "repeat (" << *expr_ << ")" << endl;
|
||||
statement_->dump(out, ind+3);
|
||||
if (statement_)
|
||||
statement_->dump(out, ind+3);
|
||||
else
|
||||
out << setw(ind+3) << "" << "/* NOOP */" << endl;
|
||||
}
|
||||
|
||||
void PReturn::dump(ostream&fd, unsigned ind) const
|
||||
@@ -1072,6 +1091,8 @@ void PTask::dump(ostream&out, unsigned ind) const
|
||||
|
||||
dump_wires_(out, ind+2);
|
||||
|
||||
dump_var_inits_(out, ind+2);
|
||||
|
||||
if (statement_)
|
||||
statement_->dump(out, ind+2);
|
||||
else
|
||||
@@ -1126,7 +1147,10 @@ void PTrigger::dump(ostream&out, unsigned ind) const
|
||||
void PWhile::dump(ostream&out, unsigned ind) const
|
||||
{
|
||||
out << setw(ind) << "" << "while (" << *cond_ << ")" << endl;
|
||||
statement_->dump(out, ind+3);
|
||||
if (statement_)
|
||||
statement_->dump(out, ind+3);
|
||||
else
|
||||
out << setw(ind+3) << "" << "/* NOOP */" << endl;
|
||||
}
|
||||
|
||||
void PProcess::dump(ostream&out, unsigned ind) const
|
||||
@@ -1136,7 +1160,10 @@ void PProcess::dump(ostream&out, unsigned ind) const
|
||||
|
||||
dump_attributes_map(out, attributes, ind+2);
|
||||
|
||||
statement_->dump(out, ind+2);
|
||||
if (statement_)
|
||||
statement_->dump(out, ind+2);
|
||||
else
|
||||
out << setw(ind+2) << "" << "/* NOOP */" << endl;
|
||||
}
|
||||
|
||||
void AProcess::dump(ostream&out, unsigned ind) const
|
||||
@@ -1157,7 +1184,10 @@ void AProcess::dump(ostream&out, unsigned ind) const
|
||||
|
||||
dump_attributes_map(out, attributes, ind+2);
|
||||
|
||||
statement_->dump(out, ind+2);
|
||||
if (statement_)
|
||||
statement_->dump(out, ind+2);
|
||||
else
|
||||
out << setw(ind+2) << "" << "/* NOOP */" << endl;
|
||||
}
|
||||
|
||||
void PSpecPath::dump(std::ostream&out, unsigned ind) const
|
||||
@@ -1269,6 +1299,8 @@ void PGenerate::dump(ostream&out, unsigned indent) const
|
||||
(*idx)->dump(out, indent+2);
|
||||
}
|
||||
|
||||
dump_var_inits_(out, indent+2);
|
||||
|
||||
for (list<PProcess*>::const_iterator idx = behaviors.begin()
|
||||
; idx != behaviors.end() ; ++ idx ) {
|
||||
(*idx)->dump(out, indent+2);
|
||||
@@ -1408,6 +1440,14 @@ void LexicalScope::dump_wires_(ostream&out, unsigned indent) const
|
||||
}
|
||||
}
|
||||
|
||||
void LexicalScope::dump_var_inits_(ostream&out, unsigned indent) const
|
||||
{
|
||||
// Iterate through and display all the register initializations.
|
||||
for (unsigned idx = 0; idx < var_inits.size(); idx += 1) {
|
||||
var_inits[idx]->dump(out, indent);
|
||||
}
|
||||
}
|
||||
|
||||
void PScopeExtra::dump_classes_(ostream&out, unsigned indent) const
|
||||
{
|
||||
// Dump the task definitions.
|
||||
@@ -1564,6 +1604,7 @@ void Module::dump(ostream&out) const
|
||||
(*gate)->dump(out);
|
||||
}
|
||||
|
||||
dump_var_inits_(out, 4);
|
||||
|
||||
for (list<PProcess*>::const_iterator behav = behaviors.begin()
|
||||
; behav != behaviors.end() ; ++ behav ) {
|
||||
|
||||
+4
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2012-2016 Stephen Williams (steve@icarus.com)
|
||||
* Copyright CERN 2013 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
@@ -35,12 +35,13 @@ map<perm_string,PPackage*> pform_packages;
|
||||
|
||||
static PPackage*pform_cur_package = 0;
|
||||
|
||||
void pform_start_package_declaration(const struct vlltype&loc, const char*name)
|
||||
void pform_start_package_declaration(const struct vlltype&loc, const char*name,
|
||||
LexicalScope::lifetime_t lifetime)
|
||||
{
|
||||
ivl_assert(loc, pform_cur_package == 0);
|
||||
|
||||
perm_string use_name = lex_strings.make(name);
|
||||
PPackage*pkg_scope = pform_push_package_scope(loc, use_name);
|
||||
PPackage*pkg_scope = pform_push_package_scope(loc, use_name, lifetime);
|
||||
FILE_NAME(pkg_scope, loc);
|
||||
pform_cur_package = pkg_scope;
|
||||
}
|
||||
|
||||
+10
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2012-2016 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
|
||||
@@ -36,9 +36,13 @@ static PClass*pform_cur_class = 0;
|
||||
* if present, are the "exprs" that would be passed to a chained
|
||||
* constructor.
|
||||
*/
|
||||
void pform_start_class_declaration(const struct vlltype&loc, class_type_t*type, data_type_t*base_type, list<PExpr*>*base_exprs)
|
||||
void pform_start_class_declaration(const struct vlltype&loc,
|
||||
class_type_t*type,
|
||||
data_type_t*base_type,
|
||||
list<PExpr*>*base_exprs,
|
||||
LexicalScope::lifetime_t lifetime)
|
||||
{
|
||||
PClass*class_scope = pform_push_class_scope(loc, type->name);
|
||||
PClass*class_scope = pform_push_class_scope(loc, type->name, lifetime);
|
||||
class_scope->type = type;
|
||||
assert(pform_cur_class == 0);
|
||||
pform_cur_class = class_scope;
|
||||
@@ -75,6 +79,7 @@ void pform_class_property(const struct vlltype&loc,
|
||||
if (! curp->index.empty()) {
|
||||
list<pform_range_t>*pd = new list<pform_range_t> (curp->index);
|
||||
use_type = new uarray_type_t(use_type, pd);
|
||||
FILE_NAME(use_type, loc);
|
||||
}
|
||||
|
||||
pform_cur_class->type->properties[curp->name]
|
||||
@@ -127,7 +132,7 @@ void pform_set_constructor_return(PFunction*net)
|
||||
PFunction*pform_push_constructor_scope(const struct vlltype&loc)
|
||||
{
|
||||
assert(pform_cur_class);
|
||||
PFunction*func = pform_push_function_scope(loc, "new", true);
|
||||
PFunction*func = pform_push_function_scope(loc, "new", LexicalScope::AUTOMATIC);
|
||||
return func;
|
||||
}
|
||||
|
||||
@@ -138,7 +143,7 @@ void pform_end_class_declaration(const struct vlltype&loc)
|
||||
// If there were initializer statements, then collect them
|
||||
// into an implicit constructor function.
|
||||
if (! pform_cur_class->type->initialize.empty()) {
|
||||
PFunction*func = pform_push_function_scope(loc, "new@", true);
|
||||
PFunction*func = pform_push_function_scope(loc, "new@", LexicalScope::AUTOMATIC);
|
||||
func->set_ports(0);
|
||||
pform_set_constructor_return(func);
|
||||
pform_set_this_class(loc, func);
|
||||
|
||||
@@ -79,8 +79,8 @@ static void pform_set_struct_type(struct_type_t*struct_type, perm_string name, N
|
||||
return;
|
||||
}
|
||||
|
||||
// For now, can only handle packed structs.
|
||||
ivl_assert(*struct_type, 0);
|
||||
// For now, can only handle packed structs. The parser generates
|
||||
// a "sorry" message, so no need to do anything here.
|
||||
}
|
||||
|
||||
void pform_set_struct_type(struct_type_t*struct_type, list<perm_string>*names, NetNet::Type net_type, list<named_pexpr_t>*attr)
|
||||
|
||||
+17
-2
@@ -1,7 +1,7 @@
|
||||
#ifndef IVL_pform_types_H
|
||||
#define IVL_pform_types_H
|
||||
/*
|
||||
* Copyright (c) 2007-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2007-2016 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -50,7 +50,7 @@ typedef named<verinum> named_number_t;
|
||||
typedef named<PExpr*> named_pexpr_t;
|
||||
|
||||
/*
|
||||
* The pform_range_t holds variable diimensions for type
|
||||
* The pform_range_t holds variable dimensions for type
|
||||
* declarations. The two expressions are interpreted as the first and
|
||||
* last values of the range. For example:
|
||||
*
|
||||
@@ -72,6 +72,21 @@ typedef named<PExpr*> named_pexpr_t;
|
||||
*/
|
||||
typedef std::pair<PExpr*,PExpr*> pform_range_t;
|
||||
|
||||
/*
|
||||
* The pform_port_t holds the name and optional unpacked dimensions
|
||||
* and initialization expression for a single port in a list of port
|
||||
* declarations.
|
||||
*/
|
||||
struct pform_port_t {
|
||||
pform_port_t(perm_string n, list<pform_range_t>*ud, PExpr*e)
|
||||
: name(n), udims(ud), expr(e) { }
|
||||
~pform_port_t() { }
|
||||
|
||||
perm_string name;
|
||||
list<pform_range_t>*udims;
|
||||
PExpr*expr;
|
||||
};
|
||||
|
||||
/*
|
||||
* Semantic NOTES:
|
||||
* - The SEL_BIT is a single expression. This might me a bit select
|
||||
|
||||
+11
-7
@@ -4,22 +4,26 @@
|
||||
# the number for a snapshot and the path to a temporary directory.
|
||||
# for example:
|
||||
#
|
||||
# sh scripts/MAKE_RELEASE.sh 0.9.1 ~/tmp
|
||||
# sh scripts/MAKE_RELEASE.sh 10.1 ~/tmp
|
||||
#
|
||||
# The above assumes that there is a tag "v0_9_1" at the point
|
||||
# The above assumes that there is a tag "v10_1" at the point
|
||||
# to be released. (The tag has the "v", but the argument to this
|
||||
# script does not have the "v"). This script extracts based on the
|
||||
# tag, uses the temporary directory to stage intermediate results,
|
||||
# and finally creates a file called verilog-0.9.1.tar.gz that
|
||||
# and finally creates a file called verilog-10.1.tar.gz that
|
||||
# contains the release ready to go.
|
||||
#
|
||||
# The complete steps to make a release x.y.z generally are:
|
||||
# The complete steps to make a release x.y generally are:
|
||||
#
|
||||
# git tag -a v0_9_1
|
||||
# Edit version_base.h to suit.
|
||||
#
|
||||
# Edit verilog.spec to suit.
|
||||
#
|
||||
# git tag -a v10_1
|
||||
# (Make the tag in the local git repository.)
|
||||
#
|
||||
# sh scripts/MAKE_RELEASE.sh 0.9.1 ~/tmp
|
||||
# (Make the snapshot bundle verilog-0.9.1.tar.gz)
|
||||
# sh scripts/MAKE_RELEASE.sh 10.1 ~/tmp
|
||||
# (Make the snapshot bundle verilog-10.1.tar.gz)
|
||||
#
|
||||
# git push --tags
|
||||
# (Publish the tag to the repository.)
|
||||
|
||||
@@ -15,7 +15,7 @@ iwidth:32
|
||||
sys_func:vpi/system.sft
|
||||
sys_func:vpi/v2005_math.sft
|
||||
sys_func:vpi/va_math.sft
|
||||
warnings:ailnpstv
|
||||
warnings:adfilnpstv
|
||||
debug:eval_tree
|
||||
debug:elaborate
|
||||
debug:emit
|
||||
|
||||
@@ -9,6 +9,6 @@
|
||||
#
|
||||
# NOTE: DO NOT INSTALL THIS FILE.
|
||||
|
||||
./ivl -v -Ctgt-stub/stub.conf -C./scripts/devel-stub.conf -Pa.pf -Na.net -fDLL=tgt-stub/stub.tgt foo.vl |& tee foo.log
|
||||
./ivl -v -Ctgt-stub/stub.conf -C./scripts/devel-stub.conf -Pa.pf -Na.net -fDLL=tgt-stub/stub.tgt foo.vl | tee foo.log 2>&1
|
||||
|
||||
echo "*** ivl command completed"
|
||||
|
||||
+1
-1
@@ -88,7 +88,7 @@ static bool symbol_search(const LineInfo*li, Design*des, NetScope*scope,
|
||||
return false;
|
||||
|
||||
// The prefix is found to be a scope, so switch to that
|
||||
// scope, set the hier_path to turn of upwards searches,
|
||||
// scope, set the hier_path to turn off upwards searches,
|
||||
// and continue our search for the tail.
|
||||
if (recurse.is_scope()) {
|
||||
scope = recurse.scope;
|
||||
|
||||
+3
-7
@@ -1,7 +1,7 @@
|
||||
|
||||
%{
|
||||
/*
|
||||
* Copyright (c) 2000-2014 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2000-2015 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
|
||||
@@ -121,11 +121,6 @@ static void hookup_DFF_CE(NetFF*ff, NetESignal*d, NetEvProbe*pclk,
|
||||
connect(ff->pin_Clock(), pclk->pin(0));
|
||||
if (ce) connect(ff->pin_Enable(), ce->pin(0));
|
||||
|
||||
ff->attribute(perm_string::literal("LPM_FFType"), verinum("DFF"));
|
||||
if (pclk->edge() == NetEvProbe::NEGEDGE)
|
||||
ff->attribute(perm_string::literal("Clock:LPM_Polarity"), verinum("INVERT"));
|
||||
|
||||
|
||||
/* This lval_ represents a reg that is a WIRE in the
|
||||
synthesized results. This function signals the destructor
|
||||
to change the REG that this l-value refers to into a
|
||||
@@ -165,7 +160,8 @@ static void make_DFF_CE(Design*des, NetProcTop*top,
|
||||
|
||||
if (a->sig()) {
|
||||
// cerr << "new NetFF named " << a->name() << endl;
|
||||
NetFF*ff = new NetFF(top->scope(), a->name(),
|
||||
bool negedge = pclk->edge() == NetEvProbe::NEGEDGE;
|
||||
NetFF*ff = new NetFF(top->scope(), a->name(), negedge,
|
||||
a->sig()->vector_width());
|
||||
hookup_DFF_CE(ff, d, pclk, ce, a, rval_pinoffset);
|
||||
des->add_node(ff);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2002-2016 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
|
||||
@@ -34,8 +34,10 @@ bool NetProc::synth_async(Design*, NetScope*, NexusSet&, NetBus&, NetBus&)
|
||||
}
|
||||
|
||||
bool NetProc::synth_sync(Design*des, NetScope*scope,
|
||||
bool& /* ff_negedge */,
|
||||
NetNet* /* ff_clk */, NetBus& /* ff_ce */,
|
||||
NetBus& /* ff_aclr*/, NetBus& /* ff_aset*/,
|
||||
vector<verinum>& /*ff_aset_value*/,
|
||||
NexusSet&nex_map, NetBus&nex_out,
|
||||
const vector<NetEvProbe*>&events)
|
||||
{
|
||||
@@ -70,9 +72,45 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope,
|
||||
NexusSet&nex_map, NetBus&nex_out,
|
||||
NetBus&accumulated_nex_out)
|
||||
{
|
||||
/* If the lval is a concatenation, synthesise each part
|
||||
separately. */
|
||||
if (lval_->more ) {
|
||||
/* Temporarily set the lval_ and rval_ fields for each
|
||||
part in turn and recurse. Restore them when done. */
|
||||
NetAssign_*full_lval = lval_;
|
||||
NetExpr*full_rval = rval_;
|
||||
unsigned offset = 0;
|
||||
bool flag = true;
|
||||
while (lval_) {
|
||||
unsigned width = lval_->lwidth();
|
||||
NetEConst*base = new NetEConst(verinum(offset));
|
||||
base->set_line(*this);
|
||||
rval_ = new NetESelect(full_rval->dup_expr(), base, width);
|
||||
rval_->set_line(*this);
|
||||
eval_expr(rval_, width);
|
||||
NetAssign_*more = lval_->more;
|
||||
lval_->more = 0;
|
||||
if (!synth_async(des, scope, nex_map, nex_out, accumulated_nex_out))
|
||||
flag = false;
|
||||
lval_ = lval_->more = more;
|
||||
offset += width;
|
||||
}
|
||||
lval_ = full_lval;
|
||||
rval_ = full_rval;
|
||||
return flag;
|
||||
}
|
||||
|
||||
NetNet*rsig = rval_->synthesize(des, scope, rval_);
|
||||
assert(rsig);
|
||||
|
||||
if (lval_->word() && ! dynamic_cast<NetEConst*>(lval_->word())) {
|
||||
cerr << get_fileline() << ": sorry: assignment to variable "
|
||||
"location in memory is not currently supported in "
|
||||
"synthesis." << endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
NetNet*lsig = lval_->sig();
|
||||
if (!lsig) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
@@ -82,15 +120,6 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope,
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
if (lval_->more) {
|
||||
cerr << get_fileline() << ": sorry: "
|
||||
<< "NetAssignBase::synth_async does not support an "
|
||||
<< "L-value concatenation ";
|
||||
dump_lval(cerr);
|
||||
cerr << endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (debug_synth2) {
|
||||
cerr << get_fileline() << ": NetAssignBase::synth_async: "
|
||||
@@ -136,6 +165,7 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope,
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, NetNet::not_an_array, tmp_type);
|
||||
tmp->local_flag(true);
|
||||
tmp->set_line(*this);
|
||||
|
||||
NetPartSelect*ps = new NetPartSelect(tmp, base_off, lval_->lwidth(), NetPartSelect::PV);
|
||||
ps->set_line(*this);
|
||||
@@ -166,7 +196,8 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope,
|
||||
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, NetNet::not_an_array, tmp_type);
|
||||
//tmp->local_flag(true);
|
||||
tmp->local_flag(true);
|
||||
tmp->set_line(*this);
|
||||
|
||||
ivl_assert(*this, accumulated_nex_out.pin_count()==1);
|
||||
NetNet*use_lsig = lsig;
|
||||
@@ -185,7 +216,6 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope,
|
||||
<< " Found no use_sig, resorting to lsig." << endl;
|
||||
}
|
||||
}
|
||||
|
||||
NetSubstitute*ps = new NetSubstitute(use_lsig, rsig,
|
||||
tmp->vector_width(),
|
||||
base_off);
|
||||
@@ -196,6 +226,8 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope,
|
||||
rsig = tmp;
|
||||
}
|
||||
|
||||
rsig = crop_to_width(des, rsig, lsig->vector_width());
|
||||
|
||||
if (nex_out.pin_count() > 1) {
|
||||
NexusSet tmp_set;
|
||||
nex_output(tmp_set);
|
||||
@@ -338,6 +370,103 @@ bool NetBlock::synth_async(Design*des, NetScope*scope,
|
||||
return flag;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is used to fix up a MUX selector to be no longer than
|
||||
* it needs to be. The general idea is that if the selector needs to
|
||||
* be only N bits, but is actually M bits, we translate it to this:
|
||||
*
|
||||
* osig = { |esig[M-1:N-1], esig[N-2:0] }
|
||||
*
|
||||
* This obviously implies that (N >= 2) and (M >= N). In the code
|
||||
* below, N is sel_need, and M is sel_got (= esig->vector_width()).
|
||||
*/
|
||||
static NetNet* mux_selector_reduce_width(Design*des, NetScope*scope,
|
||||
const LineInfo&loc,
|
||||
NetNet*esig, unsigned sel_need)
|
||||
{
|
||||
const unsigned sel_got = esig->vector_width();
|
||||
|
||||
ivl_assert(*esig, sel_got >= sel_need);
|
||||
|
||||
// If the actual width matches the desired width (M==N) then
|
||||
// osig is esig itself. We're done.
|
||||
if (sel_got == sel_need)
|
||||
return esig;
|
||||
|
||||
if (debug_synth2) {
|
||||
cerr << loc.get_fileline() << ": mux_selector_reduce_width: "
|
||||
<< "Reduce selector width=" << sel_got
|
||||
<< " to " << sel_need << " bits." << endl;
|
||||
}
|
||||
|
||||
ivl_assert(*esig, sel_need >= 2);
|
||||
|
||||
// This is the output signal, osig.
|
||||
ivl_variable_type_t osig_data_type = IVL_VT_LOGIC;
|
||||
netvector_t*osig_vec = new netvector_t(osig_data_type, sel_need-1, 0);
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::TRI, osig_vec);
|
||||
osig->local_flag(true);
|
||||
osig->set_line(loc);
|
||||
|
||||
// Create the concat: osig = {...,...}
|
||||
NetConcat*osig_cat = new NetConcat(scope, scope->local_symbol(),
|
||||
sel_need, 2, true);
|
||||
osig_cat->set_line(loc);
|
||||
des->add_node(osig_cat);
|
||||
connect(osig_cat->pin(0), osig->pin(0));
|
||||
|
||||
// Create the part select esig[N-2:0]...
|
||||
NetPartSelect*ps0 = new NetPartSelect(esig, 0, sel_need-1,
|
||||
NetPartSelect::VP);
|
||||
ps0->set_line(loc);
|
||||
des->add_node(ps0);
|
||||
connect(ps0->pin(1), esig->pin(0));
|
||||
|
||||
netvector_t*ps0_vec = new netvector_t(osig_data_type, sel_need-2, 0);
|
||||
NetNet*ps0_sig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::TRI, ps0_vec);
|
||||
ps0_sig->local_flag(true);
|
||||
ps0_sig->set_line(loc);
|
||||
connect(ps0_sig->pin(0), ps0->pin(0));
|
||||
|
||||
// osig = {..., esig[N-2:0]}
|
||||
connect(osig_cat->pin(1), ps0_sig->pin(0));
|
||||
|
||||
// Create the part select esig[M-1:N-1]
|
||||
NetPartSelect*ps1 = new NetPartSelect(esig, sel_need-1,
|
||||
sel_got-sel_need,
|
||||
NetPartSelect::VP);
|
||||
ps1->set_line(loc);
|
||||
des->add_node(ps1);
|
||||
connect(ps1->pin(1), esig->pin(0));
|
||||
|
||||
netvector_t*ps1_vec = new netvector_t(osig_data_type, sel_got-sel_need-1, 0);
|
||||
NetNet*ps1_sig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::TRI, ps1_vec);
|
||||
ps1_sig->local_flag(true);
|
||||
ps1_sig->set_line(loc);
|
||||
connect(ps1_sig->pin(0), ps1->pin(0));
|
||||
|
||||
// Create the reduction OR: | esig[M-1:N-1]
|
||||
NetUReduce*ered = new NetUReduce(scope, scope->local_symbol(),
|
||||
NetUReduce::OR, sel_got-sel_need);
|
||||
ered->set_line(loc);
|
||||
des->add_node(ered);
|
||||
connect(ered->pin(1), ps1_sig->pin(0));
|
||||
|
||||
NetNet*ered_sig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::TRI, &netvector_t::scalar_logic);
|
||||
ered_sig->local_flag(true);
|
||||
ered_sig->set_line(loc);
|
||||
connect(ered->pin(0), ered_sig->pin(0));
|
||||
|
||||
// osig = { |esig[M-1:N-1], esig[N-2:0] }
|
||||
connect(osig_cat->pin(2), ered_sig->pin(0));
|
||||
|
||||
return osig;
|
||||
}
|
||||
|
||||
bool NetCase::synth_async(Design*des, NetScope*scope,
|
||||
NexusSet&nex_map, NetBus&nex_out,
|
||||
NetBus&accumulated_nex_out)
|
||||
@@ -352,12 +481,22 @@ bool NetCase::synth_async(Design*des, NetScope*scope,
|
||||
if (dynamic_cast<NetEConst*> (expr_))
|
||||
return synth_async_casez_(des, scope, nex_map, nex_out, accumulated_nex_out);
|
||||
|
||||
if (debug_synth2) {
|
||||
cerr << get_fileline() << ": NetCase::synth_async: "
|
||||
<< "Selector expression: " << *expr_ << endl;
|
||||
}
|
||||
|
||||
/* Synthesize the select expression. */
|
||||
NetNet*esig = expr_->synthesize(des, scope, expr_);
|
||||
|
||||
unsigned sel_width = esig->vector_width();
|
||||
ivl_assert(*this, sel_width > 0);
|
||||
|
||||
if (debug_synth2) {
|
||||
cerr << get_fileline() << ": NetCase::synth_async: "
|
||||
<< "selector width (sel_width) = " << sel_width << endl;
|
||||
}
|
||||
|
||||
ivl_assert(*this, nex_map.size() == nex_out.pin_count());
|
||||
|
||||
vector<unsigned> mux_width (nex_out.pin_count());
|
||||
@@ -384,6 +523,7 @@ bool NetCase::synth_async(Design*des, NetScope*scope,
|
||||
index of the mux value, and the statement is bound to that
|
||||
index. */
|
||||
|
||||
unsigned long max_guard_value = 0;
|
||||
map<unsigned long,NetProc*>statement_map;
|
||||
NetProc*statement_default = 0;
|
||||
|
||||
@@ -416,10 +556,49 @@ bool NetCase::synth_async(Design*des, NetScope*scope,
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sel_idx > max_guard_value)
|
||||
max_guard_value = sel_idx;
|
||||
|
||||
ivl_assert(*this, items_[item].statement);
|
||||
statement_map[sel_idx] = items_[item].statement;
|
||||
}
|
||||
|
||||
// The minimum selector width is the number of inputs that
|
||||
// are selected, rounded up to the nearest power of 2.
|
||||
unsigned sel_need = max(ceil(log2(max_guard_value + 1)), 1.0);
|
||||
|
||||
// If the sel_width can select more than just the explicit
|
||||
// guard values, and there is a default statement, then adjust
|
||||
// the sel_need to allow for the implicit selections.
|
||||
if (statement_default && (sel_width > sel_need))
|
||||
sel_need += 1;
|
||||
|
||||
// The mux size is always an exact power of 2.
|
||||
if (sel_need >= 8*sizeof(unsigned)) {
|
||||
cerr << get_fileline() << ": sorry: mux select width of "
|
||||
<< sel_need << " bits is too large for synthesis." << endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
unsigned mux_size = 1U << sel_need;
|
||||
|
||||
if (debug_synth2) {
|
||||
cerr << get_fileline() << ": NetCase::synth_async: "
|
||||
<< "Adjusted mux_size is " << mux_size
|
||||
<< " (max_guard_value=" << max_guard_value
|
||||
<< ", sel_need=" << sel_need
|
||||
<< ", sel_width=" << sel_width << ")." << endl;
|
||||
}
|
||||
|
||||
if (sel_width > sel_need) {
|
||||
if (debug_synth2) {
|
||||
cerr << get_fileline() << ": NetCase::synth_async: "
|
||||
<< "Selector is " << sel_width << " bits, "
|
||||
<< "need only " << sel_need << " bits." << endl;
|
||||
}
|
||||
esig = mux_selector_reduce_width(des, scope, *this, esig, sel_need);
|
||||
}
|
||||
|
||||
if (!statement_default && (statement_map.size() != ((size_t)1 << sel_width))) {
|
||||
cerr << get_fileline() << ": sorry: Latch inferred from "
|
||||
<< "incomplete case statement. This is not supported "
|
||||
@@ -428,15 +607,6 @@ bool NetCase::synth_async(Design*des, NetScope*scope,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sel_width >= 8*sizeof(unsigned)) {
|
||||
cerr << get_fileline() << ": sorry: mux select width of "
|
||||
<< sel_width << " bits is too large for synthesis." << endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned mux_size = 1U << sel_width;
|
||||
|
||||
/* If there is a default clause, synthesize it once and we'll
|
||||
link it in wherever it is needed. */
|
||||
NetBus default_bus (scope, nex_map.size());
|
||||
@@ -464,7 +634,7 @@ bool NetCase::synth_async(Design*des, NetScope*scope,
|
||||
vector<NetMux*> mux (mux_width.size());
|
||||
for (size_t mdx = 0 ; mdx < mux_width.size() ; mdx += 1) {
|
||||
mux[mdx] = new NetMux(scope, scope->local_symbol(),
|
||||
mux_width[mdx], mux_size, sel_width);
|
||||
mux_width[mdx], mux_size, sel_need);
|
||||
des->add_node(mux[mdx]);
|
||||
|
||||
// The select signal is already synthesized, and is
|
||||
@@ -614,7 +784,7 @@ bool NetCase::synth_async_casez_(Design*des, NetScope*scope,
|
||||
|
||||
netvector_t*condit_type = new netvector_t(IVL_VT_LOGIC, 0, 0);
|
||||
|
||||
NetCaseCmp::kind_t case_kind;
|
||||
NetCaseCmp::kind_t case_kind = NetCaseCmp::EEQ;
|
||||
switch (type()) {
|
||||
case NetCase::EQ:
|
||||
case_kind = NetCaseCmp::EEQ;
|
||||
@@ -650,8 +820,8 @@ bool NetCase::synth_async_casez_(Design*des, NetScope*scope,
|
||||
sel_width, case_kind);
|
||||
des->add_node(condit_dev);
|
||||
condit_dev->set_line(*this);
|
||||
// Note that the expression that may have windcards must
|
||||
// go in the pin(2) input. This is the definiton of the
|
||||
// Note that the expression that may have wildcards must
|
||||
// go in the pin(2) input. This is the definition of the
|
||||
// NetCaseCmp statement.
|
||||
connect(condit_dev->pin(1), esig->pin(0));
|
||||
connect(condit_dev->pin(2), guard->pin(0));
|
||||
@@ -697,6 +867,7 @@ bool NetCase::synth_async_casez_(Design*des, NetScope*scope,
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::TRI, tmp_vec);
|
||||
tmp->local_flag(true);
|
||||
tmp->set_line(*this);
|
||||
ivl_assert(*this, tmp->vector_width() != 0);
|
||||
connect(mux_cur->pin_Result(), tmp->pin(0));
|
||||
|
||||
@@ -973,6 +1144,7 @@ bool NetCondit::synth_async(Design*des, NetScope*scope,
|
||||
NetNet*otmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, NetNet::not_an_array, tmp_type);
|
||||
otmp->local_flag(true);
|
||||
otmp->set_line(*this);
|
||||
connect(mux->pin_Result(),otmp->pin(0));
|
||||
|
||||
connect(mux->pin_Sel(), ssig->pin(0));
|
||||
@@ -983,6 +1155,8 @@ bool NetCondit::synth_async(Design*des, NetScope*scope,
|
||||
tmp_type = new netvector_t(mux_data_type, mux_width-1,0);
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, NetNet::not_an_array, tmp_type);
|
||||
tmp->local_flag(true);
|
||||
tmp->set_line(*this);
|
||||
connect(mux->pin_Data(1), tmp->pin(0));
|
||||
}
|
||||
|
||||
@@ -990,6 +1164,8 @@ bool NetCondit::synth_async(Design*des, NetScope*scope,
|
||||
tmp_type = new netvector_t(mux_data_type, mux_width-1,0);
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, NetNet::not_an_array, tmp_type);
|
||||
tmp->local_flag(true);
|
||||
tmp->set_line(*this);
|
||||
connect(mux->pin_Data(0), tmp->pin(0));
|
||||
}
|
||||
|
||||
@@ -1000,6 +1176,8 @@ bool NetCondit::synth_async(Design*des, NetScope*scope,
|
||||
tmp_type = new netvector_t(mux_data_type, mux_lwidth-1,0);
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, NetNet::not_an_array, tmp_type);
|
||||
tmp->local_flag(true);
|
||||
tmp->set_line(*this);
|
||||
NetPartSelect*ps = new NetPartSelect(tmp, mux_off, mux_width, NetPartSelect::PV);
|
||||
des->add_node(ps);
|
||||
connect(ps->pin(0), otmp->pin(0));
|
||||
@@ -1027,8 +1205,14 @@ bool NetCondit::synth_async(Design*des, NetScope*scope,
|
||||
<< endl;
|
||||
}
|
||||
vector<bool>mask = statement_input.pin(idx).nexus()->driven_mask();
|
||||
for (size_t bit = mux_off ; bit < mux_off+mux_width ; bit += 1) {
|
||||
ivl_assert(*this, mask[bit]==false);
|
||||
// If the mask is empty then there are no bits in the
|
||||
// nexus to check yet.
|
||||
if (! mask.empty()) {
|
||||
for (size_t bit = mux_off;
|
||||
bit < mux_off+mux_width;
|
||||
bit += 1) {
|
||||
ivl_assert(*this, mask[bit]==false);
|
||||
}
|
||||
}
|
||||
connect(nex_out.pin(idx), statement_input.pin(idx));
|
||||
}
|
||||
@@ -1176,6 +1360,7 @@ bool NetProcTop::synth_async(Design*des)
|
||||
NetNet*tmp_sig = new NetNet(scope(), scope()->local_symbol(),
|
||||
NetNet::WIRE, NetNet::not_an_array, tmp_type);
|
||||
tmp_sig->local_flag(true);
|
||||
tmp_sig->set_line(*this);
|
||||
|
||||
NetPartSelect*tmp = new NetPartSelect(tmp_sig, item.base,
|
||||
item.wid, NetPartSelect::PV);
|
||||
@@ -1209,8 +1394,10 @@ bool NetProcTop::synth_async(Design*des)
|
||||
* the statements may each infer different reset and enable signals.
|
||||
*/
|
||||
bool NetBlock::synth_sync(Design*des, NetScope*scope,
|
||||
bool&ff_negedge,
|
||||
NetNet*ff_clk, NetBus&ff_ce,
|
||||
NetBus&ff_aclr,NetBus&ff_aset,
|
||||
vector<verinum>&ff_aset_value,
|
||||
NexusSet&nex_map, NetBus&nex_out,
|
||||
const vector<NetEvProbe*>&events_in)
|
||||
{
|
||||
@@ -1234,6 +1421,16 @@ bool NetBlock::synth_sync(Design*des, NetScope*scope,
|
||||
are used to collect the outputs from the substatement
|
||||
for the inputs of the FF bank. */
|
||||
NetBus tmp_out (scope, tmp_set.size());
|
||||
for (unsigned idx = 0 ; idx < tmp_out.pin_count() ; idx += 1) {
|
||||
unsigned ptr = nex_map.find_nexus(tmp_set[idx]);
|
||||
ivl_assert(*this, ptr < nex_out.pin_count());
|
||||
if (nex_out.pin(ptr).is_linked()) {
|
||||
cerr << get_fileline() << ": sorry: multiple statements "
|
||||
"assigning to the same flip-flop are not yet "
|
||||
"supported in synthesis." << endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Create a temporary ff_ce (FF clock-enable) that
|
||||
accounts for the subset of outputs that this
|
||||
@@ -1253,8 +1450,9 @@ bool NetBlock::synth_sync(Design*des, NetScope*scope,
|
||||
subset of the statement. The tmp_map is the output
|
||||
nexa that we expect, and the tmp_out is where we want
|
||||
those outputs connected. */
|
||||
bool ok_flag = cur->synth_sync(des, scope, ff_clk, tmp_ce,
|
||||
ff_aclr, ff_aset,
|
||||
bool ok_flag = cur->synth_sync(des, scope,
|
||||
ff_negedge, ff_clk, tmp_ce,
|
||||
ff_aclr, ff_aset, ff_aset_value,
|
||||
tmp_set, tmp_out, events_in);
|
||||
flag = flag && ok_flag;
|
||||
|
||||
@@ -1290,8 +1488,10 @@ bool NetBlock::synth_sync(Design*des, NetScope*scope,
|
||||
* expression is connected to an event, or not.
|
||||
*/
|
||||
bool NetCondit::synth_sync(Design*des, NetScope*scope,
|
||||
bool&ff_negedge,
|
||||
NetNet*ff_clk, NetBus&ff_ce,
|
||||
NetBus&ff_aclr,NetBus&ff_aset,
|
||||
vector<verinum>&ff_aset_value,
|
||||
NexusSet&nex_map, NetBus&nex_out,
|
||||
const vector<NetEvProbe*>&events_in)
|
||||
{
|
||||
@@ -1338,25 +1538,13 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope,
|
||||
for (unsigned pin = 0 ; pin < tmp_out.pin_count() ; pin += 1) {
|
||||
Nexus*rst_nex = tmp_out.pin(pin).nexus();
|
||||
|
||||
vector<bool> rst_mask = rst_nex->driven_mask();
|
||||
if (debug_synth2) {
|
||||
cerr << get_fileline() << ": NetCondit::synth_sync: "
|
||||
<< "nex_out pin=" << pin
|
||||
<< ", rst_mask.size()==" << rst_mask.size()
|
||||
<< ", rst_nex->vector_width()=" << rst_nex->vector_width()
|
||||
<< endl;
|
||||
}
|
||||
|
||||
for (size_t bit = 0 ; bit < rst_mask.size() ; bit += 1) {
|
||||
if (rst_mask[bit]==false) {
|
||||
cerr << get_fileline() << ": sorry: "
|
||||
<< "Asynchronous LOAD not implemented." << endl;
|
||||
return false;
|
||||
}
|
||||
if (! rst_nex->drivers_constant()) {
|
||||
cerr << get_fileline() << ": sorry: "
|
||||
<< "Asynchronous LOAD not implemented." << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
verinum rst_drv = rst_nex->driven_vector();
|
||||
ivl_assert(*this, rst_drv.len()==rst_mask.size());
|
||||
|
||||
verinum zero (verinum::V0, rst_drv.len());
|
||||
verinum ones (verinum::V1, rst_drv.len());
|
||||
@@ -1368,22 +1556,20 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope,
|
||||
ivl_assert(*this, rst->pin_count()==1);
|
||||
connect(ff_aclr.pin(pin), rst->pin(0));
|
||||
|
||||
} else if (rst_drv==ones) {
|
||||
} else {
|
||||
// Don't yet support multiple asynchronous set inputs.
|
||||
ivl_assert(*this, ! ff_aset.pin(pin).is_linked());
|
||||
|
||||
ivl_assert(*this, rst->pin_count()==1);
|
||||
connect(ff_aset.pin(pin), rst->pin(0));
|
||||
|
||||
} else {
|
||||
cerr << get_fileline() << ": sorry: "
|
||||
<< "Forgot how to implement asynchronous scramble (set to x/z)." << endl;
|
||||
return false;
|
||||
if (rst_drv!=ones)
|
||||
ff_aset_value[pin] = rst_drv;
|
||||
}
|
||||
}
|
||||
|
||||
return else_->synth_sync(des, scope, ff_clk, ff_ce,
|
||||
ff_aclr, ff_aset,
|
||||
return else_->synth_sync(des, scope,
|
||||
ff_negedge, ff_clk, ff_ce,
|
||||
ff_aclr, ff_aset, ff_aset_value,
|
||||
nex_map, nex_out, vector<NetEvProbe*>(0));
|
||||
}
|
||||
|
||||
@@ -1538,14 +1724,19 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope,
|
||||
}
|
||||
}
|
||||
|
||||
bool flag = if_->synth_sync(des, scope, ff_clk, ff_ce, ff_aclr, ff_aset, nex_map, nex_out, events_in);
|
||||
bool flag = if_->synth_sync(des, scope,
|
||||
ff_negedge, ff_clk, ff_ce,
|
||||
ff_aclr, ff_aset, ff_aset_value,
|
||||
nex_map, nex_out, events_in);
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
||||
bool NetEvWait::synth_sync(Design*des, NetScope*scope,
|
||||
bool&ff_negedge,
|
||||
NetNet*ff_clk, NetBus&ff_ce,
|
||||
NetBus&ff_aclr,NetBus&ff_aset,
|
||||
vector<verinum>&ff_aset_value,
|
||||
NexusSet&nex_map, NetBus&nex_out,
|
||||
const vector<NetEvProbe*>&events_in)
|
||||
{
|
||||
@@ -1615,8 +1806,7 @@ bool NetEvWait::synth_sync(Design*des, NetScope*scope,
|
||||
|
||||
connect(ff_clk->pin(0), pclk->pin(0));
|
||||
if (pclk->edge() == NetEvProbe::NEGEDGE) {
|
||||
perm_string polarity = perm_string::literal("Clock:LPM_Polarity");
|
||||
ff_clk->attribute(polarity, verinum("INVERT"));
|
||||
ff_negedge = true;
|
||||
|
||||
if (debug_synth2) {
|
||||
cerr << get_fileline() << ": debug: "
|
||||
@@ -1626,8 +1816,9 @@ bool NetEvWait::synth_sync(Design*des, NetScope*scope,
|
||||
}
|
||||
|
||||
/* Synthesize the input to the DFF. */
|
||||
bool flag = statement_->synth_sync(des, scope, ff_clk, ff_ce,
|
||||
ff_aclr, ff_aset,
|
||||
bool flag = statement_->synth_sync(des, scope,
|
||||
ff_negedge, ff_clk, ff_ce,
|
||||
ff_aclr, ff_aset, ff_aset_value,
|
||||
nex_map, nex_out, events);
|
||||
|
||||
return flag;
|
||||
@@ -1648,6 +1839,7 @@ bool NetProcTop::synth_sync(Design*des)
|
||||
|
||||
NexusSet nex_set;
|
||||
statement_->nex_output(nex_set);
|
||||
vector<verinum> aset_value(nex_set.size());
|
||||
|
||||
/* Make a model FF that will connect to the first item in the
|
||||
set, and will also take the initial connection of clocks
|
||||
@@ -1657,6 +1849,7 @@ bool NetProcTop::synth_sync(Design*des)
|
||||
NetNet*clock = new NetNet(scope(), scope()->local_symbol(),
|
||||
NetNet::TRI, &netvector_t::scalar_logic);
|
||||
clock->local_flag(true);
|
||||
clock->set_line(*this);
|
||||
|
||||
#if 0
|
||||
NetNet*ce = new NetNet(scope(), scope()->local_symbol(),
|
||||
@@ -1681,7 +1874,10 @@ bool NetProcTop::synth_sync(Design*des)
|
||||
// Connect the input later.
|
||||
|
||||
/* Synthesize the input to the DFF. */
|
||||
bool flag = statement_->synth_sync(des, scope(), clock, ce, aclr, aset,
|
||||
bool negedge = false;
|
||||
bool flag = statement_->synth_sync(des, scope(),
|
||||
negedge, clock, ce,
|
||||
aclr, aset, aset_value,
|
||||
nex_set, nex_d,
|
||||
vector<NetEvProbe*>());
|
||||
if (! flag) {
|
||||
@@ -1700,9 +1896,10 @@ bool NetProcTop::synth_sync(Design*des)
|
||||
}
|
||||
|
||||
NetFF*ff2 = new NetFF(scope(), scope()->local_symbol(),
|
||||
nex_set[idx].wid);
|
||||
negedge, nex_set[idx].wid);
|
||||
des->add_node(ff2);
|
||||
ff2->set_line(*this);
|
||||
ff2->aset_value(aset_value[idx]);
|
||||
|
||||
NetNet*tmp = nex_d.pin(idx).nexus()->pick_any_net();
|
||||
tmp->set_line(*this);
|
||||
|
||||
+13
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2015 Stephen Williams (steve@icarus.com)
|
||||
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
@@ -171,13 +171,6 @@ extern "C" unsigned ivl_expr_lineno(ivl_expr_t net)
|
||||
return net->lineno;
|
||||
}
|
||||
|
||||
inline static const char *basename(ivl_scope_t scope, const char *inst)
|
||||
{
|
||||
inst += strlen(ivl_scope_name(scope));
|
||||
assert(*inst == '.');
|
||||
return inst+1;
|
||||
}
|
||||
|
||||
extern "C" ivl_variable_type_t ivl_const_type(ivl_net_const_t net)
|
||||
{
|
||||
assert(net);
|
||||
@@ -1090,6 +1083,18 @@ extern "C" unsigned ivl_lpm_base(ivl_lpm_t net)
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" unsigned ivl_lpm_negedge(ivl_lpm_t net)
|
||||
{
|
||||
assert(net);
|
||||
switch (net->type) {
|
||||
case IVL_LPM_FF:
|
||||
return net->u_.ff.negedge_flag;
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" ivl_nexus_t ivl_lpm_clk(ivl_lpm_t net)
|
||||
{
|
||||
assert(net);
|
||||
|
||||
+2
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2011 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2015 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
|
||||
@@ -364,6 +364,7 @@ void dll_target::expr_last(const NetELast*net)
|
||||
esig->value_ = IVL_VT_DARRAY;
|
||||
esig->net_type= sig->net_type;
|
||||
esig->width_ = 1;
|
||||
esig->signed_ = sig->net_type->get_signed()? 1 : 0;
|
||||
FILE_NAME(esig, net);
|
||||
esig->u_.signal_.word = 0;
|
||||
esig->u_.signal_.sig = sig;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2015 Stephen Williams (steve@icarus.com)
|
||||
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
@@ -151,13 +151,6 @@ void ivl_net_const_s::operator delete(void*, size_t)
|
||||
|
||||
static StringHeapLex net_const_strings;
|
||||
|
||||
inline static const char *basename(ivl_scope_t scope, const char *inst)
|
||||
{
|
||||
inst += strlen(ivl_scope_name(scope));
|
||||
assert(*inst == '.');
|
||||
return inst+1;
|
||||
}
|
||||
|
||||
static perm_string make_scope_name(const hname_t&name)
|
||||
{
|
||||
if (! name.has_numbers())
|
||||
@@ -1057,20 +1050,17 @@ void dll_target::logic(const NetLogic*net)
|
||||
obj->npins_ = net->pin_count();
|
||||
obj->pins_ = new ivl_nexus_t[obj->npins_];
|
||||
|
||||
ivl_nexus_ptr_t out_ptr = 0;
|
||||
|
||||
for (unsigned idx = 0 ; idx < obj->npins_ ; idx += 1) {
|
||||
const Nexus*nex = net->pin(idx).nexus();
|
||||
assert(nex->t_cookie());
|
||||
obj->pins_[idx] = nex->t_cookie();
|
||||
ivl_nexus_ptr_t tmp = nexus_log_add(obj->pins_[idx], obj, idx);
|
||||
if (idx == 0)
|
||||
out_ptr = tmp;
|
||||
if (idx == 0) {
|
||||
tmp->drive0 = net->pin(0).drive0();
|
||||
tmp->drive1 = net->pin(0).drive1();
|
||||
}
|
||||
}
|
||||
|
||||
out_ptr->drive0 = net->pin(0).drive0();
|
||||
out_ptr->drive1 = net->pin(0).drive1();
|
||||
|
||||
assert(net->scope());
|
||||
ivl_scope_t scop = find_scope(des_, net->scope());
|
||||
assert(scop);
|
||||
@@ -1941,6 +1931,9 @@ void dll_target::lpm_ff(const NetFF*net)
|
||||
|
||||
const Nexus*nex;
|
||||
|
||||
/* Set the clock polarity. */
|
||||
obj->u_.ff.negedge_flag = net->is_negedge();
|
||||
|
||||
/* Set the clk signal to point to the nexus, and the nexus to
|
||||
point back to this device. */
|
||||
nex = net->pin_Clock().nexus();
|
||||
@@ -1979,7 +1972,10 @@ void dll_target::lpm_ff(const NetFF*net)
|
||||
nexus_lpm_add(obj->u_.ff.aset, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
|
||||
verinum tmp = net->aset_value();
|
||||
obj->u_.ff.aset_value = expr_from_value_(tmp);
|
||||
if (tmp.len() > 0)
|
||||
obj->u_.ff.aset_value = expr_from_value_(tmp);
|
||||
else
|
||||
obj->u_.ff.aset_value = 0;
|
||||
|
||||
} else {
|
||||
obj->u_.ff.aset = 0;
|
||||
@@ -2004,7 +2000,10 @@ void dll_target::lpm_ff(const NetFF*net)
|
||||
nexus_lpm_add(obj->u_.ff.sset, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
|
||||
verinum tmp = net->sset_value();
|
||||
obj->u_.ff.sset_value = expr_from_value_(tmp);
|
||||
if (tmp.len() > 0)
|
||||
obj->u_.ff.sset_value = expr_from_value_(tmp);
|
||||
else
|
||||
obj->u_.ff.sset_value = 0;
|
||||
|
||||
} else {
|
||||
obj->u_.ff.sset = 0;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef IVL_t_dll_H
|
||||
#define IVL_t_dll_H
|
||||
/*
|
||||
* Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2015 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
|
||||
@@ -370,6 +370,7 @@ struct ivl_lpm_s {
|
||||
|
||||
union {
|
||||
struct ivl_lpm_ff_s {
|
||||
unsigned negedge_flag :1;
|
||||
ivl_nexus_t clk;
|
||||
ivl_nexus_t we;
|
||||
ivl_nexus_t aclr;
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ using namespace std;
|
||||
|
||||
static const char*version_string =
|
||||
"Icarus Verilog BLIF Code Generator " VERSION " (" VERSION_TAG ")\n\n"
|
||||
"Copyright (c) 2013 Stephen Williams ([email protected])\n\n"
|
||||
"Copyright (c) 2013,2015 Stephen Williams ([email protected])\n\n"
|
||||
" This program is free software; you can redistribute it and/or modify\n"
|
||||
" it under the terms of the GNU General Public License as published by\n"
|
||||
" the Free Software Foundation; either version 2 of the License, or\n"
|
||||
|
||||
@@ -51,7 +51,7 @@ static int print_lpm_cmp_gt_s(FILE*fd, ivl_lpm_t net)
|
||||
return 0;
|
||||
}
|
||||
|
||||
fprintf(stderr, "%s:%u: sorry: blif: Signed agnitude compare not implemented yet\n",
|
||||
fprintf(stderr, "%s:%u: sorry: blif: Signed magnitude compare not implemented yet\n",
|
||||
ivl_lpm_file(net), ivl_lpm_lineno(net));
|
||||
|
||||
return 1;
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2015 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
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
static const char*version_string =
|
||||
"Icarus Verilog NULL Code Generator " VERSION " (" VERSION_TAG ")\n\n"
|
||||
"Copyright (c) 2000-2014 Stephen Williams ([email protected])\n\n"
|
||||
"Copyright (c) 2000-2015 Stephen Williams ([email protected])\n\n"
|
||||
" This program is free software; you can redistribute it and/or modify\n"
|
||||
" it under the terms of the GNU General Public License as published by\n"
|
||||
" the Free Software Foundation; either version 2 of the License, or\n"
|
||||
|
||||
+6
-3
@@ -82,12 +82,15 @@ pcb_config.h: stamp-pcb_config-h
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) @DEPENDENCY_FLAG@ -c $< -o $*.o
|
||||
mv $*.d dep
|
||||
|
||||
fp_lex.o: fp_lex.cc fp.h
|
||||
|
||||
fp_lex.cc: $(srcdir)/fp.lex
|
||||
$(LEX) -s -ofp_lex.cc $(srcdir)/fp.lex
|
||||
|
||||
fp.cc fp.h: $(srcdir)/fp.y
|
||||
$(YACC) --verbose -t -d -o fp.cc $(srcdir)/fp.y
|
||||
mv fp.cc.h fp.h 2>/dev/null || mv fp.hh fp.h
|
||||
fp.cc: $(srcdir)/fp.y
|
||||
$(YACC) --verbose -t -p fp -d -o $@ $<
|
||||
fp.h: fp.cc
|
||||
mv fp.cc.h $@ 2>/dev/null || mv fp.hh $@
|
||||
|
||||
ifeq (@WIN32@,yes)
|
||||
TGTLDFLAGS=-L.. -livl
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
|
||||
%name-prefix="fp"
|
||||
%pure-parser
|
||||
%parse-param {const char*file_path}
|
||||
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2014,2015 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
|
||||
@@ -34,7 +34,7 @@ using namespace std;
|
||||
|
||||
static const char*version_string =
|
||||
"Icarus Verilog SIZER Statistics Generator " VERSION " (" VERSION_TAG ")\n\n"
|
||||
"Copyright (c) 2014 Stephen Williams ([email protected])\n\n"
|
||||
"Copyright (c) 2014,2015 Stephen Williams ([email protected])\n\n"
|
||||
" This program is free software; you can redistribute it and/or modify\n"
|
||||
" it under the terms of the GNU General Public License as published by\n"
|
||||
" the Free Software Foundation; either version 2 of the License, or\n"
|
||||
|
||||
+19
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2013-2015 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,13 +25,26 @@
|
||||
|
||||
void show_constant(ivl_net_const_t net)
|
||||
{
|
||||
unsigned idx;
|
||||
const char*bits = ivl_const_bits(net);
|
||||
assert(net);
|
||||
|
||||
fprintf(out, "constant ");
|
||||
for (idx = 0 ; idx < ivl_const_width(net) ; idx += 1)
|
||||
fprintf(out, "%c", bits[idx]);
|
||||
|
||||
switch (ivl_const_type(net)) {
|
||||
case IVL_VT_BOOL:
|
||||
case IVL_VT_LOGIC:
|
||||
{
|
||||
const char*bits = ivl_const_bits(net);
|
||||
unsigned idx;
|
||||
assert(bits);
|
||||
for (idx = 0 ; idx < ivl_const_width(net) ; idx += 1)
|
||||
fprintf(out, "%c", bits[idx]);
|
||||
}
|
||||
break;
|
||||
case IVL_VT_REAL:
|
||||
fprintf(out, "%f", ivl_const_real(net));
|
||||
break;
|
||||
default:
|
||||
fprintf(out, "<unsupported type>");
|
||||
break;
|
||||
}
|
||||
fprintf(out, " at %s:%u\n", ivl_const_file(net), ivl_const_lineno(net));
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// are not used here.
|
||||
|
||||
// target_design()
|
||||
unusedFunction:stub.c:1770
|
||||
unusedFunction:stub.c:1774
|
||||
|
||||
// target_query()
|
||||
unusedFunction:stub.c:1834
|
||||
unusedFunction:stub.c:1844
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user