mirror of
https://github.com/steveicarus/iverilog.git
synced 2026-08-23 06:16:47 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c66d319d9c | ||
|
|
ae27165ffe | ||
|
|
32f1ca6f8b | ||
|
|
9ce2806710 | ||
|
|
3d4593d4d5 | ||
|
|
df5ae54ec7 | ||
|
|
fbee1b424d | ||
|
|
555017b525 | ||
|
|
1e170ee005 | ||
|
|
43501809b1 | ||
|
|
c0c67a101a | ||
|
|
1eb714e097 | ||
|
|
54a8e12856 | ||
|
|
6203f05ef9 | ||
|
|
703ad04067 | ||
|
|
778e96330d | ||
|
|
e3eb89fb12 | ||
|
|
166621bcb3 | ||
|
|
879a5a4cbe | ||
|
|
9faabfe995 | ||
|
|
6f23fa61ac | ||
|
|
30b6cf7821 | ||
|
|
6258011210 | ||
|
|
7557a46382 | ||
|
|
a0a91f358c | ||
|
|
0128286966 | ||
|
|
acd5e86e04 | ||
|
|
ab94b0a636 | ||
|
|
de6d696667 | ||
|
|
63946c4cfb | ||
|
|
475b603d15 | ||
|
|
096956cda9 | ||
|
|
3d3116d48b | ||
|
|
616360d751 | ||
|
|
7a5c30d297 | ||
|
|
9c5ab36a8b | ||
|
|
466656b167 | ||
|
|
5d6567cb02 | ||
|
|
c44c123ef5 | ||
|
|
4ecbf56e2b | ||
|
|
ed9a2c4b3f | ||
|
|
90751b9250 | ||
|
|
7d8011669d | ||
|
|
eb81062d85 | ||
|
|
8fbacc966e | ||
|
|
75801a12e3 | ||
|
|
9f1ce170e6 | ||
|
|
327c8826f4 | ||
|
|
fb0383d2bd | ||
|
|
28725d0d74 | ||
|
|
dac99b9374 | ||
|
|
1573477caf | ||
|
|
70a7513781 | ||
|
|
0277035496 | ||
|
|
33f462fdf6 | ||
|
|
639b9f346f | ||
|
|
447fee6f43 | ||
|
|
c9212a9a09 | ||
|
|
ea21fab379 | ||
|
|
4d090b64bd | ||
|
|
7e1e44e87a | ||
|
|
0a2a9dcd94 | ||
|
|
c9b4b66af2 | ||
|
|
7b6678b2a1 | ||
|
|
e79f62c5fa | ||
|
|
60046cc790 | ||
|
|
3fca25181a | ||
|
|
cbca31555d | ||
|
|
d5aa700b4b | ||
|
|
1db8319bce | ||
|
|
aa390f2a91 | ||
|
|
bd9e66d333 | ||
|
|
c34e318f8c | ||
|
|
4fc858b676 | ||
|
|
ac8b582b3d | ||
|
|
6f748d3d4f | ||
|
|
2854a524f0 | ||
|
|
985c34bfd9 | ||
|
|
63f97d8ec6 | ||
|
|
d2ac85e2c7 | ||
|
|
1b42f6232f | ||
|
|
4de141ab1d | ||
|
|
8ab2ec6f86 | ||
|
|
2fad8d4cff | ||
|
|
d94b0fe3c8 | ||
|
|
98956ef88f | ||
|
|
ac21d96bd8 | ||
|
|
c794aa02b8 | ||
|
|
dd564ab321 | ||
|
|
c0046e845e | ||
|
|
640767b748 | ||
|
|
d4eaede435 | ||
|
|
52bf4e613f | ||
|
|
9533a8dbdf | ||
|
|
774f78cd3e | ||
|
|
aca1dcf848 | ||
|
|
d24cd015b6 | ||
|
|
4d41525a91 | ||
|
|
b170a85fef | ||
|
|
90c6bc3a61 | ||
|
|
a4f6217a2f | ||
|
|
faff19af7b | ||
|
|
bc86bd4efa | ||
|
|
b4b18f3f30 | ||
|
|
1bcacf06d4 | ||
|
|
27178cedda | ||
|
|
6151d796a2 | ||
|
|
6ace9659e0 | ||
|
|
14942b4b43 | ||
|
|
9ede67ea63 | ||
|
|
cc74d2a6b0 | ||
|
|
ea779ac7dd | ||
|
|
693e9e5ad0 | ||
|
|
a1bc8ca6ca | ||
|
|
4e753a2c15 | ||
|
|
89314d4772 | ||
|
|
41f7ecacfc | ||
|
|
dd8da912f5 | ||
|
|
65ad911a2a | ||
|
|
37331d1c1b | ||
|
|
db2c842d15 | ||
|
|
c0e22a6533 | ||
|
|
bb87c368b8 | ||
|
|
76665b9404 | ||
|
|
a265ba2162 | ||
|
|
461a0fa2fb | ||
|
|
e51bbcb85a | ||
|
|
58ec62c895 | ||
|
|
843e1f9c44 | ||
|
|
45382144c3 | ||
|
|
e2f537628f | ||
|
|
91baa938e2 | ||
|
|
7fcaeacd65 | ||
|
|
2478d6f5d3 | ||
|
|
fbc1f6fb81 | ||
|
|
57aee7ca26 | ||
|
|
2fcfe9f2c3 | ||
|
|
2df2619029 | ||
|
|
9260d0d245 | ||
|
|
15becdaee4 | ||
|
|
80c9db3c88 | ||
|
|
c5d03d3a25 | ||
|
|
9e1570dc80 | ||
|
|
68da84e84a | ||
|
|
18ba73382e | ||
|
|
dabbfdb80a | ||
|
|
4eea8720a0 | ||
|
|
41239078a9 | ||
|
|
e375078dda | ||
|
|
da6b4c447f | ||
|
|
b72c0a0089 | ||
|
|
fbaf8f91bb | ||
|
|
329e943e4e | ||
|
|
31bd3e6056 | ||
|
|
15b94050ce | ||
|
|
c610699227 | ||
|
|
f0d2e20342 | ||
|
|
26a80005d6 | ||
|
|
5cf033a6ad | ||
|
|
e41ee7632d | ||
|
|
66a86433e7 | ||
|
|
2354a90e9f | ||
|
|
b7aaf51fbd | ||
|
|
5a885165b2 | ||
|
|
a748604418 | ||
|
|
e1a4e27173 | ||
|
|
2b06a293b6 | ||
|
|
472f98affe | ||
|
|
8114523be2 | ||
|
|
33ee1da817 | ||
|
|
301040a67a | ||
|
|
54b96ea7bd | ||
|
|
d0dfe2e7e7 | ||
|
|
fd8ceac170 | ||
|
|
a05d8c2823 | ||
|
|
626f418ab0 | ||
|
|
5792220dcb | ||
|
|
29d5d44f03 | ||
|
|
b2762f63a2 | ||
|
|
7d97f8a964 | ||
|
|
d3e63088d8 | ||
|
|
dddaa0ebcf | ||
|
|
ccbb1e5f5a | ||
|
|
3f1cd14f6c | ||
|
|
70abb2ce5c | ||
|
|
3f80bead1b | ||
|
|
93bb4283b8 | ||
|
|
5b5b31286b | ||
|
|
c5bde6560c | ||
|
|
cb4eb6236c | ||
|
|
d5e9e13555 | ||
|
|
3595b6d186 | ||
|
|
210010a390 | ||
|
|
99b3cc4464 | ||
|
|
9b6b081e38 | ||
|
|
b54ee3b1cd | ||
|
|
9fc4e1eddd | ||
|
|
73cca6ec39 | ||
|
|
58c2e12507 | ||
|
|
6dd80611a1 | ||
|
|
c2132039d2 | ||
|
|
d8d07eb129 | ||
|
|
f9768cd579 | ||
|
|
b6a15b2f4d | ||
|
|
5eca5d9948 | ||
|
|
f4a4ee00d0 | ||
|
|
cd94019733 | ||
|
|
d7fb47268f | ||
|
|
b4b5ac9944 | ||
|
|
df0b81d94d | ||
|
|
067d09720c | ||
|
|
870c35eece | ||
|
|
a82c178fd9 | ||
|
|
809bd18e66 | ||
|
|
4f0ffa2258 | ||
|
|
f45b17973c | ||
|
|
0bbea355c2 | ||
|
|
2be3507422 | ||
|
|
d6c946f390 | ||
|
|
96b6eb6b30 | ||
|
|
9cef973d9b | ||
|
|
88722a2831 | ||
|
|
d6b5c67313 | ||
|
|
4fed9d6532 | ||
|
|
28e0616543 | ||
|
|
6173e6b78a | ||
|
|
b5018cd994 | ||
|
|
f19a7c617d | ||
|
|
53d8cdd9f8 | ||
|
|
4bac5c06ba | ||
|
|
91a755d0e8 | ||
|
|
8cae7a4d44 | ||
|
|
11d1c45e45 | ||
|
|
5454a15b94 | ||
|
|
3ad0ec77ce | ||
|
|
3966e852ac | ||
|
|
83bfa9345f | ||
|
|
7d1d3847d8 | ||
|
|
a91c4f66ce | ||
|
|
ca2486ea61 | ||
|
|
24a2487c18 | ||
|
|
d68153dea3 | ||
|
|
89329fc0cc | ||
|
|
cba5a22714 | ||
|
|
1ce50993f0 | ||
|
|
2c0c934ad5 | ||
|
|
b6db8b63ec | ||
|
|
f1ab9e63fa | ||
|
|
12c574d5c9 | ||
|
|
af6f0c800f | ||
|
|
48f65cef40 | ||
|
|
b5a1d116fa | ||
|
|
b9339d3c60 | ||
|
|
0838dd24a4 | ||
|
|
9537fd7f0b | ||
|
|
95876feb46 | ||
|
|
19d817503d | ||
|
|
b6b364a09d | ||
|
|
f704d4d3ff | ||
|
|
450b9ab85c | ||
|
|
a1774bd3bd | ||
|
|
5aa69516bb | ||
|
|
c594dcec52 | ||
|
|
8126384726 | ||
|
|
96e6a9b02f | ||
|
|
d44ff4fd91 | ||
|
|
9a4ee873e1 | ||
|
|
597ed1681a | ||
|
|
bcd49b94dd | ||
|
|
422754f36f | ||
|
|
bfad382fd1 | ||
|
|
8941a594ee | ||
|
|
6bd8ab46d5 | ||
|
|
57f2ad6d15 | ||
|
|
33efeca0da | ||
|
|
be1888ed5f | ||
|
|
6ede18d41c | ||
|
|
d63e994ea5 | ||
|
|
700887d657 | ||
|
|
42674be38b | ||
|
|
fde7cd8f10 | ||
|
|
7ce713356e | ||
|
|
6511fc610b | ||
|
|
8dd4f77f3f | ||
|
|
004bfad348 | ||
|
|
ff90a5735d | ||
|
|
e6c0629626 | ||
|
|
01efffedfc | ||
|
|
74c219f171 | ||
|
|
bf10c5762a | ||
|
|
ca9abaf0c5 | ||
|
|
cfab250671 | ||
|
|
b1c0f7306d | ||
|
|
a156d8b8ce | ||
|
|
a7b7781fe9 | ||
|
|
21fe6afe8d | ||
|
|
48da46986b | ||
|
|
8d6239301f | ||
|
|
2e6807493f | ||
|
|
94cef20e49 | ||
|
|
c787a36af2 | ||
|
|
da0c4c7565 | ||
|
|
9c28f085d8 | ||
|
|
e9af0c7485 | ||
|
|
be54bfdc21 | ||
|
|
c6a6f4bc79 | ||
|
|
88ae1b7b3c | ||
|
|
f5d3b78653 | ||
|
|
68f1316eba | ||
|
|
e70e04d6e8 | ||
|
|
a3eb6868ea | ||
|
|
186759c95e | ||
|
|
8667b9a35d | ||
|
|
00defb0265 | ||
|
|
822a085d97 | ||
|
|
f23aec7f14 | ||
|
|
fb457128bf | ||
|
|
d126a414bd | ||
|
|
844fe3b9bc | ||
|
|
271855377f | ||
|
|
84020b16e3 | ||
|
|
c6035ab06e | ||
|
|
d94a40ecd9 | ||
|
|
c3be17ccae | ||
|
|
10dc978778 | ||
|
|
7f8f0eb65a | ||
|
|
c7107dc973 | ||
|
|
74eb544962 | ||
|
|
0696e3d558 | ||
|
|
714ca3542d | ||
|
|
7e27217dac | ||
|
|
4a7e14786c | ||
|
|
1ddb736f4c | ||
|
|
9ef49379f4 | ||
|
|
96213fe0ac | ||
|
|
d482da4803 | ||
|
|
4502da608d | ||
|
|
0976fd393b | ||
|
|
5882c6a481 | ||
|
|
52ea13819a | ||
|
|
048d044fdc | ||
|
|
9dda15a186 | ||
|
|
b094bbdcf4 | ||
|
|
eb708c1540 | ||
|
|
47a3b1f744 | ||
|
|
76b5d7e9e1 | ||
|
|
0071c9b0aa | ||
|
|
0ab42597d9 | ||
|
|
95ccc1e904 | ||
|
|
ea44866b2f | ||
|
|
6d4c6b56f6 | ||
|
|
f03ec88c2a | ||
|
|
e630ecdb0d | ||
|
|
eb27dc8db3 | ||
|
|
5cf7355c91 | ||
|
|
84bf0cee59 | ||
|
|
a18662ed13 | ||
|
|
3275d1f252 | ||
|
|
b14a0b885a | ||
|
|
e95a902b3d | ||
|
|
6733f7625b | ||
|
|
f7f61a8696 | ||
|
|
e1a6bb10de | ||
|
|
07bee5ca72 | ||
|
|
fa97ba0d9a | ||
|
|
bc95b02854 | ||
|
|
1893e7c8e5 | ||
|
|
0c04e2976b | ||
|
|
ac4fbb3e41 | ||
|
|
c98c24b9ff | ||
|
|
284c6fd85d | ||
|
|
3c8551ce90 | ||
|
|
65159a2733 | ||
|
|
007d702223 | ||
|
|
362b2aa604 | ||
|
|
de252965ac | ||
|
|
7349a6beaf | ||
|
|
828ca0ef9d | ||
|
|
f5049c2f14 | ||
|
|
f77c7f3d18 | ||
|
|
f75fb3cd95 | ||
|
|
8b9c26598a | ||
|
|
53600d3361 | ||
|
|
0dc5e5e29d | ||
|
|
eae9153b40 | ||
|
|
3d646aa92c | ||
|
|
b7c2bd4f72 | ||
|
|
b0a489fb7f | ||
|
|
01b9d5e023 | ||
|
|
6fa9415482 | ||
|
|
c159ff3134 | ||
|
|
efa5338e3b | ||
|
|
6dcf880482 | ||
|
|
b5fbb82ba1 | ||
|
|
ba8465abd2 | ||
|
|
0964dd99c5 | ||
|
|
a6a78f5776 | ||
|
|
23f73390a4 | ||
|
|
d55a890fdd | ||
|
|
84de8f2b93 | ||
|
|
08dac488c1 | ||
|
|
f2cff31b6e | ||
|
|
7c3f5c9fae | ||
|
|
aa16e82102 | ||
|
|
ddd3566d50 | ||
|
|
ec82af0c74 | ||
|
|
78bb3d6f09 | ||
|
|
54dab22042 | ||
|
|
9756cb6382 | ||
|
|
9fa0f95003 | ||
|
|
a624021a2e | ||
|
|
928df5caf7 | ||
|
|
5796524f06 | ||
|
|
b761a105b3 | ||
|
|
364ffc9024 | ||
|
|
712080f7e0 | ||
|
|
b906f4c0a1 | ||
|
|
d48bb4d744 | ||
|
|
d67ad166cd | ||
|
|
4e286ea86b | ||
|
|
a9be4e009f | ||
|
|
2f05d4b227 | ||
|
|
0b68639f7d | ||
|
|
5f09e01a44 | ||
|
|
6a98764b3b | ||
|
|
853c1f4387 | ||
|
|
b99c5aa394 | ||
|
|
349be0f169 | ||
|
|
4f28f6a770 | ||
|
|
fcf64c0c38 | ||
|
|
da8d59757e | ||
|
|
a02cfe0f1b | ||
|
|
f3255121a2 | ||
|
|
608555ce7e | ||
|
|
ec8b6e126e | ||
|
|
a697157257 | ||
|
|
ec070ee65b | ||
|
|
02f5ccd5d9 | ||
|
|
361d4f2147 | ||
|
|
c09a148cd9 | ||
|
|
b274dada85 | ||
|
|
c6a937e2e7 | ||
|
|
5840368f2d | ||
|
|
dee52dd2d0 | ||
|
|
a0e3b3386d | ||
|
|
6535b48c1c | ||
|
|
4d3611c5f1 | ||
|
|
77c4c88a4c | ||
|
|
4291866b9f | ||
|
|
8aef782411 | ||
|
|
0aa033ddf3 | ||
|
|
edba542c7a | ||
|
|
0e5289b022 | ||
|
|
6be3be0f16 | ||
|
|
03d188fc52 | ||
|
|
6e1e658922 | ||
|
|
a87575a76e | ||
|
|
336624c7b9 | ||
|
|
71660fbaa5 | ||
|
|
dd79885f6d | ||
|
|
51ffeb7c06 | ||
|
|
912749342c | ||
|
|
4bb91c4f98 | ||
|
|
400580179f | ||
|
|
c9d6b5431d | ||
|
|
51db00fb44 | ||
|
|
e20acfc9f9 | ||
|
|
a3fe753826 | ||
|
|
03aebd7525 | ||
|
|
fd5c0cfa28 | ||
|
|
357a0ff23e | ||
|
|
1a22f37d92 | ||
|
|
a5890b914f | ||
|
|
b397b10104 | ||
|
|
5de8e0555c | ||
|
|
91b01cd67e | ||
|
|
9c6b17c887 | ||
|
|
000d187c94 | ||
|
|
989e9d4d94 | ||
|
|
40ef704cc3 | ||
|
|
7c9fe0c173 | ||
|
|
dddbeb957a | ||
|
|
fd0cb30a4d | ||
|
|
125c631091 | ||
|
|
443dc7853f |
@@ -5,6 +5,7 @@ parse.cc.output
|
||||
syn-rules.cc
|
||||
syn-rules.cc.output
|
||||
lexor.cc
|
||||
iverilog-vpi
|
||||
ivl
|
||||
ivl.exp
|
||||
dep
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: Attrib.cc,v 1.2 2001/07/25 03:10:48 steve Exp $"
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: Attrib.cc,v 1.5 2002/08/12 01:34:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -36,14 +36,15 @@ Attrib::~Attrib()
|
||||
delete[] list_;
|
||||
}
|
||||
|
||||
void Attrib::set_attributes(const map<string,string>&attr)
|
||||
#if 0
|
||||
void Attrib::copy_attributes(const map<string,verinum>&attr)
|
||||
{
|
||||
assert(list_ == 0);
|
||||
|
||||
nlist_ = attr.size();
|
||||
list_ = new cell_[nlist_];
|
||||
|
||||
map<string,string>::const_iterator idx;
|
||||
map<string,verinum>::const_iterator idx;
|
||||
unsigned jdx;
|
||||
for (idx = attr.begin(), jdx = 0 ; idx != attr.end() ; idx ++, jdx++) {
|
||||
struct cell_*tmp = list_ + jdx;
|
||||
@@ -51,8 +52,9 @@ void Attrib::set_attributes(const map<string,string>&attr)
|
||||
tmp->val = (*idx).second;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
string Attrib::attribute(const string&key) const
|
||||
const verinum& Attrib::attribute(const string&key) const
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < nlist_ ; idx += 1) {
|
||||
|
||||
@@ -60,10 +62,11 @@ string Attrib::attribute(const string&key) const
|
||||
return list_[idx].val;
|
||||
}
|
||||
|
||||
return "";
|
||||
static const verinum null;
|
||||
return null;
|
||||
}
|
||||
|
||||
void Attrib::attribute(const string&key, const string&value)
|
||||
void Attrib::attribute(const string&key, const verinum&value)
|
||||
{
|
||||
unsigned idx;
|
||||
|
||||
@@ -92,7 +95,7 @@ bool Attrib::has_compat_attributes(const Attrib&that) const
|
||||
|
||||
for (idx = 0 ; idx < that.nlist_ ; idx += 1) {
|
||||
|
||||
string tmp = attribute(that.list_[idx].key);
|
||||
verinum tmp = attribute(that.list_[idx].key);
|
||||
if (tmp != that.list_[idx].val)
|
||||
return false;
|
||||
}
|
||||
@@ -100,18 +103,18 @@ bool Attrib::has_compat_attributes(const Attrib&that) const
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned Attrib::size() const
|
||||
unsigned Attrib::attr_cnt() const
|
||||
{
|
||||
return nlist_;
|
||||
}
|
||||
|
||||
string Attrib::key(unsigned idx) const
|
||||
const char* Attrib::attr_key(unsigned idx) const
|
||||
{
|
||||
assert(idx < nlist_);
|
||||
return list_[idx].key;
|
||||
return list_[idx].key.c_str();
|
||||
}
|
||||
|
||||
string Attrib::value(unsigned idx) const
|
||||
const verinum& Attrib::attr_value(unsigned idx) const
|
||||
{
|
||||
assert(idx < nlist_);
|
||||
return list_[idx].val;
|
||||
@@ -120,6 +123,24 @@ string Attrib::value(unsigned idx) const
|
||||
|
||||
/*
|
||||
* $Log: Attrib.cc,v $
|
||||
* Revision 1.5 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.4 2002/05/26 01:39:02 steve
|
||||
* Carry Verilog 2001 attributes with processes,
|
||||
* all the way through to the ivl_target API.
|
||||
*
|
||||
* Divide signal reference counts between rval
|
||||
* and lval references.
|
||||
*
|
||||
* Revision 1.3 2002/05/23 03:08:50 steve
|
||||
* Add language support for Verilog-2001 attribute
|
||||
* syntax. Hook this support into existing $attribute
|
||||
* handling, and add number and void value types.
|
||||
*
|
||||
* Add to the ivl_target API new functions for access
|
||||
* of complex attributes attached to gates.
|
||||
*
|
||||
* Revision 1.2 2001/07/25 03:10:48 steve
|
||||
* Create a config.h.in file to hold all the config
|
||||
* junk, and support gcc 3.0. (Stephan Boettcher)
|
||||
|
||||
@@ -18,12 +18,12 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: Attrib.h,v 1.1 2000/12/04 17:37:03 steve Exp $"
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: Attrib.h,v 1.4 2002/08/12 01:34:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <string>
|
||||
# include <map>
|
||||
# include "verinum.h"
|
||||
|
||||
/*
|
||||
* This class keeps a map of key/value pairs. The map can be set from
|
||||
@@ -35,21 +35,21 @@ class Attrib {
|
||||
Attrib();
|
||||
~Attrib();
|
||||
|
||||
void set_attributes(const map<string,string>&attr);
|
||||
string attribute(const string&key) const;
|
||||
void attribute(const string&key, const string&value);
|
||||
const verinum&attribute(const string&key) const;
|
||||
void attribute(const string&key, const verinum&value);
|
||||
bool has_compat_attributes(const Attrib&that) const;
|
||||
|
||||
|
||||
/* Provide a means of iterating over the entries in the map. */
|
||||
unsigned size() const;
|
||||
string key(unsigned idx) const;
|
||||
string value(unsigned idx) const;
|
||||
unsigned attr_cnt() const;
|
||||
const char* attr_key(unsigned idx) const;
|
||||
const verinum& attr_value(unsigned idx) const;
|
||||
|
||||
|
||||
private:
|
||||
struct cell_ {
|
||||
string key;
|
||||
string val;
|
||||
string key;
|
||||
verinum val;
|
||||
};
|
||||
|
||||
unsigned nlist_;
|
||||
@@ -62,6 +62,24 @@ class Attrib {
|
||||
|
||||
/*
|
||||
* $Log: Attrib.h,v $
|
||||
* Revision 1.4 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.3 2002/05/26 01:39:02 steve
|
||||
* Carry Verilog 2001 attributes with processes,
|
||||
* all the way through to the ivl_target API.
|
||||
*
|
||||
* Divide signal reference counts between rval
|
||||
* and lval references.
|
||||
*
|
||||
* Revision 1.2 2002/05/23 03:08:50 steve
|
||||
* Add language support for Verilog-2001 attribute
|
||||
* syntax. Hook this support into existing $attribute
|
||||
* handling, and add number and void value types.
|
||||
*
|
||||
* Add to the ivl_target API new functions for access
|
||||
* of complex attributes attached to gates.
|
||||
*
|
||||
* Revision 1.1 2000/12/04 17:37:03 steve
|
||||
* Add Attrib class for holding NetObj attributes.
|
||||
*
|
||||
|
||||
@@ -16,14 +16,18 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: HName.cc,v 1.1 2001/12/03 04:47:14 steve Exp $"
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: HName.cc,v 1.4 2002/08/12 01:34:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
# include "HName.h"
|
||||
# include <iostream>
|
||||
# include <string.h>
|
||||
# include <stdlib.h>
|
||||
#ifdef HAVE_MALLOC_H
|
||||
# include <malloc.h>
|
||||
#endif
|
||||
|
||||
hname_t::hname_t()
|
||||
{
|
||||
@@ -249,6 +253,15 @@ ostream& operator<< (ostream&out, const hname_t&that)
|
||||
|
||||
/*
|
||||
* $Log: HName.cc,v $
|
||||
* Revision 1.4 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.3 2002/01/05 04:36:06 steve
|
||||
* include malloc.h only when available.
|
||||
*
|
||||
* Revision 1.2 2001/12/18 04:52:45 steve
|
||||
* Include config.h for namespace declaration.
|
||||
*
|
||||
* Revision 1.1 2001/12/03 04:47:14 steve
|
||||
* Parser and pform use hierarchical names as hname_t
|
||||
* objects instead of encoded strings.
|
||||
|
||||
@@ -18,14 +18,15 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: HName.h,v 1.1 2001/12/03 04:47:14 steve Exp $"
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: HName.h,v 1.3 2002/08/12 01:34:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_IOSFWD
|
||||
# include <iosfwd>
|
||||
#else
|
||||
class ostream;
|
||||
# include <iostream>
|
||||
#ifdef __GNUC__
|
||||
#if __GNUC__ > 2
|
||||
using namespace std;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -78,6 +79,12 @@ extern bool operator == (const hname_t&, const hname_t&);
|
||||
|
||||
/*
|
||||
* $Log: HName.h,v $
|
||||
* Revision 1.3 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.2 2002/06/14 03:25:51 steve
|
||||
* Compiler portability.
|
||||
*
|
||||
* Revision 1.1 2001/12/03 04:47:14 steve
|
||||
* Parser and pform use hierarchical names as hname_t
|
||||
* objects instead of encoded strings.
|
||||
|
||||
+5
-2
@@ -16,8 +16,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: LineInfo.cc,v 1.2 2001/07/25 03:10:48 steve Exp $"
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: LineInfo.cc,v 1.3 2002/08/12 01:34:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -44,6 +44,9 @@ void LineInfo::set_line(const LineInfo&that)
|
||||
|
||||
/*
|
||||
* $Log: LineInfo.cc,v $
|
||||
* Revision 1.3 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.2 2001/07/25 03:10:48 steve
|
||||
* Create a config.h.in file to hold all the config
|
||||
* junk, and support gcc 3.0. (Stephan Boettcher)
|
||||
|
||||
+5
-2
@@ -18,8 +18,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: LineInfo.h,v 1.5 2000/11/30 17:31:42 steve Exp $"
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: LineInfo.h,v 1.6 2002/08/12 01:34:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <string>
|
||||
@@ -52,6 +52,9 @@ class LineInfo {
|
||||
|
||||
/*
|
||||
* $Log: LineInfo.h,v $
|
||||
* Revision 1.6 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.5 2000/11/30 17:31:42 steve
|
||||
* Change LineInfo to store const C strings.
|
||||
*
|
||||
|
||||
+85
-32
@@ -16,12 +16,16 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.109 2001/12/06 02:55:24 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.134 2002/09/16 00:30:33 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
|
||||
VERSION = 0.5
|
||||
# This version string is only used in the version message printed
|
||||
# by the compiler. It reflects the assigned version number for the
|
||||
# product as a whole. Most components also print the CVS Name: token
|
||||
# in order to get a more automatic version stamp as well.
|
||||
VERSION = 0.6
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
@@ -34,6 +38,7 @@ VPATH = $(srcdir)
|
||||
bindir = @bindir@
|
||||
libdir = @libdir@
|
||||
includedir = $(prefix)/include
|
||||
mandir = @mandir@
|
||||
|
||||
dllib=@DLLIB@
|
||||
rdynamic=@rdynamic@
|
||||
@@ -46,6 +51,8 @@ INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
STRIP = @STRIP@
|
||||
LEX = @LEX@
|
||||
YACC = @YACC@
|
||||
|
||||
CPPFLAGS = @CPPFLAGS@ @DEFS@
|
||||
CXXFLAGS = @CXXFLAGS@ -I. -I$(srcdir)
|
||||
@@ -60,13 +67,11 @@ ifeq ('@HAVE_IPAL@','yes')
|
||||
TARGETS += tgt-pal
|
||||
endif
|
||||
|
||||
|
||||
all: ivl@EXEEXT@ libvpi.a
|
||||
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) all); done
|
||||
cd vvm ; $(MAKE) all
|
||||
for dir in $(SUBDIRS) ; do (cd $$dir ; $(MAKE) all); done
|
||||
cd vpi ; $(MAKE) all
|
||||
cd ivlpp ; $(MAKE) all
|
||||
cd driver ; $(MAKE) all
|
||||
cd driver ; $(MAKE) VERSION=$(VERSION) all
|
||||
cd tgt-verilog ; $(MAKE) all
|
||||
cd tgt-stub ; $(MAKE) all
|
||||
for tgt in $(TARGETS); do (cd $$tgt ; $(MAKE) all); done
|
||||
@@ -77,19 +82,20 @@ ifeq (@WIN32@,yes)
|
||||
all: dosify.exe
|
||||
dosify.exe: dosify.c
|
||||
$(CC) -o dosify.exe dosify.c
|
||||
|
||||
else
|
||||
all: iverilog-vpi
|
||||
endif
|
||||
|
||||
# This rule rules the compiler in the trivial hello.vl program to make
|
||||
# sure the basics were compiled properly.
|
||||
check: all
|
||||
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) check); done
|
||||
driver/iverilog -Ccheck.conf -ocheck -tvvm-check -B./ivlpp examples/hello.vl
|
||||
$(CXX) -o check $(rdynamic) -fno-exceptions -I$(srcdir) -I$(srcdir)/vvm -I$(srcdir)/vpip -Lvvm -Lvpip check.cc -lvvm -lvpip $(dllib)
|
||||
./check | grep 'Hello, World'
|
||||
driver/iverilog -Ccheck.conf -ocheck.vvp -tvvp-check -B./ivlpp $(srcdir)/examples/hello.vl
|
||||
vvp/vvp -M./vpi ./check.vvp | grep 'Hello, World'
|
||||
|
||||
clean:
|
||||
rm -f *.o parse.cc parse.cc.output parse.h dep/*.d lexor.cc lexor_keyword.cc ivl@EXEEXT@ libivl.a libvpi.a
|
||||
cd vvm ; $(MAKE) clean
|
||||
rm -f *.o parse.cc parse.cc.output parse.h dep/*.d lexor.cc lexor_keyword.cc ivl@EXEEXT@ libivl.a libvpi.a iverilog-vpi
|
||||
cd vpi ; $(MAKE) clean
|
||||
cd driver ; $(MAKE) clean
|
||||
cd ivlpp ; $(MAKE) clean
|
||||
@@ -101,29 +107,30 @@ clean:
|
||||
distclean: clean
|
||||
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) distclean); done
|
||||
for tgt in $(TARGETS); do (cd $$tgt ; $(MAKE) distclean); done
|
||||
rm -f vvm/Makefile
|
||||
rm -f vpi/Makefile
|
||||
rm -f ivlpp/Makefile
|
||||
rm -f driver/Makefile
|
||||
rm -f config.status config.cache config.log
|
||||
rm -f Makefile
|
||||
rm -f tgt-pal/Makefile tgt-stub/Makefile tgt-verilog/Makefile
|
||||
|
||||
TT = t-dll.o t-dll-api.o t-dll-expr.o t-dll-proc.o t-vvm.o t-xnf.o
|
||||
FF = nodangle.o synth.o syn-rules.o xnfio.o
|
||||
TT = t-dll.o t-dll-api.o t-dll-expr.o t-dll-proc.o t-xnf.o
|
||||
FF = cprop.o nodangle.o synth.o synth2.o syn-rules.o xnfio.o
|
||||
|
||||
O = main.o cprop.o design_dump.o dup_expr.o elaborate.o elab_expr.o \
|
||||
O = main.o async.o design_dump.o dup_expr.o elaborate.o elab_expr.o \
|
||||
elab_lval.o elab_net.o elab_anet.o elab_pexpr.o elab_scope.o \
|
||||
elab_sig.o emit.o eval.o eval_rconst.o \
|
||||
elab_sig.o emit.o eval.o eval_attrib.o eval_rconst.o \
|
||||
eval_tree.o expr_synth.o functor.o lexor.o lexor_keyword.o link_const.o \
|
||||
load_module.o mangle.o netlist.o netmisc.o net_assign.o \
|
||||
net_design.o net_event.o net_force.o net_link.o net_modulo.o net_proc.o \
|
||||
net_scope.o net_udp.o pad_to_width.o \
|
||||
load_module.o netlist.o netmisc.o net_assign.o \
|
||||
net_design.o net_event.o net_expr.o net_force.o net_func.o \
|
||||
net_link.o net_modulo.o net_nex_input.o net_nex_output.o \
|
||||
net_proc.o net_scope.o net_udp.o pad_to_width.o \
|
||||
parse.o parse_misc.o pform.o pform_dump.o \
|
||||
set_width.o \
|
||||
set_width.o sync.o \
|
||||
verinum.o verireal.o target.o targets.o \
|
||||
Attrib.o HName.o LineInfo.o Module.o PDelays.o PEvent.o \
|
||||
PExpr.o PGate.o \
|
||||
PTask.o PFunction.o PWire.o Statement.o \
|
||||
PTask.o PFunction.o PWire.o Statement.o StringHeap.o \
|
||||
$(FF) $(TT)
|
||||
|
||||
Makefile: Makefile.in config.h.in config.status
|
||||
@@ -159,9 +166,18 @@ ivl@EXEEXT@: $O
|
||||
endif
|
||||
|
||||
|
||||
ifeq (@WIN32@,yes)
|
||||
|
||||
else
|
||||
iverilog-vpi: iverilog-vpi.sh
|
||||
sed -e 's;@SHARED@;@shared@;' -e 's;@PIC@;@PICFLAG@;' \
|
||||
-e 's;@INCLUDEDIR@;@includedir@;' -e 's;@LIBDIR@;@libdir@;' $< > $@
|
||||
chmod +x $@
|
||||
endif
|
||||
|
||||
%.o: %.cc
|
||||
@[ -d dep ] || mkdir dep
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -MD -c $< -o $*.o
|
||||
$(CXX) @ident_support@ $(CPPFLAGS) $(CXXFLAGS) -MD -c $< -o $*.o
|
||||
mv $*.d dep/$*.d
|
||||
|
||||
|
||||
@@ -170,32 +186,51 @@ lexor.o: lexor.cc parse.h
|
||||
parse.o: parse.cc
|
||||
|
||||
parse.h parse.cc: $(srcdir)/parse.y
|
||||
bison --verbose -t -p VL -d -o parse.cc $(srcdir)/parse.y
|
||||
$(YACC) --verbose -t -p VL -d -o parse.cc $(srcdir)/parse.y
|
||||
mv parse.cc.h parse.h || mv parse.hh parse.h
|
||||
|
||||
syn-rules.cc: $(srcdir)/syn-rules.y
|
||||
bison --verbose -p syn_ -o syn-rules.cc $(srcdir)/syn-rules.y
|
||||
$(YACC) --verbose -p syn_ -o syn-rules.cc $(srcdir)/syn-rules.y
|
||||
|
||||
lexor.cc: $(srcdir)/lexor.lex
|
||||
flex -PVL -s -olexor.cc $(srcdir)/lexor.lex
|
||||
$(LEX) -PVL -s -olexor.cc $(srcdir)/lexor.lex
|
||||
|
||||
lexor_keyword.o: lexor_keyword.cc
|
||||
|
||||
lexor_keyword.cc: lexor_keyword.gperf
|
||||
gperf -o -i 7 -C -k 1-3,$$ -L ANSI-C -H keyword_hash -N check_identifier -t $(srcdir)/lexor_keyword.gperf > lexor_keyword.cc || (rm -f lexor_keyword.cc ; false)
|
||||
|
||||
iverilog-vpi.ps: $(srcdir)/iverilog-vpi.man
|
||||
man -t $(srcdir)/iverilog-vpi.man > iverilog-vpi.ps
|
||||
|
||||
iverilog-vpi.pdf: iverilog-vpi.ps
|
||||
ps2pdf iverilog-vpi.ps iverilog-vpi.pdf
|
||||
|
||||
ifeq (@WIN32@,yes)
|
||||
WIN32_INSTALL = $(prefix)/hello.vl $(prefix)/sqrt.vl $(prefix)/QUICK_START.txt
|
||||
INSTALL_DOC = $(prefix)/iverilog-vpi.pdf
|
||||
INSTALL_DOCDIR =
|
||||
all: iverilog-vpi.pdf
|
||||
else
|
||||
INSTALL_DOC = $(mandir)/man1/iverilog-vpi.1
|
||||
INSTALL_DOCDIR = $(mandir)/man1
|
||||
endif
|
||||
|
||||
install: all installdirs $(libdir)/ivl/ivl@EXEEXT@ $(libdir)/ivl/iverilog.conf $(includedir)/ivl_target.h $(includedir)/vpi_user.h $(libdir)/libvpi.a $(WIN32_INSTALL)
|
||||
cd vvm ; $(MAKE) install
|
||||
ifeq (@WIN32@,yes)
|
||||
WIN32_INSTALL = $(prefix)/hello.vl $(prefix)/sqrt.vl $(prefix)/QUICK_START.txt
|
||||
else
|
||||
WIN32_INSTALL = $(bindir)/iverilog-vpi
|
||||
endif
|
||||
|
||||
install: all installdirs $(libdir)/ivl/ivl@EXEEXT@ $(libdir)/ivl/iverilog.conf $(includedir)/ivl_target.h $(includedir)/vpi_user.h $(includedir)/acc_user.h $(includedir)/veriuser.h $(libdir)/libvpi.a $(WIN32_INSTALL) $(INSTALL_DOC)
|
||||
cd vpi ; $(MAKE) install
|
||||
cd ivlpp ; $(MAKE) install
|
||||
cd driver ; $(MAKE) install
|
||||
for tgt in $(SUBDIRS); do (cd $$tgt ; $(MAKE) install); done
|
||||
for tgt in $(TARGETS); do (cd $$tgt ; $(MAKE) install); done
|
||||
|
||||
$(bindir)/iverilog-vpi: ./iverilog-vpi
|
||||
$(INSTALL_PROGRAM) ./iverilog-vpi $(bindir)/iverilog-vpi
|
||||
|
||||
$(libdir)/libvpi.a : ./libvpi.a
|
||||
$(INSTALL_DATA) libvpi.a $(libdir)/libvpi.a
|
||||
|
||||
@@ -212,6 +247,18 @@ $(includedir)/ivl_target.h: $(srcdir)/ivl_target.h
|
||||
$(includedir)/vpi_user.h: $(srcdir)/vpi_user.h
|
||||
$(INSTALL_DATA) $(srcdir)/vpi_user.h $(includedir)/vpi_user.h
|
||||
|
||||
$(includedir)/acc_user.h: $(srcdir)/acc_user.h
|
||||
$(INSTALL_DATA) $(srcdir)/acc_user.h $(includedir)/acc_user.h
|
||||
|
||||
$(includedir)/veriuser.h: $(srcdir)/veriuser.h
|
||||
$(INSTALL_DATA) $(srcdir)/veriuser.h $(includedir)/veriuser.h
|
||||
|
||||
$(mandir)/man1/iverilog-vpi.1: $(srcdir)/iverilog-vpi.man
|
||||
$(INSTALL_DATA) $(srcdir)/iverilog-vpi.man $(mandir)/man1/iverilog-vpi.1
|
||||
|
||||
$(prefix)/iverilog-vpi.pdf: iverilog-vpi.pdf
|
||||
$(INSTALL_DATA) iverilog-vpi.pdf $(prefix)/iverilog-vpi.pdf
|
||||
|
||||
# In windows installations, put a few examples and the quick_start
|
||||
# into the destination directory.
|
||||
ifeq (@WIN32@,yes)
|
||||
@@ -229,18 +276,24 @@ $(prefix)/QUICK_START.txt: $(srcdir)/QUICK_START.txt
|
||||
endif
|
||||
|
||||
installdirs: mkinstalldirs
|
||||
$(srcdir)/mkinstalldirs $(bindir) $(includedir) $(libdir)/ivl
|
||||
|
||||
$(srcdir)/mkinstalldirs $(bindir) $(includedir) $(libdir)/ivl \
|
||||
$(mandir) $(mandir)/man1
|
||||
|
||||
uninstall:
|
||||
rm -f $(libdir)/ivl/ivl@EXEEXT@
|
||||
rm -f $(libdir)/ivl/iverilog.conf
|
||||
rm -f $(libdir)/ivl/ivl
|
||||
-rmdir $(libdir)/ivl
|
||||
rm -f $(libdir)/libvpi.a
|
||||
rm -f $(bindir)/verilog
|
||||
rm -f $(bindir)/iverilog-vpi
|
||||
rm -f $(bindir)/gverilog@EXEEXT@
|
||||
rm -f $(includedir)/ivl_target.h
|
||||
rm -f $(includedir)/vpi_user.h
|
||||
rm -f $(includedir)/acc_user.h
|
||||
rm -f $(includedir)/veriuser.h
|
||||
rm -f $(mandir)/man1/iverilog-vpi.1
|
||||
cd driver ; $(MAKE) uninstall
|
||||
cd vpi ; $(MAKE) uninstall
|
||||
cd vvm ; $(MAKE) uninstall
|
||||
cd ivlpp ; $(MAKE) uninstall
|
||||
for tgt in $(SUBDIRS); do (cd $$tgt ; $(MAKE) uninstall); done
|
||||
for tgt in $(TARGETS); do (cd $$tgt ; $(MAKE) uninstall); done
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: Module.cc,v 1.17 2001/12/03 04:47:14 steve Exp $"
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: Module.cc,v 1.19 2002/08/12 01:34:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -27,12 +27,9 @@
|
||||
# include "PWire.h"
|
||||
# include <assert.h>
|
||||
|
||||
Module::Module(const char*name, const svector<Module::port_t*>*pp)
|
||||
Module::Module(const char*name)
|
||||
: name_(strdup(name))
|
||||
{
|
||||
if (pp)
|
||||
ports_ = *pp;
|
||||
|
||||
}
|
||||
|
||||
Module::~Module()
|
||||
@@ -72,7 +69,7 @@ void Module::add_behavior(PProcess*b)
|
||||
|
||||
unsigned Module::port_count() const
|
||||
{
|
||||
return ports_.count();
|
||||
return ports.count();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -82,11 +79,11 @@ unsigned Module::port_count() const
|
||||
*/
|
||||
const svector<PEIdent*>& Module::get_port(unsigned idx) const
|
||||
{
|
||||
assert(idx < ports_.count());
|
||||
assert(idx < ports.count());
|
||||
static svector<PEIdent*> zero;
|
||||
|
||||
if (ports_[idx])
|
||||
return ports_[idx]->expr;
|
||||
if (ports[idx])
|
||||
return ports[idx]->expr;
|
||||
else
|
||||
return zero;
|
||||
}
|
||||
@@ -94,11 +91,11 @@ const svector<PEIdent*>& Module::get_port(unsigned idx) const
|
||||
unsigned Module::find_port(const string&name) const
|
||||
{
|
||||
assert(name != "");
|
||||
for (unsigned idx = 0 ; idx < ports_.count() ; idx += 1)
|
||||
if (ports_[idx]->name == name)
|
||||
for (unsigned idx = 0 ; idx < ports.count() ; idx += 1)
|
||||
if (ports[idx]->name == name)
|
||||
return idx;
|
||||
|
||||
return ports_.count();
|
||||
return ports.count();
|
||||
}
|
||||
|
||||
|
||||
@@ -142,6 +139,12 @@ const list<PProcess*>& Module::get_behaviors() const
|
||||
|
||||
/*
|
||||
* $Log: Module.cc,v $
|
||||
* Revision 1.19 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.18 2002/05/19 23:37:28 steve
|
||||
* Parse port_declaration_lists from the 2001 Standard.
|
||||
*
|
||||
* Revision 1.17 2001/12/03 04:47:14 steve
|
||||
* Parser and pform use hierarchical names as hname_t
|
||||
* objects instead of encoded strings.
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: Module.h,v 1.24 2001/12/03 04:47:14 steve Exp $"
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: Module.h,v 1.27 2002/08/19 02:39:16 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <list>
|
||||
@@ -60,15 +60,21 @@ class Module : public LineInfo {
|
||||
};
|
||||
|
||||
public:
|
||||
explicit Module(const char*name, const svector<port_t*>*);
|
||||
explicit Module(const char*name);
|
||||
~Module();
|
||||
|
||||
|
||||
/* The module has parameters that are evaluated when the
|
||||
module is elaborated. During parsing, I put the parameters
|
||||
into this map. */
|
||||
map<string,PExpr*>parameters;
|
||||
map<string,PExpr*>localparams;
|
||||
struct param_expr_t {
|
||||
PExpr*expr;
|
||||
PExpr*msb;
|
||||
PExpr*lsb;
|
||||
bool signed_flag;
|
||||
};
|
||||
map<string,param_expr_t>parameters;
|
||||
map<string,param_expr_t>localparams;
|
||||
|
||||
/* The module also has defparam assignments which don't create
|
||||
new parameters within the module, but may be used to set
|
||||
@@ -84,6 +90,10 @@ class Module : public LineInfo {
|
||||
a parameter-index to its name. */
|
||||
list<string> param_names;
|
||||
|
||||
/* This is an array of port descriptors, which is in turn a
|
||||
named array of PEident pointers. */
|
||||
svector<port_t*> ports;
|
||||
|
||||
/* Keep a table of named events declared in the module. */
|
||||
map<string,PEvent*>events;
|
||||
|
||||
@@ -127,10 +137,6 @@ class Module : public LineInfo {
|
||||
private:
|
||||
char* name_;
|
||||
|
||||
/* This is an array of port descriptors, which is in turn a
|
||||
named array of PEident pointers. */
|
||||
svector<port_t*> ports_;
|
||||
|
||||
map<hname_t,PWire*> wires_;
|
||||
list<PGate*> gates_;
|
||||
list<PProcess*> behaviors_;
|
||||
@@ -145,6 +151,15 @@ class Module : public LineInfo {
|
||||
|
||||
/*
|
||||
* $Log: Module.h,v $
|
||||
* Revision 1.27 2002/08/19 02:39:16 steve
|
||||
* Support parameters with defined ranges.
|
||||
*
|
||||
* Revision 1.26 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.25 2002/05/19 23:37:28 steve
|
||||
* Parse port_declaration_lists from the 2001 Standard.
|
||||
*
|
||||
* Revision 1.24 2001/12/03 04:47:14 steve
|
||||
* Parser and pform use hierarchical names as hname_t
|
||||
* objects instead of encoded strings.
|
||||
|
||||
+17
-5
@@ -16,8 +16,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: PDelays.cc,v 1.7 2001/11/22 06:20:59 steve Exp $"
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PDelays.cc,v 1.9 2002/08/12 01:34:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -30,14 +30,17 @@
|
||||
|
||||
PDelays::PDelays()
|
||||
{
|
||||
delete_flag_ = true;
|
||||
for (unsigned idx = 0 ; idx < 3 ; idx += 1)
|
||||
delay_[idx] = 0;
|
||||
}
|
||||
|
||||
PDelays::~PDelays()
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < 3 ; idx += 1)
|
||||
delete delay_[idx];
|
||||
if (delete_flag_) {
|
||||
for (unsigned idx = 0 ; idx < 3 ; idx += 1)
|
||||
delete delay_[idx];
|
||||
}
|
||||
}
|
||||
|
||||
void PDelays::set_delay(PExpr*del)
|
||||
@@ -45,15 +48,18 @@ void PDelays::set_delay(PExpr*del)
|
||||
assert(del);
|
||||
assert(delay_[0] == 0);
|
||||
delay_[0] = del;
|
||||
delete_flag_ = true;
|
||||
}
|
||||
|
||||
|
||||
void PDelays::set_delays(const svector<PExpr*>*del)
|
||||
void PDelays::set_delays(const svector<PExpr*>*del, bool df)
|
||||
{
|
||||
assert(del);
|
||||
assert(del->count() <= 3);
|
||||
for (unsigned idx = 0 ; idx < del->count() ; idx += 1)
|
||||
delay_[idx] = (*del)[idx];
|
||||
|
||||
delete_flag_ = df;
|
||||
}
|
||||
|
||||
static unsigned long calculate_val(Design*des, const NetScope*scope,
|
||||
@@ -125,6 +131,12 @@ void PDelays::eval_delays(Design*des, NetScope*scope,
|
||||
|
||||
/*
|
||||
* $Log: PDelays.cc,v $
|
||||
* Revision 1.9 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.8 2001/12/29 20:19:31 steve
|
||||
* Do not delete delay expressions of UDP instances.
|
||||
*
|
||||
* Revision 1.7 2001/11/22 06:20:59 steve
|
||||
* Use NetScope instead of string for scope path.
|
||||
*
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __PDelays_H
|
||||
#define __PDelays_H
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1999-2002 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -18,17 +18,18 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: PDelays.h,v 1.4 2001/11/22 06:20:59 steve Exp $"
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PDelays.h,v 1.7 2002/08/12 01:34:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "svector.h"
|
||||
# include <string>
|
||||
# include <iostream>
|
||||
|
||||
#ifdef HAVE_IOSFWD
|
||||
# include <iosfwd>
|
||||
#else
|
||||
class ostream;
|
||||
#ifdef __GNUC__
|
||||
#if __GNUC__ > 2
|
||||
using namespace std;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
class Design;
|
||||
@@ -45,8 +46,11 @@ class PDelays {
|
||||
PDelays();
|
||||
~PDelays();
|
||||
|
||||
/* Set the delay expressions. If the delete_flag is true, then
|
||||
this object takes ownership of the expressions, and will
|
||||
delete it in the destructor. */
|
||||
void set_delay(PExpr*);
|
||||
void set_delays(const svector<PExpr*>*del);
|
||||
void set_delays(const svector<PExpr*>*del, bool delete_flag=true);
|
||||
|
||||
void eval_delays(Design*des, NetScope*scope,
|
||||
unsigned long&rise_time,
|
||||
@@ -57,6 +61,7 @@ class PDelays {
|
||||
|
||||
private:
|
||||
PExpr* delay_[3];
|
||||
bool delete_flag_;
|
||||
|
||||
private: // not implemented
|
||||
PDelays(const PDelays&);
|
||||
@@ -67,6 +72,15 @@ ostream& operator << (ostream&o, const PDelays&);
|
||||
|
||||
/*
|
||||
* $Log: PDelays.h,v $
|
||||
* Revision 1.7 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.6 2002/06/14 03:25:51 steve
|
||||
* Compiler portability.
|
||||
*
|
||||
* Revision 1.5 2001/12/29 20:19:31 steve
|
||||
* Do not delete delay expressions of UDP instances.
|
||||
*
|
||||
* Revision 1.4 2001/11/22 06:20:59 steve
|
||||
* Use NetScope instead of string for scope path.
|
||||
*
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: PEvent.cc,v 1.2 2001/07/25 03:10:48 steve Exp $"
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PEvent.cc,v 1.3 2002/08/12 01:34:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -40,6 +40,9 @@ string PEvent::name() const
|
||||
|
||||
/*
|
||||
* $Log: PEvent.cc,v $
|
||||
* Revision 1.3 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.2 2001/07/25 03:10:48 steve
|
||||
* Create a config.h.in file to hold all the config
|
||||
* junk, and support gcc 3.0. (Stephan Boettcher)
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: PEvent.h,v 1.5 2001/12/03 04:47:14 steve Exp $"
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PEvent.h,v 1.6 2002/08/12 01:34:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "LineInfo.h"
|
||||
@@ -53,6 +53,9 @@ class PEvent : public LineInfo {
|
||||
|
||||
/*
|
||||
* $Log: PEvent.h,v $
|
||||
* Revision 1.6 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.5 2001/12/03 04:47:14 steve
|
||||
* Parser and pform use hierarchical names as hname_t
|
||||
* objects instead of encoded strings.
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: PExpr.cc,v 1.28 2001/12/03 04:47:14 steve Exp $"
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PExpr.cc,v 1.31 2002/08/19 02:39:16 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -46,18 +46,6 @@ bool PExpr::is_constant(Module*) const
|
||||
return false;
|
||||
}
|
||||
|
||||
NetNet* PExpr::elaborate_net(Design*des, NetScope*scope, unsigned,
|
||||
unsigned long,
|
||||
unsigned long,
|
||||
unsigned long,
|
||||
Link::strength_t,
|
||||
Link::strength_t) const
|
||||
{
|
||||
cerr << get_line() << ": error: Unable to elaborate `"
|
||||
<< *this << "' as gates." << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetNet* PExpr::elaborate_lnet(Design*des, NetScope*) const
|
||||
{
|
||||
cerr << get_line() << ": error: expression not valid in assign l-value: "
|
||||
@@ -173,12 +161,12 @@ bool PEIdent::is_constant(Module*mod) const
|
||||
{
|
||||
if (mod == 0) return false;
|
||||
|
||||
{ map<string,PExpr*>::const_iterator cur;
|
||||
{ map<string,Module::param_expr_t>::const_iterator cur;
|
||||
cur = mod->parameters.find(path_.peek_name(0));
|
||||
if (cur != mod->parameters.end()) return true;
|
||||
}
|
||||
|
||||
{ map<string,PExpr*>::const_iterator cur;
|
||||
{ map<string,Module::param_expr_t>::const_iterator cur;
|
||||
cur = mod->localparams.find(path_.peek_name(0));
|
||||
if (cur != mod->localparams.end()) return true;
|
||||
}
|
||||
@@ -216,13 +204,14 @@ bool PENumber::is_constant(Module*) const
|
||||
return true;
|
||||
}
|
||||
|
||||
PEString::PEString(const string&s)
|
||||
PEString::PEString(char*s)
|
||||
: text_(s)
|
||||
{
|
||||
}
|
||||
|
||||
PEString::~PEString()
|
||||
{
|
||||
delete[]text_;
|
||||
}
|
||||
|
||||
string PEString::value() const
|
||||
@@ -267,6 +256,15 @@ bool PEUnary::is_constant(Module*m) const
|
||||
|
||||
/*
|
||||
* $Log: PExpr.cc,v $
|
||||
* Revision 1.31 2002/08/19 02:39:16 steve
|
||||
* Support parameters with defined ranges.
|
||||
*
|
||||
* Revision 1.30 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.29 2001/12/30 21:32:03 steve
|
||||
* Support elaborate_net for PEString objects.
|
||||
*
|
||||
* Revision 1.28 2001/12/03 04:47:14 steve
|
||||
* Parser and pform use hierarchical names as hname_t
|
||||
* objects instead of encoded strings.
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: PExpr.h,v 1.53 2001/12/03 04:47:14 steve Exp $"
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PExpr.h,v 1.62 2002/08/12 01:34:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <string>
|
||||
@@ -51,8 +51,11 @@ class PExpr : public LineInfo {
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
// Procedural elaboration of the expression.
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope) const;
|
||||
// Procedural elaboration of the expression. Set thie
|
||||
// bare_memory_ok flag if the result is allowed to be a
|
||||
// NetEMemory without an index.
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
||||
bool sys_task_arg =false) const;
|
||||
|
||||
// Elaborate expressions that are the r-value of parameter
|
||||
// assignments. This elaboration follows the restrictions of
|
||||
@@ -131,7 +134,8 @@ class PEConcat : public PExpr {
|
||||
unsigned long decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*) const;
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
|
||||
bool sys_task_arg =false) const;
|
||||
virtual NetEConcat*elaborate_pexpr(Design*des, NetScope*) const;
|
||||
virtual NetAssign_* elaborate_lval(Design*des, NetScope*scope) const;
|
||||
virtual bool is_constant(Module*) const;
|
||||
@@ -190,7 +194,8 @@ class PEFNumber : public PExpr {
|
||||
/* A PEFNumber is a constant, so this returns true. */
|
||||
virtual bool is_constant(Module*) const;
|
||||
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*) const;
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
|
||||
bool sys_task_arg =false) const;
|
||||
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
@@ -225,7 +230,8 @@ class PEIdent : public PExpr {
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*) const;
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
|
||||
bool sys_task_arg =false) const;
|
||||
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
|
||||
// Elaborate the PEIdent as a port to a module. This method
|
||||
@@ -255,6 +261,19 @@ class PEIdent : public PExpr {
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const;
|
||||
|
||||
NetNet* elaborate_net_bitmux_(Design*des, NetScope*scope,
|
||||
NetNet*sig,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
|
||||
private:
|
||||
NetAssign_* elaborate_mem_lval_(Design*des, NetScope*scope,
|
||||
NetMemory*mem) const;
|
||||
|
||||
};
|
||||
|
||||
class PENumber : public PExpr {
|
||||
@@ -273,8 +292,11 @@ class PENumber : public PExpr {
|
||||
unsigned long decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
virtual NetEConst*elaborate_expr(Design*des, NetScope*) const;
|
||||
virtual NetEConst*elaborate_expr(Design*des, NetScope*,
|
||||
bool sys_task_arg =false) const;
|
||||
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
virtual NetAssign_* elaborate_lval(Design*des, NetScope*scope) const;
|
||||
|
||||
virtual verinum* eval_const(const Design*des, const NetScope*sc) const;
|
||||
virtual verireal*eval_rconst(const Design*, const NetScope*) const;
|
||||
|
||||
@@ -285,21 +307,37 @@ class PENumber : public PExpr {
|
||||
verinum*const value_;
|
||||
};
|
||||
|
||||
/*
|
||||
* This represents a string constant in an expression.
|
||||
*
|
||||
* The s parameter to the PEString constructor is a C string that this
|
||||
* class instance will take for its own. The caller should not delete
|
||||
* the string, the destructor will do it.
|
||||
*/
|
||||
class PEString : public PExpr {
|
||||
|
||||
public:
|
||||
explicit PEString(const string&s);
|
||||
explicit PEString(char*s);
|
||||
~PEString();
|
||||
|
||||
string value() const;
|
||||
virtual void dump(ostream&) const;
|
||||
virtual NetEConst*elaborate_expr(Design*des, NetScope*) const;
|
||||
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
|
||||
unsigned width,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
virtual NetEConst*elaborate_expr(Design*des, NetScope*,
|
||||
bool sys_task_arg =false) const;
|
||||
virtual NetEConst*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
verinum* PEString::eval_const(const Design*, const NetScope*) const;
|
||||
|
||||
virtual bool is_constant(Module*) const;
|
||||
|
||||
private:
|
||||
const string text_;
|
||||
char*text_;
|
||||
};
|
||||
|
||||
class PEUnary : public PExpr {
|
||||
@@ -316,7 +354,8 @@ class PEUnary : public PExpr {
|
||||
unsigned long decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
virtual NetEUnary*elaborate_expr(Design*des, NetScope*) const;
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
|
||||
bool sys_task_arg =false) const;
|
||||
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
virtual verinum* eval_const(const Design*des, const NetScope*sc) const;
|
||||
|
||||
@@ -343,7 +382,8 @@ class PEBinary : public PExpr {
|
||||
unsigned long decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
virtual NetEBinary*elaborate_expr(Design*des, NetScope*) const;
|
||||
virtual NetEBinary*elaborate_expr(Design*des, NetScope*,
|
||||
bool sys_task_arg =false) const;
|
||||
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
virtual verinum* eval_const(const Design*des, const NetScope*sc) const;
|
||||
virtual verireal*eval_rconst(const Design*des, const NetScope*sc) const;
|
||||
@@ -417,7 +457,8 @@ class PETernary : public PExpr {
|
||||
unsigned long decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
virtual NetETernary*elaborate_expr(Design*des, NetScope*) const;
|
||||
virtual NetETernary*elaborate_expr(Design*des, NetScope*,
|
||||
bool sys_task_arg =false) const;
|
||||
virtual NetETernary*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
virtual verinum* eval_const(const Design*des, const NetScope*sc) const;
|
||||
|
||||
@@ -429,7 +470,8 @@ class PETernary : public PExpr {
|
||||
|
||||
/*
|
||||
* This class represents a parsed call to a function, including calls
|
||||
* to system functions.
|
||||
* to system functions. The parameters in the parms list are the
|
||||
* expressions that are passed as input to the ports of the function.
|
||||
*/
|
||||
class PECallFunction : public PExpr {
|
||||
public:
|
||||
@@ -438,17 +480,61 @@ class PECallFunction : public PExpr {
|
||||
~PECallFunction();
|
||||
|
||||
virtual void dump(ostream &) const;
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope) const;
|
||||
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
|
||||
unsigned width,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
||||
bool sys_task_arg =false) const;
|
||||
|
||||
private:
|
||||
hname_t path_;
|
||||
svector<PExpr *> parms_;
|
||||
|
||||
bool check_call_matches_definition_(Design*des, NetScope*dscope) const;
|
||||
|
||||
NetExpr* elaborate_sfunc_(Design*des, NetScope*scope) const;
|
||||
};
|
||||
|
||||
/*
|
||||
* $Log: PExpr.h,v $
|
||||
* Revision 1.62 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.61 2002/06/04 05:38:43 steve
|
||||
* Add support for memory words in l-value of
|
||||
* blocking assignments, and remove the special
|
||||
* NetAssignMem class.
|
||||
*
|
||||
* Revision 1.60 2002/05/23 03:08:51 steve
|
||||
* Add language support for Verilog-2001 attribute
|
||||
* syntax. Hook this support into existing $attribute
|
||||
* handling, and add number and void value types.
|
||||
*
|
||||
* Add to the ivl_target API new functions for access
|
||||
* of complex attributes attached to gates.
|
||||
*
|
||||
* Revision 1.59 2002/04/23 03:53:59 steve
|
||||
* Add support for non-constant bit select.
|
||||
*
|
||||
* Revision 1.58 2002/04/14 03:55:25 steve
|
||||
* Precalculate unary - if possible.
|
||||
*
|
||||
* Revision 1.57 2002/04/13 02:33:17 steve
|
||||
* Detect missing indices to memories (PR#421)
|
||||
*
|
||||
* Revision 1.56 2002/03/09 04:02:26 steve
|
||||
* Constant expressions are not l-values for task ports.
|
||||
*
|
||||
* Revision 1.55 2002/03/09 02:10:22 steve
|
||||
* Add the NetUserFunc netlist node.
|
||||
*
|
||||
* Revision 1.54 2001/12/30 21:32:03 steve
|
||||
* Support elaborate_net for PEString objects.
|
||||
*
|
||||
* Revision 1.53 2001/12/03 04:47:14 steve
|
||||
* Parser and pform use hierarchical names as hname_t
|
||||
* objects instead of encoded strings.
|
||||
@@ -461,26 +547,5 @@ class PECallFunction : public PExpr {
|
||||
*
|
||||
* Revision 1.50 2001/11/07 04:01:59 steve
|
||||
* eval_const uses scope instead of a string path.
|
||||
*
|
||||
* Revision 1.49 2001/11/06 06:11:55 steve
|
||||
* Support more real arithmetic in delay constants.
|
||||
*
|
||||
* Revision 1.48 2001/01/14 23:04:55 steve
|
||||
* Generalize the evaluation of floating point delays, and
|
||||
* get it working with delay assignment statements.
|
||||
*
|
||||
* Allow parameters to be referenced by hierarchical name.
|
||||
*
|
||||
* Revision 1.47 2000/12/16 19:03:30 steve
|
||||
* Evaluate <= and ?: in parameter expressions (PR#81)
|
||||
*
|
||||
* Revision 1.46 2000/12/10 22:01:35 steve
|
||||
* Support decimal constants in behavioral delays.
|
||||
*
|
||||
* Revision 1.45 2000/12/06 06:31:09 steve
|
||||
* Check lvalue of procedural continuous assign (PR#29)
|
||||
*
|
||||
* Revision 1.44 2000/09/17 21:26:15 steve
|
||||
* Add support for modulus (Eric Aardoom)
|
||||
*/
|
||||
#endif
|
||||
|
||||
+5
-2
@@ -16,8 +16,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: PFunction.cc,v 1.5 2001/07/25 03:10:48 steve Exp $"
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PFunction.cc,v 1.6 2002/08/12 01:34:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -54,6 +54,9 @@ void PFunction::set_output(PWire*o)
|
||||
|
||||
/*
|
||||
* $Log: PFunction.cc,v $
|
||||
* Revision 1.6 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.5 2001/07/25 03:10:48 steve
|
||||
* Create a config.h.in file to hold all the config
|
||||
* junk, and support gcc 3.0. (Stephan Boettcher)
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: PGate.cc,v 1.13 2001/11/22 06:20:59 steve Exp $"
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PGate.cc,v 1.14 2002/08/12 01:34:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -192,6 +192,9 @@ const char* PGModule::get_type()
|
||||
|
||||
/*
|
||||
* $Log: PGate.cc,v $
|
||||
* Revision 1.14 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.13 2001/11/22 06:20:59 steve
|
||||
* Use NetScope instead of string for scope path.
|
||||
*
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: PGate.h,v 1.22 2001/11/22 06:20:59 steve Exp $"
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PGate.h,v 1.24 2002/08/12 01:34:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "svector.h"
|
||||
@@ -79,7 +79,7 @@ class PGate : public LineInfo {
|
||||
void strength0(strength_t);
|
||||
void strength1(strength_t);
|
||||
|
||||
map<string,string> attributes;
|
||||
map<string,PExpr*> attributes;
|
||||
|
||||
virtual void dump(ostream&out) const;
|
||||
virtual void elaborate(Design*des, NetScope*scope) const;
|
||||
@@ -222,6 +222,17 @@ class PGModule : public PGate {
|
||||
|
||||
/*
|
||||
* $Log: PGate.h,v $
|
||||
* Revision 1.24 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.23 2002/05/23 03:08:51 steve
|
||||
* Add language support for Verilog-2001 attribute
|
||||
* syntax. Hook this support into existing $attribute
|
||||
* handling, and add number and void value types.
|
||||
*
|
||||
* Add to the ivl_target API new functions for access
|
||||
* of complex attributes attached to gates.
|
||||
*
|
||||
* Revision 1.22 2001/11/22 06:20:59 steve
|
||||
* Use NetScope instead of string for scope path.
|
||||
*
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: PTask.cc,v 1.6 2001/07/25 03:10:48 steve Exp $"
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PTask.cc,v 1.7 2002/08/12 01:34:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -48,6 +48,9 @@ void PTask::set_statement(Statement*s)
|
||||
|
||||
/*
|
||||
* $Log: PTask.cc,v $
|
||||
* Revision 1.7 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.6 2001/07/25 03:10:48 steve
|
||||
* Create a config.h.in file to hold all the config
|
||||
* junk, and support gcc 3.0. (Stephan Boettcher)
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: PTask.h,v 1.11 2001/11/22 06:20:59 steve Exp $"
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PTask.h,v 1.12 2002/08/12 01:34:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "LineInfo.h"
|
||||
@@ -98,6 +98,9 @@ class PFunction : public LineInfo {
|
||||
|
||||
/*
|
||||
* $Log: PTask.h,v $
|
||||
* Revision 1.12 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.11 2001/11/22 06:20:59 steve
|
||||
* Use NetScope instead of string for scope path.
|
||||
*
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: PUdp.h,v 1.5 2001/04/22 23:09:45 steve Exp $"
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PUdp.h,v 1.7 2002/08/12 01:34:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <map>
|
||||
@@ -27,6 +27,8 @@
|
||||
# include <string>
|
||||
# include "verinum.h"
|
||||
|
||||
class PExpr;
|
||||
|
||||
svector<string>::svector<string>(unsigned size)
|
||||
: nitems_(size), items_(new string[size])
|
||||
{
|
||||
@@ -68,7 +70,7 @@ class PUdp {
|
||||
|
||||
verinum::V initial;
|
||||
|
||||
map<string,string> attributes;
|
||||
map<string,PExpr*> attributes;
|
||||
|
||||
void dump(ostream&out) const;
|
||||
|
||||
@@ -82,6 +84,17 @@ class PUdp {
|
||||
|
||||
/*
|
||||
* $Log: PUdp.h,v $
|
||||
* Revision 1.7 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.6 2002/05/23 03:08:51 steve
|
||||
* Add language support for Verilog-2001 attribute
|
||||
* syntax. Hook this support into existing $attribute
|
||||
* handling, and add number and void value types.
|
||||
*
|
||||
* Add to the ivl_target API new functions for access
|
||||
* of complex attributes attached to gates.
|
||||
*
|
||||
* Revision 1.5 2001/04/22 23:09:45 steve
|
||||
* More UDP consolidation from Stephan Boettcher.
|
||||
*
|
||||
|
||||
@@ -16,37 +16,41 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: PWire.cc,v 1.7 2001/12/03 04:47:14 steve Exp $"
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PWire.cc,v 1.10 2002/08/12 01:34:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include "PWire.h"
|
||||
# include <assert.h>
|
||||
|
||||
PWire::PWire(const hname_t&n, NetNet::Type t, NetNet::PortType pt)
|
||||
: hname_(n), type_(t), port_type_(pt), signed_(false), lidx_(0), ridx_(0)
|
||||
: hname_(n), type_(t), port_type_(pt), signed_(false), isint_(false),
|
||||
lidx_(0), ridx_(0)
|
||||
{
|
||||
if (t == NetNet::INTEGER) {
|
||||
type_ = NetNet::REG;
|
||||
signed_ = true;
|
||||
isint_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
PWire::PWire(char*n, NetNet::Type t, NetNet::PortType pt)
|
||||
: hname_(n), type_(t), port_type_(pt), signed_(false), lidx_(0), ridx_(0)
|
||||
: hname_(n), type_(t), port_type_(pt), signed_(false), isint_(false),
|
||||
lidx_(0), ridx_(0)
|
||||
{
|
||||
if (t == NetNet::INTEGER) {
|
||||
type_ = NetNet::REG;
|
||||
signed_ = true;
|
||||
isint_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
NetNet::Type PWire::get_wire_type() const
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
#if 0
|
||||
string PWire::name() const
|
||||
{
|
||||
string name = hname_[0];
|
||||
for (unsigned idx = 1 ; hname_[idx] ; idx += 1)
|
||||
name = name + "." + hname_[idx];
|
||||
}
|
||||
#endif
|
||||
|
||||
const hname_t& PWire::path() const
|
||||
{
|
||||
return hname_;
|
||||
@@ -64,6 +68,10 @@ bool PWire::set_wire_type(NetNet::Type t)
|
||||
if (t == NetNet::REG) { type_ = t; return true; }
|
||||
return false;
|
||||
case NetNet::REG:
|
||||
if (t == NetNet::INTEGER) {
|
||||
isint_ = true;
|
||||
return true;
|
||||
}
|
||||
if (t == NetNet::REG) return true;
|
||||
return false;
|
||||
default:
|
||||
@@ -110,6 +118,11 @@ bool PWire::get_signed() const
|
||||
return signed_;
|
||||
}
|
||||
|
||||
bool PWire::get_isint() const
|
||||
{
|
||||
return isint_;
|
||||
}
|
||||
|
||||
void PWire::set_range(PExpr*m, PExpr*l)
|
||||
{
|
||||
msb_ = svector<PExpr*>(msb_,m);
|
||||
@@ -127,6 +140,15 @@ void PWire::set_memory_idx(PExpr*ldx, PExpr*rdx)
|
||||
|
||||
/*
|
||||
* $Log: PWire.cc,v $
|
||||
* Revision 1.10 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.9 2002/06/21 04:59:35 steve
|
||||
* Carry integerness throughout the compilation.
|
||||
*
|
||||
* Revision 1.8 2002/01/26 05:28:28 steve
|
||||
* Detect scalar/vector declarion mismatch.
|
||||
*
|
||||
* Revision 1.7 2001/12/03 04:47:14 steve
|
||||
* Parser and pform use hierarchical names as hname_t
|
||||
* objects instead of encoded strings.
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: PWire.h,v 1.11 2001/12/03 04:47:14 steve Exp $"
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PWire.h,v 1.14 2002/08/12 01:34:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
@@ -64,12 +64,13 @@ class PWire : public LineInfo {
|
||||
|
||||
void set_signed(bool flag);
|
||||
bool get_signed() const;
|
||||
bool get_isint() const;
|
||||
|
||||
void set_range(PExpr*msb, PExpr*lsb);
|
||||
|
||||
void set_memory_idx(PExpr*ldx, PExpr*rdx);
|
||||
|
||||
map<string,string> attributes;
|
||||
map<string,PExpr*> attributes;
|
||||
|
||||
// Write myself to the specified stream.
|
||||
void dump(ostream&out) const;
|
||||
@@ -81,6 +82,7 @@ class PWire : public LineInfo {
|
||||
NetNet::Type type_;
|
||||
NetNet::PortType port_type_;
|
||||
bool signed_;
|
||||
bool isint_; // original type of integer
|
||||
|
||||
// These members hold expressions for the bit width of the
|
||||
// wire. If they do not exist, the wire is 1 bit wide.
|
||||
@@ -99,6 +101,20 @@ class PWire : public LineInfo {
|
||||
|
||||
/*
|
||||
* $Log: PWire.h,v $
|
||||
* Revision 1.14 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.13 2002/06/21 04:59:35 steve
|
||||
* Carry integerness throughout the compilation.
|
||||
*
|
||||
* Revision 1.12 2002/05/23 03:08:51 steve
|
||||
* Add language support for Verilog-2001 attribute
|
||||
* syntax. Hook this support into existing $attribute
|
||||
* handling, and add number and void value types.
|
||||
*
|
||||
* Add to the ivl_target API new functions for access
|
||||
* of complex attributes attached to gates.
|
||||
*
|
||||
* Revision 1.11 2001/12/03 04:47:14 steve
|
||||
* Parser and pform use hierarchical names as hname_t
|
||||
* objects instead of encoded strings.
|
||||
|
||||
+133
-139
@@ -12,14 +12,13 @@ home page at <http://www.icarus.com/eda/verilog>.
|
||||
|
||||
Icarus Verilog is not aimed at being a simulator in the traditional
|
||||
sense, but a compiler that generates code employed by back-end
|
||||
tools. These back-end tools currently include a simulator written in
|
||||
C++ called VVM, another faster simulator called VVP and an XNF (Xilinx
|
||||
Netlist Format) generator. See "vvm.txt" and "xnf.txt" for further
|
||||
details on these back-end processors. In the future, backends are
|
||||
expected for EDIF/LPM, structural Verilog, VHDL, etc.
|
||||
tools. These back-end tools currently include a simulator engine
|
||||
called VVP, an XNF (Xilinx Netlist Format) generator and an EDIF fpga
|
||||
netlist generator. In the future, backends are expected for EDIF/LPM,
|
||||
structural Verilog, VHDL, etc.
|
||||
|
||||
For instructions on how to run Icarus Verilog, see the ``iverilog''
|
||||
man page.
|
||||
For instructions on how to run Icarus Verilog,
|
||||
see the ``iverilog'' man page.
|
||||
|
||||
|
||||
2.0 Building/Installing Icarus Verilog From Source
|
||||
@@ -30,6 +29,8 @@ system and C/C++ compilation should be able to build the source
|
||||
distribution with little effort. Some actual programming skills are
|
||||
not required, but helpful in case of problems.
|
||||
|
||||
If you are building for Windows, see the mingw.txt file.
|
||||
|
||||
2.1 Compile Time Prerequisites
|
||||
|
||||
You need the following software to compile Icarus Verilog from source
|
||||
@@ -38,7 +39,7 @@ on a UNIX-like system:
|
||||
- GNU Make
|
||||
The Makefiles use some GNU extensions, so a basic POSIX
|
||||
make will not work. Linux systems typically come with a
|
||||
satisfactory make. BSD based systems (i.e. NetBSD, FreeBSD)
|
||||
satisfactory make. BSD based systems (i.e., NetBSD, FreeBSD)
|
||||
typically have GNU make as the gmake program.
|
||||
|
||||
- ISO C++ Compiler
|
||||
@@ -73,7 +74,7 @@ configure script that modify its behavior:
|
||||
|
||||
--without-ipal
|
||||
This turns off support for Icarus PAL, whether ipal
|
||||
libaries are installed or not.
|
||||
libraries are installed or not.
|
||||
|
||||
--prefix=<root>
|
||||
The default is /usr/local, which causes the tool suite to
|
||||
@@ -81,8 +82,9 @@ configure script that modify its behavior:
|
||||
/usr/local/share/ivl, etc.
|
||||
|
||||
I recommend that if you are configuring for precompiled
|
||||
binaries, use --prefix=/usr. On Solaris systems, it is
|
||||
common to use --prefix=/opt.
|
||||
binaries, use --prefix=/usr. On Solaris systems, it is
|
||||
common to use --prefix=/opt. You can configure for a non-root
|
||||
install with --prefix=$HOME.
|
||||
|
||||
2.3 (Optional) Testing
|
||||
|
||||
@@ -91,7 +93,7 @@ To run a simple test before installation, execute
|
||||
make check
|
||||
|
||||
The commands printed by this run might help you in running Icarus
|
||||
Verilog on your own verilog sources before the package is installed
|
||||
Verilog on your own Verilog sources before the package is installed
|
||||
by root.
|
||||
|
||||
2.4 Installation
|
||||
@@ -127,7 +129,7 @@ only sees a single input file. See ivlpp/ivlpp.txt for details.
|
||||
|
||||
3.2 Parse
|
||||
|
||||
The verilog compiler starts by parsing the verilog source file. The
|
||||
The Verilog compiler starts by parsing the Verilog source file. The
|
||||
output of the parse in a list of Module objects in PFORM. The pform
|
||||
(see pform.h) is mostly a direct reflection of the compilation
|
||||
step. There may be dangling references, and it is not yet clear which
|
||||
@@ -150,10 +152,10 @@ The elaborate() function performs the elaboration.
|
||||
|
||||
One can see a human readable version of the final, elaborated and
|
||||
optimized netlist by using the ``-N <path>'' flag to the compiler. If
|
||||
elaboration succeeds, the final netlist (i.e. after optimizations but
|
||||
elaboration succeeds, the final netlist (i.e., after optimizations but
|
||||
before code generation) will be dumped into the file named <path>.
|
||||
|
||||
Elaboration is actually performed it two steps: scopes and parameters
|
||||
Elaboration is actually performed in two steps: scopes and parameters
|
||||
first, followed by the structural and behavioral elaboration.
|
||||
|
||||
3.3.1 Scope Elaboration
|
||||
@@ -182,19 +184,19 @@ simply passing through the pform.
|
||||
|
||||
This is actually a collection of processing steps that perform
|
||||
optimizations that do not depend on the target technology. Examples of
|
||||
some useful transformations would be,
|
||||
some useful transformations are
|
||||
|
||||
- eliminate null effect circuitry,
|
||||
- eliminate null effect circuitry
|
||||
- combinational reduction
|
||||
- Constant propagation
|
||||
- constant propagation
|
||||
|
||||
The actual functions performed are specified on the ivl command line by
|
||||
the -F flags (See below).
|
||||
the -F flags (see below).
|
||||
|
||||
3.5 Code Generation
|
||||
|
||||
This step takes the design netlist and uses it to drive the code
|
||||
generator. (See target.h.) This may require transforming the
|
||||
generator (see target.h). This may require transforming the
|
||||
design to suit the technology.
|
||||
|
||||
The emit() method of the Design class performs this step. It runs
|
||||
@@ -206,7 +208,10 @@ command line.
|
||||
|
||||
3.6 ATTRIBUTES
|
||||
|
||||
The parser accepts as an extension to Verilog the $attribute module
|
||||
NOTE: The $attribute syntax will soon be deprecated in favor of the
|
||||
Verilog-2001 attribute syntax, which is cleaner and standardized.
|
||||
|
||||
The parser accepts, as an extension to Verilog, the $attribute module
|
||||
item. The syntax of the $attribute item is:
|
||||
|
||||
$attribute (<identifier>, <key>, <value>);
|
||||
@@ -234,6 +239,11 @@ between processing steps. Processing steps that are aware of others
|
||||
may place attributes on netlist objects to communicate information to
|
||||
later steps.
|
||||
|
||||
Icarus Verilog also accepts the Verilog 2001 syntax for
|
||||
attributes. They have the same general meaning as with the $attribute
|
||||
syntax, but they are attached to objects by position instead of by
|
||||
name. Also, the key is a Verilog identifier instead of a string.
|
||||
|
||||
4.0 Running iverilog
|
||||
|
||||
The preferred way to invoke the compiler is with the iverilog(1)
|
||||
@@ -241,102 +251,8 @@ command. This program invokes the preprocessor (ivlpp) and the
|
||||
compiler (ivl) with the proper command line options to get the job
|
||||
done in a friendly way. See the iverilog(1) man page for usage details.
|
||||
|
||||
4.1 Running IVL Directly (not recommended)
|
||||
|
||||
NOTE: The preferred method of running Icarus Verilog is the
|
||||
iverilog command described above. The instructions below may
|
||||
change at any time without notice.
|
||||
|
||||
The ivl command is the compiler driver, that invokes the parser,
|
||||
optimization functions and the code generator, but not the preprocessor.
|
||||
|
||||
Usage: ivl <options>... file
|
||||
ivl -h
|
||||
ivl -V
|
||||
|
||||
-F <name>
|
||||
Use this flag to request an optimization function be applied
|
||||
to the netlist before it is sent to the target output
|
||||
stage. Any number of -F options may be given, to specify a
|
||||
variety of processing steps. The steps will be applied in
|
||||
order, with the output of one uses as the input to the next.
|
||||
|
||||
The function is specified by name. Use the "ivl -h" command to
|
||||
get a list of configured function names.
|
||||
|
||||
-h
|
||||
Print usage information, and exit.
|
||||
|
||||
-m <module>
|
||||
Cause a named VPI module to be included in the module
|
||||
list. This parameter appends the named module to the end of
|
||||
the VPI_MODULE_LIST. This is an ordered list of modules to be
|
||||
loaded into the simulation at runtime.
|
||||
|
||||
This list can also be set with -fVPI_MODULE_LIST=<list> which
|
||||
sets the list completely. Then, -m after this will append
|
||||
module names to the list sp specified. The default list
|
||||
includes "system".
|
||||
|
||||
-N <file>
|
||||
Dump the elaborated netlist to the named file. The netlist is
|
||||
the folly elaborated netlist, after all the function modules
|
||||
are applied and right before the output generator is
|
||||
called. This is an aid for debugging the compiler, and the
|
||||
output generator in particular.
|
||||
|
||||
-o <file>
|
||||
Normally, the generated result is sent to standard
|
||||
output. Use the -o flag to specify an output file for the
|
||||
generated result.
|
||||
|
||||
-P <file>
|
||||
Write the PForm of the parsed input to the specified file.
|
||||
The pform is the compiler's understanding of the input after
|
||||
parsing and before elaboration. This is an aid for debugging
|
||||
the compiler.
|
||||
|
||||
-p <assign>
|
||||
Use this flag to set a parameter value. The format of the
|
||||
assignment is <key>=<value> where key is any string up to the
|
||||
first '=', and <value> is the rest of the option. If the '='
|
||||
is omitted, then the key is assigned the empty string.
|
||||
|
||||
The useful keys are defined by the functions and the target in
|
||||
use. These assignments are specifically useful for passing
|
||||
target specific information to the target back-end, or
|
||||
options/parameters to optimization functions, if any are defined.
|
||||
|
||||
-s <module>
|
||||
Normally, ivl will locate all the modules that are defined but
|
||||
never instantiated, and use these as the design roots for
|
||||
elaboration. This flag allows the choice of root module(s) to
|
||||
be manually overridden. It can be used more than once on the
|
||||
command line if multiple root modules are needed.
|
||||
|
||||
-T [min|typ|max]
|
||||
Normally, ivl will select typ values from min:type:max
|
||||
expressions and print a warning. This flag tells the compiler
|
||||
exactly which value to choose, and suppresses the warning.
|
||||
|
||||
-t <name>
|
||||
Select the output format for the compiled result. Use the
|
||||
"ivl -h" command to get a list of configured targets.
|
||||
|
||||
-v Print progress indications, and (if supported by the system)
|
||||
executions times in ivl precessing steps.
|
||||
|
||||
-V
|
||||
Print version and copyright information for ivl, and exit.
|
||||
|
||||
-y <dir>
|
||||
Add the specified directory to the library search path. If
|
||||
missing modules are discovered during elaboration, ivl will
|
||||
attempt to locate an implementation by searching the library
|
||||
directories for a Verilog source file with the same name as
|
||||
the module.
|
||||
|
||||
4.2 EXAMPLES
|
||||
4.1 EXAMPLES
|
||||
|
||||
Example: Compiling "hello.vl"
|
||||
|
||||
@@ -353,7 +269,7 @@ endmodule
|
||||
|
||||
--------------------------------------------------------------
|
||||
|
||||
Insure that "iverilog" is on your search path, and the vpi library
|
||||
Ensure that "iverilog" is on your search path, and the vpi library
|
||||
is available.
|
||||
|
||||
To compile the program:
|
||||
@@ -374,25 +290,12 @@ by the compiler. See the iverilog(1) man page.
|
||||
|
||||
Icarus Verilog is in development - as such it still only supports a
|
||||
(growing) subset of Verilog. Below is a description of some of the
|
||||
currently unsupported verilog features. This list is not exhaustive,
|
||||
currently unsupported Verilog features. This list is not exhaustive,
|
||||
and does not account for errors in the compiler. See the Icarus
|
||||
Verilog web page for the current state of support for Verilog, and in
|
||||
particular, browse the bug report database for reported unsupported
|
||||
constructs.
|
||||
|
||||
- block disable not supported, i.e.:
|
||||
|
||||
begin : foo
|
||||
[...]
|
||||
disable foo; // sorry
|
||||
[...]
|
||||
end
|
||||
|
||||
- Functions in structural contexts are not supported.
|
||||
|
||||
assign foo = user_function(a,b); // sorry
|
||||
always @(a or b) foo = user_function(a,b); // OK
|
||||
|
||||
- real data types not supported. This includes real and
|
||||
realtime. However, floating point constants in delay expressions
|
||||
are supported so that `timescale works properly.
|
||||
@@ -404,6 +307,94 @@ constructs.
|
||||
|
||||
- trireg is not supported. tri0 and tri1 are supported.
|
||||
|
||||
- tran primitives, i.e. tran, tranif1, tranif0, rtran, rtranif1
|
||||
and rtranif0 are not supported.
|
||||
|
||||
- Module instance arrays are not supported, although gate instance
|
||||
arrays do work.
|
||||
|
||||
- Net delays, of the form "wire #N foo;" do not work. Delays in
|
||||
every other context do work properly, including the V2001 form
|
||||
"wire #5 foo = bar;"
|
||||
|
||||
- Event controls inside non-blocking assignments are not supported.
|
||||
i.e.: a <= @(posedge clk) b;
|
||||
|
||||
- Lists of named events of the form @(event_1 or event_2) are not
|
||||
supported. Named events are otherwise supported, and lists of
|
||||
other kinds of events are also supported.
|
||||
|
||||
- Macro arguments are not supported. `define macros are supported,
|
||||
but they cannot take arguments.
|
||||
|
||||
5.1 Nonstandard Constructs or Behaviors
|
||||
|
||||
Icarus Verilog includes some features that are not part of the
|
||||
IEEE1364 standard, but have well defined meaning, and also sometimes
|
||||
gives nonstandard (but extended) meanings to some features of the
|
||||
language that are defined.
|
||||
|
||||
$sizeof(<expr>)
|
||||
$bits(<expr>)
|
||||
The $bits system function returns the size in bits of the
|
||||
expression that is its argument. The result of this
|
||||
function is undefined if the argument doesn't have a
|
||||
self-determined size.
|
||||
|
||||
The $sizeof function is deprecated in favor of $bits, which is
|
||||
the same thing, but included in the SystemVerilog definition.
|
||||
|
||||
Builtin system functions
|
||||
|
||||
Certain of the system functions have well defined meanings, so
|
||||
can theoretically be evaluated at compile time, instead of
|
||||
using runtime VPI code. Doing so means that VPI cannot
|
||||
override the definitions of functions handled in this
|
||||
manner. On the other hand, this makes them synthesizeable, and
|
||||
also allows for more aggressive constant propagation. The
|
||||
functions handled in this manner are:
|
||||
|
||||
$bits
|
||||
$signed
|
||||
$sizeof
|
||||
$unsigned
|
||||
|
||||
Implementations of these system functions in VPI modules will
|
||||
be ignored.
|
||||
|
||||
Preprocessing Library Modules
|
||||
|
||||
Icarus Verilog does preprocess modules that are loaded from
|
||||
libraries via the -y mechanism. However, the only macros
|
||||
defined during compilation of that file are those that it
|
||||
defines itself (or includes) or that are defined on the
|
||||
command line or command file.
|
||||
|
||||
Specifically, macros defined in the non-library source files
|
||||
are not remembered when the library module is loaded. This is
|
||||
intentional. If it were otherwise, then compilation results
|
||||
might vary depending on the order that libraries are loaded,
|
||||
and that is too unpredictable.
|
||||
|
||||
It is said that some commercial compilers do allow macro
|
||||
definitions to span library modules. That's just plain weird.
|
||||
|
||||
Width in %t Time Formats
|
||||
|
||||
Standard Verilog does not allow width fields in the %t formats
|
||||
of display strings. For example, this is illegal:
|
||||
|
||||
$display("Time is %0t", %time);
|
||||
|
||||
Standard Verilog instead relies on the $timeformat to
|
||||
completely specify the format.
|
||||
|
||||
Icarus Verilog allows the programmer to specify the field
|
||||
with. The "%t" format in Icarus Verilog works exactly as it
|
||||
does in standard Verilog. However, if the programmer chooses
|
||||
to specify a minimum width (i.e., "%5t"), then for that display
|
||||
Icarus Verilog will override the $timeformat minimum width and
|
||||
use the explicit minimum width.
|
||||
|
||||
6.0 CREDITS
|
||||
|
||||
@@ -420,15 +411,18 @@ Verilog guidance, and especially testing from many people, including
|
||||
Guy Hutchison <[email protected]>
|
||||
Ales Hvezda <[email protected]>
|
||||
Venkat Iyer <[email protected]>
|
||||
Yasuhisa Kato <ykato@mac.com>
|
||||
Yasuhisa Kato <kato@y.email.ne.jp>
|
||||
James Lee <[email protected]>
|
||||
Peter Monta <[email protected]>
|
||||
Daniel H. Nelsen <[email protected]>
|
||||
Stefan Petersen <[email protected]>
|
||||
Michael Ruff <[email protected]>
|
||||
Mike Runyan <[email protected]>
|
||||
Jason Schonberg <[email protected]>
|
||||
Stuart Sutherland <[email protected]>
|
||||
Stephen Tell <[email protected]>
|
||||
Stefan Theide <[email protected]>
|
||||
Tom Verbeure
|
||||
Steve Wilson <[email protected]>
|
||||
|
||||
and others. Testers in particular include a larger community of people
|
||||
@@ -454,7 +448,7 @@ removed from the list) send e-mail to me.
|
||||
Hamish Moffatt <[email protected]>
|
||||
|
||||
Macintosh -- MacO/S
|
||||
Yasuhisa Kato <ykato@mac.com>
|
||||
Yasuhisa Kato <kato@y.email.ne.jp>
|
||||
|
||||
Mac O/S X
|
||||
Timothy J. Wood <[email protected]>
|
||||
@@ -477,10 +471,10 @@ just the systems where precompiled binaries are publicly available.
|
||||
|
||||
6.2 TEST SUITE MANAGER
|
||||
|
||||
Steve Wilson <stevew@home.com> or <[email protected]> has taken on
|
||||
the large task of managing the test suite. He has maintained the
|
||||
regression test scripts, the driver list, received submissions from
|
||||
myself and others, and has written a great many tests on his own. Any
|
||||
compiler writer, for any language, will tell you that the test suite
|
||||
is at least as important as the compiler code itself.
|
||||
Steve Wilson <stevew@ka6s.com> has taken on the large task of managing
|
||||
the test suite. He has maintained the regression test scripts, the
|
||||
driver list, received submissions from myself and others, and has
|
||||
written a great many tests on his own. Any compiler writer, for any
|
||||
language, will tell you that the test suite is at least as important
|
||||
as the compiler code itself.
|
||||
|
||||
|
||||
+24
-3
@@ -16,8 +16,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: Statement.cc,v 1.25 2001/12/03 04:47:14 steve Exp $"
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: Statement.cc,v 1.28 2002/08/12 01:34:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -32,17 +32,19 @@ Statement::~Statement()
|
||||
PAssign_::PAssign_(PExpr*lval, PExpr*ex)
|
||||
: event_(0), lval_(lval), rval_(ex)
|
||||
{
|
||||
delay_ = 0;
|
||||
}
|
||||
|
||||
PAssign_::PAssign_(PExpr*lval, PExpr*de, PExpr*ex)
|
||||
: event_(0), lval_(lval), rval_(ex)
|
||||
{
|
||||
if (de) delay_.set_delay(de);
|
||||
delay_ = de;
|
||||
}
|
||||
|
||||
PAssign_::PAssign_(PExpr*lval, PEventStatement*ev, PExpr*ex)
|
||||
: event_(ev), lval_(lval), rval_(ex)
|
||||
{
|
||||
delay_ = 0;
|
||||
}
|
||||
|
||||
PAssign_::~PAssign_()
|
||||
@@ -188,6 +190,7 @@ PDisable::~PDisable()
|
||||
PEventStatement::PEventStatement(const svector<PEEvent*>&ee)
|
||||
: expr_(ee), statement_(0)
|
||||
{
|
||||
assert(expr_.count() > 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -197,6 +200,11 @@ PEventStatement::PEventStatement(PEEvent*ee)
|
||||
expr_[0] = ee;
|
||||
}
|
||||
|
||||
PEventStatement::PEventStatement(void)
|
||||
: statement_(0)
|
||||
{
|
||||
}
|
||||
|
||||
PEventStatement::~PEventStatement()
|
||||
{
|
||||
// delete the events and the statement?
|
||||
@@ -287,6 +295,19 @@ PWhile::~PWhile()
|
||||
|
||||
/*
|
||||
* $Log: Statement.cc,v $
|
||||
* Revision 1.28 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.27 2002/04/21 22:31:02 steve
|
||||
* Redo handling of assignment internal delays.
|
||||
* Leave it possible for them to be calculated
|
||||
* at run time.
|
||||
*
|
||||
* Revision 1.26 2002/04/21 04:59:07 steve
|
||||
* Add support for conbinational events by finding
|
||||
* the inputs to expressions and some statements.
|
||||
* Get case and assignment statements working.
|
||||
*
|
||||
* Revision 1.25 2001/12/03 04:47:14 steve
|
||||
* Parser and pform use hierarchical names as hname_t
|
||||
* objects instead of encoded strings.
|
||||
|
||||
+33
-5
@@ -18,8 +18,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: Statement.h,v 1.31 2001/12/03 04:47:14 steve Exp $"
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: Statement.h,v 1.36 2002/08/12 01:34:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <string>
|
||||
@@ -56,6 +56,8 @@ class PProcess : public LineInfo {
|
||||
Type type() const { return type_; }
|
||||
Statement*statement() { return statement_; }
|
||||
|
||||
map<string,PExpr*> attributes;
|
||||
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
@@ -97,7 +99,7 @@ class PAssign_ : public Statement {
|
||||
protected:
|
||||
NetAssign_* elaborate_lval(Design*, NetScope*scope) const;
|
||||
|
||||
PDelays delay_;
|
||||
PExpr* delay_;
|
||||
PEventStatement*event_;
|
||||
|
||||
private:
|
||||
@@ -117,8 +119,6 @@ class PAssign : public PAssign_ {
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
|
||||
private:
|
||||
NetProc*assign_to_memory_(class NetMemory*, PExpr*,
|
||||
Design*des, NetScope*scope) const;
|
||||
};
|
||||
|
||||
class PAssignNB : public PAssign_ {
|
||||
@@ -308,6 +308,7 @@ class PDisable : public Statement {
|
||||
*
|
||||
* @name <statement>;
|
||||
* @(expr) <statement>;
|
||||
* @* <statement>;
|
||||
*/
|
||||
class PEventStatement : public Statement {
|
||||
|
||||
@@ -315,6 +316,8 @@ class PEventStatement : public Statement {
|
||||
|
||||
explicit PEventStatement(const svector<PEEvent*>&ee);
|
||||
explicit PEventStatement(PEEvent*ee);
|
||||
// Make an @* statement.
|
||||
explicit PEventStatement(void);
|
||||
|
||||
~PEventStatement();
|
||||
|
||||
@@ -450,6 +453,31 @@ class PWhile : public Statement {
|
||||
|
||||
/*
|
||||
* $Log: Statement.h,v $
|
||||
* Revision 1.36 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.35 2002/06/04 05:38:44 steve
|
||||
* Add support for memory words in l-value of
|
||||
* blocking assignments, and remove the special
|
||||
* NetAssignMem class.
|
||||
*
|
||||
* Revision 1.34 2002/05/26 01:39:02 steve
|
||||
* Carry Verilog 2001 attributes with processes,
|
||||
* all the way through to the ivl_target API.
|
||||
*
|
||||
* Divide signal reference counts between rval
|
||||
* and lval references.
|
||||
*
|
||||
* Revision 1.33 2002/04/21 22:31:02 steve
|
||||
* Redo handling of assignment internal delays.
|
||||
* Leave it possible for them to be calculated
|
||||
* at run time.
|
||||
*
|
||||
* Revision 1.32 2002/04/21 04:59:07 steve
|
||||
* Add support for conbinational events by finding
|
||||
* the inputs to expressions and some statements.
|
||||
* Get case and assignment statements working.
|
||||
*
|
||||
* Revision 1.31 2001/12/03 04:47:14 steve
|
||||
* Parser and pform use hierarchical names as hname_t
|
||||
* objects instead of encoded strings.
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (c) 2002 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
* ---
|
||||
* You should also have recieved a copy of the Picture Elements
|
||||
* Binary Software License offer along with the source. This offer
|
||||
* allows you to obtain the right to redistribute the software in
|
||||
* binary (compiled) form. If you have not received it, contact
|
||||
* Picture Elements, Inc., 777 Panoramic Way, Berkeley, CA 94704.
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: StringHeap.cc,v 1.2 2002/08/12 01:34:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "StringHeap.h"
|
||||
#ifdef HAVE_MALLOC_H
|
||||
# include <malloc.h>
|
||||
#endif
|
||||
# include <stdlib.h>
|
||||
# include <string.h>
|
||||
# include <assert.h>
|
||||
|
||||
StringHeap::StringHeap()
|
||||
{
|
||||
cell_base_ = 0;
|
||||
cell_ptr_ = HEAPCELL;
|
||||
}
|
||||
|
||||
StringHeap::~StringHeap()
|
||||
{
|
||||
// This is a planned memory leak. The string heap is indended
|
||||
// to hold permanently-allocated strings.
|
||||
}
|
||||
|
||||
const char* StringHeap::add(const char*text)
|
||||
{
|
||||
unsigned len = strlen(text);
|
||||
assert((len+1) <= HEAPCELL);
|
||||
|
||||
unsigned rem = HEAPCELL - cell_ptr_;
|
||||
if (rem < (len+1)) {
|
||||
cell_base_ = (char*)malloc(HEAPCELL);
|
||||
cell_ptr_ = 0;
|
||||
}
|
||||
|
||||
char*res = cell_base_ + cell_ptr_;
|
||||
memcpy(res, text, len);
|
||||
cell_ptr_ += len;
|
||||
cell_base_[cell_ptr_++] = 0;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: StringHeap.cc,v $
|
||||
* Revision 1.2 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.1 2002/08/04 19:13:16 steve
|
||||
* dll uses StringHeap for named items.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
#ifndef __StringHeap_H
|
||||
#define __StringHeap_H
|
||||
/*
|
||||
* Copyright (c) 2002 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: StringHeap.h,v 1.2 2002/08/12 01:34:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
class StringHeap {
|
||||
|
||||
public:
|
||||
StringHeap();
|
||||
~StringHeap();
|
||||
|
||||
const char*add(const char*);
|
||||
|
||||
private:
|
||||
enum { HEAPCELL = 0x10000 };
|
||||
|
||||
char*cell_base_;
|
||||
unsigned cell_ptr_;
|
||||
|
||||
private: // not implemented
|
||||
StringHeap(const StringHeap&);
|
||||
StringHeap& operator= (const StringHeap&);
|
||||
};
|
||||
|
||||
/*
|
||||
* $Log: StringHeap.h,v $
|
||||
* Revision 1.2 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.1 2002/08/04 19:13:16 steve
|
||||
* dll uses StringHeap for named items.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
+159
@@ -0,0 +1,159 @@
|
||||
#ifndef __acc_user_H
|
||||
#define __acc_user_H
|
||||
/*
|
||||
* Copyright (c) 2002 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: acc_user.h,v 1.6 2002/08/12 01:34:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This header file contains the definitions and declarations needed
|
||||
* by an Icarus Verilog user using acc_ routines.
|
||||
*
|
||||
* NOTE: Icarus Verilog does not support acc_ routines. This is just a
|
||||
* stub. The functions that are implemented here are actually
|
||||
* implemented using VPI routines.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
# define EXTERN_C_START extern "C" {
|
||||
# define EXTERN_C_END }
|
||||
#else
|
||||
# define EXTERN_C_START
|
||||
# define EXTERN_C_END
|
||||
# define bool int
|
||||
#endif
|
||||
|
||||
EXTERN_C_START
|
||||
|
||||
/*
|
||||
* This is a declaration of the "handle" type that is compatible with
|
||||
* the vpiHandle from vpi_user.h.
|
||||
*/
|
||||
typedef struct __vpiHandle *handle;
|
||||
|
||||
/* OBJECT TYPES */
|
||||
#define accScope 21
|
||||
#define accScalar 300
|
||||
#define accVector 302
|
||||
|
||||
/* type VALUES FOR t_setval_delay STRUCTURE */
|
||||
#define accNoDelay 0
|
||||
#define accInertialDelay 1
|
||||
#define accTransportDelay 2
|
||||
#define accPureTransportDelay 3
|
||||
#define accForceFlag 4
|
||||
#define accReleaseFlag 5
|
||||
|
||||
/* type VALUES FOR t_setval_value STRUCTURE */
|
||||
#define accBinStrVal 1
|
||||
#define accOctStrVal 2
|
||||
#define accDecStrVal 3
|
||||
#define accHexStrVal 4
|
||||
#define accScalarVal 5
|
||||
#define accIntVal 6
|
||||
#define accRealVal 7
|
||||
#define accStringVal 8
|
||||
#define accVectorVal 9
|
||||
|
||||
/* type VALUES FOR t_acc_time STRUCTURE */
|
||||
#define accTime 1
|
||||
#define accSimTime 2
|
||||
#define accRealTime 3
|
||||
|
||||
|
||||
typedef struct t_acc_time {
|
||||
int type;
|
||||
int low, high;
|
||||
double real;
|
||||
} s_acc_time, *p_acc_time;
|
||||
|
||||
typedef struct t_setval_delay {
|
||||
s_acc_time time;
|
||||
int model;
|
||||
} s_setval_delay, *p_setval_delay;
|
||||
|
||||
typedef struct t_acc_vecval {
|
||||
int aval;
|
||||
int bval;
|
||||
} s_acc_vecval, *p_acc_vecval;
|
||||
|
||||
typedef struct t_setval_value {
|
||||
int format;
|
||||
union {
|
||||
char*str;
|
||||
int scalar;
|
||||
int integer;
|
||||
double real;
|
||||
p_acc_vecval vector;
|
||||
} value;
|
||||
} s_setval_value, *p_setval_value, s_acc_value, *p_acc_value;
|
||||
|
||||
extern int acc_error_flag;
|
||||
|
||||
extern int acc_initialize(void);
|
||||
|
||||
extern void acc_close(void);
|
||||
|
||||
extern int acc_fetch_argc(void);
|
||||
extern char**acc_fetch_argv(void);
|
||||
|
||||
extern char* acc_fetch_fullname(handle obj);
|
||||
|
||||
extern int acc_fetch_tfarg_int(int n);
|
||||
extern char* acc_fetch_tfarg_str(int n);
|
||||
|
||||
extern handle acc_handle_tfarg(int n);
|
||||
|
||||
extern handle acc_next_topmod(handle prev_topmod);
|
||||
|
||||
extern int acc_object_of_type(handle object, int type);
|
||||
|
||||
extern char*acc_product_version(void);
|
||||
|
||||
extern int acc_set_value(handle obj, p_setval_value value,
|
||||
p_setval_delay delay);
|
||||
|
||||
extern char* acc_version(void);
|
||||
|
||||
EXTERN_C_END
|
||||
|
||||
/*
|
||||
* $Log: acc_user.h,v $
|
||||
* Revision 1.6 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.5 2002/06/11 15:19:12 steve
|
||||
* Add acc_fetch_argc/argv/version (mruff)
|
||||
*
|
||||
* Revision 1.4 2002/06/07 02:58:58 steve
|
||||
* Add a bunch of acc/tf functions. (mruff)
|
||||
*
|
||||
* Revision 1.3 2002/06/02 19:03:29 steve
|
||||
* Add acc_handle_tfarg and acc_next_topmode
|
||||
*
|
||||
* Revision 1.2 2002/05/30 02:06:05 steve
|
||||
* Implement acc_product_version.
|
||||
*
|
||||
* Revision 1.1 2002/05/23 03:46:42 steve
|
||||
* Add the acc_user.h header file.
|
||||
*
|
||||
*/
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (c) 2002 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: async.cc,v 1.4 2002/08/18 22:07:16 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include "functor.h"
|
||||
# include "netlist.h"
|
||||
# include <assert.h>
|
||||
|
||||
bool NetAssign::is_asynchronous()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetCondit::is_asynchronous()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NetEvWait::is_asynchronous()
|
||||
{
|
||||
/* The "sense" set contains the set of Nexa that are in the
|
||||
sensitivity list. We also presume here that the list is
|
||||
only LEVEL sensitive. */
|
||||
NexusSet*sense = new NexusSet;
|
||||
for (unsigned idx = 0 ; idx < nevents_ ; idx += 1) {
|
||||
NexusSet*tmp = event(idx)->nex_async_();
|
||||
if (tmp == 0) {
|
||||
delete sense;
|
||||
return false;
|
||||
}
|
||||
|
||||
sense->add(*tmp);
|
||||
delete tmp;
|
||||
}
|
||||
|
||||
NexusSet*inputs = statement_->nex_input();
|
||||
|
||||
if (! sense->contains(*inputs)) {
|
||||
delete sense;
|
||||
delete inputs;
|
||||
return false;
|
||||
}
|
||||
|
||||
delete sense;
|
||||
delete inputs;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetProc::is_asynchronous()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NetProcTop::is_asynchronous()
|
||||
{
|
||||
if (type_ == NetProcTop::KINITIAL)
|
||||
return false;
|
||||
|
||||
return statement_->is_asynchronous();
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: async.cc,v $
|
||||
* Revision 1.4 2002/08/18 22:07:16 steve
|
||||
* Detect temporaries in sequential block synthesis.
|
||||
*
|
||||
* Revision 1.3 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.2 2002/07/04 00:24:16 steve
|
||||
* initial statements are not asynchronous.
|
||||
*
|
||||
* Revision 1.1 2002/06/30 02:21:31 steve
|
||||
* Add structure for asynchronous logic synthesis.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
|
||||
ATTRIBUTES TO CONTROL SYNTHESIS
|
||||
|
||||
The following is a summary of Verilog attributes that Icarus Verilog
|
||||
understands within Verilog source files to control synthesis
|
||||
behavior. This section documents generic synthesis attributes. For
|
||||
target specific attributes, see target specific documentation.
|
||||
|
||||
These attributes only effect the behavior of the synthesizer. For
|
||||
example, the ivl_combinational will not generate an error message
|
||||
if the Verilog is being compiled for simulation. (It may generate a
|
||||
warning.)
|
||||
|
||||
|
||||
* Attributes for "always" and "initial" statements
|
||||
|
||||
(* ivl_combinational *)
|
||||
|
||||
This attribute tells the compiler that the statement models
|
||||
combinational logic. If the compiler finds that it cannot make
|
||||
combinational logic out of a marked always statement, it will
|
||||
report an error.
|
||||
|
||||
This attribute can be used to prevent accidentally inferring
|
||||
latches or flip-flops where the user intended combinational
|
||||
logic.
|
||||
|
||||
(* ivl_synthesis_on *)
|
||||
|
||||
This attribute tells the compiler that the marked always statement
|
||||
is synthesizeable. The compiler will attempt to synthesize the
|
||||
code in the marked "always" statement. If it cannot in any way
|
||||
synthesize it, then it will report an error.
|
||||
|
||||
(* ivl_synthesis_off *)
|
||||
|
||||
If this value is attached to an "always" statement, then the
|
||||
compiler will *not* synthesize the "always" statment. This can be
|
||||
used, for example, to mark embedded test bench code.
|
||||
|
||||
|
||||
* Attributes for signals (wire/reg/integer/tri/etc.)
|
||||
|
||||
[ none defined yet ]
|
||||
|
||||
|
||||
* Other Attributes
|
||||
|
||||
[ none defined yet ]
|
||||
+5
-2
@@ -9,8 +9,11 @@
|
||||
echo "Autoconf in root..."
|
||||
autoconf
|
||||
|
||||
for dir in vpip vvp tgt-vvp tgt-fpga
|
||||
for dir in vpip vvp tgt-vvp tgt-fpga libveriuser
|
||||
do
|
||||
echo "Autoconf in $dir..."
|
||||
( cd $dir ; autoconf )
|
||||
( cd ./$dir ; autoconf )
|
||||
done
|
||||
|
||||
echo "Precompiling lexor_keyword.gperf"
|
||||
gperf -o -i 7 -C -k 1-3,\$ -L ANSI-C -H keyword_hash -N check_identifier -t ./lexor_keyword.gperf > lexor_keyword.cc
|
||||
|
||||
@@ -4,3 +4,6 @@
|
||||
|
||||
[-tvvm-check]
|
||||
<ivl>./ivl %W %[s-s%s] %[N-N%N] %[T-T%T] -tvvm -Fcprop -Fnodangle -fVPI_MODULE_PATH=vpi %f %m -o%o.cc -- -
|
||||
|
||||
[-tvvp-check]
|
||||
<ivl>./ivl %W %[s-s%s] %[N-N%N] %[T-T%T] -tdll -fDLL=./tgt-vvp/vvp.tgt -Fcprop -Fnodangle -fVPI_MODULE_PATH=vpi %f %m -o%o -- -
|
||||
|
||||
+43
-24
@@ -18,8 +18,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: compiler.h,v 1.7 2001/11/16 05:07:19 steve Exp $"
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: compiler.h,v 1.13 2002/08/12 01:34:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <list>
|
||||
@@ -67,37 +67,56 @@
|
||||
|
||||
/* Implicit definitions of wires. */
|
||||
extern bool warn_implicit;
|
||||
extern bool error_implicit;
|
||||
|
||||
/* inherit timescales accross files. */
|
||||
extern bool warn_timescale;
|
||||
|
||||
/* This is true if verbose output is requested. */
|
||||
extern bool verbose_flag;
|
||||
|
||||
/* This is an ordered list of libraries to search. */
|
||||
extern list<const char*>library_dirs;
|
||||
/* This is an ordered list of library suffixxes to search. */
|
||||
extern list<const char*>library_suff;
|
||||
extern int build_library_index(const char*path, bool key_case_sensitive);
|
||||
|
||||
/* This is the generation of Verilog that the compiler is asked to
|
||||
support. */
|
||||
enum generation_t {
|
||||
GN_VER1995 = 1,
|
||||
GN_VER2001 = 2,
|
||||
GN_SYSVER30 = 3,
|
||||
GN_DEFAULT = 3
|
||||
};
|
||||
|
||||
extern generation_t generation_flag;
|
||||
|
||||
/* This is the string to use to invoke the preprocessor. */
|
||||
extern char*ivlpp_string;
|
||||
|
||||
/*
|
||||
* $Log: compiler.h,v $
|
||||
* Revision 1.13 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.12 2002/05/28 20:40:37 steve
|
||||
* ivl indexes the search path for libraries, and
|
||||
* supports case insensitive module-to-file lookup.
|
||||
*
|
||||
* Revision 1.11 2002/05/28 00:50:39 steve
|
||||
* Add the ivl -C flag for bulk configuration
|
||||
* from the driver, and use that to run library
|
||||
* modules through the preprocessor.
|
||||
*
|
||||
* Revision 1.10 2002/05/24 01:13:00 steve
|
||||
* Support language generation flag -g.
|
||||
*
|
||||
* Revision 1.9 2002/04/22 00:53:39 steve
|
||||
* Do not allow implicit wires in sensitivity lists.
|
||||
*
|
||||
* Revision 1.8 2002/04/15 00:04:22 steve
|
||||
* Timescale warnings.
|
||||
*
|
||||
* Revision 1.7 2001/11/16 05:07:19 steve
|
||||
* Add support for +libext+ in command files.
|
||||
*
|
||||
* Revision 1.6 2001/10/20 23:02:40 steve
|
||||
* Add automatic module libraries.
|
||||
*
|
||||
* Revision 1.5 2000/10/31 17:49:02 steve
|
||||
* Support time variables.
|
||||
*
|
||||
* Revision 1.4 2000/08/20 04:13:56 steve
|
||||
* Add ivl_target support for logic gates, and
|
||||
* make the interface more accessible.
|
||||
*
|
||||
* Revision 1.3 2000/03/17 21:50:25 steve
|
||||
* Switch to control warnings.
|
||||
*
|
||||
* Revision 1.2 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.1 1999/06/06 20:42:48 steve
|
||||
* Make compiler width a compile time constant.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
|
||||
+7
-1
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: config.h.in,v 1.3 2001/10/18 16:16:23 steve Exp $"
|
||||
#ident "$Id: config.h.in,v 1.5 2002/08/11 23:39:33 steve Exp $"
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
@@ -46,6 +46,12 @@
|
||||
|
||||
/*
|
||||
* $Log: config.h.in,v $
|
||||
* Revision 1.5 2002/08/11 23:39:33 steve
|
||||
* Remove VVM option.
|
||||
*
|
||||
* Revision 1.4 2002/02/16 03:18:53 steve
|
||||
* Make vvm optional, normally off.
|
||||
*
|
||||
* Revision 1.3 2001/10/18 16:16:23 steve
|
||||
* Include HAVE_SYS_WAIT in config.h (PR#306)
|
||||
*
|
||||
|
||||
+98
-64
@@ -14,6 +14,22 @@ then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
AC_CHECK_PROGS(LEX,flex,none)
|
||||
if test "$LEX" = "none"
|
||||
then
|
||||
echo "*** Error: No suitable flex found. ***"
|
||||
echo " Please install the 'flex' package."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
AC_CHECK_PROGS(YACC,bison,none)
|
||||
if test "$YACC" = "none"
|
||||
then
|
||||
echo "*** Error: No suitable bison found. ***"
|
||||
echo " Please install the 'bison' package."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
AC_LANG_CPLUSPLUS
|
||||
|
||||
AC_CHECK_HEADERS(getopt.h malloc.h iosfwd sys/wait.h)
|
||||
@@ -30,7 +46,8 @@ do_times=no
|
||||
AC_MSG_RESULT($do_times)
|
||||
|
||||
AC_CHECK_HEADER(ipal.h, HAVE_IPAL=yes, HAVE_IPAL=)
|
||||
AC_ARG_WITH(ipal,enable PAL target,
|
||||
AC_ARG_WITH(ipal,
|
||||
[ --with-ipal enable PAL target],
|
||||
if test "$with_ipal" = no; then
|
||||
echo Disabling ipal support
|
||||
HAVE_IPAL=
|
||||
@@ -58,66 +75,6 @@ AC_LANG_C
|
||||
AC_CANONICAL_HOST
|
||||
# $host
|
||||
|
||||
|
||||
#######################
|
||||
## test for underscores. The vpi module loader in vvm needs to know this
|
||||
## in order to know the name of the start symbol for the .vpi module.
|
||||
#######################
|
||||
|
||||
AC_CYGWIN
|
||||
AC_EXEEXT
|
||||
AC_MINGW32
|
||||
|
||||
|
||||
WIN32=no
|
||||
AC_MSG_CHECKING("Checking for windows")
|
||||
if test "$CYGWIN" = "yes" -o "$MINGW32" = "yes"
|
||||
then
|
||||
WIN32=yes
|
||||
fi
|
||||
AC_SUBST(WIN32)
|
||||
AC_MSG_RESULT($WIN32)
|
||||
AC_SUBST(EXEEXT)
|
||||
|
||||
|
||||
AC_MSG_CHECKING("for leading and/or trailing underscores")
|
||||
cat << EOF > underscore.c
|
||||
void underscore(void){}
|
||||
EOF
|
||||
$CC -shared -c underscore.c > /dev/null 2>&1
|
||||
|
||||
CC_LEADING_UNDERSCORE=no
|
||||
CC_TRAILING_UNDERSCORE=no
|
||||
|
||||
output=`nm underscore.o|grep _underscore 2>&1`
|
||||
if test ! -z "$output" -a -z "$CYGWIN" -a -z "$MINGW32"; then
|
||||
CC_LEADING_UNDERSCORE=yes
|
||||
AC_DEFINE(NEED_LU)
|
||||
fi
|
||||
|
||||
|
||||
|
||||
output=`nm underscore.o|grep underscore_ 2>&1`
|
||||
if test ! -z "$output"; then
|
||||
CC_TRAILING_UNDERSCORE=yes
|
||||
AC_DEFINE(NEED_TU)
|
||||
fi
|
||||
|
||||
if test "$CC_LEADING_UNDERSCORE" = yes; then
|
||||
AC_DEFINE(WLU)
|
||||
fi
|
||||
if test "$CC_TRAILING_UNDERSCORE" = yes; then
|
||||
AC_DEFINE(WTU)
|
||||
fi
|
||||
|
||||
rm underscore.c underscore.o
|
||||
|
||||
AC_MSG_RESULT("$CC_LEADING_UNDERSCORE $CC_TRAILING_UNDERSCORE")
|
||||
|
||||
#######################
|
||||
## end of test for underscores
|
||||
#######################
|
||||
|
||||
# The -fPIC flag is used to tell the compiler to make position
|
||||
# independent code. It is needed when making shared objects.
|
||||
|
||||
@@ -215,10 +172,87 @@ case "${host}" in
|
||||
esac
|
||||
|
||||
AC_SUBST(shared)
|
||||
|
||||
AC_MSG_RESULT($shared)
|
||||
|
||||
#######################
|
||||
## test for underscores. The vpi module loader needs to know this
|
||||
## in order to know the name of the start symbol for the .vpi module.
|
||||
#######################
|
||||
|
||||
AC_CONFIG_SUBDIRS(vpip vvp tgt-vvp tgt-fpga)
|
||||
AC_CYGWIN
|
||||
AC_EXEEXT
|
||||
AC_MINGW32
|
||||
|
||||
AC_OUTPUT(Makefile vpi/Makefile ivlpp/Makefile vvm/Makefile driver/Makefile tgt-null/Makefile tgt-stub/Makefile tgt-verilog/Makefile tgt-pal/Makefile)
|
||||
|
||||
WIN32=no
|
||||
AC_MSG_CHECKING("Checking for windows")
|
||||
if test "$CYGWIN" = "yes" -o "$MINGW32" = "yes"
|
||||
then
|
||||
WIN32=yes
|
||||
fi
|
||||
AC_SUBST(WIN32)
|
||||
AC_MSG_RESULT($WIN32)
|
||||
AC_SUBST(EXEEXT)
|
||||
|
||||
|
||||
AC_MSG_CHECKING("for leading and/or trailing underscores")
|
||||
cat << EOF > underscore.c
|
||||
void underscore(void){}
|
||||
EOF
|
||||
|
||||
$CC $shared -c underscore.c > /dev/null 2>&1
|
||||
|
||||
CC_LEADING_UNDERSCORE=no
|
||||
CC_TRAILING_UNDERSCORE=no
|
||||
|
||||
output=`nm underscore.o|grep _underscore 2>&1`
|
||||
if test ! -z "$output" -o $WIN32 = "yes"; then
|
||||
CC_LEADING_UNDERSCORE=yes
|
||||
AC_DEFINE(NEED_LU)
|
||||
fi
|
||||
|
||||
output=`nm underscore.o|grep underscore_ 2>&1`
|
||||
if test ! -z "$output"; then
|
||||
CC_TRAILING_UNDERSCORE=yes
|
||||
AC_DEFINE(NEED_TU)
|
||||
fi
|
||||
|
||||
if test "$CC_LEADING_UNDERSCORE" = yes; then
|
||||
AC_DEFINE(WLU)
|
||||
fi
|
||||
if test "$CC_TRAILING_UNDERSCORE" = yes; then
|
||||
AC_DEFINE(WTU)
|
||||
fi
|
||||
|
||||
rm underscore.c underscore.o
|
||||
|
||||
AC_MSG_RESULT("$CC_LEADING_UNDERSCORE $CC_TRAILING_UNDERSCORE")
|
||||
|
||||
#######################
|
||||
## end of test for underscores
|
||||
#######################
|
||||
|
||||
AC_MSG_CHECKING("for ident support in C compiler")
|
||||
ident_support='-DHAVE_CVS_IDENT=1'
|
||||
case "${host}" in
|
||||
|
||||
*-*-cygwin*)
|
||||
ident_support=
|
||||
;;
|
||||
|
||||
*-*-darwin*)
|
||||
ident_support=
|
||||
;;
|
||||
|
||||
*-*-machten*)
|
||||
ident_support=
|
||||
;;
|
||||
esac
|
||||
|
||||
AC_SUBST(ident_support)
|
||||
AC_MSG_RESULT($ident_support)
|
||||
|
||||
|
||||
AC_CONFIG_SUBDIRS(vvp tgt-vvp tgt-fpga libveriuser)
|
||||
|
||||
AC_OUTPUT(Makefile vpi/Makefile ivlpp/Makefile driver/Makefile tgt-null/Makefile tgt-stub/Makefile tgt-verilog/Makefile tgt-pal/Makefile)
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: cprop.cc,v 1.30 2001/10/28 01:14:53 steve Exp $"
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: cprop.cc,v 1.39 2002/08/20 04:12:22 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -56,7 +56,7 @@ void cprop_functor::signal(Design*des, NetNet*obj)
|
||||
void cprop_functor::lpm_add_sub(Design*des, NetAddSub*obj)
|
||||
{
|
||||
// For now, only additions are handled.
|
||||
if (obj->attribute("LPM_Direction") != "ADD")
|
||||
if (obj->attribute("LPM_Direction") != verinum("ADD"))
|
||||
return;
|
||||
|
||||
// If the low bit on the A side is 0, then eliminate it from
|
||||
@@ -64,8 +64,8 @@ void cprop_functor::lpm_add_sub(Design*des, NetAddSub*obj)
|
||||
// result. Don't reduce the adder smaller then a 1-bit
|
||||
// adder. These will be eliminated later.
|
||||
while ((obj->width() > 1)
|
||||
&& link_drivers_constant(obj->pin_DataA(0))
|
||||
&& (driven_value(obj->pin_DataA(0)) == verinum::V0)) {
|
||||
&& obj->pin_DataA(0).nexus()->drivers_constant()
|
||||
&& (obj->pin_DataA(0).nexus()->driven_value() == verinum::V0)) {
|
||||
|
||||
NetAddSub*tmp = 0;
|
||||
tmp = new NetAddSub(obj->scope(), obj->name(), obj->width()-1);
|
||||
@@ -89,8 +89,8 @@ void cprop_functor::lpm_add_sub(Design*des, NetAddSub*obj)
|
||||
|
||||
// Now do the same thing on the B side.
|
||||
while ((obj->width() > 1)
|
||||
&& link_drivers_constant(obj->pin_DataB(0))
|
||||
&& (driven_value(obj->pin_DataB(0)) == verinum::V0)) {
|
||||
&& obj->pin_DataB(0).nexus()->drivers_constant()
|
||||
&& (obj->pin_DataB(0).nexus()->driven_value() == verinum::V0)) {
|
||||
|
||||
NetAddSub*tmp = 0;
|
||||
tmp = new NetAddSub(obj->scope(), obj->name(), obj->width()-1);
|
||||
@@ -160,12 +160,12 @@ void cprop_functor::lpm_compare_eq_(Design*des, NetCompare*obj)
|
||||
be completely eliminated and replaced with a constant 0. */
|
||||
|
||||
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) {
|
||||
if (! link_drivers_constant(obj->pin_DataA(idx)))
|
||||
if (! obj->pin_DataA(idx).nexus()->drivers_constant())
|
||||
continue;
|
||||
if (! link_drivers_constant(obj->pin_DataB(idx)))
|
||||
if (! obj->pin_DataB(idx).nexus()->drivers_constant())
|
||||
continue;
|
||||
if (driven_value(obj->pin_DataA(idx)) ==
|
||||
driven_value(obj->pin_DataB(idx)))
|
||||
if (obj->pin_DataA(idx).nexus()->driven_value() ==
|
||||
obj->pin_DataB(idx).nexus()->driven_value())
|
||||
continue;
|
||||
|
||||
NetConst*zero = new NetConst(scope, obj->name(), verinum::V0);
|
||||
@@ -181,11 +181,11 @@ void cprop_functor::lpm_compare_eq_(Design*des, NetCompare*obj)
|
||||
|
||||
unsigned top = obj->width();
|
||||
for (unsigned idx = 0 ; idx < top ; ) {
|
||||
if (! link_drivers_constant(obj->pin_DataA(idx))) {
|
||||
if (! obj->pin_DataA(idx).nexus()->drivers_constant()) {
|
||||
idx += 1;
|
||||
continue;
|
||||
}
|
||||
if (! link_drivers_constant(obj->pin_DataB(idx))) {
|
||||
if (! obj->pin_DataB(idx).nexus()->drivers_constant()) {
|
||||
idx += 1;
|
||||
continue;
|
||||
}
|
||||
@@ -217,7 +217,7 @@ void cprop_functor::lpm_compare_eq_(Design*des, NetCompare*obj)
|
||||
with a simple XOR gate. */
|
||||
if (top == 1) {
|
||||
NetLogic*tmp = new NetLogic(scope, obj->name(), 3,
|
||||
NetLogic::XOR);
|
||||
NetLogic::XNOR);
|
||||
connect(tmp->pin(0), obj->pin_AEB());
|
||||
connect(tmp->pin(1), obj->pin_DataA(0));
|
||||
connect(tmp->pin(2), obj->pin_DataB(0));
|
||||
@@ -310,12 +310,12 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
|
||||
on the output of an AND gate. */
|
||||
|
||||
while (idx < top) {
|
||||
if (! link_drivers_constant(obj->pin(idx))) {
|
||||
if (! obj->pin(idx).nexus()->drivers_constant()) {
|
||||
idx += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (driven_value(obj->pin(idx)) == verinum::V1) {
|
||||
if (obj->pin(idx).nexus()->driven_value()==verinum::V1) {
|
||||
obj->pin(idx).unlink();
|
||||
top -= 1;
|
||||
if (idx < top) {
|
||||
@@ -326,7 +326,7 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (driven_value(obj->pin(idx)) != verinum::V0) {
|
||||
if (obj->pin(idx).nexus()->driven_value() != verinum::V0) {
|
||||
idx += 1;
|
||||
xs += 1;
|
||||
continue;
|
||||
@@ -348,6 +348,10 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
|
||||
assert(0);
|
||||
}
|
||||
|
||||
tmp->rise_time(obj->rise_time());
|
||||
tmp->fall_time(obj->fall_time());
|
||||
tmp->decay_time(obj->decay_time());
|
||||
|
||||
des->add_node(tmp);
|
||||
tmp->pin(0).drive0(obj->pin(0).drive0());
|
||||
tmp->pin(0).drive1(obj->pin(0).drive1());
|
||||
@@ -373,6 +377,10 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
|
||||
assert(0);
|
||||
}
|
||||
|
||||
tmp->rise_time(obj->rise_time());
|
||||
tmp->fall_time(obj->fall_time());
|
||||
tmp->decay_time(obj->decay_time());
|
||||
|
||||
des->add_node(tmp);
|
||||
tmp->pin(0).drive0(obj->pin(0).drive0());
|
||||
tmp->pin(0).drive1(obj->pin(0).drive1());
|
||||
@@ -416,6 +424,11 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
tmp->rise_time(obj->rise_time());
|
||||
tmp->fall_time(obj->fall_time());
|
||||
tmp->decay_time(obj->decay_time());
|
||||
|
||||
des->add_node(tmp);
|
||||
tmp->pin(0).drive0(obj->pin(0).drive0());
|
||||
tmp->pin(0).drive1(obj->pin(0).drive1());
|
||||
@@ -427,12 +440,16 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
|
||||
}
|
||||
|
||||
/* Finally, this cleans up the gate by creating a
|
||||
new [N]OR gate that has the right number of
|
||||
new [N]AND gate that has the right number of
|
||||
inputs, connected in the right place. */
|
||||
if (top < obj->pin_count()) {
|
||||
NetLogic*tmp = new NetLogic(scope,
|
||||
obj->name(), top,
|
||||
obj->type());
|
||||
tmp->rise_time(obj->rise_time());
|
||||
tmp->fall_time(obj->fall_time());
|
||||
tmp->decay_time(obj->decay_time());
|
||||
|
||||
des->add_node(tmp);
|
||||
tmp->pin(0).drive0(obj->pin(0).drive0());
|
||||
tmp->pin(0).drive1(obj->pin(0).drive1());
|
||||
@@ -457,12 +474,12 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
|
||||
on the output of an OR gate. */
|
||||
|
||||
while (idx < top) {
|
||||
if (! link_drivers_constant(obj->pin(idx))) {
|
||||
if (! obj->pin(idx).nexus()->drivers_constant()) {
|
||||
idx += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (driven_value(obj->pin(idx)) == verinum::V0) {
|
||||
if (obj->pin(idx).nexus()->driven_value() == verinum::V0) {
|
||||
obj->pin(idx).unlink();
|
||||
top -= 1;
|
||||
if (idx < top) {
|
||||
@@ -473,7 +490,7 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (driven_value(obj->pin(idx)) != verinum::V1) {
|
||||
if (obj->pin(idx).nexus()->driven_value() != verinum::V1) {
|
||||
idx += 1;
|
||||
continue;
|
||||
}
|
||||
@@ -494,6 +511,10 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
|
||||
assert(0);
|
||||
}
|
||||
|
||||
tmp->rise_time(obj->rise_time());
|
||||
tmp->fall_time(obj->fall_time());
|
||||
tmp->decay_time(obj->decay_time());
|
||||
|
||||
des->add_node(tmp);
|
||||
tmp->pin(0).drive0(obj->pin(0).drive0());
|
||||
tmp->pin(0).drive1(obj->pin(0).drive1());
|
||||
@@ -519,6 +540,10 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
|
||||
assert(0);
|
||||
}
|
||||
|
||||
tmp->rise_time(obj->rise_time());
|
||||
tmp->fall_time(obj->fall_time());
|
||||
tmp->decay_time(obj->decay_time());
|
||||
|
||||
des->add_node(tmp);
|
||||
tmp->pin(0).drive0(obj->pin(0).drive0());
|
||||
tmp->pin(0).drive1(obj->pin(0).drive1());
|
||||
@@ -547,6 +572,10 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
tmp->rise_time(obj->rise_time());
|
||||
tmp->fall_time(obj->fall_time());
|
||||
tmp->decay_time(obj->decay_time());
|
||||
|
||||
des->add_node(tmp);
|
||||
tmp->pin(0).drive0(obj->pin(0).drive0());
|
||||
tmp->pin(0).drive1(obj->pin(0).drive1());
|
||||
@@ -564,6 +593,10 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
|
||||
NetLogic*tmp = new NetLogic(scope,
|
||||
obj->name(), top,
|
||||
obj->type());
|
||||
tmp->rise_time(obj->rise_time());
|
||||
tmp->fall_time(obj->fall_time());
|
||||
tmp->decay_time(obj->decay_time());
|
||||
|
||||
des->add_node(tmp);
|
||||
tmp->pin(0).drive0(obj->pin(0).drive0());
|
||||
tmp->pin(0).drive1(obj->pin(0).drive1());
|
||||
@@ -583,14 +616,17 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
|
||||
unsigned idx = 1;
|
||||
|
||||
/* Eliminate all the 0 inputs. They have no effect
|
||||
on the output of an XOR gate. */
|
||||
on the output of an XOR gate. The eliminate works
|
||||
by unlinking the current input and relinking the
|
||||
last input to this position. It's like bubbling
|
||||
all the 0 inputs to the end. */
|
||||
while (idx < top) {
|
||||
if (! link_drivers_constant(obj->pin(idx))) {
|
||||
if (! obj->pin(idx).nexus()->drivers_constant()) {
|
||||
idx += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (driven_value(obj->pin(idx)) == verinum::V0) {
|
||||
if (obj->pin(idx).nexus()->driven_value() == verinum::V0) {
|
||||
obj->pin(idx).unlink();
|
||||
top -= 1;
|
||||
if (idx < top) {
|
||||
@@ -615,12 +651,12 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
|
||||
unsigned one = 0, ones = 0;
|
||||
idx = 1;
|
||||
while (idx < top) {
|
||||
if (! link_drivers_constant(obj->pin(idx))) {
|
||||
if (! obj->pin(idx).nexus()->drivers_constant()) {
|
||||
idx += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (driven_value(obj->pin(idx)) == verinum::V1) {
|
||||
if (obj->pin(idx).nexus()->driven_value() == verinum::V1) {
|
||||
if (one == 0) {
|
||||
one = idx;
|
||||
ones += 1;
|
||||
@@ -628,6 +664,8 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Here we found two constant V1
|
||||
inputs. Unlink both. */
|
||||
obj->pin(idx).unlink();
|
||||
top -= 1;
|
||||
if (idx < top) {
|
||||
@@ -642,8 +680,11 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
|
||||
obj->pin(top).unlink();
|
||||
}
|
||||
|
||||
/* Reset ones counter and one index,
|
||||
start looking for the next pair. */
|
||||
assert(ones == 1);
|
||||
ones = 0;
|
||||
one = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -651,13 +692,17 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
|
||||
}
|
||||
|
||||
/* If all the inputs were eliminated, then replace
|
||||
the gate with a constant 0 and I am done. */
|
||||
the gate with a constant value and I am done. */
|
||||
if (top == 1) {
|
||||
verinum::V out = obj->type()==NetLogic::XNOR
|
||||
? verinum::V1
|
||||
: verinum::V0;
|
||||
NetConst*tmp = new NetConst(scope, obj->name(), out);
|
||||
|
||||
tmp->rise_time(obj->rise_time());
|
||||
tmp->fall_time(obj->fall_time());
|
||||
tmp->decay_time(obj->decay_time());
|
||||
|
||||
des->add_node(tmp);
|
||||
tmp->pin(0).drive0(obj->pin(0).drive0());
|
||||
tmp->pin(0).drive1(obj->pin(0).drive1());
|
||||
@@ -674,9 +719,9 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
|
||||
|
||||
if ((top == 3) && (ones == 1)) {
|
||||
unsigned save;
|
||||
if (! link_drivers_constant(obj->pin(1)))
|
||||
if (! obj->pin(1).nexus()->drivers_constant())
|
||||
save = 1;
|
||||
else if (driven_value(obj->pin(1)) != verinum::V1)
|
||||
else if (obj->pin(1).nexus()->driven_value() != verinum::V1)
|
||||
save = 1;
|
||||
else
|
||||
save = 2;
|
||||
@@ -692,6 +737,10 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
|
||||
obj->name(), 2,
|
||||
NetLogic::BUF);
|
||||
|
||||
tmp->rise_time(obj->rise_time());
|
||||
tmp->fall_time(obj->fall_time());
|
||||
tmp->decay_time(obj->decay_time());
|
||||
|
||||
des->add_node(tmp);
|
||||
tmp->pin(0).drive0(obj->pin(0).drive0());
|
||||
tmp->pin(0).drive1(obj->pin(0).drive1());
|
||||
@@ -717,6 +766,10 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
|
||||
obj->name(), 2,
|
||||
NetLogic::NOT);
|
||||
|
||||
tmp->rise_time(obj->rise_time());
|
||||
tmp->fall_time(obj->fall_time());
|
||||
tmp->decay_time(obj->decay_time());
|
||||
|
||||
des->add_node(tmp);
|
||||
tmp->pin(0).drive0(obj->pin(0).drive0());
|
||||
tmp->pin(0).drive1(obj->pin(0).drive1());
|
||||
@@ -769,12 +822,12 @@ void cprop_functor::lpm_mux(Design*des, NetMux*obj)
|
||||
connected to the select input. */
|
||||
bool flag = true;
|
||||
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) {
|
||||
if (! link_drivers_constant(obj->pin_Data(idx, 0))) {
|
||||
if (! obj->pin_Data(idx, 0).nexus()->drivers_constant()) {
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (driven_value(obj->pin_Data(idx, 0)) != verinum::Vz) {
|
||||
if (obj->pin_Data(idx, 0).nexus()->driven_value() != verinum::Vz) {
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
@@ -801,12 +854,12 @@ void cprop_functor::lpm_mux(Design*des, NetMux*obj)
|
||||
NetMux with an array of BUFIF0 devices. */
|
||||
flag = true;
|
||||
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) {
|
||||
if (! link_drivers_constant(obj->pin_Data(idx, 1))) {
|
||||
if (! obj->pin_Data(idx, 1).nexus()->drivers_constant()) {
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (driven_value(obj->pin_Data(idx, 1)) != verinum::Vz) {
|
||||
if (obj->pin_Data(idx, 1).nexus()->driven_value() != verinum::Vz) {
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
@@ -887,7 +940,7 @@ void cprop_dc_functor::lpm_const(Design*des, NetConst*obj)
|
||||
return;
|
||||
|
||||
// Look for signals that have NetESignal nodes attached to
|
||||
// them. If I find any, this this constant is used by a
|
||||
// them. If I find any, then this constant is used by a
|
||||
// behavioral expression somewhere.
|
||||
for (unsigned idx = 0 ; idx < obj->pin_count() ; idx += 1) {
|
||||
Nexus*nex = obj->pin(idx).nexus();
|
||||
@@ -907,7 +960,7 @@ void cprop_dc_functor::lpm_const(Design*des, NetConst*obj)
|
||||
// If the net has an eref, then there is an
|
||||
// expression somewhere that reads this signal. So
|
||||
// the constant does get read.
|
||||
if (tmp->get_eref() > 0)
|
||||
if (tmp->peek_eref() > 0)
|
||||
return;
|
||||
|
||||
// If the net is a port of the root module, then
|
||||
@@ -920,7 +973,6 @@ void cprop_dc_functor::lpm_const(Design*des, NetConst*obj)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Done. Delete me.
|
||||
delete obj;
|
||||
}
|
||||
@@ -942,6 +994,43 @@ void cprop(Design*des)
|
||||
|
||||
/*
|
||||
* $Log: cprop.cc,v $
|
||||
* Revision 1.39 2002/08/20 04:12:22 steve
|
||||
* Copy gate delays when doing gate delay substitutions.
|
||||
*
|
||||
* Revision 1.38 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.37 2002/06/25 01:33:22 steve
|
||||
* Cache calculated driven value.
|
||||
*
|
||||
* Revision 1.36 2002/06/24 01:49:38 steve
|
||||
* Make link_drive_constant cache its results in
|
||||
* the Nexus, to improve cprop performance.
|
||||
*
|
||||
* Revision 1.35 2002/05/26 01:39:02 steve
|
||||
* Carry Verilog 2001 attributes with processes,
|
||||
* all the way through to the ivl_target API.
|
||||
*
|
||||
* Divide signal reference counts between rval
|
||||
* and lval references.
|
||||
*
|
||||
* Revision 1.34 2002/05/23 03:08:51 steve
|
||||
* Add language support for Verilog-2001 attribute
|
||||
* syntax. Hook this support into existing $attribute
|
||||
* handling, and add number and void value types.
|
||||
*
|
||||
* Add to the ivl_target API new functions for access
|
||||
* of complex attributes attached to gates.
|
||||
*
|
||||
* Revision 1.33 2002/04/14 02:51:37 steve
|
||||
* Fix bug removing pairs of ones in XOR.
|
||||
*
|
||||
* Revision 1.32 2002/02/03 00:06:28 steve
|
||||
* Comments about xor evaluation.
|
||||
*
|
||||
* Revision 1.31 2001/12/31 01:56:08 steve
|
||||
* Get sense of 1-bit == operator right.
|
||||
*
|
||||
* Revision 1.30 2001/10/28 01:14:53 steve
|
||||
* NetObj constructor finally requires a scope.
|
||||
*
|
||||
|
||||
+133
-37
@@ -16,8 +16,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: design_dump.cc,v 1.120 2001/12/03 04:47:14 steve Exp $"
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: design_dump.cc,v 1.135 2002/10/23 01:47:17 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -93,7 +93,7 @@ void NetNet::dump_net(ostream&o, unsigned ind) const
|
||||
o << " inout";
|
||||
break;
|
||||
}
|
||||
o << " (eref=" << get_eref() << ")";
|
||||
o << " (eref=" << peek_eref() << ", lref=" << peek_lref() << ")";
|
||||
if (scope())
|
||||
o << " scope=" << scope()->name();
|
||||
o << " #(" << rise_time() << "," << fall_time() << "," <<
|
||||
@@ -117,6 +117,13 @@ void NetNet::dump_net(ostream&o, unsigned ind) const
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetSubnet::dump_net(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "** " << name() << " is a NetSubnet **"
|
||||
<< endl;
|
||||
NetNet::dump_net(o, ind);
|
||||
}
|
||||
|
||||
void NetMemory::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << name_ << "[" << width_ << "] " <<
|
||||
@@ -174,9 +181,9 @@ void NetObj::dump_node_pins(ostream&o, unsigned ind) const
|
||||
void NetObj::dump_obj_attr(ostream&o, unsigned ind) const
|
||||
{
|
||||
unsigned idx;
|
||||
for (idx = 0 ; idx < attributes_.size() ; idx += 1) {
|
||||
o << setw(ind) << "" << attributes_.key(idx) << " = \"" <<
|
||||
attributes_.value(idx) << "\"" << endl;
|
||||
for (idx = 0 ; idx < attr_cnt() ; idx += 1) {
|
||||
o << setw(ind) << "" << attr_key(idx) << " = \"" <<
|
||||
attr_value(idx) << "\"" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -264,7 +271,8 @@ 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()? scope()->name() : "") << endl;
|
||||
<< " scope=" << (scope()? scope()->name() : "")
|
||||
<< " aset_value=" << aset_value_ << endl;
|
||||
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
@@ -353,6 +361,14 @@ void NetRamDq::dump_node(ostream&o, unsigned ind) const
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetUserFunc::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << def_->name() << "(";
|
||||
o << ")" << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetTaskDef::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "task " << name_ << ";" << endl;
|
||||
@@ -405,6 +421,11 @@ void NetProcTop::dump(ostream&o, unsigned ind) const
|
||||
break;
|
||||
}
|
||||
|
||||
for (unsigned idx = 0 ; idx < attr_cnt() ; idx += 1) {
|
||||
o << setw(ind+2) << "" << "(* " << attr_key(idx) << " = "
|
||||
<< attr_value(idx) << " *)" << endl;
|
||||
}
|
||||
|
||||
statement_->dump(o, ind+2);
|
||||
}
|
||||
|
||||
@@ -418,6 +439,14 @@ void NetAssign_::dump_lval(ostream&o) const
|
||||
} else {
|
||||
o << "[" << (loff_+lwid_-1) << ":" << loff_ << "]";
|
||||
}
|
||||
} else if (mem_) {
|
||||
// Is there an obvious way to flag memories in the dump
|
||||
// as different from the _real_ bit mux case?
|
||||
// o << "**memory**";
|
||||
o << mem_->name() << "[";
|
||||
if (bmux_) o << *bmux_;
|
||||
else o << "**oops**";
|
||||
o << "]";
|
||||
} else {
|
||||
o << "";
|
||||
}
|
||||
@@ -464,30 +493,13 @@ void NetAssignNB::dump(ostream&o, unsigned ind) const
|
||||
|
||||
}
|
||||
|
||||
void NetAssignMem::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "";
|
||||
o << "/* " << get_line() << " */" << endl;
|
||||
o << setw(ind) << "";
|
||||
o << memory()->name() << "[" << *index() << "] = ";
|
||||
rval()->dump(o);
|
||||
o << ";" << endl;
|
||||
}
|
||||
|
||||
void NetAssignMemNB::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "";
|
||||
o << "/* " << get_line() << " */" << endl;
|
||||
o << setw(ind) << "";
|
||||
o << memory()->name() << "[" << *index() << "] <= ";
|
||||
rval()->dump(o);
|
||||
o << ";" << endl;
|
||||
}
|
||||
|
||||
/* Dump a block statement */
|
||||
void NetBlock::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << type_ << endl;
|
||||
o << setw(ind) << "" << type_;
|
||||
if (subscope_)
|
||||
o << " : " << subscope_->name();
|
||||
o << endl;
|
||||
|
||||
if (last_) {
|
||||
const NetProc*cur = last_;
|
||||
@@ -647,8 +659,12 @@ void NetPDelay::dump(ostream&o, unsigned ind) const
|
||||
|
||||
void NetRelease::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "release " << lval_->name() << "; "
|
||||
<< "/* " << get_line() << " */" << endl;
|
||||
if (lval_)
|
||||
o << setw(ind) << "" << "release " << lval_->name() << "; "
|
||||
<< "/* " << get_line() << " */" << endl;
|
||||
else
|
||||
o << setw(ind) << "" << "release (null); "
|
||||
<< "/* " << get_line() << " */" << endl;
|
||||
}
|
||||
|
||||
void NetRepeat::dump(ostream&o, unsigned ind) const
|
||||
@@ -684,17 +700,26 @@ void NetScope::dump(ostream&o) const
|
||||
|
||||
/* Dump the parameters for this scope. */
|
||||
{
|
||||
map<string,NetExpr*>::const_iterator pp;
|
||||
map<string,param_expr_t>::const_iterator pp;
|
||||
for (pp = parameters_.begin()
|
||||
; pp != parameters_.end() ; pp ++) {
|
||||
o << " parameter " << (*pp).first << " = " <<
|
||||
*(*pp).second << ";" << endl;
|
||||
o << " parameter ";
|
||||
|
||||
if ((*pp).second.signed_flag)
|
||||
o << "signed ";
|
||||
|
||||
if ((*pp).second.msb)
|
||||
o << "[" << *(*pp).second.msb
|
||||
<< ":" << *(*pp).second.lsb << "] ";
|
||||
|
||||
o << (*pp).first << " = " <<
|
||||
*(*pp).second.expr << ";" << endl;
|
||||
}
|
||||
|
||||
for (pp = localparams_.begin()
|
||||
; pp != localparams_.end() ; pp ++) {
|
||||
o << " localparam " << (*pp).first << " = " <<
|
||||
*(*pp).second << ";" << endl;
|
||||
*(*pp).second.expr << ";" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -842,8 +867,12 @@ void NetEBinary::dump(ostream&o) const
|
||||
|
||||
void NetEConcat::dump(ostream&o) const
|
||||
{
|
||||
if (repeat_ != 1)
|
||||
o << repeat_;
|
||||
if (repeat_calculated_) {
|
||||
if (repeat_value_ != 1)
|
||||
o << repeat_value_;
|
||||
} else if (repeat_) {
|
||||
o << "<" << *repeat_ << ">";
|
||||
}
|
||||
|
||||
if (parms_[0])
|
||||
o << "{" << *parms_[0];
|
||||
@@ -884,6 +913,8 @@ void NetESFunc::dump(ostream&o) const
|
||||
|
||||
void NetESignal::dump(ostream&o) const
|
||||
{
|
||||
if (has_sign())
|
||||
o << "+";
|
||||
o << name() << "[" << msi_<<":"<<lsi_ << "]";
|
||||
}
|
||||
|
||||
@@ -904,7 +935,10 @@ void NetEMemory::dump(ostream&o) const
|
||||
|
||||
void NetEParam::dump(ostream&o) const
|
||||
{
|
||||
o << "<" << scope_->name() << "." << name_ << ">";
|
||||
if (scope_ != 0)
|
||||
o << "<" << scope_->name() << "." << name_ << ">";
|
||||
else
|
||||
o << "<" << name_ << ">";
|
||||
}
|
||||
|
||||
void NetETernary::dump(ostream&o) const
|
||||
@@ -970,6 +1004,68 @@ void Design::dump(ostream&o) const
|
||||
|
||||
/*
|
||||
* $Log: design_dump.cc,v $
|
||||
* Revision 1.135 2002/10/23 01:47:17 steve
|
||||
* Fix synth2 handling of aset/aclr signals where
|
||||
* flip-flops are split by begin-end blocks.
|
||||
*
|
||||
* Revision 1.134 2002/10/19 22:59:49 steve
|
||||
* Redo the parameter vector support to allow
|
||||
* parameter names in range expressions.
|
||||
*
|
||||
* Revision 1.133 2002/08/19 00:06:11 steve
|
||||
* Allow release to handle removal of target net.
|
||||
*
|
||||
* Revision 1.132 2002/08/13 05:35:00 steve
|
||||
* Do not elide named blocks.
|
||||
*
|
||||
* Revision 1.131 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.130 2002/08/04 18:28:14 steve
|
||||
* Do not use hierarchical names of memories to
|
||||
* generate vvp labels. -tdll target does not
|
||||
* used hierarchical name string to look up the
|
||||
* memory objects in the design.
|
||||
*
|
||||
* Revision 1.129 2002/06/19 04:20:03 steve
|
||||
* Remove NetTmp and add NetSubnet class.
|
||||
*
|
||||
* Revision 1.128 2002/06/14 21:38:41 steve
|
||||
* Fix expression width for repeat concatenations.
|
||||
*
|
||||
* Revision 1.127 2002/06/08 23:42:46 steve
|
||||
* Add NetRamDq synthsesis from memory l-values.
|
||||
*
|
||||
* Revision 1.126 2002/06/05 03:44:25 steve
|
||||
* Add support for memory words in l-value of
|
||||
* non-blocking assignments, and remove the special
|
||||
* NetAssignMem_ and NetAssignMemNB classes.
|
||||
*
|
||||
* Revision 1.125 2002/06/04 05:38:44 steve
|
||||
* Add support for memory words in l-value of
|
||||
* blocking assignments, and remove the special
|
||||
* NetAssignMem class.
|
||||
*
|
||||
* Revision 1.124 2002/05/26 01:39:02 steve
|
||||
* Carry Verilog 2001 attributes with processes,
|
||||
* all the way through to the ivl_target API.
|
||||
*
|
||||
* Divide signal reference counts between rval
|
||||
* and lval references.
|
||||
*
|
||||
* Revision 1.123 2002/05/05 21:11:49 steve
|
||||
* Put off evaluation of concatenation repeat expresions
|
||||
* until after parameters are defined. This allows parms
|
||||
* to be used in repeat expresions.
|
||||
*
|
||||
* Add the builtin $signed system function.
|
||||
*
|
||||
* Revision 1.122 2002/03/09 02:10:22 steve
|
||||
* Add the NetUserFunc netlist node.
|
||||
*
|
||||
* Revision 1.121 2001/12/31 00:03:05 steve
|
||||
* Include s indicator in dump of signed numbers.
|
||||
*
|
||||
* Revision 1.120 2001/12/03 04:47:14 steve
|
||||
* Parser and pform use hierarchical names as hname_t
|
||||
* objects instead of encoded strings.
|
||||
|
||||
@@ -15,9 +15,10 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*
|
||||
* $Id: dosify.c,v 1.1 2001/08/03 17:06:47 steve Exp $
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: dosify.c,v 1.3 2002/08/12 01:34:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This is a simple program to make a dosified copy of the
|
||||
@@ -68,6 +69,12 @@ int main(int argc, char*argv[])
|
||||
|
||||
/*
|
||||
* $Log: dosify.c,v $
|
||||
* Revision 1.3 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.2 2002/08/11 23:47:04 steve
|
||||
* Add missing Log and Ident strings.
|
||||
*
|
||||
* Revision 1.1 2001/08/03 17:06:47 steve
|
||||
* Add install of examples for Windows.
|
||||
*
|
||||
|
||||
@@ -10,3 +10,6 @@ cfparse.output
|
||||
cflexor.c
|
||||
foo.*
|
||||
iverilog
|
||||
iverilog.ps
|
||||
iverilog.pdf
|
||||
tmp.pdf
|
||||
|
||||
+10
-8
@@ -18,12 +18,12 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.10 2001/11/17 17:57:58 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.15 2002/08/10 22:36:59 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
|
||||
VERSION = 0.0
|
||||
VERSION = 0.6
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
@@ -37,7 +37,6 @@ includedir = $(prefix)/include
|
||||
mandir = @mandir@
|
||||
|
||||
dllib=@DLLIB@
|
||||
rdynamic=@rdynamic@
|
||||
|
||||
CC = @CC@
|
||||
CXX = @CXX@
|
||||
@@ -46,7 +45,7 @@ INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
|
||||
CPPFLAGS = @CPPFLAGS@ @DEFS@
|
||||
CFLAGS = @CFLAGS@ -I. -I$(srcdir)/..
|
||||
CFLAGS = @CFLAGS@ -I. -I$(srcdir)/.. -DVERSION='"$(VERSION)"'
|
||||
CXXFLAGS = @CXXFLAGS@ -I. -I$(srcdir)/..
|
||||
LDFLAGS = @LDFLAGS@
|
||||
|
||||
@@ -56,7 +55,7 @@ clean:
|
||||
rm -f *.o lexor.c parse.c parse.h parse.output
|
||||
rm -f cflexor.c cfparse.c cfparse.h cfparse.output
|
||||
|
||||
O = main.o build_string.o lexor.o parse.o cflexor.o cfparse.o
|
||||
O = main.o build_string.o lexor.o parse.o substit.o cflexor.o cfparse.o
|
||||
|
||||
iverilog@EXEEXT@: $O
|
||||
$(CC) $(LDFLAGS) $O -o iverilog@EXEEXT@ @EXTRALIBS@
|
||||
@@ -75,7 +74,7 @@ cfparse.h cfparse.c: cfparse.y
|
||||
|
||||
|
||||
main.o: main.c globals.h
|
||||
$(CC) $(CFLAGS) -c -DCXX='"@CXX@"' -DIVL_ROOT='"@libdir@/ivl"' -DIVL_INC='"@includedir@"' -DIVL_LIB='"@libdir@"' -DRDYNAMIC=\"$(rdynamic)\" -DDLLIB='"@DLLIB@"' -DEXEEXT='"@EXEEXT@"' $(srcdir)/main.c
|
||||
$(CC) $(CFLAGS) -c -DCXX='"@CXX@"' -DIVL_ROOT='"@libdir@/ivl"' -DIVL_INC='"@includedir@"' -DIVL_LIB='"@libdir@"' -DDLLIB='"@DLLIB@"' $(srcdir)/main.c
|
||||
|
||||
build_string.o: build_string.c globals.h
|
||||
lexor.o: lexor.c parse.h globals.h
|
||||
@@ -83,8 +82,11 @@ parse.o: parse.c globals.h
|
||||
cflexor.o: cflexor.c cfparse.h cfparse_misc.h globals.h
|
||||
cfparse.o: cfparse.c globals.h cfparse_misc.h
|
||||
|
||||
iverilog.pdf: $(srcdir)/iverilog.man
|
||||
man -t $(srcdir)/iverilog.man | ps2pdf - iverilog.pdf
|
||||
iverilog.ps: $(srcdir)/iverilog.man
|
||||
man -t $(srcdir)/iverilog.man > iverilog.ps
|
||||
|
||||
iverilog.pdf: iverilog.ps
|
||||
ps2pdf iverilog.ps iverilog.pdf
|
||||
|
||||
ifeq (@WIN32@,yes)
|
||||
INSTALL_DOC = $(prefix)/iverilog.pdf
|
||||
|
||||
+40
-18
@@ -16,8 +16,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: build_string.c,v 1.6 2001/11/16 05:07:19 steve Exp $"
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: build_string.c,v 1.11 2002/08/12 01:35:01 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -54,6 +54,7 @@ int build_string(char*output, size_t olen, const char*pattern)
|
||||
|
||||
if (((*pattern == 's') && start)
|
||||
|| ((*pattern == 'v') && verbose_flag)
|
||||
|| ((*pattern == 'M') && depfile)
|
||||
|| ((*pattern == 'N') && npath)
|
||||
|| ((*pattern == 'T') && mtm)) {
|
||||
int rc = build_string(output, olen,
|
||||
@@ -71,6 +72,18 @@ int build_string(char*output, size_t olen, const char*pattern)
|
||||
olen -= strlen(base);
|
||||
break;
|
||||
|
||||
case 'C':
|
||||
strcpy(output, iconfig_path);
|
||||
output += strlen(iconfig_path);
|
||||
olen -= strlen(iconfig_path);
|
||||
break;
|
||||
|
||||
case 'g':
|
||||
strcpy(output, generation);
|
||||
output += strlen(generation);
|
||||
olen -= strlen(generation);
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
if (f_list) {
|
||||
strcpy(output, f_list);
|
||||
@@ -87,6 +100,14 @@ int build_string(char*output, size_t olen, const char*pattern)
|
||||
}
|
||||
break;
|
||||
|
||||
case 'M':
|
||||
if (depfile) {
|
||||
strcpy(output, depfile);
|
||||
output += strlen(depfile);
|
||||
olen -= strlen(depfile);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'N':
|
||||
if (npath) {
|
||||
strcpy(output, npath);
|
||||
@@ -129,22 +150,6 @@ int build_string(char*output, size_t olen, const char*pattern)
|
||||
olen -= strlen(warning_flags);
|
||||
break;
|
||||
|
||||
case 'y':
|
||||
if (library_flags) {
|
||||
strcpy(output, library_flags);
|
||||
output += strlen(library_flags);
|
||||
olen -= strlen(library_flags);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'Y':
|
||||
if (library_flags2) {
|
||||
strcpy(output, library_flags2);
|
||||
output += strlen(library_flags2);
|
||||
olen -= strlen(library_flags2);
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
pattern += 1;
|
||||
|
||||
@@ -160,6 +165,23 @@ int build_string(char*output, size_t olen, const char*pattern)
|
||||
|
||||
/*
|
||||
* $Log: build_string.c,v $
|
||||
* Revision 1.11 2002/08/12 01:35:01 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.10 2002/05/28 02:25:03 steve
|
||||
* Pass library paths through -Cfile instead of command line.
|
||||
*
|
||||
* Revision 1.9 2002/05/28 00:50:39 steve
|
||||
* Add the ivl -C flag for bulk configuration
|
||||
* from the driver, and use that to run library
|
||||
* modules through the preprocessor.
|
||||
*
|
||||
* Revision 1.8 2002/05/24 01:13:00 steve
|
||||
* Support language generation flag -g.
|
||||
*
|
||||
* Revision 1.7 2002/04/04 05:26:13 steve
|
||||
* Add dependency generation.
|
||||
*
|
||||
* Revision 1.6 2001/11/16 05:07:19 steve
|
||||
* Add support for +libext+ in command files.
|
||||
*
|
||||
|
||||
+5
-1
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: cflexor.lex,v 1.5 2001/12/08 04:13:07 steve Exp $"
|
||||
#ident "$Id: cflexor.lex,v 1.6 2002/05/28 20:40:37 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "cfparse.h"
|
||||
@@ -70,6 +70,10 @@ static int comment_enter;
|
||||
|
||||
"+incdir+" { BEGIN(PLUS_ARGS); return TOK_INCDIR; }
|
||||
|
||||
"+libdir+" { BEGIN(PLUS_ARGS); return TOK_LIBDIR; }
|
||||
|
||||
"+libdir-nocase+" { BEGIN(PLUS_ARGS); return TOK_LIBDIR_NOCASE; }
|
||||
|
||||
"+libext+" { BEGIN(PLUS_ARGS); return TOK_LIBEXT; }
|
||||
|
||||
|
||||
|
||||
+31
-8
@@ -18,11 +18,12 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: cfparse.y,v 1.5 2001/12/08 04:13:07 steve Exp $"
|
||||
#ident "$Id: cfparse.y,v 1.8 2002/06/23 20:10:51 steve Exp $"
|
||||
#endif
|
||||
|
||||
|
||||
# include "globals.h"
|
||||
# include "cfparse_misc.h"
|
||||
# include <ctype.h>
|
||||
|
||||
/*
|
||||
@@ -57,7 +58,7 @@ static void translate_file_name(char*text)
|
||||
};
|
||||
|
||||
%token TOK_Da TOK_Dv TOK_Dy
|
||||
%token TOK_DEFINE TOK_INCDIR TOK_LIBEXT
|
||||
%token TOK_DEFINE TOK_INCDIR TOK_LIBDIR TOK_LIBDIR_NOCASE TOK_LIBEXT
|
||||
%token <text> TOK_PLUSARG TOK_PLUSWORD TOK_STRING
|
||||
|
||||
%%
|
||||
@@ -77,9 +78,11 @@ item
|
||||
of a source file. Add the file to the file list. */
|
||||
|
||||
: TOK_STRING
|
||||
{ translate_file_name($1);
|
||||
process_file_name($1);
|
||||
{ char*tmp = substitutions($1);
|
||||
translate_file_name(tmp);
|
||||
process_file_name(tmp);
|
||||
free($1);
|
||||
free(tmp);
|
||||
}
|
||||
|
||||
/* The -a flag is completely ignored. */
|
||||
@@ -90,11 +93,13 @@ item
|
||||
as an ordinary source file. */
|
||||
|
||||
| TOK_Dv TOK_STRING
|
||||
{ translate_file_name($2);
|
||||
process_file_name($2);
|
||||
{ char*tmp = substitutions($2);
|
||||
translate_file_name(tmp);
|
||||
process_file_name(tmp);
|
||||
fprintf(stderr, "%s:%u: Ignoring -v in front of %s\n",
|
||||
@1.text, @1.first_line, $2);
|
||||
free($2);
|
||||
free(tmp);
|
||||
}
|
||||
|
||||
/* This rule matches "-y <path>" sequences. This does the same thing
|
||||
@@ -102,8 +107,24 @@ item
|
||||
directory list. */
|
||||
|
||||
| TOK_Dy TOK_STRING
|
||||
{ process_library_switch($2);
|
||||
{ char*tmp = substitutions($2);
|
||||
process_library_switch(tmp);
|
||||
free($2);
|
||||
free(tmp);
|
||||
}
|
||||
|
||||
| TOK_LIBDIR TOK_PLUSARG
|
||||
{ char*tmp = substitutions($2);
|
||||
process_library_switch(tmp);
|
||||
free($2);
|
||||
free(tmp);
|
||||
}
|
||||
|
||||
| TOK_LIBDIR_NOCASE TOK_PLUSARG
|
||||
{ char*tmp = substitutions($2);
|
||||
process_library_nocase_switch(tmp);
|
||||
free($2);
|
||||
free(tmp);
|
||||
}
|
||||
|
||||
| TOK_DEFINE TOK_PLUSARG
|
||||
@@ -150,8 +171,10 @@ inc_args
|
||||
;
|
||||
|
||||
inc_arg : TOK_PLUSARG
|
||||
{ process_include_dir($1);
|
||||
{ char*tmp = substitutions($1);
|
||||
process_include_dir(tmp);
|
||||
free($1);
|
||||
free(tmp);
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
+22
-2
@@ -19,13 +19,33 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT)
|
||||
#ident "$Id: cfparse_misc.h,v 1.2 2001/11/12 18:47:32 steve Exp $"
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: cfparse_misc.h,v 1.4 2002/08/12 01:35:01 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The vlltype supports the passing of detailed source file location
|
||||
* information between the lexical analyzer and the parser. Defining
|
||||
* YYLTYPE compels the lexor to use this type and not something other.
|
||||
*/
|
||||
struct cfltype {
|
||||
unsigned first_line;
|
||||
unsigned first_column;
|
||||
unsigned last_line;
|
||||
unsigned last_column;
|
||||
const char*text;
|
||||
};
|
||||
# define YYLTYPE struct cfltype
|
||||
extern YYLTYPE yylloc;
|
||||
|
||||
/*
|
||||
* $Log: cfparse_misc.h,v $
|
||||
* Revision 1.4 2002/08/12 01:35:01 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.3 2002/01/02 02:39:34 steve
|
||||
* Use my own cfltype to defend against bison 1.30.
|
||||
*
|
||||
* Revision 1.2 2001/11/12 18:47:32 steve
|
||||
* Support +incdir in command files, and ignore other
|
||||
* +args flags. Also ignore -a and -v flags.
|
||||
|
||||
+36
-2
@@ -18,8 +18,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: globals.h,v 1.10 2001/11/16 05:07:19 steve Exp $"
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: globals.h,v 1.16 2002/08/12 01:35:01 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <stddef.h>
|
||||
@@ -27,6 +27,9 @@
|
||||
/* This is the base (i.e. -B<value>) of the Icarus Verilog files. */
|
||||
extern const char*base;
|
||||
|
||||
/* This is the path to the iconfig file sent to ivl. */
|
||||
extern char* iconfig_path;
|
||||
|
||||
/* This is a list of all the -f<key>=<value> options from the
|
||||
command line, concatenated together. */
|
||||
extern char*f_list;
|
||||
@@ -36,6 +39,9 @@ extern char*mod_list;
|
||||
/* This is the optional -Tmin|typ|max setting. */
|
||||
extern const char*mtm;
|
||||
|
||||
/* Ths is the optional -M<dependfile> value, if one was supplied. */
|
||||
extern const char*depfile;
|
||||
|
||||
/* Ths is the optional -N<path> value, if one was supplied. */
|
||||
extern const char*npath;
|
||||
|
||||
@@ -51,11 +57,18 @@ extern int synth_flag;
|
||||
/* This is the name of the selected target. */
|
||||
extern const char*targ;
|
||||
|
||||
/* This is the language generation flag. */
|
||||
extern const char*generation;
|
||||
|
||||
/* Perform variable substitutions on the string. */
|
||||
extern char* substitutions(const char*str);
|
||||
|
||||
/* Add the name to the list of source files. */
|
||||
extern void process_file_name(const char*name);
|
||||
|
||||
/* Add the name to the list of library directories. */
|
||||
extern void process_library_switch(const char*name);
|
||||
extern void process_library_nocase_switch(const char*name);
|
||||
extern void process_library2_switch(const char*name);
|
||||
|
||||
/* Add a new include file search directory */
|
||||
@@ -79,6 +92,27 @@ extern int build_string(char*out, size_t olen, const char*pattern);
|
||||
|
||||
/*
|
||||
* $Log: globals.h,v $
|
||||
* Revision 1.16 2002/08/12 01:35:01 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.15 2002/06/23 20:10:51 steve
|
||||
* Variable substitution in command files.
|
||||
*
|
||||
* Revision 1.14 2002/05/28 20:40:37 steve
|
||||
* ivl indexes the search path for libraries, and
|
||||
* supports case insensitive module-to-file lookup.
|
||||
*
|
||||
* Revision 1.13 2002/05/28 00:50:40 steve
|
||||
* Add the ivl -C flag for bulk configuration
|
||||
* from the driver, and use that to run library
|
||||
* modules through the preprocessor.
|
||||
*
|
||||
* Revision 1.12 2002/05/24 01:13:00 steve
|
||||
* Support language generation flag -g.
|
||||
*
|
||||
* Revision 1.11 2002/04/04 05:26:13 steve
|
||||
* Add dependency generation.
|
||||
*
|
||||
* Revision 1.10 2001/11/16 05:07:19 steve
|
||||
* Add support for +libext+ in command files.
|
||||
*
|
||||
|
||||
+75
-23
@@ -1,21 +1,20 @@
|
||||
.TH iverilog 1 "$Date: 2001/12/08 04:13:07 $" Version "$Date: 2001/12/08 04:13:07 $"
|
||||
.TH iverilog 1 "$Date: 2002/06/23 20:10:51 $" Version "$Date: 2002/06/23 20:10:51 $"
|
||||
.SH NAME
|
||||
iverilog - Icarus Verilog compiler
|
||||
|
||||
.SH SYNOPSIS
|
||||
.B iverilog
|
||||
[-ESv] [-Cpath] [-ccmdfile] [-Dmacro[=defn]] [-pflag=value]
|
||||
[-Iincludedir] [-mmodule] [-Nfile] [-ooutputfilename] [-stopmodule]
|
||||
[-ttype] [-Tmin/typ/max] [-Wclass] [-ypath] sourcefile
|
||||
[-ESVv] [-Cpath] [-ccmdfile] [-g1|-g2|-g3.0] [-Dmacro[=defn]] [-pflag=value]
|
||||
[-Iincludedir] [-mmodule] [-Mfile] [-Nfile] [-ooutputfilename]
|
||||
[-stopmodule] [-ttype] [-Tmin/typ/max] [-Wclass] [-ypath] sourcefile
|
||||
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
\fIiverilog\fP is a compiler that translates Verilog source code into
|
||||
executable programs for simulation, or other netlist formats for
|
||||
further processing. The currently supported targets are \fIvvm\fP (for
|
||||
executable simulation) and \fIvvp\fP for simulation, and \fIxnf\fP for
|
||||
synthesis. Other target types are added as code generators are
|
||||
implemented.
|
||||
further processing. The currently supported targets are \fIvvp\fP for
|
||||
simulation, and \fIxnf\fP and \fIfpga\fP for synthesis. Other target
|
||||
types are added as code generators are implemented.
|
||||
|
||||
.SH OPTIONS
|
||||
.l
|
||||
@@ -56,12 +55,28 @@ is the Verilog input, but with file inclusions and macro references
|
||||
expanded and removed. This is useful, for example, to preprocess
|
||||
Verilog source for use by other compilers.
|
||||
.TP 8
|
||||
.B -g1\fI|\fP-g2\fI|\fP-g3.0
|
||||
Select the Verilog language \fIgeneration\fP to support in the
|
||||
compiler. This selects between \fIIEEE1364-1995\fP(1),
|
||||
\fIIEEE1364-2001\fP(2), or \fISystemVerilog 3.0\fP(3.0). Normally,
|
||||
Icarus Verilog defaults to the latest known generation of the
|
||||
language. This flag is most useful to restrict the language to a set
|
||||
supported by tools of specific generations, for compatibility with
|
||||
other tools.
|
||||
.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 -M\fIpath\fP
|
||||
Write into the file specified by path a list of files that contribute
|
||||
to the compilation of the design. This includes files that are
|
||||
included by include directives and files that are automatically loaded
|
||||
by library support. The output is one file name per line, with no
|
||||
leading or trailing space.
|
||||
.TP 8
|
||||
.B -m\fImodule\fP
|
||||
Add this module to the list of VPI modules to be loaded by the
|
||||
simulation. Many modules can be specified, and all will be loaded, in
|
||||
@@ -111,7 +126,11 @@ Use this switch to specify the target output format. See the
|
||||
.B -v
|
||||
Turn on verbose messages. This will print the command lines that are
|
||||
executed to perform the actual compilation, along with version
|
||||
information from the various components.
|
||||
information from the various components, as well as the version of the
|
||||
product as a whole.
|
||||
.TP 8
|
||||
.B -V
|
||||
Print the version of the compiler, and exit.
|
||||
.TP 8
|
||||
.B -W\fIclass\fP
|
||||
Turn on different classes of warnings. See the \fBWARNING TYPES\fP
|
||||
@@ -149,31 +168,27 @@ desired target.
|
||||
The null target causes no code to be generated. It is useful for
|
||||
checking the syntax of the Verilog source.
|
||||
.TP 8
|
||||
.B vvm
|
||||
The target is an executable program that uses the vvm simulation
|
||||
runtime. The compiler actually generates C++ code, then compiles and
|
||||
links that code to make the output executable.
|
||||
.TP 8
|
||||
.B vvp
|
||||
This is the default. The vvp target generates code for the vvp
|
||||
runtime. The output is a complete program that simulates the design
|
||||
(like with vvm) but must be run by the \fBvvp\fP command. This target
|
||||
is much faster then the \fBvvm\fP target, but not quite as complete.
|
||||
but must be run by the \fBvvp\fP command.
|
||||
.TP 8
|
||||
.B xnf
|
||||
This is the Xilinx Netlist Format used by many tools for placing
|
||||
devices in FPGAs or other programmable devices. The Icarus Verilog XNF
|
||||
code generator can generate complete designs or XNF macros that can be
|
||||
imported into larger designs by other tools.
|
||||
imported into larger designs by other tools. (This target is obsolete,
|
||||
use the \fBfpga\fP target instead.)
|
||||
.TP 8
|
||||
.B fpga
|
||||
This is a variant of the XNF code generator that supports a wider
|
||||
variety of target devices. It is intended as a future replacement for
|
||||
the existing \fBxnf\fP target, but for now is still experimental.
|
||||
This is a synthesis target that supports a variety of fpga devices,
|
||||
mostly by EDIF format output.
|
||||
|
||||
.SH "WARNING TYPES"
|
||||
These are the types of warnings that can be selected by the \fB-W\fP
|
||||
switch.
|
||||
switch. All the warning types (other then \fBall\fP) can also be
|
||||
prefixed with \fBno-\fP to turn off that warning. This is most useful
|
||||
after a \fB-Wall\fP argument to suppress isolated warning types.
|
||||
|
||||
.TP 8
|
||||
.B all
|
||||
@@ -185,6 +200,14 @@ This enables warnings for creation of implicit declarations. For
|
||||
example, if a scalar wire X is used but not declared in the Verilog
|
||||
source, this will print a warning at its first use.
|
||||
|
||||
.TP 8
|
||||
.B timescale
|
||||
This enables warnings for inconsistent use of the timescale
|
||||
directive. It detects if some modules have no timescale, or if modules
|
||||
inherit timescale from another file. Both probably mean that
|
||||
timescales are inconsistent, and simulation timing can be confusing
|
||||
and dependent on compilation order.
|
||||
|
||||
.SH "COMMAND FILES"
|
||||
The command file allows the user to place source file names and
|
||||
certain command line switches into a text file instead of on a long
|
||||
@@ -194,7 +217,8 @@ well as # comments, if the # starts the line.
|
||||
.TP 8
|
||||
.I "file name"
|
||||
A simple file name or file path is taken to be the name of a Verilog
|
||||
source file. The path starts with the first non-white-space character.
|
||||
source file. The path starts with the first non-white-space
|
||||
character. Variables are substitued in file names.
|
||||
|
||||
.TP 8
|
||||
.B -y\ \fIlibdir\fP
|
||||
@@ -202,6 +226,8 @@ A \fB-y\fP token prefixes a library directory in the command file,
|
||||
exactly like it does on the command line. The parameter to the \fB-y\fP
|
||||
flag may be on the same line or the next non-comment line.
|
||||
|
||||
Variables in the \fIlibdir\fP are substituted.
|
||||
|
||||
.TP 8
|
||||
.B +incdir+\fIincludedir\fP
|
||||
The \fB+incdir+\fP token in command files gives directories to search
|
||||
@@ -210,6 +236,8 @@ command line. The difference is that multiple \fI+includedir\fP
|
||||
directories are valid parameters to a single \fB+incdir+\fP token,
|
||||
although you may also have multiple \fB+incdir+\fP lines.
|
||||
|
||||
Variables in the \fIincludedir\fP are substituted.
|
||||
|
||||
.TP 8
|
||||
.B +libext+\fIext\fP
|
||||
The \fB+libext\fP token in command files fives file extensions to try
|
||||
@@ -217,6 +245,18 @@ when looking for a library file. This is useful in conjunction with
|
||||
\fB-y\fP flags to list suffixes to try in each directory before moving
|
||||
on to the next library directory.
|
||||
|
||||
.TP 8
|
||||
.B +libdir+\fIdir\fP
|
||||
This is another way to specify library directories. See the -y flag.
|
||||
|
||||
.TP 8
|
||||
.B +libdir-nocase+\fIdir\fP
|
||||
This is like the \fB+libdir\fP statement, but file names inside the
|
||||
directories declared here are case insensitive. The missing module
|
||||
name in a lookup need not match the file name case, as long as the
|
||||
letters are correct. For example, "foo" matches "Foo.v" but not
|
||||
"bar.v".
|
||||
|
||||
.TP 8
|
||||
.B +define+\fINAME\fP=\fIvalue\fP
|
||||
The \fB+define+\fP token is the same as the \fB-D\fP option on the
|
||||
@@ -233,6 +273,18 @@ become munged.
|
||||
.B +tolower-filename\fP
|
||||
This is similar to the \fB+toupper-filename\fP hack described above.
|
||||
|
||||
.SH "VARIABLES IN COMMAND FILES"
|
||||
|
||||
In certain cases, iverilog supports variables in command files. These
|
||||
are strings of the form "$(\fIvarname\fP)", where \fIvarname\fP is the
|
||||
name of the environment variable to read. The entire string is
|
||||
replaced with the contents of that variable. Variables are only
|
||||
substitued in contexts that explicitly support them, including file
|
||||
and directory strings.
|
||||
|
||||
Variable values come from the operating system environment, and not
|
||||
from preprocessor defines elsewhere in the file or the command line.
|
||||
|
||||
.SH EXAMPLES
|
||||
These examples assume that you have a Verilog source file called hello.v in
|
||||
the current directory
|
||||
@@ -264,7 +316,7 @@ vvp(1),
|
||||
|
||||
.SH COPYRIGHT
|
||||
.nf
|
||||
Copyright \(co 2000 Stephen Williams
|
||||
Copyright \(co 2002 Stephen Williams
|
||||
|
||||
This document can be freely redistributed according to the terms of the
|
||||
GNU General Public License version 2.0
|
||||
|
||||
+216
-132
@@ -16,13 +16,14 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ident "$Id: main.c,v 1.31 2001/11/21 02:20:34 steve Exp $"
|
||||
#ident "$Id: main.c,v 1.47 2002/08/12 01:27:48 steve Exp $"
|
||||
|
||||
# include "config.h"
|
||||
|
||||
|
||||
const char HELP[] =
|
||||
"Usage: iverilog [-ESv] [-B base] [-C path] [-c cmdfile]\n"
|
||||
" [-D macro[=defn]] [-I includedir] [-m module]\n"
|
||||
"Usage: iverilog [-ESvV] [-B base] [-C path] [-c cmdfile] [-g1|-g2|-g3.0]\n"
|
||||
" [-D macro[=defn]] [-I includedir] [-M 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"
|
||||
@@ -43,6 +44,7 @@ const char HELP[] =
|
||||
|
||||
#ifdef __MINGW32__
|
||||
#include <windows.h>
|
||||
#include <libiberty.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_GETOPT_H
|
||||
@@ -67,10 +69,6 @@ extern const char*optarg;
|
||||
# define IVL_ROOT "."
|
||||
#endif
|
||||
|
||||
#ifndef RDYNAMIC
|
||||
# define RDYNAMIC "-rdynamic"
|
||||
#endif
|
||||
|
||||
# include "globals.h"
|
||||
|
||||
#ifdef __MINGW32__
|
||||
@@ -83,13 +81,14 @@ extern void cfreset(FILE*fd, const char*path);
|
||||
|
||||
const char*base = 0;
|
||||
const char*mtm = 0;
|
||||
const char*opath = "a.out" EXEEXT;
|
||||
const char*opath = "a.out";
|
||||
const char*npath = 0;
|
||||
const char*targ = "vvp";
|
||||
const char*depfile = 0;
|
||||
|
||||
const char*generation = "-g3.0";
|
||||
|
||||
char warning_flags[16] = "";
|
||||
char *library_flags = 0;
|
||||
char *library_flags2 = 0;
|
||||
|
||||
char*inc_list = 0;
|
||||
char*def_list = 0;
|
||||
@@ -106,6 +105,9 @@ char*source_path = 0;
|
||||
FILE*source_file = 0;
|
||||
unsigned source_count = 0;
|
||||
|
||||
char*iconfig_path = 0;
|
||||
FILE*iconfig_file = 0;
|
||||
|
||||
int synth_flag = 0;
|
||||
int verbose_flag = 0;
|
||||
int command_file = 0;
|
||||
@@ -117,6 +119,43 @@ char tmp[MAXSIZE];
|
||||
|
||||
static char ivl_root[MAXSIZE];
|
||||
|
||||
static const char*my_tempfile(const char*str, FILE**fout)
|
||||
{
|
||||
FILE*file;
|
||||
int retry;
|
||||
|
||||
static char pathbuf[8192];
|
||||
|
||||
const char*tmpdir = getenv("TMP");
|
||||
if (tmpdir == 0)
|
||||
tmpdir = getenv("TMPDIR");
|
||||
if (tmpdir == 0)
|
||||
tmpdir = getenv("TEMP");
|
||||
#ifdef __MINGW32__
|
||||
if (tmpdir == 0)
|
||||
tmpdir = "C:\\TEMP";
|
||||
#else
|
||||
if (tmpdir == 0)
|
||||
tmpdir = "/tmp";
|
||||
#endif
|
||||
|
||||
assert(tmpdir);
|
||||
assert((strlen(tmpdir) + strlen(str)) < sizeof pathbuf - 10);
|
||||
|
||||
srand(getpid());
|
||||
retry = 100;
|
||||
file = NULL;
|
||||
while ((retry > 0) && (file == NULL)) {
|
||||
unsigned code = rand();
|
||||
sprintf(pathbuf, "%s%c%s%04x", tmpdir, sep, str, code);
|
||||
file = fopen(pathbuf, "w");
|
||||
retry -= 1;
|
||||
}
|
||||
|
||||
*fout = file;
|
||||
return pathbuf;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the default target type. It looks up the bits that are
|
||||
* needed to run the command from the configuration file (which is
|
||||
@@ -157,6 +196,7 @@ static int t_default(char*cmd, unsigned ncmd)
|
||||
|
||||
rc = system(cmd);
|
||||
remove(source_path);
|
||||
remove(iconfig_path);
|
||||
if (rc != 0) {
|
||||
if (rc == 127) {
|
||||
fprintf(stderr, "Failed to execute: %s\n", cmd);
|
||||
@@ -173,97 +213,6 @@ static int t_default(char*cmd, unsigned ncmd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function handles the vvm target. After preprocessing, run the
|
||||
* ivl translator to get C++, then run g++ to make an executable
|
||||
* program out of that.
|
||||
*/
|
||||
static int t_vvm(char*cmd, unsigned ncmd)
|
||||
{
|
||||
int rc;
|
||||
|
||||
const char*pattern = lookup_pattern("<ivl>");
|
||||
if (pattern == 0) {
|
||||
fprintf(stderr, "No such target: %s\n", targ);
|
||||
return -1;
|
||||
}
|
||||
|
||||
tmp[0] = ' ';
|
||||
tmp[1] = '|';
|
||||
tmp[2] = ' ';
|
||||
rc = build_string(tmp+3, sizeof tmp - 3, pattern);
|
||||
cmd = realloc(cmd, ncmd+3+rc+1);
|
||||
|
||||
#ifdef __MINGW32__
|
||||
{
|
||||
char *t;
|
||||
for (t = tmp; *t; t++)
|
||||
{
|
||||
if (*t == '/') *t = '\\';
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
strcpy(cmd+ncmd, tmp);
|
||||
|
||||
|
||||
if (verbose_flag)
|
||||
printf("translate: %s\n", cmd);
|
||||
|
||||
rc = system(cmd);
|
||||
remove(source_path);
|
||||
if (rc != 0) {
|
||||
if (WIFEXITED(rc)) {
|
||||
fprintf(stderr, "errors translating Verilog program.\n");
|
||||
return WEXITSTATUS(rc);
|
||||
} else {
|
||||
fprintf(stderr, "Command signaled: %s\n", cmd);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__MINGW32__)
|
||||
/* In the Windows world, the path to headers and libraries
|
||||
for vvm is relative the ivl_root, which is in something like:
|
||||
|
||||
d:\iverilog\lib\ivl <-- ivl_root
|
||||
d:\iverilog\include <-- vvm headers
|
||||
d:\iverilog\lib <-- vvm libraries
|
||||
|
||||
So we make up all the ugly references that are the g++
|
||||
command line to compile a .cc file generated by vvm. */
|
||||
sprintf(tmp, "%s " RDYNAMIC " -s -fno-exceptions -o %s "
|
||||
"-I%s\\..\\..\\include -L%s\\.. %s.cc -lvvm -lvpip %s",
|
||||
CXX, opath, ivl_root, ivl_root, opath, DLLIB);
|
||||
#else
|
||||
/* In the UNIX universe, life is easy. The configure script
|
||||
has figured everything out and wrote it into the Makefile,
|
||||
which passes it on as the IVL_INC and IVL_LIB defines. */
|
||||
sprintf(tmp, "%s " RDYNAMIC " -s -fno-exceptions -o %s -I%s "
|
||||
"-L%s %s.cc -lvvm -lvpip %s", CXX, opath, IVL_INC,
|
||||
IVL_LIB, opath, DLLIB);
|
||||
#endif
|
||||
if (verbose_flag)
|
||||
printf("compile: %s\n", tmp);
|
||||
|
||||
rc = system(tmp);
|
||||
if (rc != 0) {
|
||||
if (WIFEXITED(rc)) {
|
||||
fprintf(stderr, "errors compiling translated program.\n");
|
||||
return WEXITSTATUS(rc);
|
||||
} else {
|
||||
fprintf(stderr, "Command signaled: %s\n", tmp);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
sprintf(tmp, "%s.cc", opath);
|
||||
unlink(tmp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void process_warning_switch(const char*name)
|
||||
{
|
||||
@@ -271,38 +220,42 @@ static void process_warning_switch(const char*name)
|
||||
strcpy(warning_flags, "-W");
|
||||
|
||||
if (strcmp(name,"all") == 0) {
|
||||
strcat(warning_flags, "i");
|
||||
strcat(warning_flags, "it");
|
||||
|
||||
} else if (strcmp(name,"implicit") == 0) {
|
||||
if (! strchr(warning_flags+2, 'i'))
|
||||
strcat(warning_flags, "i");
|
||||
} else if (strcmp(name,"timescale") == 0) {
|
||||
if (! strchr(warning_flags+2, 't'))
|
||||
strcat(warning_flags, "t");
|
||||
} else if (strcmp(name,"no-implicit") == 0) {
|
||||
char*cp = strchr(warning_flags+2, 'i');
|
||||
if (cp) while (*cp) {
|
||||
cp[0] = cp[1];
|
||||
cp += 1;
|
||||
}
|
||||
} else if (strcmp(name,"no-timescale") == 0) {
|
||||
char*cp = strchr(warning_flags+2, 't');
|
||||
if (cp) while (*cp) {
|
||||
cp[0] = cp[1];
|
||||
cp += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void process_library_switch(const char *name)
|
||||
{
|
||||
if (library_flags) {
|
||||
library_flags = realloc(library_flags,
|
||||
strlen(library_flags) + strlen(name) + 5);
|
||||
strcat(library_flags, " -y ");
|
||||
} else {
|
||||
library_flags = malloc(strlen(name) + 4);
|
||||
strcpy(library_flags, "-y ");
|
||||
}
|
||||
strcat(library_flags, name);
|
||||
fprintf(iconfig_file, "-y:%s\n", name);
|
||||
}
|
||||
|
||||
void process_library_nocase_switch(const char *name)
|
||||
{
|
||||
fprintf(iconfig_file, "-yl:%s\n", name);
|
||||
}
|
||||
|
||||
void process_library2_switch(const char *name)
|
||||
{
|
||||
if (library_flags2) {
|
||||
library_flags2 = realloc(library_flags2,
|
||||
strlen(library_flags2) + strlen(name) + 5);
|
||||
strcat(library_flags2, " -Y ");
|
||||
} else {
|
||||
library_flags2 = malloc(strlen(name) + 4);
|
||||
strcpy(library_flags2, "-Y ");
|
||||
}
|
||||
strcat(library_flags2, name);
|
||||
fprintf(iconfig_file, "-Y:%s\n", name);
|
||||
}
|
||||
|
||||
void process_include_dir(const char *name)
|
||||
@@ -341,13 +294,38 @@ void process_file_name(const char*name)
|
||||
source_count += 1;
|
||||
}
|
||||
|
||||
int process_generation(const char*name)
|
||||
{
|
||||
if (strcmp(name,"1") == 0)
|
||||
generation = "-g1";
|
||||
|
||||
else if (strcmp(name,"2") == 0)
|
||||
generation = "-g2";
|
||||
|
||||
else if (strcmp(name,"3.0") == 0)
|
||||
generation = "-g3.0";
|
||||
|
||||
else {
|
||||
fprintf(stderr, "Unknown/Unsupported Language generation "
|
||||
"%s\n", name);
|
||||
fprintf(stderr, "Supported generations are:\n");
|
||||
fprintf(stderr, " 1 -- IEEE1364-1995 (Verilog 1)\n"
|
||||
" 2 -- IEEE1364-2001 (Verilog 2001)\n"
|
||||
" 3.0 -- SystemVerilog 3.0\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char*config_path = 0;
|
||||
char*cmd;
|
||||
unsigned ncmd;
|
||||
int e_flag = 0;
|
||||
int opt, idx;
|
||||
int version_flag = 0;
|
||||
int opt, idx, rc;
|
||||
char*cp;
|
||||
|
||||
#ifdef __MINGW32__
|
||||
@@ -379,6 +357,7 @@ int main(int argc, char **argv)
|
||||
|
||||
base = ivl_root;
|
||||
}
|
||||
|
||||
#else
|
||||
/* In a UNIX environment, the IVL_ROOT from the Makefile is
|
||||
dependable. It points to the $prefix/lib/ivl directory,
|
||||
@@ -387,12 +366,29 @@ int main(int argc, char **argv)
|
||||
base = ivl_root;
|
||||
#endif
|
||||
|
||||
source_path = strdup(tmpnam(0));
|
||||
assert(source_path);
|
||||
source_file = fopen(source_path, "w");
|
||||
assert(source_file);
|
||||
/* Create a temporary file for communicating input parameters
|
||||
to the preprocessor. */
|
||||
source_path = strdup(my_tempfile("ivrlg", &source_file));
|
||||
if (NULL == source_file) {
|
||||
fprintf(stderr, "%s: Error opening temporary file %s\n",
|
||||
argv[0], source_path);
|
||||
fprintf(stderr, "%s: Please check TMP or TMPDIR.\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
while ((opt = getopt(argc, argv, "B:C:c:D:Ef:hI:m:N::o:p:Ss:T:t:vW:y:")) != EOF) {
|
||||
/* Create another temporary file for passing configuration
|
||||
information to ivl. */
|
||||
iconfig_path = strdup(my_tempfile("ivrlh", &iconfig_file));
|
||||
if (NULL == iconfig_file) {
|
||||
fprintf(stderr, "%s: Error opening temporary file %s\n",
|
||||
argv[0], iconfig_path);
|
||||
fprintf(stderr, "%s: Please check TMP or TMPDIR.\n", argv[0]);
|
||||
fclose(source_file);
|
||||
remove(source_path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
while ((opt = getopt(argc, argv, "B:C:c:D:Ef:g:hI:M:m:N::o:p:Ss:T:t:vVW:y:Y:")) != EOF) {
|
||||
|
||||
switch (opt) {
|
||||
case 'B':
|
||||
@@ -427,6 +423,11 @@ int main(int argc, char **argv)
|
||||
}
|
||||
break;
|
||||
|
||||
case 'g':
|
||||
rc = process_generation(optarg);
|
||||
if (rc != 0)
|
||||
return -1;
|
||||
break;
|
||||
case 'h':
|
||||
fprintf(stderr, "%s\n", HELP);
|
||||
return 1;
|
||||
@@ -435,6 +436,10 @@ int main(int argc, char **argv)
|
||||
process_include_dir(optarg);
|
||||
break;
|
||||
|
||||
case 'M':
|
||||
depfile = optarg;
|
||||
break;
|
||||
|
||||
case 'm':
|
||||
if (mod_list == 0) {
|
||||
mod_list = malloc(strlen(" -m")+strlen(optarg)+1);
|
||||
@@ -493,6 +498,9 @@ int main(int argc, char **argv)
|
||||
case 'v':
|
||||
verbose_flag = 1;
|
||||
break;
|
||||
case 'V':
|
||||
version_flag = 1;
|
||||
break;
|
||||
case 'W':
|
||||
process_warning_switch(optarg);
|
||||
break;
|
||||
@@ -508,6 +516,15 @@ int main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
if (version_flag || verbose_flag) {
|
||||
printf("Icarus Verilog version " VERSION "\n");
|
||||
printf("Copyright 1998-2002 Stephen Williams\n");
|
||||
printf("$Name: $\n");
|
||||
|
||||
if (version_flag)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (command_filename) {
|
||||
int rc;
|
||||
|
||||
@@ -562,7 +579,7 @@ int main(int argc, char **argv)
|
||||
|
||||
/* Start building the preprocess command line. */
|
||||
|
||||
sprintf(tmp, "%s%civlpp %s%s -f%s ", base,sep,
|
||||
sprintf(tmp, "%s%civlpp %s%s -D__ICARUS__=1 -f%s ", base,sep,
|
||||
verbose_flag?" -v":"",
|
||||
e_flag?"":" -L", source_path);
|
||||
|
||||
@@ -582,6 +599,12 @@ int main(int argc, char **argv)
|
||||
ncmd += strlen(def_list);
|
||||
}
|
||||
|
||||
if (depfile) {
|
||||
cmd = realloc(cmd, ncmd + strlen(depfile) + 5);
|
||||
strcat(cmd, " -M ");
|
||||
strcat(cmd, depfile);
|
||||
ncmd += strlen(depfile) + 4;
|
||||
}
|
||||
|
||||
/* If the -E flag was given on the command line, then all we
|
||||
do is run the preprocessor and put the output where the
|
||||
@@ -600,6 +623,9 @@ int main(int argc, char **argv)
|
||||
|
||||
rc = system(cmd);
|
||||
remove(source_path);
|
||||
fclose(iconfig_file);
|
||||
remove(iconfig_path);
|
||||
|
||||
if (rc != 0) {
|
||||
if (WIFEXITED(rc)) {
|
||||
fprintf(stderr, "errors preprocessing Verilog program.\n");
|
||||
@@ -613,17 +639,75 @@ int main(int argc, char **argv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strcmp(targ,"vvm") == 0)
|
||||
return t_vvm(cmd, ncmd);
|
||||
else {
|
||||
return t_default(cmd, ncmd);
|
||||
}
|
||||
/* Write the preprocessor command needed to preprocess a
|
||||
single file. This may be used to preprocess library
|
||||
files. */
|
||||
fprintf(iconfig_file, "ivlpp:%s%civlpp -D__ICARUS__ -L %s %s\n",
|
||||
base, sep,
|
||||
inc_list? inc_list : "",
|
||||
def_list? def_list : "");
|
||||
|
||||
/* Done writing to the iconfig file. Close it now. */
|
||||
fclose(iconfig_file);
|
||||
|
||||
return t_default(cmd, ncmd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: main.c,v $
|
||||
* Revision 1.47 2002/08/12 01:27:48 steve
|
||||
* Escape the backslash in the windows file name.
|
||||
*
|
||||
* Revision 1.46 2002/08/10 22:36:59 steve
|
||||
* No longer any nead for -rdynamic flag
|
||||
*
|
||||
* Revision 1.45 2002/08/10 22:27:13 steve
|
||||
* Kill links to vvm.
|
||||
*
|
||||
* Revision 1.44 2002/07/15 00:33:50 steve
|
||||
* Improve temporary file name guess.
|
||||
*
|
||||
* Revision 1.43 2002/07/14 23:32:31 steve
|
||||
* No longer need the .exe on generated files.
|
||||
*
|
||||
* Revision 1.42 2002/07/14 23:11:35 steve
|
||||
* Do temp file creation by hand.
|
||||
*
|
||||
* Revision 1.41 2002/05/28 20:40:37 steve
|
||||
* ivl indexes the search path for libraries, and
|
||||
* supports case insensitive module-to-file lookup.
|
||||
*
|
||||
* Revision 1.40 2002/05/28 02:25:03 steve
|
||||
* Pass library paths through -Cfile instead of command line.
|
||||
*
|
||||
* Revision 1.39 2002/05/28 00:50:40 steve
|
||||
* Add the ivl -C flag for bulk configuration
|
||||
* from the driver, and use that to run library
|
||||
* modules through the preprocessor.
|
||||
*
|
||||
* Revision 1.38 2002/05/27 23:14:06 steve
|
||||
* Predefine __ICARUS__
|
||||
*
|
||||
* Revision 1.37 2002/05/24 01:13:00 steve
|
||||
* Support language generation flag -g.
|
||||
*
|
||||
* Revision 1.36 2002/04/24 02:02:31 steve
|
||||
* add -Wno- arguments to the driver.
|
||||
*
|
||||
* Revision 1.35 2002/04/15 00:04:23 steve
|
||||
* Timescale warnings.
|
||||
*
|
||||
* Revision 1.34 2002/04/04 05:26:13 steve
|
||||
* Add dependency generation.
|
||||
*
|
||||
* Revision 1.33 2002/03/15 23:27:42 steve
|
||||
* Patch to allow user to set place for temporary files.
|
||||
*
|
||||
* Revision 1.32 2002/02/03 07:05:37 steve
|
||||
* Support print of version number.
|
||||
*
|
||||
* Revision 1.31 2001/11/21 02:20:34 steve
|
||||
* Pass list of file to ivlpp via temporary file.
|
||||
*
|
||||
|
||||
+2
-2
@@ -18,7 +18,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: parse.y,v 1.4 2001/09/15 18:27:04 steve Exp $"
|
||||
#ident "$Id: parse.y,v 1.5 2002/03/31 04:07:16 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -132,7 +132,7 @@ const char*lookup_pattern(const char*key)
|
||||
|
||||
%%
|
||||
|
||||
start: section_list
|
||||
start: section_list ;
|
||||
|
||||
section_list
|
||||
: section
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright (c) 2002 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: substit.c,v 1.4 2002/08/12 01:35:01 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <string.h>
|
||||
# include <stdlib.h>
|
||||
#ifdef HAVE_MALLOC_H
|
||||
# include <malloc.h>
|
||||
#endif
|
||||
|
||||
|
||||
char* substitutions(const char*str)
|
||||
{
|
||||
size_t nbuf = strlen(str) + 1;
|
||||
char*buf = malloc(nbuf);
|
||||
char*cp = buf;
|
||||
|
||||
while (*str) {
|
||||
|
||||
if ((str[0] == '$') && (str[1] == '(')) {
|
||||
/* If I find a $(x) string in the source, replace
|
||||
it in the destination with the contents of the
|
||||
environment variable x. */
|
||||
char*name;
|
||||
char*value;
|
||||
const char*ep = strchr(str, ')');
|
||||
str += 2;
|
||||
|
||||
name = malloc(ep-str+1);
|
||||
strncpy(name, str, ep-str);
|
||||
name[ep-str] = 0;
|
||||
|
||||
str = ep + 1;
|
||||
|
||||
value = getenv(name);
|
||||
free(name);
|
||||
if (value == 0)
|
||||
continue;
|
||||
|
||||
if (strlen(value) >= (nbuf - (cp-buf))) {
|
||||
size_t old_size = cp - buf;
|
||||
nbuf = (cp - buf) + strlen(value) + 1;
|
||||
buf = realloc(buf, nbuf);
|
||||
cp = buf + old_size;
|
||||
}
|
||||
|
||||
strcpy(cp, value);
|
||||
cp += strlen(cp);
|
||||
|
||||
} else {
|
||||
if ( (cp - buf) == nbuf ) {
|
||||
size_t old_size = nbuf;
|
||||
nbuf = old_size + 32;
|
||||
buf = realloc(buf, nbuf);
|
||||
cp = buf + old_size;
|
||||
}
|
||||
|
||||
*cp++ = *str++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add the trailing nul to the string, and reallocate the
|
||||
buffer to be a tight fit. */
|
||||
if ( (cp - buf) == nbuf ) {
|
||||
size_t old_size = nbuf;
|
||||
nbuf = old_size + 1;
|
||||
buf = realloc(buf, nbuf);
|
||||
buf[old_size] = 0;
|
||||
} else {
|
||||
*cp++ = 0;
|
||||
nbuf = cp - buf;
|
||||
buf = realloc(buf, nbuf);
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* $Log: substit.c,v $
|
||||
* Revision 1.4 2002/08/12 01:35:01 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.3 2002/08/11 23:47:04 steve
|
||||
* Add missing Log and Ident strings.
|
||||
*
|
||||
* Revision 1.2 2002/06/25 01:33:01 steve
|
||||
* include malloc.h only when available.
|
||||
*
|
||||
* Revision 1.1 2002/06/23 20:10:51 steve
|
||||
* Variable substitution in command files.
|
||||
*
|
||||
*/
|
||||
|
||||
+16
-2
@@ -16,8 +16,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: dup_expr.cc,v 1.6 2001/11/19 01:54:14 steve Exp $"
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: dup_expr.cc,v 1.8 2002/08/12 01:34:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -31,6 +31,12 @@ NetEScope* NetEScope::dup_expr() const
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetESelect* NetESelect::dup_expr() const
|
||||
{
|
||||
return new NetESelect(expr_->dup_expr(), base_->dup_expr(),
|
||||
expr_width());
|
||||
}
|
||||
|
||||
NetESFunc* NetESFunc::dup_expr() const
|
||||
{
|
||||
NetESFunc*tmp = new NetESFunc(name_, expr_width(), nparms());
|
||||
@@ -68,6 +74,14 @@ NetEUnary* NetEUnary::dup_expr() const
|
||||
|
||||
/*
|
||||
* $Log: dup_expr.cc,v $
|
||||
* Revision 1.8 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.7 2002/01/28 00:52:41 steve
|
||||
* Add support for bit select of parameters.
|
||||
* This leads to a NetESelect node and the
|
||||
* vvp code generator to support that.
|
||||
*
|
||||
* Revision 1.6 2001/11/19 01:54:14 steve
|
||||
* Port close cropping behavior from mcrgb
|
||||
* Move window array reset to libmc.
|
||||
|
||||
+5
-2
@@ -16,8 +16,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: elab_anet.cc,v 1.4 2001/12/03 04:47:14 steve Exp $"
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elab_anet.cc,v 1.5 2002/08/12 01:34:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -149,6 +149,9 @@ NetNet* PEIdent::elaborate_anet(Design*des, NetScope*scope) const
|
||||
|
||||
/*
|
||||
* $Log: elab_anet.cc,v $
|
||||
* Revision 1.5 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.4 2001/12/03 04:47:14 steve
|
||||
* Parser and pform use hierarchical names as hname_t
|
||||
* objects instead of encoded strings.
|
||||
|
||||
+339
-76
@@ -16,8 +16,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: elab_expr.cc,v 1.46 2001/12/03 04:47:14 steve Exp $"
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elab_expr.cc,v 1.66 2002/09/21 21:28:18 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -28,7 +28,7 @@
|
||||
# include "netmisc.h"
|
||||
# include "util.h"
|
||||
|
||||
NetExpr* PExpr::elaborate_expr(Design*des, NetScope*) const
|
||||
NetExpr* PExpr::elaborate_expr(Design*des, NetScope*, bool) const
|
||||
{
|
||||
cerr << get_line() << ": internal error: I do not know how to elaborate"
|
||||
<< " expression. " << endl;
|
||||
@@ -43,7 +43,7 @@ NetExpr* PExpr::elaborate_expr(Design*des, NetScope*) const
|
||||
* and right sides, and creating one of a variety of different NetExpr
|
||||
* types.
|
||||
*/
|
||||
NetEBinary* PEBinary::elaborate_expr(Design*des, NetScope*scope) const
|
||||
NetEBinary* PEBinary::elaborate_expr(Design*des, NetScope*scope, bool) const
|
||||
{
|
||||
assert(left_);
|
||||
assert(right_);
|
||||
@@ -120,7 +120,8 @@ NetEBinary* PEBinary::elaborate_expr_base_(Design*des,
|
||||
case '^':
|
||||
case '&':
|
||||
case '|':
|
||||
case 'O':
|
||||
case 'O': // NOR (~|)
|
||||
case 'A': // NAND (~&)
|
||||
case 'X':
|
||||
tmp = new NetEBBits(op_, lp, rp);
|
||||
tmp->set_line(*this);
|
||||
@@ -162,10 +163,60 @@ NetEBinary* PEBinary::elaborate_expr_base_(Design*des,
|
||||
*/
|
||||
NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope) const
|
||||
{
|
||||
|
||||
/* Catch the special case that the system function is the
|
||||
$signed function. This function is special, in that it does
|
||||
not lead to executable code but takes the single parameter
|
||||
and makes it into a signed expression. No bits are changed,
|
||||
it just changes the interpretation. */
|
||||
if (strcmp(path_.peek_name(0), "$signed") == 0) {
|
||||
if ((parms_.count() != 1) || (parms_[0] == 0)) {
|
||||
cerr << get_line() << ": error: The $signed() function "
|
||||
<< "takes exactly one(1) argument." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
PExpr*expr = parms_[0];
|
||||
NetExpr*sub = expr->elaborate_expr(des, scope, true);
|
||||
sub->cast_signed(true);
|
||||
return sub;
|
||||
}
|
||||
|
||||
/* Interpret the internal $sizeof system function to return
|
||||
the bit width of the sub-expression. The value of the
|
||||
sub-expression is not used, so the expression itself can be
|
||||
deleted. */
|
||||
if ((strcmp(path_.peek_name(0), "$sizeof") == 0)
|
||||
|| (strcmp(path_.peek_name(0), "$bits") == 0)) {
|
||||
if ((parms_.count() != 1) || (parms_[0] == 0)) {
|
||||
cerr << get_line() << ": error: The $bits() function "
|
||||
<< "takes exactly one(1) argument." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strcmp(path_.peek_name(0), "$sizeof") == 0)
|
||||
cerr << get_line() << ": warning: $sizeof is deprecated."
|
||||
<< " Use $bits() instead." << endl;
|
||||
|
||||
PExpr*expr = parms_[0];
|
||||
NetExpr*sub = expr->elaborate_expr(des, scope, true);
|
||||
verinum val (sub->expr_width(), 8*sizeof(unsigned));
|
||||
delete sub;
|
||||
|
||||
sub = new NetEConst(val);
|
||||
sub->set_line(*this);
|
||||
|
||||
return sub;
|
||||
}
|
||||
|
||||
unsigned wid = 32;
|
||||
|
||||
if (strcmp(path_.peek_name(0), "$time") == 0)
|
||||
wid = 64;
|
||||
if (strcmp(path_.peek_name(0), "$stime") == 0)
|
||||
wid = 32;
|
||||
|
||||
|
||||
/* How many parameters are there? The Verilog language allows
|
||||
@@ -193,7 +244,7 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope) const
|
||||
for (unsigned idx = 0 ; idx < nparms ; idx += 1) {
|
||||
PExpr*expr = parms_[idx];
|
||||
if (expr) {
|
||||
NetExpr*tmp1 = expr->elaborate_expr(des, scope);
|
||||
NetExpr*tmp1 = expr->elaborate_expr(des, scope, true);
|
||||
if (NetExpr*tmp2 = tmp1->eval_tree()) {
|
||||
delete tmp1;
|
||||
fun->parm(idx, tmp2);
|
||||
@@ -219,7 +270,7 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope) const
|
||||
return fun;
|
||||
}
|
||||
|
||||
NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope) const
|
||||
NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope, bool) const
|
||||
{
|
||||
if (path_.peek_name(0)[0] == '$')
|
||||
return elaborate_sfunc_(des, scope);
|
||||
@@ -236,30 +287,14 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope) const
|
||||
NetScope*dscope = def->scope();
|
||||
assert(dscope);
|
||||
|
||||
/* How many parameters have I got? Normally the size of the
|
||||
list is correct, but there is the special case of a list of
|
||||
1 nil pointer. This is how the parser tells me of no
|
||||
parameter. In other words, ``func()'' is 1 nil parameter. */
|
||||
if (! check_call_matches_definition_(des, dscope))
|
||||
return 0;
|
||||
|
||||
unsigned parms_count = parms_.count();
|
||||
if ((parms_count == 1) && (parms_[0] == 0))
|
||||
parms_count = 0;
|
||||
|
||||
if (dscope->type() != NetScope::FUNC) {
|
||||
cerr << get_line() << ": error: Attempt to call scope "
|
||||
<< dscope->name() << " as a function." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((parms_count+1) != dscope->func_def()->port_count()) {
|
||||
cerr << get_line() << ": error: Function " << dscope->name()
|
||||
<< " expects " << (dscope->func_def()->port_count()-1)
|
||||
<< " parameters, you passed " << parms_count << "."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
svector<NetExpr*> parms (parms_count);
|
||||
|
||||
@@ -314,9 +349,9 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope) const
|
||||
}
|
||||
|
||||
|
||||
NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope) const
|
||||
NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope, bool) const
|
||||
{
|
||||
unsigned repeat = 1;
|
||||
NetExpr* repeat = 0;
|
||||
|
||||
/* If there is a repeat expression, then evaluate the constant
|
||||
value and set the repeat count. */
|
||||
@@ -332,20 +367,21 @@ NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope) const
|
||||
cerr << get_line() << ": : The expression is: "
|
||||
<< *tmp << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
repeat = rep->value().as_ulong();
|
||||
repeat = rep;
|
||||
}
|
||||
|
||||
/* Make the empty concat expression. */
|
||||
NetEConcat*tmp = new NetEConcat(parms_.count(), repeat);
|
||||
tmp->set_line(*this);
|
||||
|
||||
unsigned wid_sum = 0;
|
||||
|
||||
/* Elaborate all the parameters and attach them to the concat node. */
|
||||
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
|
||||
assert(parms_[idx]);
|
||||
NetExpr*ex = parms_[idx]->elaborate_expr(des, scope);
|
||||
NetExpr*ex = elab_and_eval(des, scope, parms_[idx]);
|
||||
if (ex == 0) continue;
|
||||
|
||||
ex->set_line(*parms_[idx]);
|
||||
@@ -357,22 +393,35 @@ NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope) const
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
wid_sum += ex->expr_width();
|
||||
tmp->set(idx, ex);
|
||||
}
|
||||
|
||||
tmp->set_width(wid_sum * tmp->repeat());
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetExpr* PEFNumber::elaborate_expr(Design*des, NetScope*scope) const
|
||||
NetExpr* PEFNumber::elaborate_expr(Design*des, NetScope*scope, bool) const
|
||||
{
|
||||
long val = value_->as_long();
|
||||
return new NetEConst(verinum(val));
|
||||
}
|
||||
|
||||
NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope) const
|
||||
/*
|
||||
* Elaborate an identifier in an expression. The identifier can be a
|
||||
* parameter name, a signal name or a memory name. It can also be a
|
||||
* scope name (Return a NetEScope) but only certain callers can use
|
||||
* scope names. However, we still support it here.
|
||||
*
|
||||
* Function names are not handled here, they are detected by the
|
||||
* parser and are elaborated by PECallFunction.
|
||||
*
|
||||
* The signal name may be escaped, but that affects nothing here.
|
||||
*/
|
||||
NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
||||
bool sys_task_arg) const
|
||||
{
|
||||
assert(path_.peek_name(0)[0] != '$');
|
||||
|
||||
assert(scope);
|
||||
|
||||
// If the identifier name is a parameter name, then return
|
||||
@@ -384,6 +433,120 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope) const
|
||||
else
|
||||
tmp = new NetEParam(des, scope, path_);
|
||||
|
||||
if (msb_ && lsb_) {
|
||||
/* If the parameter has a part select, we support
|
||||
it by pulling the right bits out and making a
|
||||
sized unsigned constant. This code assumes the
|
||||
lsb of a parameter is 0 and the msb is the
|
||||
width of the parameter. */
|
||||
|
||||
verinum*lsn = lsb_->eval_const(des, scope);
|
||||
verinum*msn = msb_->eval_const(des, scope);
|
||||
if ((lsn == 0) || (msn == 0)) {
|
||||
cerr << get_line() << ": error: "
|
||||
"Part select expresions must be "
|
||||
"constant expressions." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
long lsb = lsn->as_long();
|
||||
long msb = msn->as_long();
|
||||
if ((lsb < 0) || (msb < lsb)) {
|
||||
cerr << get_line() << ": error: invalid part "
|
||||
<< "select: " << path_
|
||||
<< "["<<msb<<":"<<lsb<<"]" << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetEConst*le = dynamic_cast<NetEConst*>(tmp);
|
||||
assert(le);
|
||||
|
||||
verinum result (verinum::V0, msb-lsb+1, true);
|
||||
verinum exl = le->value();
|
||||
|
||||
/* Pull the bits from the parameter, one at a
|
||||
time. If the bit is within the range, simply
|
||||
copy it to the result. If the bit is outside
|
||||
the range, we sign extend signed unsized
|
||||
numbers, zero extend unsigned unsigned numbers,
|
||||
and X extend sized numbers. */
|
||||
for (long idx = lsb ; idx <= msb ; idx += 1) {
|
||||
if (idx < exl.len())
|
||||
result.set(idx-lsb, exl.get(idx));
|
||||
else if (exl.is_string())
|
||||
result.set(idx-lsb, verinum::V0);
|
||||
else if (exl.has_len())
|
||||
result.set(idx-lsb, verinum::Vx);
|
||||
else if (exl.has_sign())
|
||||
result.set(idx-lsb, exl.get(exl.len()-1));
|
||||
else
|
||||
result.set(idx-lsb, verinum::V0);
|
||||
}
|
||||
|
||||
/* If the input is a string, and the part select
|
||||
is working on byte boundaries, then the result
|
||||
can be made into a string. */
|
||||
if (exl.is_string()
|
||||
&& (lsb%8 == 0)
|
||||
&& (result.len()%8 == 0))
|
||||
result = verinum(result.as_string());
|
||||
|
||||
delete tmp;
|
||||
tmp = new NetEConst(result);
|
||||
|
||||
} else if (msb_) {
|
||||
/* Handle the case where a parameter has a bit
|
||||
select attached to it. Generate a NetESelect
|
||||
object to select the bit as desired. */
|
||||
NetExpr*mtmp = msb_->elaborate_expr(des, scope);
|
||||
if (! dynamic_cast<NetEConst*>(mtmp)) {
|
||||
NetExpr*re = mtmp->eval_tree();
|
||||
if (re) {
|
||||
delete mtmp;
|
||||
mtmp = re;
|
||||
}
|
||||
}
|
||||
|
||||
/* Let's first try to get constant values for both
|
||||
the parameter and the bit select. If they are
|
||||
both constant, then evaluate the bit select and
|
||||
return instead a single-bit constant. */
|
||||
|
||||
NetEConst*le = dynamic_cast<NetEConst*>(tmp);
|
||||
NetEConst*re = dynamic_cast<NetEConst*>(mtmp);
|
||||
if (le && re) {
|
||||
|
||||
verinum lv = le->value();
|
||||
verinum rv = re->value();
|
||||
verinum::V rb = verinum::Vx;
|
||||
|
||||
long ridx = rv.as_long();
|
||||
if ((ridx >= 0) && (ridx < lv.len())) {
|
||||
rb = lv[ridx];
|
||||
|
||||
} else if ((ridx >= 0) && (!lv.has_len())) {
|
||||
if (lv.has_sign())
|
||||
rb = lv[lv.len()-1];
|
||||
else
|
||||
rb = verinum::V0;
|
||||
}
|
||||
|
||||
NetEConst*re = new NetEConst(verinum(rb, 1));
|
||||
delete tmp;
|
||||
delete mtmp;
|
||||
tmp = re;
|
||||
|
||||
} else {
|
||||
|
||||
NetESelect*stmp = new NetESelect(tmp, mtmp, 1);
|
||||
tmp->set_line(*this);
|
||||
tmp = stmp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
@@ -470,11 +633,21 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope) const
|
||||
unsigned idx = net->sb_to_idx(msv);
|
||||
|
||||
if (idx >= net->pin_count()) {
|
||||
cerr << get_line() << ": internal error: "
|
||||
<< "bit " << msv << " out of range of net "
|
||||
/* The bit select is out of range of the
|
||||
vector. This is legal, but returns a
|
||||
constant 1'bx value. */
|
||||
verinum x (verinum::Vx);
|
||||
NetEConst*tmp = new NetEConst(x);
|
||||
tmp->set_line(*this);
|
||||
|
||||
cerr << get_line() << ": warning: Bit select ["
|
||||
<< msv << "] out of range of vector "
|
||||
<< net->name() << "[" << net->msb()
|
||||
<< ":" << net->lsb() << "]." << endl;
|
||||
return 0;
|
||||
cerr << get_line() << ": : Replacing "
|
||||
<< "expression with a constant 1'bx." << endl;
|
||||
delete msn;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetESignal*tmp = new NetESignal(net, idx, idx);
|
||||
@@ -506,10 +679,23 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope) const
|
||||
// object to handle it.
|
||||
if (NetMemory*mem = des->find_memory(scope, path_)) {
|
||||
if (msb_ == 0) {
|
||||
NetEMemory*node = new NetEMemory(mem);
|
||||
node->set_line(*this);
|
||||
return node;
|
||||
|
||||
// If this memory is an argument to a system task,
|
||||
// then it is OK for it to not have an index.
|
||||
if (sys_task_arg) {
|
||||
NetEMemory*node = new NetEMemory(mem);
|
||||
node->set_line(*this);
|
||||
return node;
|
||||
}
|
||||
|
||||
// If it is not a simple system task argument,
|
||||
// this a missing index is an error.
|
||||
cerr << get_line() << ": error: memory " << mem->name()
|
||||
<< " needs an index in this context." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(msb_ != 0);
|
||||
if (lsb_) {
|
||||
cerr << get_line() << ": error: part select of a memory: "
|
||||
@@ -522,7 +708,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope) const
|
||||
assert(idx_ == 0);
|
||||
NetExpr*i = msb_->elaborate_expr(des, scope);
|
||||
if (msb_ && i == 0) {
|
||||
cerr << get_line() << ": error: Unable to exaborate "
|
||||
cerr << get_line() << ": error: Unable to elaborate "
|
||||
"index expression `" << *msb_ << "'" << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
@@ -559,7 +745,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetEConst* PENumber::elaborate_expr(Design*des, NetScope*) const
|
||||
NetEConst* PENumber::elaborate_expr(Design*des, NetScope*, bool) const
|
||||
{
|
||||
assert(value_);
|
||||
NetEConst*tmp = new NetEConst(*value_);
|
||||
@@ -567,7 +753,7 @@ NetEConst* PENumber::elaborate_expr(Design*des, NetScope*) const
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetEConst* PEString::elaborate_expr(Design*des, NetScope*) const
|
||||
NetEConst* PEString::elaborate_expr(Design*des, NetScope*, bool) const
|
||||
{
|
||||
NetEConst*tmp = new NetEConst(value());
|
||||
tmp->set_line(*this);
|
||||
@@ -579,7 +765,7 @@ NetEConst* PEString::elaborate_expr(Design*des, NetScope*) const
|
||||
* parsed so I can presume that they exist, and call elaboration
|
||||
* methods. If any elaboration fails, then give up and return 0.
|
||||
*/
|
||||
NetETernary*PETernary::elaborate_expr(Design*des, NetScope*scope) const
|
||||
NetETernary*PETernary::elaborate_expr(Design*des, NetScope*scope, bool) const
|
||||
{
|
||||
assert(expr_);
|
||||
assert(tru_);
|
||||
@@ -606,7 +792,7 @@ NetETernary*PETernary::elaborate_expr(Design*des, NetScope*scope) const
|
||||
return res;
|
||||
}
|
||||
|
||||
NetEUnary* PEUnary::elaborate_expr(Design*des, NetScope*scope) const
|
||||
NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope, bool) const
|
||||
{
|
||||
NetExpr*ip = expr_->elaborate_expr(des, scope);
|
||||
if (ip == 0) return 0;
|
||||
@@ -615,13 +801,69 @@ NetEUnary* PEUnary::elaborate_expr(Design*des, NetScope*scope) const
|
||||
* just like in PEBinary::elaborate_expr() ?
|
||||
*/
|
||||
|
||||
NetEUnary*tmp;
|
||||
NetExpr*tmp;
|
||||
switch (op_) {
|
||||
default:
|
||||
tmp = new NetEUnary(op_, ip);
|
||||
tmp->set_line(*this);
|
||||
break;
|
||||
|
||||
case '-':
|
||||
if (NetEConst*ipc = dynamic_cast<NetEConst*>(ip)) {
|
||||
verinum val = ipc->value();
|
||||
verinum zero (verinum::V0, val.len(), val.has_len());
|
||||
val = zero - val;
|
||||
val.has_sign(ipc->has_sign());
|
||||
tmp = new NetEConst(val);
|
||||
delete ip;
|
||||
} else {
|
||||
tmp = new NetEUnary(op_, ip);
|
||||
tmp->set_line(*this);
|
||||
}
|
||||
break;
|
||||
|
||||
case '+':
|
||||
tmp = ip;
|
||||
break;
|
||||
|
||||
case '!': // Logical NOT
|
||||
/* If the operand to unary ! is a constant, then I can
|
||||
evaluate this expression here and return a logical
|
||||
constant in its place. */
|
||||
if (NetEConst*ipc = dynamic_cast<NetEConst*>(ip)) {
|
||||
verinum val = ipc->value();
|
||||
unsigned v1 = 0;
|
||||
unsigned vx = 0;
|
||||
for (unsigned idx = 0 ; idx < val.len() ; idx += 1)
|
||||
switch (val[idx]) {
|
||||
case verinum::V0:
|
||||
break;
|
||||
case verinum::V1:
|
||||
v1 += 1;
|
||||
break;
|
||||
default:
|
||||
vx += 1;
|
||||
break;
|
||||
}
|
||||
|
||||
verinum::V res;
|
||||
if (v1 > 0)
|
||||
res = verinum::V0;
|
||||
else if (vx > 0)
|
||||
res = verinum::Vx;
|
||||
else
|
||||
res = verinum::V1;
|
||||
|
||||
verinum vres (res, 1, true);
|
||||
tmp = new NetEConst(vres);
|
||||
tmp->set_line(*this);
|
||||
delete ip;
|
||||
} else {
|
||||
tmp = new NetEUReduce(op_, ip);
|
||||
tmp->set_line(*this);
|
||||
}
|
||||
break;
|
||||
|
||||
case '&': // Reduction AND
|
||||
case '|': // Reduction OR
|
||||
case '^': // Reduction XOR
|
||||
@@ -631,6 +873,7 @@ NetEUnary* PEUnary::elaborate_expr(Design*des, NetScope*scope) const
|
||||
tmp = new NetEUReduce(op_, ip);
|
||||
tmp->set_line(*this);
|
||||
break;
|
||||
|
||||
case '~':
|
||||
tmp = new NetEUBits(op_, ip);
|
||||
tmp->set_line(*this);
|
||||
@@ -642,44 +885,64 @@ NetEUnary* PEUnary::elaborate_expr(Design*des, NetScope*scope) const
|
||||
|
||||
/*
|
||||
* $Log: elab_expr.cc,v $
|
||||
* Revision 1.46 2001/12/03 04:47:14 steve
|
||||
* Parser and pform use hierarchical names as hname_t
|
||||
* objects instead of encoded strings.
|
||||
* Revision 1.66 2002/09/21 21:28:18 steve
|
||||
* Allow constant bit selects out of range.
|
||||
*
|
||||
* Revision 1.45 2001/11/19 02:54:12 steve
|
||||
* Handle division and modulus by zero while
|
||||
* evaluating run-time constants.
|
||||
* Revision 1.65 2002/09/18 04:08:45 steve
|
||||
* Spelling errors.
|
||||
*
|
||||
* Revision 1.44 2001/11/19 01:54:14 steve
|
||||
* Port close cropping behavior from mcrgb
|
||||
* Move window array reset to libmc.
|
||||
* Revision 1.64 2002/09/12 15:49:43 steve
|
||||
* Add support for binary nand operator.
|
||||
*
|
||||
* Revision 1.43 2001/11/07 04:01:59 steve
|
||||
* eval_const uses scope instead of a string path.
|
||||
* Revision 1.63 2002/08/19 02:39:16 steve
|
||||
* Support parameters with defined ranges.
|
||||
*
|
||||
* Revision 1.42 2001/07/29 22:22:40 steve
|
||||
* support local reference to scope in expressions.
|
||||
* Revision 1.62 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.41 2001/07/27 04:51:44 steve
|
||||
* Handle part select expressions as variants of
|
||||
* NetESignal/IVL_EX_SIGNAL objects, instead of
|
||||
* creating new and useless temporary signals.
|
||||
* Revision 1.61 2002/06/14 21:38:41 steve
|
||||
* Fix expression width for repeat concatenations.
|
||||
*
|
||||
* Revision 1.40 2001/07/25 03:10:48 steve
|
||||
* Create a config.h.in file to hold all the config
|
||||
* junk, and support gcc 3.0. (Stephan Boettcher)
|
||||
* Revision 1.60 2002/05/24 00:44:54 steve
|
||||
* Add support for $bits (SystemVerilog)
|
||||
*
|
||||
* Revision 1.39 2001/06/30 21:28:35 steve
|
||||
* Detect parameter mismatches.
|
||||
* Revision 1.59 2002/05/06 02:30:27 steve
|
||||
* Allow parameters in concatenation of widths are defined.
|
||||
*
|
||||
* Revision 1.38 2001/06/23 19:53:03 steve
|
||||
* Look up functor return register with tail of name.
|
||||
* Revision 1.58 2002/05/05 21:11:49 steve
|
||||
* Put off evaluation of concatenation repeat expresions
|
||||
* until after parameters are defined. This allows parms
|
||||
* to be used in repeat expresions.
|
||||
*
|
||||
* Revision 1.37 2001/04/06 02:28:02 steve
|
||||
* Generate vvp code for functions with ports.
|
||||
* Add the builtin $signed system function.
|
||||
*
|
||||
* Revision 1.36 2001/02/10 20:29:39 steve
|
||||
* In the context of range declarations, use elab_and_eval instead
|
||||
* of the less robust eval_const methods.
|
||||
* Revision 1.57 2002/04/27 05:03:46 steve
|
||||
* Preserve stringiness string part select and concatenation.
|
||||
*
|
||||
* Revision 1.56 2002/04/27 02:38:04 steve
|
||||
* Support selecting bits from parameters.
|
||||
*
|
||||
* Revision 1.55 2002/04/25 05:04:31 steve
|
||||
* Evaluate constant bit select of constants.
|
||||
*
|
||||
* Revision 1.54 2002/04/14 21:16:48 steve
|
||||
* Evaluate logical not at elaboration time.
|
||||
*
|
||||
* Revision 1.53 2002/04/14 03:55:25 steve
|
||||
* Precalculate unary - if possible.
|
||||
*
|
||||
* Revision 1.52 2002/04/13 02:33:17 steve
|
||||
* Detect missing indices to memories (PR#421)
|
||||
*
|
||||
* Revision 1.51 2002/03/09 02:10:22 steve
|
||||
* Add the NetUserFunc netlist node.
|
||||
*
|
||||
* Revision 1.50 2002/01/28 00:52:41 steve
|
||||
* Add support for bit select of parameters.
|
||||
* This leads to a NetESelect node and the
|
||||
* vvp code generator to support that.
|
||||
*
|
||||
* Revision 1.49 2002/01/11 05:25:45 steve
|
||||
* The stime system function is 32bits.
|
||||
*/
|
||||
|
||||
|
||||
+44
-11
@@ -16,8 +16,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: elab_lval.cc,v 1.17 2001/12/03 04:47:14 steve Exp $"
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elab_lval.cc,v 1.20 2002/08/12 01:34:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -67,7 +67,7 @@
|
||||
*/
|
||||
NetAssign_* PExpr::elaborate_lval(Design*des, NetScope*scope) const
|
||||
{
|
||||
NetNet*ll = elaborate_net(des, scope, 0, 0, 0, 0);
|
||||
NetNet*ll = 0;
|
||||
if (ll == 0) {
|
||||
cerr << get_line() << ": Assignment l-value too complex."
|
||||
<< endl;
|
||||
@@ -139,14 +139,13 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope) const
|
||||
|
||||
if (reg == 0) {
|
||||
NetMemory*mem = des->find_memory(scope, path_);
|
||||
if (mem != 0) {
|
||||
cerr << get_line() << ": sorry: I cannot handle "
|
||||
<< "memories in this l-value context." << endl;
|
||||
} else {
|
||||
cerr << get_line() << ": error: Could not find variable ``"
|
||||
<< path_ << "'' in ``" << scope->name() <<
|
||||
"''" << endl;
|
||||
}
|
||||
if (mem != 0)
|
||||
return elaborate_mem_lval_(des, scope, mem);
|
||||
|
||||
cerr << get_line() << ": error: Could not find variable ``"
|
||||
<< path_ << "'' in ``" << scope->name() <<
|
||||
"''" << endl;
|
||||
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
@@ -275,8 +274,42 @@ NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope) const
|
||||
return lv;
|
||||
}
|
||||
|
||||
NetAssign_* PEIdent::elaborate_mem_lval_(Design*des, NetScope*scope,
|
||||
NetMemory*mem) const
|
||||
{
|
||||
assert(msb_ && !lsb_);
|
||||
|
||||
NetExpr*ix = msb_->elaborate_expr(des, scope);
|
||||
if (ix == 0)
|
||||
return 0;
|
||||
|
||||
NetAssign_*lv = new NetAssign_(mem);
|
||||
lv->set_bmux(ix);
|
||||
lv->set_part(0, mem->width());
|
||||
return lv;
|
||||
}
|
||||
|
||||
NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*) const
|
||||
{
|
||||
cerr << get_line() << ": error: Constant values not allowed "
|
||||
<< "in l-value expressions." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: elab_lval.cc,v $
|
||||
* Revision 1.20 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.19 2002/06/04 05:38:44 steve
|
||||
* Add support for memory words in l-value of
|
||||
* blocking assignments, and remove the special
|
||||
* NetAssignMem class.
|
||||
*
|
||||
* Revision 1.18 2002/03/09 04:02:26 steve
|
||||
* Constant expressions are not l-values for task ports.
|
||||
*
|
||||
* Revision 1.17 2001/12/03 04:47:14 steve
|
||||
* Parser and pform use hierarchical names as hname_t
|
||||
* objects instead of encoded strings.
|
||||
|
||||
+452
-96
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2000 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2002 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -16,8 +16,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: elab_net.cc,v 1.82 2001/12/03 04:47:14 steve Exp $"
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elab_net.cc,v 1.101 2002/09/18 04:29:55 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -29,6 +29,18 @@
|
||||
|
||||
# include <iostream>
|
||||
|
||||
NetNet* PExpr::elaborate_net(Design*des, NetScope*scope, unsigned,
|
||||
unsigned long,
|
||||
unsigned long,
|
||||
unsigned long,
|
||||
Link::strength_t,
|
||||
Link::strength_t) const
|
||||
{
|
||||
cerr << get_line() << ": error: Unable to elaborate `"
|
||||
<< *this << "' as gates." << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Elaborating binary operations generally involves elaborating the
|
||||
* left and right expressions, then making an output wire and
|
||||
@@ -55,6 +67,8 @@ NetNet* PEBinary::elaborate_net(Design*des, NetScope*scope,
|
||||
case '|': // Bitwise OR
|
||||
case '&':
|
||||
case '^':
|
||||
case 'A': // Bitwise NAND (~&)
|
||||
case 'O': // Bitwise NOR (~|)
|
||||
case 'X': // Exclusing NOR
|
||||
return elaborate_net_bit_(des, scope, width, rise, fall, decay);
|
||||
case 'E': // === (case equals)
|
||||
@@ -126,9 +140,9 @@ NetNet* PEBinary::elaborate_net(Design*des, NetScope*scope,
|
||||
osig = 0;
|
||||
}
|
||||
|
||||
if (NetTmp*tmp = dynamic_cast<NetTmp*>(lsig))
|
||||
if (NetSubnet*tmp = dynamic_cast<NetSubnet*>(lsig))
|
||||
delete tmp;
|
||||
if (NetTmp*tmp = dynamic_cast<NetTmp*>(rsig))
|
||||
if (NetSubnet*tmp = dynamic_cast<NetSubnet*>(rsig))
|
||||
delete tmp;
|
||||
|
||||
return osig;
|
||||
@@ -228,10 +242,10 @@ NetNet* PEBinary::elaborate_net_add_(Design*des, NetScope*scope,
|
||||
|
||||
switch (op_) {
|
||||
case '+':
|
||||
gate->attribute("LPM_Direction", "ADD");
|
||||
gate->attribute("LPM_Direction", verinum("ADD"));
|
||||
break;
|
||||
case '-':
|
||||
gate->attribute("LPM_Direction", "SUB");
|
||||
gate->attribute("LPM_Direction", verinum("SUB"));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -328,6 +342,20 @@ NetNet* PEBinary::elaborate_net_bit_(Design*des, NetScope*scope,
|
||||
}
|
||||
break;
|
||||
|
||||
case 'A': // NAND (~&)
|
||||
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) {
|
||||
NetLogic*gate = new NetLogic(scope, scope->local_hsymbol(),
|
||||
3, NetLogic::NAND);
|
||||
connect(gate->pin(1), lsig->pin(idx));
|
||||
connect(gate->pin(2), rsig->pin(idx));
|
||||
connect(gate->pin(0), osig->pin(idx));
|
||||
gate->rise_time(rise);
|
||||
gate->fall_time(fall);
|
||||
gate->decay_time(decay);
|
||||
des->add_node(gate);
|
||||
}
|
||||
break;
|
||||
|
||||
case '|': // Bitwise OR
|
||||
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) {
|
||||
NetLogic*gate = new NetLogic(scope, scope->local_hsymbol(),
|
||||
@@ -342,6 +370,20 @@ NetNet* PEBinary::elaborate_net_bit_(Design*des, NetScope*scope,
|
||||
}
|
||||
break;
|
||||
|
||||
case 'O': // Bitwise NOR
|
||||
for (unsigned idx = 0 ; idx < lsig->pin_count() ; idx += 1) {
|
||||
NetLogic*gate = new NetLogic(scope, scope->local_hsymbol(),
|
||||
3, NetLogic::NOR);
|
||||
connect(gate->pin(1), lsig->pin(idx));
|
||||
connect(gate->pin(2), rsig->pin(idx));
|
||||
connect(gate->pin(0), osig->pin(idx));
|
||||
gate->rise_time(rise);
|
||||
gate->fall_time(fall);
|
||||
gate->decay_time(decay);
|
||||
des->add_node(gate);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
@@ -386,6 +428,7 @@ NetNet* PEBinary::elaborate_net_cmp_(Design*des, NetScope*scope,
|
||||
verinum::V0);
|
||||
des->add_node(tmp);
|
||||
zero = new NetNet(scope, scope->local_hsymbol(), NetNet::WIRE);
|
||||
zero->local_flag(true);
|
||||
connect(tmp->pin(0), zero->pin(0));
|
||||
}
|
||||
|
||||
@@ -642,9 +685,12 @@ NetNet* PEBinary::elaborate_net_mod_(Design*des, NetScope*scope,
|
||||
NetNet*rsig = right_->elaborate_net(des, scope, 0, 0, 0, 0);
|
||||
if (rsig == 0) return 0;
|
||||
|
||||
unsigned rwidth = lsig->pin_count();
|
||||
if (rsig->pin_count() > rwidth)
|
||||
rwidth = rsig->pin_count();
|
||||
unsigned rwidth = lwidth;
|
||||
if (rwidth == 0) {
|
||||
rwidth = lsig->pin_count();
|
||||
if (rsig->pin_count() > rwidth)
|
||||
rwidth = rsig->pin_count();
|
||||
}
|
||||
NetModulo*mod = new NetModulo(scope, scope->local_hsymbol(), rwidth,
|
||||
lsig->pin_count(),
|
||||
rsig->pin_count());
|
||||
@@ -729,7 +775,9 @@ NetNet* PEBinary::elaborate_net_log_(Design*des, NetScope*scope,
|
||||
|
||||
/* The reduced logical value is a new nexus, create a
|
||||
temporary signal to represent it. */
|
||||
NetNet*tmp = new NetTmp(scope, scope->local_hsymbol());
|
||||
NetNet*tmp = new NetNet(scope, scope->local_hsymbol(),
|
||||
NetNet::IMPLICIT, 1);
|
||||
tmp->local_flag(true);
|
||||
connect(gate->pin(1), tmp->pin(0));
|
||||
|
||||
des->add_node(gate_t);
|
||||
@@ -748,7 +796,9 @@ NetNet* PEBinary::elaborate_net_log_(Design*des, NetScope*scope,
|
||||
|
||||
/* The reduced logical value is a new nexus, create a
|
||||
temporary signal to represent it. */
|
||||
NetNet*tmp = new NetTmp(scope, scope->local_hsymbol());
|
||||
NetNet*tmp = new NetNet(scope, scope->local_hsymbol(),
|
||||
NetNet::IMPLICIT, 1);
|
||||
tmp->local_flag(true);
|
||||
connect(gate->pin(2), tmp->pin(0));
|
||||
|
||||
des->add_node(gate_t);
|
||||
@@ -771,12 +821,45 @@ NetNet* PEBinary::elaborate_net_mul_(Design*des, NetScope*scope,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const
|
||||
{
|
||||
verinum*lnum = left_->eval_const(des, scope);
|
||||
verinum*rnum = right_->eval_const(des, scope);
|
||||
|
||||
/* Detect and handle the special case that both the operands
|
||||
of the multiply are constant expressions. Evalulate the
|
||||
value and make this a simple constant. */
|
||||
if (lnum && rnum) {
|
||||
verinum prod = *lnum * *rnum;
|
||||
if (lwidth == 0)
|
||||
lwidth = prod.len();
|
||||
|
||||
verinum res (verinum::V0, lwidth);
|
||||
for (unsigned idx = 0
|
||||
; idx < prod.len() && idx < lwidth
|
||||
; idx += 1) {
|
||||
res.set(idx, prod.get(idx));
|
||||
}
|
||||
|
||||
NetConst*odev = new NetConst(scope, scope->local_hsymbol(), res);
|
||||
NetNet*osig = new NetNet(scope, scope->local_hsymbol(),
|
||||
NetNet::IMPLICIT, lwidth);
|
||||
for (unsigned idx = 0 ; idx < lwidth ; idx += 1)
|
||||
connect(odev->pin(idx), osig->pin(idx));
|
||||
|
||||
des->add_node(odev);
|
||||
osig->local_flag(true);
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetNet*lsig = left_->elaborate_net(des, scope, lwidth, 0, 0, 0);
|
||||
if (lsig == 0) return 0;
|
||||
NetNet*rsig = right_->elaborate_net(des, scope, lwidth, 0, 0, 0);
|
||||
if (rsig == 0) return 0;
|
||||
|
||||
unsigned rwidth = lwidth;
|
||||
if (rwidth == 0) {
|
||||
rwidth = lsig->pin_count() + rsig->pin_count();
|
||||
}
|
||||
|
||||
NetMult*mult = new NetMult(scope, scope->local_hsymbol(), rwidth,
|
||||
lsig->pin_count(),
|
||||
rsig->pin_count());
|
||||
@@ -896,7 +979,9 @@ NetNet* PEBinary::elaborate_net_shift_(Design*des, NetScope*scope,
|
||||
if (lsig->pin_count() < lwidth) {
|
||||
NetConst*zero = new NetConst(scope, scope->local_hsymbol(),
|
||||
verinum::V0);
|
||||
NetTmp*tmp = new NetTmp(scope, scope->local_hsymbol());
|
||||
NetNet*tmp = new NetNet(scope, scope->local_hsymbol(),
|
||||
NetNet::IMPLICIT, 1);
|
||||
tmp->local_flag(true);
|
||||
des->add_node(zero);
|
||||
connect(zero->pin(0), tmp->pin(0));
|
||||
for (unsigned idx = lsig->pin_count() ; idx < lwidth ; idx += 1)
|
||||
@@ -909,7 +994,9 @@ NetNet* PEBinary::elaborate_net_shift_(Design*des, NetScope*scope,
|
||||
connect(rsig->pin(idx), gate->pin_Distance(idx));
|
||||
|
||||
if (op_ == 'r') {
|
||||
NetTmp*tmp = new NetTmp(scope, scope->local_hsymbol());
|
||||
NetNet*tmp = new NetNet(scope, scope->local_hsymbol(),
|
||||
NetNet::IMPLICIT, 1);
|
||||
tmp->local_flag(true);
|
||||
NetConst*dir = new NetConst(scope, scope->local_hsymbol(),
|
||||
verinum::V1);
|
||||
connect(dir->pin(0), gate->pin_Direction());
|
||||
@@ -922,6 +1009,95 @@ NetNet* PEBinary::elaborate_net_shift_(Design*des, NetScope*scope,
|
||||
return osig;
|
||||
}
|
||||
|
||||
/*
|
||||
* This method elaborates a call to a function in the context of a
|
||||
* continuous assignment.
|
||||
*/
|
||||
NetNet* PECallFunction::elaborate_net(Design*des, NetScope*scope, unsigned,
|
||||
unsigned long,
|
||||
unsigned long,
|
||||
unsigned long,
|
||||
Link::strength_t,
|
||||
Link::strength_t) const
|
||||
{
|
||||
unsigned errors = 0;
|
||||
unsigned func_pins = 0;
|
||||
|
||||
/* Look up the function definition. */
|
||||
NetFuncDef*def = des->find_function(scope, path_);
|
||||
if (def == 0) {
|
||||
cerr << get_line() << ": error: No function " << path_ <<
|
||||
" in this context (" << scope->name() << ")." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
assert(def);
|
||||
|
||||
NetScope*dscope = def->scope();
|
||||
assert(dscope);
|
||||
|
||||
/* check the validity of the parameters. */
|
||||
if (! check_call_matches_definition_(des, dscope))
|
||||
return 0;
|
||||
|
||||
/* Elaborate all the parameters of the function call,
|
||||
and collect the resulting NetNet objects. All the
|
||||
parameters take on the size of the target port. */
|
||||
|
||||
svector<NetNet*> eparms (def->port_count()-1);
|
||||
for (unsigned idx = 0 ; idx < eparms.count() ; idx += 1) {
|
||||
const NetNet* port_reg = def->port(idx+1);
|
||||
NetNet*tmp = parms_[idx]->elaborate_net(des, scope,
|
||||
port_reg->pin_count(),
|
||||
0, 0, 0,
|
||||
Link::STRONG,
|
||||
Link::STRONG);
|
||||
if (tmp == 0) {
|
||||
cerr << get_line() << ": error: Unable to elaborate "
|
||||
<< "port " << idx << " of call to " << path_ <<
|
||||
"." << endl;
|
||||
errors += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
func_pins += tmp->pin_count();
|
||||
eparms[idx] = tmp;
|
||||
}
|
||||
|
||||
if (errors > 0)
|
||||
return 0;
|
||||
|
||||
|
||||
NetUserFunc*net = new NetUserFunc(scope,
|
||||
scope->local_hsymbol().c_str(),
|
||||
dscope);
|
||||
des->add_node(net);
|
||||
|
||||
/* Create an output signal and connect it to the output pins
|
||||
of the function net. */
|
||||
NetNet*osig = new NetNet(scope, scope->local_hsymbol(),
|
||||
NetNet::WIRE,
|
||||
def->port(0)->pin_count());
|
||||
osig->local_flag(true);
|
||||
|
||||
for (unsigned idx = 0 ; idx < osig->pin_count() ; idx += 1)
|
||||
connect(net->port_pin(0, idx), osig->pin(idx));
|
||||
|
||||
/* Connect the parameter pins to the parameter expressions. */
|
||||
for (unsigned idx = 0 ; idx < eparms.count() ; idx += 1) {
|
||||
const NetNet* port = def->port(idx+1);
|
||||
NetNet*cur = eparms[idx];
|
||||
|
||||
NetNet*tmp = pad_to_width(des, cur, port->pin_count());
|
||||
|
||||
for (unsigned pin = 0 ; pin < port->pin_count() ; pin += 1)
|
||||
connect(net->port_pin(idx+1, pin), tmp->pin(pin));
|
||||
}
|
||||
|
||||
return osig;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The concatenation operator, as a net, is a wide signal that is
|
||||
* connected to all the pins of the elaborated expression nets.
|
||||
@@ -1026,6 +1202,54 @@ NetNet* PEConcat::elaborate_net(Design*des, NetScope*scope,
|
||||
return osig;
|
||||
}
|
||||
|
||||
/*
|
||||
* This private method handles the special case that we have a
|
||||
* non-constant bit-select of an identifier. We already know that the
|
||||
* signal that is represented is "sig".
|
||||
*/
|
||||
NetNet* PEIdent::elaborate_net_bitmux_(Design*des, NetScope*scope,
|
||||
NetNet*sig,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const
|
||||
{
|
||||
/* Elaborate the selector. */
|
||||
NetNet*sel = msb_->elaborate_net(des, scope, 0, 0, 0, 0);
|
||||
|
||||
unsigned sig_width = sig->pin_count();
|
||||
NetMux*mux = new NetMux(scope, scope->local_hsymbol(), 1,
|
||||
sig_width, sel->pin_count());
|
||||
|
||||
/* Connect the signal bits to the mux. Account for the
|
||||
direction of the numbering (lsb to msb vs. msb to lsb) by
|
||||
swapping the connection order. */
|
||||
|
||||
if (sig->msb() > sig->lsb()) {
|
||||
|
||||
sel = add_to_net(des, sel, -sig->lsb());
|
||||
for (unsigned idx = 0 ; idx < sig_width ; idx += 1)
|
||||
connect(mux->pin_Data(0, idx), sig->pin(idx));
|
||||
} else {
|
||||
|
||||
sel = add_to_net(des, sel, -sig->msb());
|
||||
for (unsigned idx = 0 ; idx < sig_width ; idx += 1)
|
||||
connect(mux->pin_Data(0, idx), sig->pin(sig_width-idx-1));
|
||||
}
|
||||
|
||||
for (unsigned idx = 0 ; idx < sel->pin_count() ; idx += 1)
|
||||
connect(mux->pin_Sel(idx), sel->pin(idx));
|
||||
|
||||
NetNet*out = new NetNet(scope, scope->local_hsymbol(),
|
||||
NetNet::IMPLICIT, 1);
|
||||
connect(mux->pin_Result(0), out->pin(0));
|
||||
|
||||
des->add_node(mux);
|
||||
out->local_flag(true);
|
||||
return out;
|
||||
}
|
||||
|
||||
NetNet* PEIdent::elaborate_net(Design*des, NetScope*scope,
|
||||
unsigned lwidth,
|
||||
unsigned long rise,
|
||||
@@ -1063,10 +1287,17 @@ NetNet* PEIdent::elaborate_net(Design*des, NetScope*scope,
|
||||
sig = new NetNet(scope, scope->name()+"."+path_.peek_name(0),
|
||||
NetNet::IMPLICIT, 1);
|
||||
|
||||
if (warn_implicit)
|
||||
if (error_implicit) {
|
||||
cerr << get_line() << ": error: "
|
||||
<< scope->name() << "." << path_.peek_name(0)
|
||||
<< " not defined in this scope." << endl;
|
||||
des->errors += 1;
|
||||
|
||||
} else if (warn_implicit) {
|
||||
cerr << get_line() << ": warning: implicit "
|
||||
"definition of wire " << scope->name()
|
||||
<< "." << path_ << "." << endl;
|
||||
<< "." << path_.peek_name(0) << "." << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1119,15 +1350,13 @@ NetNet* PEIdent::elaborate_net(Design*des, NetScope*scope,
|
||||
lidx = tmp;
|
||||
}
|
||||
|
||||
NetNet*tmp = new NetNet(scope, scope->local_hsymbol(),
|
||||
sig->type(), midx-lidx+1);
|
||||
tmp->local_flag(true);
|
||||
unsigned part_count = midx-lidx+1;
|
||||
|
||||
/* Check that the bit or part select of the signal is
|
||||
within the range of the part. The lidx is the
|
||||
normalized index of the LSB, so that plus the desired
|
||||
width must be <= the width of the references signal. */
|
||||
if ((lidx + tmp->pin_count()) > sig->pin_count()) {
|
||||
if ((lidx + part_count) > sig->pin_count()) {
|
||||
cerr << get_line() << ": error: bit/part select ["
|
||||
<< mval->as_long() << ":" << lval->as_long()
|
||||
<< "] out of range for " << sig->name() << endl;
|
||||
@@ -1135,8 +1364,7 @@ NetNet* PEIdent::elaborate_net(Design*des, NetScope*scope,
|
||||
return sig;
|
||||
}
|
||||
|
||||
for (unsigned idx = lidx ; idx <= midx ; idx += 1)
|
||||
connect(tmp->pin(idx-lidx), sig->pin(idx));
|
||||
NetSubnet*tmp = new NetSubnet(sig, lidx, part_count);
|
||||
|
||||
sig = tmp;
|
||||
|
||||
@@ -1144,12 +1372,10 @@ NetNet* PEIdent::elaborate_net(Design*des, NetScope*scope,
|
||||
} else if (msb_) {
|
||||
verinum*mval = msb_->eval_const(des, scope);
|
||||
if (mval == 0) {
|
||||
cerr << get_line() << ": error: index of " << path_ <<
|
||||
" needs to be constant in this context." <<
|
||||
endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
return elaborate_net_bitmux_(des, scope, sig, rise,
|
||||
fall, decay, drive0, drive1);
|
||||
}
|
||||
|
||||
assert(mval);
|
||||
unsigned idx = sig->sb_to_idx(mval->as_long());
|
||||
if (idx >= sig->pin_count()) {
|
||||
@@ -1159,14 +1385,7 @@ NetNet* PEIdent::elaborate_net(Design*des, NetScope*scope,
|
||||
idx = 0;
|
||||
}
|
||||
|
||||
/* This is a bit select, create a compatible NetNet with
|
||||
a single bit that links to the selected bit of the
|
||||
expression. */
|
||||
NetNet*tmp = new NetNet(scope, scope->local_hsymbol(),
|
||||
sig->type(), 1);
|
||||
tmp->local_flag(true);
|
||||
|
||||
connect(tmp->pin(0), sig->pin(idx));
|
||||
NetSubnet*tmp = new NetSubnet(sig, idx, 1);
|
||||
sig = tmp;
|
||||
}
|
||||
|
||||
@@ -1196,15 +1415,19 @@ NetNet* PEIdent::elaborate_net_ram_(Design*des, NetScope*scope,
|
||||
if (adr == 0)
|
||||
return 0;
|
||||
|
||||
// Memory names are only the base names. Since NetObj names
|
||||
// are still fullnames, and we are deriving such names from
|
||||
// the memory name, make a fullname here.
|
||||
string hname = scope->name() + "." + mem->name();
|
||||
|
||||
NetRamDq*ram = new NetRamDq(scope, des->local_symbol(mem->name()),
|
||||
NetRamDq*ram = new NetRamDq(scope, des->local_symbol(hname),
|
||||
mem, adr->pin_count());
|
||||
des->add_node(ram);
|
||||
|
||||
for (unsigned idx = 0 ; idx < adr->pin_count() ; idx += 1)
|
||||
connect(ram->pin_Address(idx), adr->pin(idx));
|
||||
|
||||
NetNet*osig = new NetNet(scope, des->local_symbol(mem->name()),
|
||||
NetNet*osig = new NetNet(scope, des->local_symbol(hname),
|
||||
NetNet::IMPLICIT, ram->width());
|
||||
osig->local_flag(true);
|
||||
|
||||
@@ -1232,14 +1455,11 @@ NetNet* PEIdent::elaborate_lnet(Design*des, NetScope*scope) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Fine, create an implicit wire as an l-value. */
|
||||
sig = new NetNet(scope, path+"."+path_.peek_name(0),
|
||||
NetNet::IMPLICIT, 1);
|
||||
|
||||
if (warn_implicit)
|
||||
cerr << get_line() << ": warning: implicit "
|
||||
" definition of wire " << path << "." <<
|
||||
path_.peek_name(0) << "." << endl;
|
||||
cerr << get_line() << ": error: Net " << path_
|
||||
<< " is not defined in this context." << endl;
|
||||
cerr << get_line() << ": : Do you mean this? wire "
|
||||
<< path_ << " = <expr>;" << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(sig);
|
||||
@@ -1273,24 +1493,21 @@ NetNet* PEIdent::elaborate_lnet(Design*des, NetScope*scope) const
|
||||
unsigned lidx = sig->sb_to_idx(lval->as_long());
|
||||
|
||||
if (midx >= lidx) {
|
||||
NetTmp*tmp = new NetTmp(scope, scope->local_hsymbol(),
|
||||
midx-lidx+1);
|
||||
if (tmp->pin_count() > sig->pin_count()) {
|
||||
unsigned subnet_wid = midx-lidx+1;
|
||||
if (subnet_wid > sig->pin_count()) {
|
||||
cerr << get_line() << ": bit select out of "
|
||||
<< "range for " << sig->name() << endl;
|
||||
return sig;
|
||||
}
|
||||
|
||||
for (unsigned idx = lidx ; idx <= midx ; idx += 1)
|
||||
connect(tmp->pin(idx-lidx), sig->pin(idx));
|
||||
NetSubnet*tmp = new NetSubnet(sig, lidx, subnet_wid);
|
||||
|
||||
sig = tmp;
|
||||
|
||||
} else {
|
||||
NetTmp*tmp = new NetTmp(scope, scope->local_hsymbol(),
|
||||
lidx-midx+1);
|
||||
unsigned subnet_wid = midx-lidx+1;
|
||||
|
||||
if (tmp->pin_count() > sig->pin_count()) {
|
||||
if (subnet_wid > sig->pin_count()) {
|
||||
cerr << get_line() << ": error: "
|
||||
<< "part select out of range for "
|
||||
<< sig->name() << "." << endl;
|
||||
@@ -1298,9 +1515,7 @@ NetNet* PEIdent::elaborate_lnet(Design*des, NetScope*scope) const
|
||||
return sig;
|
||||
}
|
||||
|
||||
assert(tmp->pin_count() <= sig->pin_count());
|
||||
for (unsigned idx = lidx ; idx >= midx ; idx -= 1)
|
||||
connect(tmp->pin(idx-midx), sig->pin(idx));
|
||||
NetSubnet*tmp = new NetSubnet(sig, lidx, subnet_wid);
|
||||
|
||||
sig = tmp;
|
||||
}
|
||||
@@ -1322,8 +1537,8 @@ NetNet* PEIdent::elaborate_lnet(Design*des, NetScope*scope) const
|
||||
des->errors += 1;
|
||||
idx = 0;
|
||||
}
|
||||
NetTmp*tmp = new NetTmp(scope, scope->local_hsymbol(), 1);
|
||||
connect(tmp->pin(0), sig->pin(idx));
|
||||
|
||||
NetSubnet*tmp = new NetSubnet(sig, idx, 1);
|
||||
sig = tmp;
|
||||
}
|
||||
|
||||
@@ -1388,24 +1603,26 @@ NetNet* PEIdent::elaborate_port(Design*des, NetScope*scope) const
|
||||
unsigned lidx = sig->sb_to_idx(lval->as_long());
|
||||
|
||||
if (midx >= lidx) {
|
||||
NetTmp*tmp = new NetTmp(scope, scope->local_hsymbol(),
|
||||
midx-lidx+1);
|
||||
if (tmp->pin_count() > sig->pin_count()) {
|
||||
unsigned part_count = midx-lidx+1;
|
||||
if (part_count > sig->pin_count()) {
|
||||
cerr << get_line() << ": bit select out of "
|
||||
<< "range for " << sig->name() << endl;
|
||||
return sig;
|
||||
}
|
||||
|
||||
NetSubnet*tmp = new NetSubnet(sig, lidx, part_count);
|
||||
for (unsigned idx = lidx ; idx <= midx ; idx += 1)
|
||||
connect(tmp->pin(idx-lidx), sig->pin(idx));
|
||||
|
||||
sig = tmp;
|
||||
|
||||
} else {
|
||||
NetTmp*tmp = new NetTmp(scope, scope->local_hsymbol(),
|
||||
lidx-midx+1);
|
||||
assert(tmp->pin_count() <= sig->pin_count());
|
||||
for (unsigned idx = lidx ; idx >= midx ; idx -= 1)
|
||||
/* XXXX Signals reversed?? */
|
||||
unsigned part_count = lidx-midx+1;
|
||||
assert(part_count <= sig->pin_count());
|
||||
|
||||
NetSubnet*tmp = new NetSubnet(sig, midx, part_count);
|
||||
for (unsigned idx = midx ; idx >= lidx ; idx -= 1)
|
||||
connect(tmp->pin(idx-midx), sig->pin(idx));
|
||||
|
||||
sig = tmp;
|
||||
@@ -1428,7 +1645,7 @@ NetNet* PEIdent::elaborate_port(Design*des, NetScope*scope) const
|
||||
des->errors += 1;
|
||||
idx = 0;
|
||||
}
|
||||
NetTmp*tmp = new NetTmp(scope, scope->local_hsymbol(), 1);
|
||||
NetSubnet*tmp = new NetSubnet(sig, idx, 1);
|
||||
connect(tmp->pin(0), sig->pin(idx));
|
||||
sig = tmp;
|
||||
}
|
||||
@@ -1436,7 +1653,6 @@ NetNet* PEIdent::elaborate_port(Design*des, NetScope*scope) const
|
||||
return sig;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Elaborate a number as a NetConst object.
|
||||
*/
|
||||
@@ -1539,6 +1755,55 @@ NetNet* PENumber::elaborate_net(Design*des, NetScope*scope,
|
||||
return net;
|
||||
}
|
||||
|
||||
/*
|
||||
* A string is a NetEConst node that is made of the ASCII bits of the
|
||||
* string instead of the bits of a number. In fact, a string is just
|
||||
* another numeric notation.
|
||||
*/
|
||||
NetNet* PEString::elaborate_net(Design*des, NetScope*scope,
|
||||
unsigned lwidth,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const
|
||||
{
|
||||
unsigned strbits = strlen(text_) * 8;
|
||||
NetNet*net;
|
||||
|
||||
/* If we are constrained by a l-value size, then just make a
|
||||
number constant with the correct size and set as many bits
|
||||
in that constant as make sense. Pad excess with zeros. */
|
||||
if (lwidth > 0) {
|
||||
net = new NetNet(scope, scope->local_hsymbol(),
|
||||
NetNet::IMPLICIT, lwidth);
|
||||
|
||||
} else {
|
||||
net = new NetNet(scope, scope->local_hsymbol(),
|
||||
NetNet::IMPLICIT, strbits);
|
||||
}
|
||||
net->local_flag(true);
|
||||
|
||||
/* Make a verinum that is filled with the 0 pad. */
|
||||
verinum num(verinum::V0, net->pin_count());
|
||||
|
||||
unsigned idx;
|
||||
for (idx = 0 ; idx < num.len() && idx < strbits; idx += 1) {
|
||||
char byte = text_[strbits/8 - 1 - idx/8];
|
||||
char mask = 1<<(idx%8);
|
||||
num.set(idx, (byte & mask)? verinum::V1 : verinum::V0);
|
||||
}
|
||||
|
||||
NetConst*tmp = new NetConst(scope, scope->local_hsymbol(), num);
|
||||
for (idx = 0 ; idx < net->pin_count() ; idx += 1) {
|
||||
tmp->pin(idx).drive0(drive0);
|
||||
tmp->pin(idx).drive1(drive1);
|
||||
connect(net->pin(idx), tmp->pin(idx));
|
||||
}
|
||||
|
||||
des->add_node(tmp);
|
||||
return net;
|
||||
}
|
||||
|
||||
/*
|
||||
* Elaborate the ternary operator in a netlist by creating a LPM_MUX
|
||||
@@ -1595,7 +1860,8 @@ NetNet* PETernary::elaborate_net(Design*des, NetScope*scope,
|
||||
for (unsigned idx = 0; idx < expr_sig->pin_count(); idx += 1)
|
||||
connect(log->pin(idx+1), expr_sig->pin(idx));
|
||||
|
||||
NetNet*tmp = new NetTmp(scope, scope->local_hsymbol());
|
||||
NetNet*tmp = new NetNet(scope, scope->local_hsymbol(),
|
||||
NetNet::IMPLICIT, 1);
|
||||
tmp->local_flag(true);
|
||||
connect(tmp->pin(0), log->pin(0));
|
||||
des->add_node(log);
|
||||
@@ -1636,12 +1902,39 @@ NetNet* PETernary::elaborate_net(Design*des, NetScope*scope,
|
||||
NetMux*mux = new NetMux(scope, scope->local_hsymbol(), dwidth, 2, 1);
|
||||
connect(mux->pin_Sel(0), expr_sig->pin(0));
|
||||
|
||||
/* Connect the data inputs. */
|
||||
for (unsigned idx = 0 ; idx < dwidth ; idx += 1) {
|
||||
connect(mux->pin_Result(idx), sig->pin(idx));
|
||||
connect(mux->pin_Data(idx,0), fal_sig->pin(idx));
|
||||
connect(mux->pin_Data(idx,1), tru_sig->pin(idx));
|
||||
}
|
||||
|
||||
/* If there are non-zero output delays, then create bufz
|
||||
devices to carry the propagation delays. Otherwise, just
|
||||
connect the result to the output. */
|
||||
if (rise || fall || decay) {
|
||||
NetNet*tmp = new NetNet(scope, scope->local_hsymbol(),
|
||||
NetNet::WIRE, dwidth);
|
||||
for (unsigned idx = 0 ; idx < dwidth ; idx += 1) {
|
||||
|
||||
NetBUFZ*tmpz = new NetBUFZ(scope, scope->local_hsymbol());
|
||||
tmpz->rise_time(rise);
|
||||
tmpz->fall_time(fall);
|
||||
tmpz->decay_time(decay);
|
||||
tmpz->pin(0).drive0(drive0);
|
||||
tmpz->pin(0).drive1(drive1);
|
||||
|
||||
connect(mux->pin_Result(idx), tmp->pin(idx));
|
||||
connect(tmp->pin(idx), tmpz->pin(1));
|
||||
connect(sig->pin(idx), tmpz->pin(0));
|
||||
|
||||
des->add_node(tmpz);
|
||||
}
|
||||
|
||||
} else {
|
||||
for (unsigned idx = 0 ; idx < dwidth ; idx += 1) {
|
||||
connect(mux->pin_Result(idx), sig->pin(idx));
|
||||
}
|
||||
}
|
||||
|
||||
/* If the MUX device result is too narrow to fill out the
|
||||
desired result, pad with zeros by creating a NetConst device. */
|
||||
@@ -1689,11 +1982,19 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
|
||||
if (val == 0)
|
||||
break;
|
||||
|
||||
if (width == 0)
|
||||
width = val->len();
|
||||
|
||||
assert(width > 0);
|
||||
sig = new NetNet(scope, scope->local_hsymbol(),
|
||||
NetNet::WIRE, width);
|
||||
sig->local_flag(true);
|
||||
|
||||
verinum tmp(v_not(*val) + verinum(1UL, width), width);
|
||||
/* Take the 2s complement by taking the 1s complement
|
||||
and adding 1. */
|
||||
verinum tmp (v_not(*val));
|
||||
verinum one (1UL, width);
|
||||
tmp = tmp + one;
|
||||
NetConst*con = new NetConst(scope, scope->local_hsymbol(), tmp);
|
||||
for (unsigned idx = 0 ; idx < width ; idx += 1)
|
||||
connect(sig->pin(idx), con->pin(idx));
|
||||
@@ -1820,9 +2121,12 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
|
||||
|
||||
case '-': // Unary 2's complement.
|
||||
sig = new NetNet(scope, scope->local_hsymbol(),
|
||||
NetNet::WIRE, sub_sig->pin_count());
|
||||
NetNet::WIRE, owidth);
|
||||
sig->local_flag(true);
|
||||
|
||||
if (sub_sig->pin_count() < owidth)
|
||||
sub_sig = pad_to_width(des, sub_sig, owidth);
|
||||
|
||||
switch (sub_sig->pin_count()) {
|
||||
case 0:
|
||||
assert(0);
|
||||
@@ -1861,10 +2165,33 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
|
||||
break;
|
||||
|
||||
default:
|
||||
cerr << get_line() << ": internal error: Wide unary "
|
||||
<< "minus not supported here." << endl;
|
||||
des->errors += 1;
|
||||
sig = 0;
|
||||
NetAddSub*sub = new NetAddSub(scope, scope->local_hsymbol(),
|
||||
sig->pin_count());
|
||||
sub->attribute("LPM_Direction", verinum("SUB"));
|
||||
|
||||
des->add_node(sub);
|
||||
|
||||
for (unsigned idx = 0 ; idx < sig->pin_count(); idx += 1)
|
||||
connect(sig->pin(idx), sub->pin_Result(idx));
|
||||
|
||||
for (unsigned idx = 0; idx < sub_sig->pin_count(); idx += 1)
|
||||
connect(sub_sig->pin(idx), sub->pin_DataB(idx));
|
||||
|
||||
verinum tmp_num (verinum::V0, sub->width(), true);
|
||||
NetConst*tmp_con = new NetConst(scope,
|
||||
scope->local_hsymbol(),
|
||||
tmp_num);
|
||||
des->add_node(tmp_con);
|
||||
|
||||
NetNet*tmp_sig = new NetNet(scope, scope->local_hsymbol(),
|
||||
NetNet::WIRE,
|
||||
sub_sig->pin_count());
|
||||
tmp_sig->local_flag(true);
|
||||
|
||||
for (unsigned idx = 0; idx < sig->pin_count(); idx += 1) {
|
||||
connect(tmp_sig->pin(idx), sub->pin_DataA(idx));
|
||||
connect(tmp_sig->pin(idx), tmp_con->pin(idx));
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -1880,34 +2207,63 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
|
||||
|
||||
/*
|
||||
* $Log: elab_net.cc,v $
|
||||
* Revision 1.82 2001/12/03 04:47:14 steve
|
||||
* Parser and pform use hierarchical names as hname_t
|
||||
* objects instead of encoded strings.
|
||||
* Revision 1.101 2002/09/18 04:29:55 steve
|
||||
* Add support for binary NOR operator.
|
||||
*
|
||||
* Revision 1.81 2001/11/10 02:08:49 steve
|
||||
* Coerse input to inout when assigned to.
|
||||
* Revision 1.100 2002/09/12 15:49:43 steve
|
||||
* Add support for binary nand operator.
|
||||
*
|
||||
* Revision 1.80 2001/11/08 05:15:50 steve
|
||||
* Remove string paths from PExpr elaboration.
|
||||
* Revision 1.99 2002/09/08 01:37:13 steve
|
||||
* Fix padding of operand of unary minus.
|
||||
*
|
||||
* Revision 1.79 2001/11/07 04:26:46 steve
|
||||
* elaborate_lnet uses scope instead of string path.
|
||||
* Revision 1.98 2002/08/31 03:48:50 steve
|
||||
* Fix reverse bit ordered bit select in continuous assignment.
|
||||
*
|
||||
* Revision 1.78 2001/11/07 04:01:59 steve
|
||||
* eval_const uses scope instead of a string path.
|
||||
* Revision 1.97 2002/08/21 02:28:03 steve
|
||||
* Carry mux output delays.
|
||||
*
|
||||
* Revision 1.77 2001/10/28 01:14:53 steve
|
||||
* NetObj constructor finally requires a scope.
|
||||
* Revision 1.96 2002/08/14 03:57:27 steve
|
||||
* Constants can self-size themselves in unsized contexts.
|
||||
*
|
||||
* Revision 1.76 2001/10/16 02:19:26 steve
|
||||
* Support IVL_LPM_DIVIDE for structural divide.
|
||||
* Revision 1.95 2002/08/12 01:34:59 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.75 2001/09/14 04:20:49 steve
|
||||
* dead code.
|
||||
* Revision 1.94 2002/08/05 04:18:45 steve
|
||||
* Store only the base name of memories.
|
||||
*
|
||||
* Revision 1.74 2001/09/14 04:16:52 steve
|
||||
* Elaborate == to NetCompare instead of XNOR and AND
|
||||
* gates. This allows code generators to generate
|
||||
* better code in certain cases.
|
||||
* Revision 1.93 2002/07/05 21:26:17 steve
|
||||
* Avoid emitting to vvp local net symbols.
|
||||
*
|
||||
* Revision 1.92 2002/06/22 04:22:40 steve
|
||||
* Wide unary minus in continuous assignments.
|
||||
*
|
||||
* Revision 1.91 2002/06/19 04:20:03 steve
|
||||
* Remove NetTmp and add NetSubnet class.
|
||||
*
|
||||
* Revision 1.90 2002/05/23 03:08:51 steve
|
||||
* Add language support for Verilog-2001 attribute
|
||||
* syntax. Hook this support into existing $attribute
|
||||
* handling, and add number and void value types.
|
||||
*
|
||||
* Add to the ivl_target API new functions for access
|
||||
* of complex attributes attached to gates.
|
||||
*
|
||||
* Revision 1.89 2002/04/23 03:53:59 steve
|
||||
* Add support for non-constant bit select.
|
||||
*
|
||||
* Revision 1.88 2002/04/22 00:53:39 steve
|
||||
* Do not allow implicit wires in sensitivity lists.
|
||||
*
|
||||
* Revision 1.87 2002/03/09 02:10:22 steve
|
||||
* Add the NetUserFunc netlist node.
|
||||
*
|
||||
* Revision 1.86 2002/01/23 05:23:17 steve
|
||||
* No implicit declaration in assign l-values.
|
||||
*
|
||||
* Revision 1.85 2002/01/03 04:19:01 steve
|
||||
* Add structural modulus support down to vvp.
|
||||
*
|
||||
* Revision 1.84 2001/12/31 04:23:59 steve
|
||||
* Elaborate multiply nets with constant operands ad NetConst.
|
||||
*/
|
||||
|
||||
|
||||
+38
-16
@@ -16,8 +16,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: elab_pexpr.cc,v 1.12 2001/12/03 04:47:14 steve Exp $"
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elab_pexpr.cc,v 1.16 2002/08/12 01:34:59 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -66,28 +66,21 @@ NetExpr*PEBinary::elaborate_pexpr (Design*des, NetScope*scope) const
|
||||
*/
|
||||
NetEConcat* PEConcat::elaborate_pexpr(Design*des, NetScope*scope) const
|
||||
{
|
||||
unsigned repeat = 1;
|
||||
NetExpr* repeat = 0;
|
||||
|
||||
/* If there is a repeat expression, then evaluate the constant
|
||||
value and set the repeat count.
|
||||
|
||||
XXXX Potential bug XXX In principle, the repeat expression
|
||||
can have a parameter name in it. Since where are in the
|
||||
working of parameters now, we will not be able to
|
||||
accurately evaluate such expressions. So eventually, I will
|
||||
need to be able to defer the evaluation of the expression. */
|
||||
value and set the repeat count. */
|
||||
if (repeat_) {
|
||||
verinum*vrep = repeat_->eval_const(des, scope);
|
||||
if (vrep == 0) {
|
||||
repeat = repeat_->elaborate_pexpr(des, scope);
|
||||
if (repeat == 0) {
|
||||
cerr << get_line() << ": error: "
|
||||
"concatenation repeat expression cannot be evaluated."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
repeat = vrep->as_ulong();
|
||||
delete vrep;
|
||||
/* continue on even if the repeat expression doesn't
|
||||
work, as we can find more errors. */
|
||||
}
|
||||
|
||||
/* Make the empty concat expression. */
|
||||
@@ -104,7 +97,12 @@ NetEConcat* PEConcat::elaborate_pexpr(Design*des, NetScope*scope) const
|
||||
|
||||
ex->set_line(*parms_[idx]);
|
||||
|
||||
if (! ex->has_width()) {
|
||||
if (dynamic_cast<NetEParam*>(ex)) {
|
||||
|
||||
/* If this parameter is a NetEParam, then put off
|
||||
the width check for later. */
|
||||
|
||||
} else if (! ex->has_width()) {
|
||||
cerr << ex->get_line() << ": error: operand of "
|
||||
<< "concatenation has indefinite width: "
|
||||
<< *ex << endl;
|
||||
@@ -152,6 +150,12 @@ NetExpr*PEIdent::elaborate_pexpr(Design*des, NetScope*scope) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (msb_ || lsb_ || idx_) {
|
||||
cerr << get_line() << ": error: Cannot bit/part select "
|
||||
"bits of parameters." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
NetExpr*res = new NetEParam(des, pscope, hname_t(name));
|
||||
assert(res);
|
||||
delete name;
|
||||
@@ -218,6 +222,24 @@ NetExpr*PEUnary::elaborate_pexpr (Design*des, NetScope*scope) const
|
||||
|
||||
/*
|
||||
* $Log: elab_pexpr.cc,v $
|
||||
* Revision 1.16 2002/08/12 01:34:59 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.15 2002/05/06 02:30:27 steve
|
||||
* Allow parameters in concatenation of widths are defined.
|
||||
*
|
||||
* Revision 1.14 2002/05/05 21:11:50 steve
|
||||
* Put off evaluation of concatenation repeat expresions
|
||||
* until after parameters are defined. This allows parms
|
||||
* to be used in repeat expresions.
|
||||
*
|
||||
* Add the builtin $signed system function.
|
||||
*
|
||||
* Revision 1.13 2002/01/28 00:52:41 steve
|
||||
* Add support for bit select of parameters.
|
||||
* This leads to a NetESelect node and the
|
||||
* vvp code generator to support that.
|
||||
*
|
||||
* Revision 1.12 2001/12/03 04:47:14 steve
|
||||
* Parser and pform use hierarchical names as hname_t
|
||||
* objects instead of encoded strings.
|
||||
|
||||
+72
-19
@@ -16,8 +16,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: elab_scope.cc,v 1.12 2001/12/03 04:47:14 steve Exp $"
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elab_scope.cc,v 1.17 2002/10/19 22:59:49 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -54,7 +54,7 @@ bool Module::elaborate_scope(Design*des, NetScope*scope) const
|
||||
// the pform and just place a NetEParam placeholder in the
|
||||
// place of the elaborated expression.
|
||||
|
||||
typedef map<string,PExpr*>::const_iterator mparm_it_t;
|
||||
typedef map<string,param_expr_t>::const_iterator mparm_it_t;
|
||||
typedef map<hname_t,PExpr*>::const_iterator hparm_it_t;
|
||||
|
||||
|
||||
@@ -64,13 +64,21 @@ bool Module::elaborate_scope(Design*des, NetScope*scope) const
|
||||
for (mparm_it_t cur = parameters.begin()
|
||||
; cur != parameters.end() ; cur ++) {
|
||||
|
||||
scope->set_parameter((*cur).first, new NetEParam);
|
||||
NetEParam*tmp = new NetEParam;
|
||||
if ((*cur).second.msb)
|
||||
tmp->cast_signed( (*cur).second.signed_flag );
|
||||
|
||||
scope->set_parameter((*cur).first, tmp, 0, 0, false);
|
||||
}
|
||||
|
||||
for (mparm_it_t cur = localparams.begin()
|
||||
; cur != localparams.end() ; cur ++) {
|
||||
|
||||
scope->set_parameter((*cur).first, new NetEParam);
|
||||
NetEParam*tmp = new NetEParam;
|
||||
if ((*cur).second.msb)
|
||||
tmp->cast_signed( (*cur).second.signed_flag );
|
||||
|
||||
scope->set_parameter((*cur).first, tmp, 0, 0, false);
|
||||
}
|
||||
|
||||
|
||||
@@ -82,11 +90,29 @@ bool Module::elaborate_scope(Design*des, NetScope*scope) const
|
||||
for (mparm_it_t cur = parameters.begin()
|
||||
; cur != parameters.end() ; cur ++) {
|
||||
|
||||
PExpr*ex = (*cur).second;
|
||||
PExpr*ex = (*cur).second.expr;
|
||||
assert(ex);
|
||||
|
||||
NetExpr*val = ex->elaborate_pexpr(des, scope);
|
||||
val = scope->set_parameter((*cur).first, val);
|
||||
NetExpr*msb = 0;
|
||||
NetExpr*lsb = 0;
|
||||
bool signed_flag = false;
|
||||
|
||||
/* If the parameter declaration includes msb and lsb,
|
||||
then use them to calculate a width for the
|
||||
result. Then make sure the constant expression of the
|
||||
parameter value is coerced to have the correct
|
||||
and defined width. */
|
||||
if ((*cur).second.msb) {
|
||||
msb = (*cur).second.msb ->elaborate_pexpr(des, scope);
|
||||
assert(msb);
|
||||
lsb = (*cur).second.lsb ->elaborate_pexpr(des, scope);
|
||||
signed_flag = (*cur).second.signed_flag;
|
||||
}
|
||||
|
||||
val->cast_signed(signed_flag);
|
||||
val = scope->set_parameter((*cur).first, val,
|
||||
msb, lsb, signed_flag);
|
||||
assert(val);
|
||||
delete val;
|
||||
}
|
||||
@@ -94,11 +120,11 @@ bool Module::elaborate_scope(Design*des, NetScope*scope) const
|
||||
for (mparm_it_t cur = localparams.begin()
|
||||
; cur != localparams.end() ; cur ++) {
|
||||
|
||||
PExpr*ex = (*cur).second;
|
||||
PExpr*ex = (*cur).second.expr;
|
||||
assert(ex);
|
||||
|
||||
NetExpr*val = ex->elaborate_pexpr(des, scope);
|
||||
val = scope->set_parameter((*cur).first, val);
|
||||
val = scope->set_parameter((*cur).first, val, 0, 0, false);
|
||||
assert(val);
|
||||
delete val;
|
||||
}
|
||||
@@ -256,8 +282,10 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
|
||||
// later.)
|
||||
mod->elaborate_scope(des, my_scope);
|
||||
|
||||
// Look for module parameter replacements. This map receives
|
||||
// those replacements.
|
||||
// Look for module parameter replacements. The "replace" map
|
||||
// maps parameter name to replacement expression that is
|
||||
// passed. It is built up by the ordered overrices or named
|
||||
// overrides.
|
||||
|
||||
typedef map<string,PExpr*>::const_iterator mparm_it_t;
|
||||
map<string,PExpr*> replace;
|
||||
@@ -271,12 +299,18 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
|
||||
if (overrides_) {
|
||||
assert(parms_ == 0);
|
||||
list<string>::const_iterator cur = mod->param_names.begin();
|
||||
for (unsigned idx = 0
|
||||
; idx < overrides_->count()
|
||||
; idx += 1, cur++) {
|
||||
replace[*cur] = (*overrides_)[idx];
|
||||
}
|
||||
unsigned idx = 0;
|
||||
for (;;) {
|
||||
if (idx >= overrides_->count())
|
||||
break;
|
||||
if (cur == mod->param_names.end())
|
||||
break;
|
||||
|
||||
replace[*cur] = (*overrides_)[idx];
|
||||
|
||||
idx += 1;
|
||||
cur ++;
|
||||
}
|
||||
}
|
||||
|
||||
// Named parameter overrides carry a name with each override
|
||||
@@ -298,9 +332,12 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
|
||||
|
||||
PExpr*tmp = (*cur).second;
|
||||
NetExpr*val = tmp->elaborate_pexpr(des, sc);
|
||||
val = my_scope->set_parameter((*cur).first, val);
|
||||
assert(val);
|
||||
delete val;
|
||||
bool flag = my_scope->replace_parameter((*cur).first, val);
|
||||
if (! flag) {
|
||||
cerr << val->get_line() << ": warning: parameter "
|
||||
<< (*cur).first << " not found in "
|
||||
<< sc->name() << "." << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -459,6 +496,22 @@ void PWhile::elaborate_scope(Design*des, NetScope*scope) const
|
||||
|
||||
/*
|
||||
* $Log: elab_scope.cc,v $
|
||||
* Revision 1.17 2002/10/19 22:59:49 steve
|
||||
* Redo the parameter vector support to allow
|
||||
* parameter names in range expressions.
|
||||
*
|
||||
* Revision 1.16 2002/09/01 03:01:48 steve
|
||||
* Properly cast signedness of parameters with ranges.
|
||||
*
|
||||
* Revision 1.15 2002/08/19 02:39:16 steve
|
||||
* Support parameters with defined ranges.
|
||||
*
|
||||
* Revision 1.14 2002/08/12 01:34:59 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.13 2001/12/30 04:47:57 steve
|
||||
* Properly handle empty target in positionla parameter override.
|
||||
*
|
||||
* Revision 1.12 2001/12/03 04:47:14 steve
|
||||
* Parser and pform use hierarchical names as hname_t
|
||||
* objects instead of encoded strings.
|
||||
|
||||
+75
-8
@@ -16,8 +16,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: elab_sig.cc,v 1.18 2001/12/03 04:47:14 steve Exp $"
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elab_sig.cc,v 1.25 2002/08/12 01:34:59 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -71,8 +71,8 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
|
||||
|
||||
// Scan all the ports of the module, and make sure that each
|
||||
// is connected to wires that have port declarations.
|
||||
for (unsigned idx = 0 ; idx < ports_.count() ; idx += 1) {
|
||||
Module::port_t*pp = ports_[idx];
|
||||
for (unsigned idx = 0 ; idx < ports.count() ; idx += 1) {
|
||||
Module::port_t*pp = ports[idx];
|
||||
if (pp == 0)
|
||||
continue;
|
||||
|
||||
@@ -122,7 +122,7 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
|
||||
|
||||
hname_t name = (*wt).first;
|
||||
|
||||
if (! signal_is_in_port(ports_, name)) {
|
||||
if (! signal_is_in_port(ports, name)) {
|
||||
|
||||
cerr << cur->get_line() << ": error: Signal "
|
||||
<< name << " has a declared direction "
|
||||
@@ -237,6 +237,17 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
||||
string fname = scope->basename();
|
||||
assert(scope->type() == NetScope::FUNC);
|
||||
|
||||
/* Make sure the function has at least one input port. If it
|
||||
fails this test, print an error message. Keep going so we
|
||||
can find more errors. */
|
||||
if (ports_ == 0) {
|
||||
cerr << get_line() << ": error: Function " << fname
|
||||
<< " has no ports." << endl;
|
||||
cerr << get_line() << ": : Functions must have"
|
||||
<< " at least one input port." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
svector<NetNet*>ports (ports_? ports_->count()+1 : 1);
|
||||
|
||||
/* Get the reg for the return value. I know the name of the
|
||||
@@ -379,6 +390,10 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
if (msb_.count()) {
|
||||
svector<long>mnum (msb_.count());
|
||||
svector<long>lnum (msb_.count());
|
||||
/* There may be places where the signal is declared as a
|
||||
scaler. Count those here, for consistency check
|
||||
later. */
|
||||
unsigned count_scalars = 0;
|
||||
|
||||
/* There may be multiple declarations of ranges, because
|
||||
the symbol may have its range declared in i.e. input
|
||||
@@ -387,6 +402,14 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
|
||||
for (unsigned idx = 0 ; idx < msb_.count() ; idx += 1) {
|
||||
|
||||
if (msb_[idx] == 0) {
|
||||
count_scalars += 1;
|
||||
assert(lsb_[idx] == 0);
|
||||
mnum[idx] = 0;
|
||||
lnum[idx] = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
NetEConst*tmp;
|
||||
NetExpr*texpr = elab_and_eval(des, scope, msb_[idx]);
|
||||
|
||||
@@ -417,6 +440,18 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
|
||||
}
|
||||
|
||||
/* Check that the declarations were all scalar or all
|
||||
vector. It is an error to mix them. Use the
|
||||
count_scalars to know. */
|
||||
if ((count_scalars > 0) && (count_scalars != msb_.count())) {
|
||||
cerr << get_line() << ": error: Signal ``" << hname_
|
||||
<< "'' declared both as a vector and a scalar."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* Make sure all the values for msb and lsb match by
|
||||
value. If not, report an error. */
|
||||
for (unsigned idx = 1 ; idx < msb_.count() ; idx += 1) {
|
||||
@@ -440,6 +475,10 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
|
||||
}
|
||||
|
||||
unsigned nattrib = 0;
|
||||
attrib_list_t*attrib_list = evaluate_attributes(attributes, nattrib,
|
||||
des, scope);
|
||||
|
||||
if (lidx_ || ridx_) {
|
||||
assert(lidx_ && ridx_);
|
||||
|
||||
@@ -459,8 +498,7 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
assert(lval);
|
||||
assert(rval);
|
||||
|
||||
string name = scope->name();
|
||||
name = name + "." + hname_.peek_tail_name();
|
||||
string name = hname_.peek_tail_name();
|
||||
|
||||
long lnum = lval->as_long();
|
||||
long rnum = rval->as_long();
|
||||
@@ -478,12 +516,41 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
sig->set_line(*this);
|
||||
sig->port_type(port_type_);
|
||||
sig->set_signed(get_signed());
|
||||
sig->set_attributes(attributes);
|
||||
sig->set_isint(get_isint());
|
||||
|
||||
for (unsigned idx = 0 ; idx < nattrib ; idx += 1)
|
||||
sig->attribute(attrib_list[idx].key, attrib_list[idx].val);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: elab_sig.cc,v $
|
||||
* Revision 1.25 2002/08/12 01:34:59 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.24 2002/08/05 04:18:45 steve
|
||||
* Store only the base name of memories.
|
||||
*
|
||||
* Revision 1.23 2002/06/21 04:59:35 steve
|
||||
* Carry integerness throughout the compilation.
|
||||
*
|
||||
* Revision 1.22 2002/05/23 03:08:51 steve
|
||||
* Add language support for Verilog-2001 attribute
|
||||
* syntax. Hook this support into existing $attribute
|
||||
* handling, and add number and void value types.
|
||||
*
|
||||
* Add to the ivl_target API new functions for access
|
||||
* of complex attributes attached to gates.
|
||||
*
|
||||
* Revision 1.21 2002/05/19 23:37:28 steve
|
||||
* Parse port_declaration_lists from the 2001 Standard.
|
||||
*
|
||||
* Revision 1.20 2002/01/26 05:28:28 steve
|
||||
* Detect scalar/vector declarion mismatch.
|
||||
*
|
||||
* Revision 1.19 2002/01/23 03:35:17 steve
|
||||
* Detect incorrect function ports.
|
||||
*
|
||||
* Revision 1.18 2001/12/03 04:47:14 steve
|
||||
* Parser and pform use hierarchical names as hname_t
|
||||
* objects instead of encoded strings.
|
||||
|
||||
+332
-208
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998-2000 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2002 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -16,8 +16,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: elaborate.cc,v 1.236 2001/12/06 05:04:49 steve Exp $"
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elaborate.cc,v 1.263 2002/08/28 18:54:36 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -38,6 +38,8 @@
|
||||
# include "netmisc.h"
|
||||
# include "util.h"
|
||||
# include "parse_api.h"
|
||||
# include "compiler.h"
|
||||
|
||||
|
||||
static Link::strength_t drive_type(PGate::strength_t drv)
|
||||
{
|
||||
@@ -120,7 +122,44 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
|
||||
if (rid->pin_count() < cnt)
|
||||
cnt = rid->pin_count();
|
||||
|
||||
if ((rid->type() == lval->type()) && (rise_time == 0)) {
|
||||
bool need_driver_flag = false;
|
||||
|
||||
/* If the device is linked to itself, a driver is
|
||||
needed. Should I print a warning here? */
|
||||
for (unsigned idx = 0 ; idx < cnt ; idx += 1) {
|
||||
if (lval->pin(idx) .is_linked (rid->pin(idx))) {
|
||||
need_driver_flag = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* If the nets are different type (i.e. reg vs tri) then
|
||||
a driver is needed. */
|
||||
if (rid->type() != lval->type())
|
||||
need_driver_flag = true;
|
||||
|
||||
/* If there is a delay, then I need a driver to carry
|
||||
it. */
|
||||
if (rise_time || fall_time || decay_time)
|
||||
need_driver_flag = true;
|
||||
|
||||
/* If there is a strength to be carried, then I need a
|
||||
driver to carry that strength. */
|
||||
for (unsigned idx = 0 ; idx < cnt ; idx += 1) {
|
||||
if (rid->pin(idx).drive0() != drive0) {
|
||||
need_driver_flag = true;
|
||||
break;
|
||||
}
|
||||
if (rid->pin(idx).drive1() != drive1) {
|
||||
need_driver_flag = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (! need_driver_flag) {
|
||||
/* Don't need a driver, presumably because the
|
||||
r-value already has the needed drivers. Just
|
||||
hook things up. */
|
||||
unsigned idx;
|
||||
for (idx = 0 ; idx < cnt; idx += 1)
|
||||
connect(lval->pin(idx), rid->pin(idx));
|
||||
@@ -136,6 +175,8 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
|
||||
}
|
||||
|
||||
} else {
|
||||
/* Do need a driver. Use BUFZ objects to carry the
|
||||
strength and delays. */
|
||||
unsigned idx;
|
||||
for (idx = 0 ; idx < cnt ; idx += 1) {
|
||||
NetBUFZ*dev = new NetBUFZ(scope,
|
||||
@@ -264,6 +305,11 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
|
||||
unsigned long rise_time, fall_time, decay_time;
|
||||
eval_delays(des, scope, rise_time, fall_time, decay_time);
|
||||
|
||||
struct attrib_list_t*attrib_list = 0;
|
||||
unsigned attrib_list_n = 0;
|
||||
attrib_list = evaluate_attributes(attributes, attrib_list_n,
|
||||
des, scope);
|
||||
|
||||
/* Now make as many gates as the bit count dictates. Give each
|
||||
a unique name, and set the delay times. */
|
||||
|
||||
@@ -358,7 +404,10 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
|
||||
return;
|
||||
}
|
||||
|
||||
cur[idx]->set_attributes(attributes);
|
||||
for (unsigned adx = 0 ; adx < attrib_list_n ; adx += 1)
|
||||
cur[idx]->attribute(attrib_list[adx].key,
|
||||
attrib_list[adx].val);
|
||||
|
||||
cur[idx]->rise_time(rise_time);
|
||||
cur[idx]->fall_time(fall_time);
|
||||
cur[idx]->decay_time(decay_time);
|
||||
@@ -369,6 +418,9 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
|
||||
des->add_node(cur[idx]);
|
||||
}
|
||||
|
||||
|
||||
delete[]attrib_list;
|
||||
|
||||
/* The gates have all been allocated, this loop runs through
|
||||
the parameters and attaches the ports of the objects. */
|
||||
|
||||
@@ -396,7 +448,7 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
if (NetTmp*tmp = dynamic_cast<NetTmp*>(sig))
|
||||
if (NetSubnet*tmp = dynamic_cast<NetSubnet*>(sig))
|
||||
delete tmp;
|
||||
}
|
||||
}
|
||||
@@ -592,9 +644,10 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
||||
// not, they are different widths. Note that idx is 0
|
||||
// based, but users count parameter positions from 1.
|
||||
if (prts_pin_count != sig->pin_count()) {
|
||||
cerr << get_line() << ": warning: Port " << (idx+1) << " of "
|
||||
cerr << get_line() << ": warning: Port " << (idx+1)
|
||||
<< " (" << rmod->ports[idx]->name << ") of "
|
||||
<< type_ << " expects " << prts_pin_count <<
|
||||
" pins, got " << sig->pin_count() << "." << endl;
|
||||
" bits, got " << sig->pin_count() << "." << endl;
|
||||
|
||||
if (prts_pin_count > sig->pin_count()) {
|
||||
cerr << get_line() << ": : Leaving "
|
||||
@@ -604,7 +657,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
||||
} else {
|
||||
cerr << get_line() << ": : Leaving "
|
||||
<< (sig->pin_count()-prts_pin_count)
|
||||
<< " high bits of the parameter dangling."
|
||||
<< " high bits of the expression dangling."
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
@@ -643,7 +696,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
||||
}
|
||||
|
||||
|
||||
if (NetTmp*tmp = dynamic_cast<NetTmp*>(sig))
|
||||
if (NetSubnet*tmp = dynamic_cast<NetSubnet*>(sig))
|
||||
delete tmp;
|
||||
}
|
||||
}
|
||||
@@ -669,17 +722,26 @@ void PGModule::elaborate_udp_(Design*des, PUdp*udp, NetScope*scope) const
|
||||
unsigned long rise_time = 0, fall_time = 0, decay_time = 0;
|
||||
if (overrides_) {
|
||||
PDelays tmp_del;
|
||||
tmp_del.set_delays(overrides_);
|
||||
tmp_del.set_delays(overrides_, false);
|
||||
tmp_del.eval_delays(des, scope, rise_time, fall_time, decay_time);
|
||||
delete overrides_;
|
||||
}
|
||||
|
||||
|
||||
NetUDP*net = new NetUDP(scope, my_name, udp->ports.count(), udp);
|
||||
net->set_attributes(udp->attributes);
|
||||
net->rise_time(rise_time);
|
||||
net->fall_time(fall_time);
|
||||
net->decay_time(decay_time);
|
||||
|
||||
struct attrib_list_t*attrib_list = 0;
|
||||
unsigned attrib_list_n = 0;
|
||||
attrib_list = evaluate_attributes(attributes, attrib_list_n,
|
||||
des, scope);
|
||||
|
||||
for (unsigned adx = 0 ; adx < attrib_list_n ; adx += 1)
|
||||
net->attribute(attrib_list[adx].key, attrib_list[adx].val);
|
||||
|
||||
delete[]attrib_list;
|
||||
|
||||
/* Run through the pins, making netlists for the pin
|
||||
expressions and connecting them to the pin in question. All
|
||||
of this is independent of the nature of the UDP. */
|
||||
@@ -697,7 +759,7 @@ void PGModule::elaborate_udp_(Design*des, PUdp*udp, NetScope*scope) const
|
||||
connect(sig->pin(0), net->pin(idx));
|
||||
|
||||
// Delete excess holding signal.
|
||||
if (NetTmp*tmp = dynamic_cast<NetTmp*>(sig))
|
||||
if (NetSubnet*tmp = dynamic_cast<NetSubnet*>(sig))
|
||||
delete tmp;
|
||||
}
|
||||
|
||||
@@ -841,68 +903,77 @@ NetProc* Statement::elaborate(Design*des, NetScope*) const
|
||||
return cur;
|
||||
}
|
||||
|
||||
NetProc* PAssign::assign_to_memory_(NetMemory*mem, PExpr*ix,
|
||||
Design*des, NetScope*scope) const
|
||||
{
|
||||
assert(scope);
|
||||
NetExpr*rv = rval()->elaborate_expr(des, scope);
|
||||
if (rv == 0)
|
||||
return 0;
|
||||
|
||||
assert(rv);
|
||||
|
||||
rv->set_width(mem->width());
|
||||
if (ix == 0) {
|
||||
cerr << get_line() << ": internal error: No index in lval "
|
||||
<< "of assignment to memory?" << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(ix);
|
||||
NetExpr*idx = ix->elaborate_expr(des, scope);
|
||||
assert(idx);
|
||||
|
||||
if (rv->expr_width() < mem->width())
|
||||
rv = pad_to_width(rv, mem->width());
|
||||
|
||||
NetAssignMem*am = new NetAssignMem(mem, idx, rv);
|
||||
am->set_line(*this);
|
||||
return am;
|
||||
}
|
||||
|
||||
NetAssign_* PAssign_::elaborate_lval(Design*des, NetScope*scope) const
|
||||
{
|
||||
assert(lval_);
|
||||
return lval_->elaborate_lval(des, scope);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function elaborates delay expressions. This is a little
|
||||
* different from normal elaboration because the result may need to be
|
||||
* scaled.
|
||||
*/
|
||||
static NetExpr*elaborate_delay_expr(PExpr*expr, Design*des, NetScope*scope)
|
||||
{
|
||||
|
||||
if (verireal*dr = expr->eval_rconst(des, scope)) {
|
||||
int shift = scope->time_unit() - des->get_precision();
|
||||
long val = dr->as_long(shift);
|
||||
delete dr;
|
||||
return new NetEConst(verinum(val));
|
||||
|
||||
}
|
||||
|
||||
if (verinum*dv = expr->eval_const(des, scope)) {
|
||||
unsigned long val = dv->as_ulong();
|
||||
val = des->scale_to_precision(val, scope);
|
||||
return new NetEConst(verinum(val));
|
||||
|
||||
}
|
||||
|
||||
NetExpr*delay = expr->elaborate_expr(des, scope);
|
||||
|
||||
int shift = scope->time_unit() - des->get_precision();
|
||||
if (shift > 0) {
|
||||
unsigned long scale = 1;
|
||||
while (shift > 0) {
|
||||
scale *= 10;
|
||||
shift -= 1;
|
||||
}
|
||||
|
||||
NetExpr*scal_val = new NetEConst(verinum(scale));
|
||||
delay = new NetEBMult('*', delay, scal_val);
|
||||
}
|
||||
|
||||
if (shift < 0) {
|
||||
unsigned long scale = 1;
|
||||
while (shift < 0) {
|
||||
scale *= 10;
|
||||
shift += 1;
|
||||
}
|
||||
|
||||
NetExpr*scal_val = new NetEConst(verinum(scale));
|
||||
delay = new NetEBDiv('/', delay, scal_val);
|
||||
}
|
||||
|
||||
return delay;
|
||||
}
|
||||
|
||||
NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
|
||||
{
|
||||
assert(scope);
|
||||
|
||||
/* Catch the case where the lvalue is a reference to a memory
|
||||
item. These are handled differently. */
|
||||
do {
|
||||
const PEIdent*id = dynamic_cast<const PEIdent*>(lval());
|
||||
if (id == 0) break;
|
||||
|
||||
NetNet*net = des->find_signal(scope, id->path());
|
||||
if (net && (net->scope() == scope))
|
||||
break;
|
||||
|
||||
if (NetMemory*mem = des->find_memory(scope, id->path()))
|
||||
return assign_to_memory_(mem, id->msb_, des, scope);
|
||||
|
||||
} while(0);
|
||||
|
||||
|
||||
/* elaborate the lval. This detects any part selects and mux
|
||||
expressions that might exist. */
|
||||
NetAssign_*lv = elaborate_lval(des, scope);
|
||||
if (lv == 0) return 0;
|
||||
|
||||
/* If there is a delay expression, elaborate it. */
|
||||
unsigned long rise_time, fall_time, decay_time;
|
||||
delay_.eval_delays(des, scope, rise_time, fall_time, decay_time);
|
||||
/* If there is an internal delay expression, elaborate it. */
|
||||
NetExpr*delay = 0;
|
||||
if (delay_ != 0)
|
||||
delay = elaborate_delay_expr(delay_, des, scope);
|
||||
|
||||
|
||||
/* Elaborate the r-value expression. */
|
||||
@@ -947,7 +1018,7 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
|
||||
actually and literally represent the delayed assign in the
|
||||
netlist. The compound statement is exactly equivalent. */
|
||||
|
||||
if (rise_time || event_) {
|
||||
if (delay || event_) {
|
||||
string n = scope->local_hsymbol();
|
||||
unsigned wid = lv->lwidth();
|
||||
|
||||
@@ -995,12 +1066,12 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
|
||||
assert(st);
|
||||
|
||||
} else {
|
||||
NetPDelay*de = new NetPDelay(rise_time, a2);
|
||||
NetPDelay*de = new NetPDelay(delay, a2);
|
||||
st = de;
|
||||
}
|
||||
|
||||
/* And build up the complex statement. */
|
||||
NetBlock*bl = new NetBlock(NetBlock::SEQU);
|
||||
NetBlock*bl = new NetBlock(NetBlock::SEQU, 0);
|
||||
bl->append(a1);
|
||||
bl->append(st);
|
||||
|
||||
@@ -1019,36 +1090,6 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
|
||||
return cur;
|
||||
}
|
||||
|
||||
/*
|
||||
* I do not really know how to elaborate mem[x] <= expr, so this
|
||||
* method pretends it is a blocking assign and elaborates
|
||||
* that. However, I report an error so that the design isn't actually
|
||||
* executed by anyone.
|
||||
*/
|
||||
NetProc* PAssignNB::assign_to_memory_(NetMemory*mem, PExpr*ix,
|
||||
Design*des, NetScope*scope) const
|
||||
{
|
||||
assert(scope);
|
||||
|
||||
/* Elaborate the r-value expression, ... */
|
||||
NetExpr*rv = rval()->elaborate_expr(des, scope);
|
||||
if (rv == 0)
|
||||
return 0;
|
||||
|
||||
assert(rv);
|
||||
rv->set_width(mem->width());
|
||||
|
||||
/* Elaborate the expression to calculate the index, ... */
|
||||
NetExpr*idx = ix->elaborate_expr(des, scope);
|
||||
assert(idx);
|
||||
|
||||
/* And connect them together in an assignment NetProc. */
|
||||
NetAssignMemNB*am = new NetAssignMemNB(mem, idx, rv);
|
||||
am->set_line(*this);
|
||||
|
||||
return am;
|
||||
}
|
||||
|
||||
/*
|
||||
* The l-value of a procedural assignment is a very much constrained
|
||||
* expression. To wit, only identifiers, bit selects and part selects
|
||||
@@ -1061,28 +1102,27 @@ NetProc* PAssignNB::elaborate(Design*des, NetScope*scope) const
|
||||
{
|
||||
assert(scope);
|
||||
|
||||
/* Catch the case where the lvalue is a reference to a memory
|
||||
item. These are handled differently. */
|
||||
do {
|
||||
const PEIdent*id = dynamic_cast<const PEIdent*>(lval());
|
||||
if (id == 0) break;
|
||||
|
||||
if (NetMemory*mem = des->find_memory(scope, id->path()))
|
||||
return assign_to_memory_(mem, id->msb_, des, scope);
|
||||
|
||||
} while(0);
|
||||
|
||||
|
||||
NetAssign_*lv = elaborate_lval(des, scope);
|
||||
if (lv == 0) return 0;
|
||||
|
||||
assert(rval());
|
||||
|
||||
/* Elaborate the r-value expression. This generates a
|
||||
procedural expression that I attach to the assignment. */
|
||||
NetExpr*rv = rval()->elaborate_expr(des, scope);
|
||||
if (rv == 0)
|
||||
NetExpr*rv;
|
||||
|
||||
/* Evaluate the rval expression if possible, otherwise just
|
||||
elaborate it. */
|
||||
if (verinum*val = rval()->eval_const(des, scope)) {
|
||||
rv = new NetEConst(*val);
|
||||
delete val;
|
||||
|
||||
} else if (rv = rval()->elaborate_expr(des, scope)) {
|
||||
|
||||
/* OK, go on. */
|
||||
|
||||
} else {
|
||||
/* Unable to elaborate expression. Retreat. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(rv);
|
||||
|
||||
@@ -1091,15 +1131,13 @@ NetProc* PAssignNB::elaborate(Design*des, NetScope*scope) const
|
||||
rv = pad_to_width(rv, wid);
|
||||
}
|
||||
|
||||
|
||||
unsigned long rise_time, fall_time, decay_time;
|
||||
delay_.eval_delays(des, scope, rise_time, fall_time, decay_time);
|
||||
NetExpr*delay = 0;
|
||||
if (delay_ != 0)
|
||||
delay = elaborate_delay_expr(delay_, des, scope);
|
||||
|
||||
/* All done with this node. mark its line number and check it in. */
|
||||
NetAssignNB*cur = new NetAssignNB(lv, rv);
|
||||
cur->rise_time(rise_time);
|
||||
cur->fall_time(fall_time);
|
||||
cur->decay_time(decay_time);
|
||||
cur->set_delay(delay);
|
||||
cur->set_line(*this);
|
||||
return cur;
|
||||
}
|
||||
@@ -1118,10 +1156,8 @@ NetProc* PBlock::elaborate(Design*des, NetScope*scope) const
|
||||
NetBlock::Type type = (bl_type_==PBlock::BL_PAR)
|
||||
? NetBlock::PARA
|
||||
: NetBlock::SEQU;
|
||||
NetBlock*cur = new NetBlock(type);
|
||||
bool fail_flag = false;
|
||||
|
||||
NetScope*nscope;
|
||||
NetScope*nscope = 0;
|
||||
if (name_.length()) {
|
||||
nscope = scope->child(name_);
|
||||
if (nscope == 0) {
|
||||
@@ -1129,19 +1165,24 @@ NetProc* PBlock::elaborate(Design*des, NetScope*scope) const
|
||||
"unable to find block scope " << scope->name()
|
||||
<< "<" << name_ << ">" << endl;
|
||||
des->errors += 1;
|
||||
delete cur;
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(nscope);
|
||||
|
||||
} else {
|
||||
nscope = scope;
|
||||
}
|
||||
|
||||
NetBlock*cur = new NetBlock(type, nscope);
|
||||
bool fail_flag = false;
|
||||
|
||||
if (nscope == 0)
|
||||
nscope = scope;
|
||||
|
||||
// Handle the special case that the block contains only one
|
||||
// statement. There is no need to keep the block node.
|
||||
if (list_.count() == 1) {
|
||||
// statement. There is no need to keep the block node. Also,
|
||||
// don't elide named blocks, because they might be referenced
|
||||
// elsewhere.
|
||||
if ((list_.count() == 1) && (name_.length() == 0)) {
|
||||
assert(list_[0]);
|
||||
NetProc*tmp = list_[0]->elaborate(des, nscope);
|
||||
return tmp;
|
||||
@@ -1187,6 +1228,18 @@ NetProc* PCase::elaborate(Design*des, NetScope*scope) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Try to evaluate the case expression. */
|
||||
if (! dynamic_cast<NetEConst*>(expr)) {
|
||||
NetExpr*tmp = expr->eval_tree();
|
||||
if (tmp != 0) {
|
||||
delete expr;
|
||||
expr = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
/* Count the items in the case statement. Note that ther may
|
||||
be some cases that have multiple guards. Count each as a
|
||||
separate item. */
|
||||
unsigned icount = 0;
|
||||
for (unsigned idx = 0 ; idx < items_->count() ; idx += 1) {
|
||||
PCase::Item*cur = (*items_)[idx];
|
||||
@@ -1200,6 +1253,10 @@ NetProc* PCase::elaborate(Design*des, NetScope*scope) const
|
||||
NetCase*res = new NetCase(type_, expr, icount);
|
||||
res->set_line(*this);
|
||||
|
||||
/* Iterate over all the case items (guard/statement pairs)
|
||||
elaborating them. If the guard has no expression, then this
|
||||
is a "default" cause. Otherwise, the guard has one or more
|
||||
expressions, and each guard is a case. */
|
||||
unsigned inum = 0;
|
||||
for (unsigned idx = 0 ; idx < items_->count() ; idx += 1) {
|
||||
|
||||
@@ -1227,6 +1284,16 @@ NetProc* PCase::elaborate(Design*des, NetScope*scope) const
|
||||
assert(cur->expr[e]);
|
||||
gu = cur->expr[e]->elaborate_expr(des, scope);
|
||||
|
||||
/* Try to evaluate the guard expression down to a
|
||||
simple constant. */
|
||||
if (! dynamic_cast<NetEConst*>(gu)) {
|
||||
NetExpr*tmp = gu->eval_tree();
|
||||
if (tmp != 0) {
|
||||
delete gu;
|
||||
gu = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
if (cur->stat)
|
||||
st = cur->stat->elaborate(des, scope);
|
||||
|
||||
@@ -1268,7 +1335,7 @@ NetProc* PCondit::elaborate(Design*des, NetScope*scope) const
|
||||
else if (else_)
|
||||
return else_->elaborate(des, scope);
|
||||
else
|
||||
return new NetBlock(NetBlock::SEQU);
|
||||
return new NetBlock(NetBlock::SEQU, 0);
|
||||
}
|
||||
|
||||
// If the condition expression is more then 1 bits, then
|
||||
@@ -1312,21 +1379,28 @@ NetProc* PCallTask::elaborate(Design*des, NetScope*scope) const
|
||||
* A call to a system task involves elaborating all the parameters,
|
||||
* then passing the list to the NetSTask object.
|
||||
*XXXX
|
||||
* There is a single special in the call to a system task. Normally,
|
||||
* an expression cannot take an unindexed memory. However, it is
|
||||
* possible to take a system task parameter a memory if the expression
|
||||
* is trivial.
|
||||
* There is a single special case in the call to a system
|
||||
* task. Normally, an expression cannot take an unindexed
|
||||
* memory. However, it is possible to take a system task parameter a
|
||||
* memory if the expression is trivial.
|
||||
*/
|
||||
NetProc* PCallTask::elaborate_sys(Design*des, NetScope*scope) const
|
||||
{
|
||||
assert(scope);
|
||||
|
||||
svector<NetExpr*>eparms (nparms());
|
||||
unsigned parm_count = nparms();
|
||||
|
||||
for (unsigned idx = 0 ; idx < nparms() ; idx += 1) {
|
||||
/* Catch the special case that the system task has no
|
||||
parameters. The "()" string will be parsed as a single
|
||||
empty parameter, when we really mean no parameters at all. */
|
||||
if ((nparms() == 1) && (parm(0) == 0))
|
||||
parm_count = 0;
|
||||
|
||||
svector<NetExpr*>eparms (parm_count);
|
||||
|
||||
for (unsigned idx = 0 ; idx < parm_count ; idx += 1) {
|
||||
PExpr*ex = parm(idx);
|
||||
|
||||
eparms[idx] = ex? ex->elaborate_expr(des, scope) : 0;
|
||||
eparms[idx] = ex? ex->elaborate_expr(des, scope, true) : 0;
|
||||
}
|
||||
|
||||
NetSTask*cur = new NetSTask(path_.peek_name(0), eparms);
|
||||
@@ -1401,7 +1475,7 @@ NetProc* PCallTask::elaborate_usr(Design*des, NetScope*scope) const
|
||||
return cur;
|
||||
}
|
||||
|
||||
NetBlock*block = new NetBlock(NetBlock::SEQU);
|
||||
NetBlock*block = new NetBlock(NetBlock::SEQU, 0);
|
||||
|
||||
|
||||
/* Detect the case where the definition of the task is known
|
||||
@@ -1456,26 +1530,25 @@ NetProc* PCallTask::elaborate_usr(Design*des, NetScope*scope) const
|
||||
if (port->port_type() == NetNet::PINPUT)
|
||||
continue;
|
||||
|
||||
/* Handle the special case that the output parameter is
|
||||
a memory word. Generate a NetAssignMem instead of a
|
||||
NetAssign. */
|
||||
NetMemory*mem;
|
||||
const PEIdent*id = dynamic_cast<const PEIdent*>(parms_[idx]);
|
||||
if (id && (mem = des->find_memory(scope, id->path()))) {
|
||||
|
||||
NetExpr*ix = id->msb_->elaborate_expr(des, scope);
|
||||
assert(ix);
|
||||
|
||||
NetExpr*rx = new NetESignal(port);
|
||||
NetAssignMem*am = new NetAssignMem(mem, ix, rx);
|
||||
block->append(am);
|
||||
continue;
|
||||
/* 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);
|
||||
if (lv == 0) {
|
||||
cerr << parms_[idx]->get_line() << ": error: "
|
||||
<< "I give up on task port " << (idx+1)
|
||||
<< " expression: " << *parms_[idx] << endl;
|
||||
}
|
||||
} else {
|
||||
lv = 0;
|
||||
}
|
||||
|
||||
|
||||
NetAssign_*lv = parms_[idx]
|
||||
? parms_[idx]->elaborate_lval(des, scope)
|
||||
: 0;
|
||||
if (lv == 0)
|
||||
continue;
|
||||
|
||||
@@ -1520,7 +1593,7 @@ NetDeassign* PDeassign::elaborate(Design*des, NetScope*scope) const
|
||||
{
|
||||
assert(scope);
|
||||
|
||||
NetNet*lval = lval_->elaborate_net(des, scope, 0, 0, 0, 0);
|
||||
NetNet*lval = lval_->elaborate_anet(des, scope);
|
||||
if (lval == 0)
|
||||
return 0;
|
||||
|
||||
@@ -1738,8 +1811,12 @@ NetProc* PEventStatement::elaborate_st(Design*des, NetScope*scope,
|
||||
|
||||
if ((expr_.count() == 1) && (expr_[0]->type() == PEEvent::POSITIVE)) {
|
||||
|
||||
bool save_flag = error_implicit;
|
||||
error_implicit = true;
|
||||
NetNet*ex = expr_[0]->expr()->elaborate_net(des, scope,
|
||||
1, 0, 0, 0);
|
||||
error_implicit = save_flag;
|
||||
|
||||
if (ex == 0) {
|
||||
expr_[0]->dump(cerr);
|
||||
cerr << endl;
|
||||
@@ -1762,8 +1839,10 @@ NetProc* PEventStatement::elaborate_st(Design*des, NetScope*scope,
|
||||
|
||||
des->add_node(po);
|
||||
|
||||
/* We want to wait only if the expression is something
|
||||
other then 1 (0,x,z) . */
|
||||
NetESignal*ce = new NetESignal(ex);
|
||||
NetCondit*co = new NetCondit(new NetEUnary('!', ce), we, 0);
|
||||
NetCondit*co = new NetCondit(ce, 0, we);
|
||||
|
||||
ev->set_line(*this);
|
||||
we->set_line(*this);
|
||||
@@ -1776,7 +1855,7 @@ NetProc* PEventStatement::elaborate_st(Design*des, NetScope*scope,
|
||||
block to join the wait and the statement. */
|
||||
|
||||
if (enet) {
|
||||
NetBlock*bl = new NetBlock(NetBlock::SEQU);
|
||||
NetBlock*bl = new NetBlock(NetBlock::SEQU, 0);
|
||||
bl->set_line(*this);
|
||||
bl->append(co);
|
||||
bl->append(enet);
|
||||
@@ -1794,7 +1873,7 @@ NetProc* PEventStatement::elaborate_st(Design*des, NetScope*scope,
|
||||
assert(expr_[0]->expr());
|
||||
PEIdent*id = dynamic_cast<PEIdent*>(expr_[0]->expr());
|
||||
NetEvent*ev;
|
||||
if (id && (ev = scope->find_event(id->path()))) {
|
||||
if (id && (ev = des->find_event(scope, id->path()))) {
|
||||
NetEvWait*pr = new NetEvWait(enet);
|
||||
pr->add_event(ev);
|
||||
pr->set_line(*this);
|
||||
@@ -1814,7 +1893,38 @@ NetProc* PEventStatement::elaborate_st(Design*des, NetScope*scope,
|
||||
NetEvWait*wa = new NetEvWait(enet);
|
||||
wa->set_line(*this);
|
||||
|
||||
for (unsigned idx = 0 ; idx < expr_.count() ; idx += 1) {
|
||||
/* If there are no expressions, this is a signal that it is an
|
||||
@* statement. Generate an expression to use. */
|
||||
|
||||
if (expr_.count() == 0) {
|
||||
assert(enet);
|
||||
NexusSet*nset = enet->nex_input();
|
||||
if (nset == 0) {
|
||||
cerr << get_line() << ": internal error: No NexusSet"
|
||||
<< " from statement." << endl;
|
||||
enet->dump(cerr, 6);
|
||||
des->errors += 1;
|
||||
return enet;
|
||||
}
|
||||
|
||||
if (nset->count() == 0) {
|
||||
cerr << get_line() << ": warning: No inputs to statement."
|
||||
<< " Ignoring @*." << endl;
|
||||
return enet;
|
||||
}
|
||||
|
||||
NetEvProbe*pr = new NetEvProbe(scope, scope->local_hsymbol(),
|
||||
ev, NetEvProbe::ANYEDGE,
|
||||
nset->count());
|
||||
for (unsigned idx = 0 ; idx < nset->count() ; idx += 1)
|
||||
connect(nset[0][idx], pr->pin(idx));
|
||||
|
||||
delete nset;
|
||||
des->add_node(pr);
|
||||
|
||||
expr_count = 1;
|
||||
|
||||
} else for (unsigned idx = 0 ; idx < expr_.count() ; idx += 1) {
|
||||
|
||||
assert(expr_[idx]->expr());
|
||||
|
||||
@@ -1823,7 +1933,7 @@ NetProc* PEventStatement::elaborate_st(Design*des, NetScope*scope,
|
||||
skip the rest of the expression handling. */
|
||||
|
||||
if (PEIdent*id = dynamic_cast<PEIdent*>(expr_[idx]->expr())) {
|
||||
NetEvent*tmp = scope->find_event(id->path());
|
||||
NetEvent*tmp = des->find_event(scope, id->path());
|
||||
if (tmp) {
|
||||
wa->add_event(tmp);
|
||||
continue;
|
||||
@@ -1834,8 +1944,11 @@ NetProc* PEventStatement::elaborate_st(Design*des, NetScope*scope,
|
||||
the sub-expression as a net and decide how to handle
|
||||
the edge. */
|
||||
|
||||
bool save_flag = error_implicit;
|
||||
error_implicit = true;
|
||||
NetNet*expr = expr_[idx]->expr()->elaborate_net(des, scope,
|
||||
0, 0, 0, 0);
|
||||
error_implicit = save_flag;
|
||||
if (expr == 0) {
|
||||
expr_[idx]->dump(cerr);
|
||||
cerr << endl;
|
||||
@@ -1879,15 +1992,13 @@ NetProc* PEventStatement::elaborate_st(Design*des, NetScope*scope,
|
||||
expression (and not a named event) then add this
|
||||
event. Otherwise, we didn't use it so delete it. */
|
||||
if (expr_count > 0) {
|
||||
if (NetEvent*match = ev->find_similar_event()) {
|
||||
delete ev;
|
||||
wa->add_event(match);
|
||||
|
||||
} else {
|
||||
|
||||
scope->add_event(ev);
|
||||
wa->add_event(ev);
|
||||
}
|
||||
scope->add_event(ev);
|
||||
wa->add_event(ev);
|
||||
/* NOTE: This event that I am adding to the wait may be
|
||||
a duplicate of another event somewhere else. However,
|
||||
I don't know that until all the modules are hooked
|
||||
up, so it is best to leave find_similar_event to
|
||||
after elaboration. */
|
||||
} else {
|
||||
delete ev;
|
||||
}
|
||||
@@ -1969,7 +2080,7 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const
|
||||
const PEIdent*id2 = dynamic_cast<const PEIdent*>(name2_);
|
||||
assert(id2);
|
||||
|
||||
NetBlock*top = new NetBlock(NetBlock::SEQU);
|
||||
NetBlock*top = new NetBlock(NetBlock::SEQU, 0);
|
||||
|
||||
/* make the expression, and later the initial assignment to
|
||||
the condition variable. The statement in the for loop is
|
||||
@@ -1993,7 +2104,7 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const
|
||||
|
||||
top->append(init);
|
||||
|
||||
NetBlock*body = new NetBlock(NetBlock::SEQU);
|
||||
NetBlock*body = new NetBlock(NetBlock::SEQU, 0);
|
||||
|
||||
/* Elaborate the statement that is contained in the for
|
||||
loop. If there is an error, this will return 0 and I should
|
||||
@@ -2123,7 +2234,7 @@ NetProc* PRepeat::elaborate(Design*des, NetScope*scope) const
|
||||
case 0:
|
||||
delete expr;
|
||||
delete stat;
|
||||
return new NetBlock(NetBlock::SEQU);
|
||||
return new NetBlock(NetBlock::SEQU, 0);
|
||||
case 1:
|
||||
delete expr;
|
||||
return stat;
|
||||
@@ -2174,7 +2285,7 @@ void PTask::elaborate(Design*des, NetScope*task) const
|
||||
NetProc*st;
|
||||
if (statement_ == 0) {
|
||||
cerr << get_line() << ": warning: task has no statement." << endl;
|
||||
st = new NetBlock(NetBlock::SEQU);
|
||||
st = new NetBlock(NetBlock::SEQU, 0);
|
||||
|
||||
} else {
|
||||
|
||||
@@ -2194,7 +2305,7 @@ NetProc* PTrigger::elaborate(Design*des, NetScope*scope) const
|
||||
{
|
||||
assert(scope);
|
||||
|
||||
NetEvent*ev = scope->find_event(event_);
|
||||
NetEvent*ev = des->find_event(scope, event_);
|
||||
if (ev == 0) {
|
||||
cerr << get_line() << ": error: event <" << event_ << ">"
|
||||
<< " not found." << endl;
|
||||
@@ -2260,7 +2371,9 @@ bool Module::elaborate(Design*des, NetScope*scope) const
|
||||
(*gt)->elaborate(des, scope);
|
||||
}
|
||||
|
||||
// Elaborate the behaviors, making processes out of them.
|
||||
// Elaborate the behaviors, making processes out of them. This
|
||||
// involves scanning the PProcess* list, creating a NetProcTop
|
||||
// for each process.
|
||||
const list<PProcess*>&sl = get_behaviors();
|
||||
|
||||
for (list<PProcess*>::const_iterator st = sl.begin()
|
||||
@@ -2283,6 +2396,21 @@ bool Module::elaborate(Design*des, NetScope*scope) const
|
||||
break;
|
||||
}
|
||||
|
||||
// Evaluate the attributes for this process, if there
|
||||
// are any. These attributes are to be attached to the
|
||||
// NetProcTop object.
|
||||
struct attrib_list_t*attrib_list = 0;
|
||||
unsigned attrib_list_n = 0;
|
||||
attrib_list = evaluate_attributes((*st)->attributes,
|
||||
attrib_list_n,
|
||||
des, scope);
|
||||
|
||||
for (unsigned adx = 0 ; adx < attrib_list_n ; adx += 1)
|
||||
top->attribute(attrib_list[adx].key,
|
||||
attrib_list[adx].val);
|
||||
|
||||
delete[]attrib_list;
|
||||
|
||||
top->set_line(*(*st));
|
||||
des->add_process(top);
|
||||
}
|
||||
@@ -2394,53 +2522,49 @@ Design* elaborate(list<const char*>roots)
|
||||
|
||||
/*
|
||||
* $Log: elaborate.cc,v $
|
||||
* Revision 1.236 2001/12/06 05:04:49 steve
|
||||
* Forgot to evaluate UDP delays.
|
||||
* Revision 1.263 2002/08/28 18:54:36 steve
|
||||
* Evaluate nonblocking assign r-values.
|
||||
*
|
||||
* Revision 1.235 2001/12/06 04:44:11 steve
|
||||
* Support delays on UDP instances.
|
||||
* Revision 1.262 2002/08/15 02:11:54 steve
|
||||
* Handle special case of empty system task argument list.
|
||||
*
|
||||
* Revision 1.234 2001/12/03 04:47:14 steve
|
||||
* Parser and pform use hierarchical names as hname_t
|
||||
* objects instead of encoded strings.
|
||||
* Revision 1.261 2002/08/13 05:35:00 steve
|
||||
* Do not elide named blocks.
|
||||
*
|
||||
* Revision 1.233 2001/11/22 06:20:59 steve
|
||||
* Use NetScope instead of string for scope path.
|
||||
* Revision 1.260 2002/08/12 01:34:59 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.232 2001/11/08 05:15:50 steve
|
||||
* Remove string paths from PExpr elaboration.
|
||||
* Revision 1.259 2002/07/31 23:55:38 steve
|
||||
* Add port name to pin size error message.
|
||||
*
|
||||
* Revision 1.231 2001/11/07 04:26:46 steve
|
||||
* elaborate_lnet uses scope instead of string path.
|
||||
* Revision 1.258 2002/07/24 16:22:59 steve
|
||||
* Save event matching for nodangle.
|
||||
*
|
||||
* Revision 1.230 2001/11/07 04:01:59 steve
|
||||
* eval_const uses scope instead of a string path.
|
||||
* Revision 1.257 2002/07/18 02:06:37 steve
|
||||
* Need driver for sure in assign feedback and other cases.
|
||||
*
|
||||
* Revision 1.229 2001/11/04 23:12:29 steve
|
||||
* Pad limited r-values in continuous assignments.
|
||||
* Revision 1.256 2002/07/18 00:24:22 steve
|
||||
* Careful with assign to self.
|
||||
*
|
||||
* Revision 1.228 2001/10/31 03:22:31 steve
|
||||
* Give up if roots are missing.
|
||||
* Revision 1.255 2002/07/03 05:34:59 steve
|
||||
* Fix scope search for events.
|
||||
*
|
||||
* Revision 1.227 2001/10/28 01:14:53 steve
|
||||
* NetObj constructor finally requires a scope.
|
||||
* Revision 1.254 2002/06/19 04:20:03 steve
|
||||
* Remove NetTmp and add NetSubnet class.
|
||||
*
|
||||
* Revision 1.226 2001/10/22 23:26:37 steve
|
||||
* Better error message for mising root module.
|
||||
* Revision 1.253 2002/06/05 03:44:25 steve
|
||||
* Add support for memory words in l-value of
|
||||
* non-blocking assignments, and remove the special
|
||||
* NetAssignMem_ and NetAssignMemNB classes.
|
||||
*
|
||||
* Revision 1.225 2001/10/22 02:05:20 steve
|
||||
* Handle activating tasks in another root.
|
||||
* Revision 1.252 2002/06/04 05:38:44 steve
|
||||
* Add support for memory words in l-value of
|
||||
* blocking assignments, and remove the special
|
||||
* NetAssignMem class.
|
||||
*
|
||||
* Revision 1.224 2001/10/21 00:42:47 steve
|
||||
* Module types in pform are char* instead of string.
|
||||
*
|
||||
* Revision 1.223 2001/10/20 23:02:40 steve
|
||||
* Add automatic module libraries.
|
||||
*
|
||||
* Revision 1.222 2001/10/20 05:21:51 steve
|
||||
* Scope/module names are char* instead of string.
|
||||
*
|
||||
* Revision 1.221 2001/10/19 21:53:24 steve
|
||||
* Support multiple root modules (Philip Blundell)
|
||||
* Revision 1.251 2002/05/27 00:08:45 steve
|
||||
* Support carrying the scope of named begin-end
|
||||
* blocks down to the code generator, and have
|
||||
* the vvp code generator use that to support disable.
|
||||
*/
|
||||
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: emit.cc,v 1.63 2001/10/19 21:53:24 steve Exp $"
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: emit.cc,v 1.69 2002/08/12 01:34:59 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -128,6 +128,11 @@ bool NetRamDq::emit_node(struct target_t*tgt) const
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetUserFunc::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->net_function(this);
|
||||
}
|
||||
|
||||
bool NetBUFZ::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->bufz(this);
|
||||
@@ -156,18 +161,6 @@ bool NetAssignNB::emit_proc(struct target_t*tgt) const
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetAssignMem::emit_proc(struct target_t*tgt) const
|
||||
{
|
||||
tgt->proc_assign_mem(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetAssignMemNB::emit_proc(struct target_t*tgt) const
|
||||
{
|
||||
tgt->proc_assign_mem_nb(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetBlock::emit_proc(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->proc_block(this);
|
||||
@@ -186,8 +179,7 @@ bool NetCAssign::emit_proc(struct target_t*tgt) const
|
||||
|
||||
bool NetCondit::emit_proc(struct target_t*tgt) const
|
||||
{
|
||||
tgt->proc_condit(this);
|
||||
return true;
|
||||
return tgt->proc_condit(this);
|
||||
}
|
||||
|
||||
bool NetDeassign::emit_proc(struct target_t*tgt) const
|
||||
@@ -263,16 +255,20 @@ void NetBlock::emit_recurse(struct target_t*tgt) const
|
||||
} while (cur != last_);
|
||||
}
|
||||
|
||||
void NetCondit::emit_recurse_if(struct target_t*tgt) const
|
||||
bool NetCondit::emit_recurse_if(struct target_t*tgt) const
|
||||
{
|
||||
if (if_)
|
||||
if_->emit_proc(tgt);
|
||||
return if_->emit_proc(tgt);
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
void NetCondit::emit_recurse_else(struct target_t*tgt) const
|
||||
bool NetCondit::emit_recurse_else(struct target_t*tgt) const
|
||||
{
|
||||
if (else_)
|
||||
else_->emit_proc(tgt);
|
||||
return else_->emit_proc(tgt);
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetEvProbe::emit_node(struct target_t*tgt) const
|
||||
@@ -431,6 +427,11 @@ void NetEScope::expr_scan(struct expr_scan_t*tgt) const
|
||||
tgt->expr_scope(this);
|
||||
}
|
||||
|
||||
void NetESelect::expr_scan(struct expr_scan_t*tgt) const
|
||||
{
|
||||
tgt->expr_select(this);
|
||||
}
|
||||
|
||||
void NetESFunc::expr_scan(struct expr_scan_t*tgt) const
|
||||
{
|
||||
tgt->expr_sfunc(this);
|
||||
@@ -474,6 +475,30 @@ bool emit(const Design*des, const char*type)
|
||||
|
||||
/*
|
||||
* $Log: emit.cc,v $
|
||||
* Revision 1.69 2002/08/12 01:34:59 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.68 2002/06/05 03:44:25 steve
|
||||
* Add support for memory words in l-value of
|
||||
* non-blocking assignments, and remove the special
|
||||
* NetAssignMem_ and NetAssignMemNB classes.
|
||||
*
|
||||
* Revision 1.67 2002/06/04 05:38:44 steve
|
||||
* Add support for memory words in l-value of
|
||||
* blocking assignments, and remove the special
|
||||
* NetAssignMem class.
|
||||
*
|
||||
* Revision 1.66 2002/03/09 02:10:22 steve
|
||||
* Add the NetUserFunc netlist node.
|
||||
*
|
||||
* Revision 1.65 2002/01/28 00:52:41 steve
|
||||
* Add support for bit select of parameters.
|
||||
* This leads to a NetESelect node and the
|
||||
* vvp code generator to support that.
|
||||
*
|
||||
* Revision 1.64 2002/01/19 19:02:08 steve
|
||||
* Pass back target errors processing conditionals.
|
||||
*
|
||||
* Revision 1.63 2001/10/19 21:53:24 steve
|
||||
* Support multiple root modules (Philip Blundell)
|
||||
*
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: eval.cc,v 1.24 2001/12/03 04:47:15 steve Exp $"
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: eval.cc,v 1.32 2002/10/19 22:59:49 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -46,46 +46,56 @@ verinum* PEBinary::eval_const(const Design*des, const NetScope*scope) const
|
||||
|
||||
switch (op_) {
|
||||
case '+': {
|
||||
assert(l->is_defined());
|
||||
assert(r->is_defined());
|
||||
long lv = l->as_long();
|
||||
long rv = r->as_long();
|
||||
res = new verinum(lv+rv, l->len());
|
||||
if (l->is_defined() && r->is_defined()) {
|
||||
long lv = l->as_long();
|
||||
long rv = r->as_long();
|
||||
res = new verinum(lv+rv, l->len());
|
||||
} else {
|
||||
res = new verinum(verinum::Vx, l->len());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case '-': {
|
||||
assert(l->is_defined());
|
||||
assert(r->is_defined());
|
||||
long lv = l->as_long();
|
||||
long rv = r->as_long();
|
||||
res = new verinum(lv-rv, l->len());
|
||||
if (l->is_defined() && r->is_defined()) {
|
||||
long lv = l->as_long();
|
||||
long rv = r->as_long();
|
||||
res = new verinum(lv-rv, l->len());
|
||||
} else {
|
||||
res = new verinum(verinum::Vx, l->len());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case '*': {
|
||||
assert(l->is_defined());
|
||||
assert(r->is_defined());
|
||||
long lv = l->as_long();
|
||||
long rv = r->as_long();
|
||||
res = new verinum(lv * rv, l->len());
|
||||
if (l->is_defined() && r->is_defined()) {
|
||||
long lv = l->as_long();
|
||||
long rv = r->as_long();
|
||||
res = new verinum(lv * rv, l->len());
|
||||
} else {
|
||||
res = new verinum(verinum::Vx, l->len());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case '/': {
|
||||
assert(l->is_defined());
|
||||
assert(r->is_defined());
|
||||
long lv = l->as_long();
|
||||
long rv = r->as_long();
|
||||
res = new verinum(lv / rv, l->len());
|
||||
if (l->is_defined() && r->is_defined()) {
|
||||
long lv = l->as_long();
|
||||
long rv = r->as_long();
|
||||
res = new verinum(lv / rv, l->len());
|
||||
} else {
|
||||
res = new verinum(verinum::Vx, l->len());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case '%': {
|
||||
assert(l->is_defined());
|
||||
assert(r->is_defined());
|
||||
long lv = l->as_long();
|
||||
long rv = r->as_long();
|
||||
res = new verinum(lv % rv, l->len());
|
||||
if (l->is_defined() && r->is_defined()) {
|
||||
long lv = l->as_long();
|
||||
long rv = r->as_long();
|
||||
res = new verinum(lv % rv, l->len());
|
||||
} else {
|
||||
res = new verinum(verinum::Vx, l->len());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'l': {
|
||||
case 'l': { // left shift (<<)
|
||||
assert(r->is_defined());
|
||||
unsigned long rv = r->as_ulong();
|
||||
res = new verinum(verinum::V0, l->len());
|
||||
@@ -96,6 +106,17 @@ verinum* PEBinary::eval_const(const Design*des, const NetScope*scope) const
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'r': { // right shift (>>)
|
||||
assert(r->is_defined());
|
||||
unsigned long rv = r->as_ulong();
|
||||
res = new verinum(verinum::V0, l->len());
|
||||
if (rv < res->len()) {
|
||||
unsigned cnt = res->len() - rv;
|
||||
for (unsigned idx = 0 ; idx < cnt ; idx += 1)
|
||||
res->set(idx, l->get(idx+rv));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
delete l;
|
||||
@@ -121,16 +142,20 @@ verinum* PEIdent::eval_const(const Design*des, const NetScope*scope) const
|
||||
if (expr == 0)
|
||||
return 0;
|
||||
|
||||
assert(msb_ == 0);
|
||||
|
||||
if (dynamic_cast<const NetEParam*>(expr)) {
|
||||
cerr << get_line() << ": sorry: I cannot evaluate ``" <<
|
||||
path_ << "'' in this scope: " << scope->name() << endl;
|
||||
const NetEConst*eval = dynamic_cast<const NetEConst*>(expr);
|
||||
if (eval == 0) {
|
||||
cerr << get_line() << ": internal error: Unable to evaluate "
|
||||
<< "constant expression (parameter=" << path_
|
||||
<< "): " << *expr << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const NetEConst*eval = dynamic_cast<const NetEConst*>(expr);
|
||||
assert(eval);
|
||||
|
||||
if (msb_ || lsb_)
|
||||
return 0;
|
||||
|
||||
|
||||
return new verinum(eval->value());
|
||||
}
|
||||
|
||||
@@ -145,6 +170,11 @@ verinum* PENumber::eval_const(const Design*, const NetScope*) const
|
||||
return new verinum(value());
|
||||
}
|
||||
|
||||
verinum* PEString::eval_const(const Design*, const NetScope*) const
|
||||
{
|
||||
return new verinum(string(text_));
|
||||
}
|
||||
|
||||
verinum* PETernary::eval_const(const Design*des, const NetScope*scope) const
|
||||
{
|
||||
verinum*test = expr_->eval_const(des, scope);
|
||||
@@ -196,6 +226,36 @@ verinum* PEUnary::eval_const(const Design*des, const NetScope*scope) const
|
||||
|
||||
/*
|
||||
* $Log: eval.cc,v $
|
||||
* Revision 1.32 2002/10/19 22:59:49 steve
|
||||
* Redo the parameter vector support to allow
|
||||
* parameter names in range expressions.
|
||||
*
|
||||
* Revision 1.31 2002/10/13 05:01:07 steve
|
||||
* More verbose eval_const assert message.
|
||||
*
|
||||
* Revision 1.30 2002/08/12 01:34:59 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.29 2002/06/07 02:57:54 steve
|
||||
* Simply give up on constants with indices.
|
||||
*
|
||||
* Revision 1.28 2002/06/06 18:57:04 steve
|
||||
* Better error for identifier index eval.
|
||||
*
|
||||
* Revision 1.27 2002/05/23 03:08:51 steve
|
||||
* Add language support for Verilog-2001 attribute
|
||||
* syntax. Hook this support into existing $attribute
|
||||
* handling, and add number and void value types.
|
||||
*
|
||||
* Add to the ivl_target API new functions for access
|
||||
* of complex attributes attached to gates.
|
||||
*
|
||||
* Revision 1.26 2001/12/29 22:10:10 steve
|
||||
* constant eval of arithmetic with x and z.
|
||||
*
|
||||
* Revision 1.25 2001/12/29 00:43:55 steve
|
||||
* Evaluate constant right shifts.
|
||||
*
|
||||
* Revision 1.24 2001/12/03 04:47:15 steve
|
||||
* Parser and pform use hierarchical names as hname_t
|
||||
* objects instead of encoded strings.
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright (c) 2002 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: eval_attrib.cc,v 1.5 2002/08/12 01:34:59 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
# include "util.h"
|
||||
# include "PExpr.h"
|
||||
# include "netlist.h"
|
||||
# include <iostream>
|
||||
# include <assert.h>
|
||||
|
||||
/*
|
||||
* The evaluate_attributes function evaluates the attribute
|
||||
* expressions from the map, and resturns a table in a form suitable
|
||||
* for passing to netlist devices.
|
||||
*/
|
||||
|
||||
attrib_list_t* evaluate_attributes(const map<string,PExpr*>&att,
|
||||
unsigned&natt,
|
||||
const Design*des,
|
||||
const NetScope*scope)
|
||||
{
|
||||
natt = att.size();
|
||||
if (natt == 0)
|
||||
return 0;
|
||||
|
||||
attrib_list_t*table = new attrib_list_t [natt];
|
||||
|
||||
unsigned idx = 0;
|
||||
|
||||
typedef map<string,PExpr*>::const_iterator iter_t;
|
||||
for (iter_t cur = att.begin() ; cur != att.end() ; cur ++, idx++) {
|
||||
table[idx].key = (*cur).first;
|
||||
PExpr*exp = (*cur).second;
|
||||
|
||||
/* If the attribute value is given in the source, then
|
||||
evalulate it as a constant. If the value is not
|
||||
given, then assume the value is 1. */
|
||||
verinum*tmp;
|
||||
if (exp)
|
||||
tmp = exp->eval_const(des, scope);
|
||||
else
|
||||
tmp = new verinum(1);
|
||||
|
||||
if (tmp == 0)
|
||||
cerr << "internal error: no result for " << *exp << endl;
|
||||
assert(tmp);
|
||||
|
||||
table[idx].val = *tmp;
|
||||
delete tmp;
|
||||
}
|
||||
|
||||
assert(idx == natt);
|
||||
return table;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: eval_attrib.cc,v $
|
||||
* Revision 1.5 2002/08/12 01:34:59 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.4 2002/08/10 21:59:39 steve
|
||||
* The default attribute value is 1.
|
||||
*
|
||||
* Revision 1.3 2002/06/06 18:57:18 steve
|
||||
* Use standard name for iostream.
|
||||
*
|
||||
* Revision 1.2 2002/06/03 03:55:14 steve
|
||||
* compile warnings.
|
||||
*
|
||||
* Revision 1.1 2002/05/23 03:08:51 steve
|
||||
* Add language support for Verilog-2001 attribute
|
||||
* syntax. Hook this support into existing $attribute
|
||||
* handling, and add number and void value types.
|
||||
*
|
||||
* Add to the ivl_target API new functions for access
|
||||
* of complex attributes attached to gates.
|
||||
*
|
||||
*/
|
||||
|
||||
+5
-2
@@ -16,8 +16,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: eval_rconst.cc,v 1.4 2001/11/07 04:01:59 steve Exp $"
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: eval_rconst.cc,v 1.5 2002/08/12 01:34:59 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -81,6 +81,9 @@ verireal* PEIdent::eval_rconst(const Design*des, const NetScope*scope) const
|
||||
|
||||
/*
|
||||
* $Log: eval_rconst.cc,v $
|
||||
* Revision 1.5 2002/08/12 01:34:59 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.4 2001/11/07 04:01:59 steve
|
||||
* eval_const uses scope instead of a string path.
|
||||
*
|
||||
|
||||
+202
-29
@@ -16,8 +16,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: eval_tree.cc,v 1.30 2001/12/03 04:47:15 steve Exp $"
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: eval_tree.cc,v 1.42 2002/10/19 22:59:49 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -81,8 +81,22 @@ NetEConst* NetEBBits::eval_tree()
|
||||
eval_sub_tree_();
|
||||
|
||||
NetEConst*lc = dynamic_cast<NetEConst*>(left_);
|
||||
if (lc == 0) return 0;
|
||||
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
|
||||
|
||||
/* Notice the special case where one of the operands is 0 and
|
||||
this is a bitwise &. If this happens, then the result is
|
||||
known to be 0. */
|
||||
if ((op() == '&') && lc && (lc->value() == verinum(0))) {
|
||||
verinum res (verinum::V0, expr_width());
|
||||
return new NetEConst(res);
|
||||
}
|
||||
|
||||
if ((op() == '&') && rc && (rc->value() == verinum(0))) {
|
||||
verinum res (verinum::V0, expr_width());
|
||||
return new NetEConst(res);
|
||||
}
|
||||
|
||||
if (lc == 0) return 0;
|
||||
if (rc == 0) return 0;
|
||||
|
||||
verinum lval = lc->value();
|
||||
@@ -210,14 +224,16 @@ NetEConst* NetEBComp::eval_less_()
|
||||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
if (lv.has_sign() && rv.has_sign() && (lv.as_long() < rv.as_long())) {
|
||||
verinum result(verinum::V1, 1);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
if (lv.as_ulong() < rv.as_ulong()) {
|
||||
verinum result(verinum::V1, 1);
|
||||
return new NetEConst(result);
|
||||
if (lv.has_sign() && rv.has_sign()) {
|
||||
if (lv.as_long() < rv.as_long()) {
|
||||
verinum result(verinum::V1, 1);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
} else {
|
||||
if (lv.as_ulong() < rv.as_ulong()) {
|
||||
verinum result(verinum::V1, 1);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
}
|
||||
|
||||
verinum result(verinum::V0, 1);
|
||||
@@ -235,6 +251,7 @@ NetEConst* NetEBComp::eval_leeq_()
|
||||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
|
||||
/* Detect the case where the right side is greater that or
|
||||
equal to the largest value the left side can possibly
|
||||
have. */
|
||||
@@ -254,14 +271,16 @@ NetEConst* NetEBComp::eval_leeq_()
|
||||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
if (lv.has_sign() && rv.has_sign() && (lv.as_long() <= rv.as_long())) {
|
||||
verinum result(verinum::V1, 1);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
if (lv.as_ulong() <= rv.as_ulong()) {
|
||||
verinum result(verinum::V1, 1);
|
||||
return new NetEConst(result);
|
||||
if (lv.has_sign() && rv.has_sign()) {
|
||||
if (lv.as_long() <= rv.as_long()) {
|
||||
verinum result(verinum::V1, 1);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
} else {
|
||||
if (lv.as_ulong() <= rv.as_ulong()) {
|
||||
verinum result(verinum::V1, 1);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
}
|
||||
|
||||
verinum result(verinum::V0, 1);
|
||||
@@ -700,6 +719,10 @@ NetEConst* NetEBShift::eval_tree()
|
||||
|
||||
NetEConst* NetEConcat::eval_tree()
|
||||
{
|
||||
unsigned repeat_val = repeat();
|
||||
unsigned local_errors = 0;
|
||||
|
||||
unsigned gap = 0;
|
||||
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
|
||||
|
||||
// Parameter not here? This is an error, but presumably
|
||||
@@ -707,10 +730,13 @@ NetEConst* NetEConcat::eval_tree()
|
||||
if (parms_[idx] == 0)
|
||||
continue;
|
||||
|
||||
|
||||
// If this parameter is already a constant, all is well
|
||||
// so go on.
|
||||
if (dynamic_cast<NetEConst*>(parms_[idx]))
|
||||
if (dynamic_cast<NetEConst*>(parms_[idx])) {
|
||||
gap += parms_[idx]->expr_width();
|
||||
continue;
|
||||
}
|
||||
|
||||
// Finally, try to evaluate the parameter expression
|
||||
// that is here. If I succeed, reset the parameter to
|
||||
@@ -720,37 +746,58 @@ NetEConst* NetEConcat::eval_tree()
|
||||
if (expr) {
|
||||
delete parms_[idx];
|
||||
parms_[idx] = expr;
|
||||
|
||||
if (! expr->has_width()) {
|
||||
cerr << get_line() << ": error: concatenation "
|
||||
<< "operand has indefinite width: "
|
||||
<< *parms_[idx] << endl;
|
||||
local_errors += 1;
|
||||
}
|
||||
gap += expr->expr_width();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (local_errors > 0)
|
||||
return 0;
|
||||
|
||||
// Handle the special case that the repeat expression is
|
||||
// zero. In this case, just return a 0 value with the expected
|
||||
// width.
|
||||
if (repeat_ == 0) {
|
||||
if (repeat_val == 0) {
|
||||
verinum val (verinum::V0, expr_width());
|
||||
NetEConst*res = new NetEConst(val);
|
||||
res->set_width(val.len());
|
||||
return res;
|
||||
}
|
||||
|
||||
// Figure out the width of the repeated expression, and make a
|
||||
// verinum to hold the result.
|
||||
unsigned gap = expr_width() / repeat_;
|
||||
verinum val (verinum::Vx, repeat_ * gap);
|
||||
|
||||
// At this point, the "gap" is the width of a single repeat of
|
||||
// the concatenation. The total width of the result is the gap
|
||||
// times the repeat count.
|
||||
verinum val (verinum::Vx, repeat_val * gap);
|
||||
|
||||
// build up the result from least significant to most.
|
||||
|
||||
unsigned cur = 0;
|
||||
bool is_string_flag = true;
|
||||
for (unsigned idx = parms_.count() ; idx > 0 ; idx -= 1) {
|
||||
NetEConst*expr = dynamic_cast<NetEConst*>(parms_[idx-1]);
|
||||
if (expr == 0)
|
||||
return 0;
|
||||
|
||||
verinum tmp = expr->value();
|
||||
for (unsigned bit = 0 ; bit < tmp.len() ; bit += 1, cur += 1)
|
||||
for (unsigned rep = 0 ; rep < repeat_ ; rep += 1)
|
||||
for (unsigned bit = 0; bit < tmp.len(); bit += 1, cur += 1)
|
||||
for (unsigned rep = 0 ; rep < repeat_val ; rep += 1)
|
||||
val.set(rep*gap+cur, tmp[bit]);
|
||||
|
||||
is_string_flag = is_string_flag && tmp.is_string();
|
||||
}
|
||||
|
||||
/* If all the values were strings, then re-stringify this
|
||||
constant. This might be useful information in the code
|
||||
generator or other optimizer steps. */
|
||||
if (is_string_flag) {
|
||||
val = verinum(val.as_string());
|
||||
}
|
||||
|
||||
NetEConst*res = new NetEConst(val);
|
||||
@@ -758,6 +805,50 @@ NetEConst* NetEConcat::eval_tree()
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* There are limits to our ability to evaluate a memory reference
|
||||
* expression, because the content of a memory is never
|
||||
* constant. However, the index expression may be precalculated, and
|
||||
* there are certain index values that do give us constant results.
|
||||
*/
|
||||
NetExpr* NetEMemory::eval_tree()
|
||||
{
|
||||
/* Attempt to evaluate the index expression to a constant, if
|
||||
it is not already. */
|
||||
if (idx_ && !dynamic_cast<NetEConst*>(idx_)) {
|
||||
NetExpr* tmp = idx_->eval_tree();
|
||||
if (tmp) {
|
||||
delete idx_;
|
||||
idx_ = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
NetEConst*itmp = dynamic_cast<NetEConst*>(idx_);
|
||||
if (itmp == 0)
|
||||
return 0;
|
||||
|
||||
verinum ival = itmp->value();
|
||||
|
||||
/* If the index expression has any x or z bits, then we know
|
||||
already that the expression result is a constant x. */
|
||||
if (! ival.is_defined()) {
|
||||
verinum xres (verinum::Vx, mem_->width(), false);
|
||||
NetEConst*res = new NetEConst(xres);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* If the index expression is outside the range of the memory,
|
||||
then the result is a constant x. */
|
||||
unsigned norm_idx = mem_->index_to_address(ival.as_long());
|
||||
if (norm_idx >= mem_->count()) {
|
||||
verinum xres (verinum::Vx, mem_->width(), false);
|
||||
NetEConst*res = new NetEConst(xres);
|
||||
return res;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetExpr* NetEParam::eval_tree()
|
||||
{
|
||||
if (des_ == 0)
|
||||
@@ -793,7 +884,7 @@ NetExpr* NetEParam::eval_tree()
|
||||
|
||||
// The result can be saved as the value of the parameter for
|
||||
// future reference, and return a copy to the caller.
|
||||
scope_->set_parameter(name_.peek_name(0), res);
|
||||
scope_->replace_parameter(name_.peek_name(0), res);
|
||||
return res->dup_expr();
|
||||
}
|
||||
|
||||
@@ -911,6 +1002,24 @@ NetEConst* NetEUnary::eval_tree()
|
||||
|
||||
switch (op_) {
|
||||
|
||||
case '+':
|
||||
/* Unary + is a no-op. */
|
||||
return new NetEConst(val);
|
||||
|
||||
case '-': {
|
||||
if (val.is_defined()) {
|
||||
|
||||
verinum tmp (verinum::V0, val.len());
|
||||
tmp.has_sign(val.has_sign());
|
||||
val = tmp - val;
|
||||
|
||||
} else {
|
||||
for (unsigned idx = 0 ; idx < val.len() ; idx += 1)
|
||||
val.set(idx, verinum::Vx);
|
||||
}
|
||||
|
||||
return new NetEConst(val);
|
||||
}
|
||||
|
||||
case '~': {
|
||||
/* Bitwise not is even simpler then logical
|
||||
@@ -976,6 +1085,7 @@ NetEConst* NetEUReduce::eval_tree()
|
||||
}
|
||||
|
||||
res = v1? verinum::V0 : (vx? verinum::Vx : verinum::V1);
|
||||
break;
|
||||
}
|
||||
|
||||
case '&': {
|
||||
@@ -992,6 +1102,28 @@ NetEConst* NetEUReduce::eval_tree()
|
||||
break;
|
||||
}
|
||||
|
||||
case '^': {
|
||||
/* Reduction XOR. */
|
||||
unsigned ones = 0, unknown = 0;
|
||||
for (unsigned idx = 0 ; idx < val.len() ; idx += 1)
|
||||
switch (val.get(idx)) {
|
||||
case verinum::V0:
|
||||
break;
|
||||
case verinum::V1:
|
||||
ones += 1;
|
||||
break;
|
||||
default:
|
||||
unknown += 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (unknown)
|
||||
return new NetEConst(verinum(verinum::Vx,1,true));
|
||||
if (ones%2)
|
||||
return new NetEConst(verinum(verinum::V1,1,true));
|
||||
return new NetEConst(verinum(verinum::V0,1,true));
|
||||
}
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
@@ -1002,6 +1134,47 @@ NetEConst* NetEUReduce::eval_tree()
|
||||
|
||||
/*
|
||||
* $Log: eval_tree.cc,v $
|
||||
* Revision 1.42 2002/10/19 22:59:49 steve
|
||||
* Redo the parameter vector support to allow
|
||||
* parameter names in range expressions.
|
||||
*
|
||||
* Revision 1.41 2002/08/12 01:34:59 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.40 2002/05/25 16:43:47 steve
|
||||
* Eval ^ and &0 expressions.
|
||||
*
|
||||
* Revision 1.39 2002/05/06 02:30:27 steve
|
||||
* Allow parameters in concatenation of widths are defined.
|
||||
*
|
||||
* Revision 1.38 2002/05/05 21:11:50 steve
|
||||
* Put off evaluation of concatenation repeat expresions
|
||||
* until after parameters are defined. This allows parms
|
||||
* to be used in repeat expresions.
|
||||
*
|
||||
* Add the builtin $signed system function.
|
||||
*
|
||||
* Revision 1.37 2002/04/27 05:03:46 steve
|
||||
* Preserve stringiness string part select and concatenation.
|
||||
*
|
||||
* Revision 1.36 2002/04/27 03:17:15 steve
|
||||
* Fixup eval of signed constants.
|
||||
*
|
||||
* Revision 1.35 2002/04/24 02:47:02 steve
|
||||
* Fix compile time eval of signed <= signed.
|
||||
*
|
||||
* Revision 1.34 2002/04/14 19:28:47 steve
|
||||
* Fix constant evaluation of unary
|
||||
*
|
||||
* Revision 1.33 2002/02/01 05:09:14 steve
|
||||
* Propagate sign in unary minus.
|
||||
*
|
||||
* Revision 1.32 2002/01/22 01:40:04 steve
|
||||
* Precalculate constant results of memory index expressions.
|
||||
*
|
||||
* Revision 1.31 2001/12/30 00:39:25 steve
|
||||
* Evaluate constant unary minus.
|
||||
*
|
||||
* Revision 1.30 2001/12/03 04:47:15 steve
|
||||
* Parser and pform use hierarchical names as hname_t
|
||||
* objects instead of encoded strings.
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
,*
|
||||
hello_vpi.vpi
|
||||
show_vcd.vcd
|
||||
+1035
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (c) 2002 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: hello_vpi.c,v 1.3 2002/08/12 01:35:01 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This file contains an example VPI module to demonstrate the tools
|
||||
* to create vpi modules. To compile this module, use the iverilog-vpi
|
||||
* command like so:
|
||||
*
|
||||
* iverilog-vpi hello_vpi.c
|
||||
*
|
||||
* The result is the hello_vpi.vpi module. See the hello_vpi.vl
|
||||
* program for example Verilog code to call this module.
|
||||
*/
|
||||
|
||||
# include <vpi_user.h>
|
||||
|
||||
static int my_hello_calltf(char *xx)
|
||||
{
|
||||
vpi_printf("Hello World, from VPI.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void my_hello_register()
|
||||
{
|
||||
s_vpi_systf_data tf_data;
|
||||
|
||||
tf_data.type = vpiSysTask;
|
||||
tf_data.tfname = "$my_hello";
|
||||
tf_data.calltf = my_hello_calltf;
|
||||
tf_data.compiletf = 0;
|
||||
tf_data.sizetf = 0;
|
||||
vpi_register_systf(&tf_data);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a table of register functions. This table is the external
|
||||
* symbol that the simulator looks for when loading this .vpi module.
|
||||
*/
|
||||
void (*vlog_startup_routines[])() = {
|
||||
my_hello_register,
|
||||
0
|
||||
};
|
||||
/*
|
||||
* $Log: hello_vpi.c,v $
|
||||
* Revision 1.3 2002/08/12 01:35:01 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.2 2002/08/11 23:47:04 steve
|
||||
* Add missing Log and Ident strings.
|
||||
*
|
||||
* Revision 1.1 2002/04/18 03:25:16 steve
|
||||
* More examples.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (c) 2002 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* Here we have the canonical "Hello, World" program written in Verilog,
|
||||
* with VPI. It uses the hello_vpi.vpi module that is compiled from
|
||||
* the hello_vpi.c program also in this directory. See the
|
||||
* hello_vpi.c for instructions on how to compile it.
|
||||
*
|
||||
* Compile this program with the command:
|
||||
*
|
||||
* iverilog -ohello_vpi hello_vpi.vl
|
||||
*
|
||||
* After churning for a little while, the program will create the output
|
||||
* file "hello" which is compiled, linked and ready to run. Run this
|
||||
* program like so:
|
||||
*
|
||||
* vvp -M. -mhello_vpi hello_vpi
|
||||
*
|
||||
* and the program will print the message to its output. Easy! For
|
||||
* more on how to make the iverilog command work, see the iverilog
|
||||
* manual page.
|
||||
*/
|
||||
|
||||
module main();
|
||||
|
||||
initial
|
||||
begin
|
||||
$my_hello;
|
||||
$finish ;
|
||||
end
|
||||
|
||||
endmodule
|
||||
@@ -41,7 +41,7 @@
|
||||
* To view the output generated by running show_vcd, start the GTKWave
|
||||
* viewer with the command:
|
||||
*
|
||||
* wave show_vcd.vcd
|
||||
* gtkwave show_vcd.vcd
|
||||
*
|
||||
* The GTKWave program will display its main window, and show in a small
|
||||
* status box (upper left corner) that it succeeded in loading the dump
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
// This example describes a 16x1 RAM that can be synthesized into
|
||||
// a CLB ram in a Xilinx FPGA.
|
||||
|
||||
module ram16x1 (q, d, a, we, wclk);
|
||||
output q;
|
||||
input d;
|
||||
input [3:0] a;
|
||||
input we;
|
||||
input wclk;
|
||||
|
||||
reg mem[15:0];
|
||||
|
||||
assign q = mem[a];
|
||||
always @(posedge wclk) if (we) mem[a] = d;
|
||||
|
||||
endmodule /* ram16x1 */
|
||||
|
||||
module main;
|
||||
wire q;
|
||||
reg d;
|
||||
reg [3:0] a;
|
||||
reg we, wclk;
|
||||
|
||||
ram16x1 r1 (q, d, a, we, wclk);
|
||||
|
||||
initial begin
|
||||
$monitor("q = %b", q);
|
||||
d = 0;
|
||||
wclk = 0;
|
||||
a = 5;
|
||||
we = 1;
|
||||
#1 wclk = 1;
|
||||
#1 wclk = 0;
|
||||
end
|
||||
endmodule /* main */
|
||||
+82
-6
@@ -16,8 +16,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: expr_synth.cc,v 1.29 2001/11/29 01:58:18 steve Exp $"
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: expr_synth.cc,v 1.36 2002/08/12 01:34:59 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -50,6 +50,7 @@ NetNet* NetEBAdd::synthesize(Design*des)
|
||||
|
||||
string path = lsig->scope()->name()+"."+lsig->scope()->local_symbol();
|
||||
NetNet*osig = new NetNet(lsig->scope(), path, NetNet::IMPLICIT, width);
|
||||
osig->local_flag(true);
|
||||
|
||||
string oname = des->local_symbol(path);
|
||||
NetAddSub *adder = new NetAddSub(lsig->scope(), oname, width);
|
||||
@@ -62,10 +63,10 @@ NetNet* NetEBAdd::synthesize(Design*des)
|
||||
|
||||
switch (op()) {
|
||||
case '+':
|
||||
adder->attribute("LPM_Direction", "ADD");
|
||||
adder->attribute("LPM_Direction", verinum("ADD"));
|
||||
break;
|
||||
case '-':
|
||||
adder->attribute("LPM_Direction", "SUB");
|
||||
adder->attribute("LPM_Direction", verinum("SUB"));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -107,6 +108,26 @@ NetNet* NetEBBits::synthesize(Design*des)
|
||||
string oname = des->local_symbol(path);
|
||||
NetLogic*gate;
|
||||
|
||||
/* If the rsig bit is constant, then look for special
|
||||
cases that I can use to reduce the generated
|
||||
logic. If I find one, then handle it immediately and
|
||||
skip the rest of the processing of this bit. */
|
||||
if (rsig->pin(idx).nexus()->drivers_constant()) {
|
||||
verinum::V bval = rsig->pin(idx).nexus()->driven_value();
|
||||
|
||||
/* (A & 0) is (0) */
|
||||
if ((op() == '&') && bval == verinum::V0) {
|
||||
connect(osig->pin(idx), rsig->pin(idx));
|
||||
continue;
|
||||
}
|
||||
|
||||
/* (A & 1) is A */
|
||||
if ((op() == '&') && bval == verinum::V1) {
|
||||
connect(osig->pin(idx), lsig->pin(idx));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
switch (op()) {
|
||||
case '&':
|
||||
gate = new NetLogic(scope, oname, 3, NetLogic::AND);
|
||||
@@ -378,7 +399,7 @@ NetNet* NetEConcat::synthesize(Design*des)
|
||||
obit += 1;
|
||||
}
|
||||
|
||||
if (tmp[idx-1]->local_flag() && tmp[idx-1]->get_eref() == 0)
|
||||
if (tmp[idx-1]->local_flag() && tmp[idx-1]->get_refs() == 0)
|
||||
delete tmp[idx-1];
|
||||
}
|
||||
|
||||
@@ -467,6 +488,26 @@ NetNet* NetEUReduce::synthesize(Design*des)
|
||||
NetLogic::AND);
|
||||
break;
|
||||
|
||||
case '|':
|
||||
gate = new NetLogic(scope, oname, isig->pin_count()+1,
|
||||
NetLogic::OR);
|
||||
break;
|
||||
|
||||
case '^':
|
||||
gate = new NetLogic(scope, oname, isig->pin_count()+1,
|
||||
NetLogic::XOR);
|
||||
break;
|
||||
|
||||
case 'A':
|
||||
gate = new NetLogic(scope, oname, isig->pin_count()+1,
|
||||
NetLogic::NAND);
|
||||
break;
|
||||
|
||||
case 'X':
|
||||
gate = new NetLogic(scope, oname, isig->pin_count()+1,
|
||||
NetLogic::XNOR);
|
||||
break;
|
||||
|
||||
default:
|
||||
cerr << get_line() << ": internal error: "
|
||||
<< "Unable to synthesize " << *this << "." << endl;
|
||||
@@ -481,7 +522,12 @@ NetNet* NetEUReduce::synthesize(Design*des)
|
||||
return osig;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Synthesize a ?: operator an a NetMux device. Connect the condition
|
||||
* expression to the select input, then connect the true and false
|
||||
* expressions to the B and A inputs. This way, when the select input
|
||||
* is one, the B input, which is the true expression, is selected.
|
||||
*/
|
||||
NetNet* NetETernary::synthesize(Design *des)
|
||||
{
|
||||
NetNet*csig = cond_->synthesize(des);
|
||||
@@ -562,6 +608,36 @@ NetNet* NetESignal::synthesize(Design*des)
|
||||
|
||||
/*
|
||||
* $Log: expr_synth.cc,v $
|
||||
* Revision 1.36 2002/08/12 01:34:59 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.35 2002/07/07 22:31:39 steve
|
||||
* Smart synthesis of binary AND expressions.
|
||||
*
|
||||
* Revision 1.34 2002/07/05 21:26:17 steve
|
||||
* Avoid emitting to vvp local net symbols.
|
||||
*
|
||||
* Revision 1.33 2002/05/26 01:39:02 steve
|
||||
* Carry Verilog 2001 attributes with processes,
|
||||
* all the way through to the ivl_target API.
|
||||
*
|
||||
* Divide signal reference counts between rval
|
||||
* and lval references.
|
||||
*
|
||||
* Revision 1.32 2002/05/23 03:08:51 steve
|
||||
* Add language support for Verilog-2001 attribute
|
||||
* syntax. Hook this support into existing $attribute
|
||||
* handling, and add number and void value types.
|
||||
*
|
||||
* Add to the ivl_target API new functions for access
|
||||
* of complex attributes attached to gates.
|
||||
*
|
||||
* Revision 1.31 2001/12/30 17:06:52 steve
|
||||
* Synthesize reduction logic.
|
||||
*
|
||||
* Revision 1.30 2001/12/18 05:34:02 steve
|
||||
* Comments about MUX synthesis.
|
||||
*
|
||||
* Revision 1.29 2001/11/29 01:58:18 steve
|
||||
* Handle part selects in l-values of DFF devices.
|
||||
*
|
||||
|
||||
+43
-117
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2000 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2002 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -16,8 +16,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: functor.cc,v 1.26 2001/10/19 21:53:24 steve Exp $"
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: functor.cc,v 1.31 2002/08/16 05:18:27 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -128,30 +128,31 @@ void Design::functor(functor_t*fun)
|
||||
|
||||
// apply to nodes
|
||||
if (nodes_) {
|
||||
assert(nodes_functor_cur_ == 0);
|
||||
assert(nodes_functor_nxt_ == 0);
|
||||
|
||||
/* Scan the circular list of nodes, starting with the
|
||||
front of the list. (nodes_ points to the *end* of the
|
||||
list.) The bar is the end point. At the end of the
|
||||
do-while loop, I know that the bar has been
|
||||
processed or (if bar == 0) no undeleted node has been
|
||||
processed. */
|
||||
NetNode*cur = nodes_->node_next_;
|
||||
NetNode*bar = 0;
|
||||
front of the list.
|
||||
|
||||
This loop interacts with the Design::del_node method
|
||||
so that the functor is free to delete any nodes it
|
||||
choose. The destructors of the NetNode objects call
|
||||
the del_node method, which checks with the
|
||||
nodes_functor_* members, to keep the iterator
|
||||
operating safely. */
|
||||
nodes_functor_cur_ = nodes_;
|
||||
do {
|
||||
NetNode*tmp = cur->node_next_;
|
||||
cur->functor_node(this, fun);
|
||||
nodes_functor_nxt_ = nodes_functor_cur_->node_next_;
|
||||
nodes_functor_cur_->functor_node(this, fun);
|
||||
|
||||
/* Detect the case that cur has been deleted by
|
||||
noticing if tmp->node_prev_ no longer points to
|
||||
cur. If that's the case, clear the bar. */
|
||||
if (tmp->node_prev_ != cur) {
|
||||
if (cur == bar)
|
||||
bar = 0;
|
||||
} else if (bar == 0) {
|
||||
bar = cur;
|
||||
}
|
||||
cur = tmp;
|
||||
if (nodes_functor_nxt_ == 0)
|
||||
break;
|
||||
|
||||
nodes_functor_cur_ = nodes_functor_nxt_;
|
||||
} while (nodes_ && (nodes_functor_cur_ != nodes_));
|
||||
nodes_functor_cur_ = 0;
|
||||
nodes_functor_nxt_ = 0;
|
||||
|
||||
} while (nodes_ && (cur != bar));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -234,35 +235,13 @@ int NetAssignNB::match_proc(proc_match_t*that)
|
||||
return that->assign_nb(this);
|
||||
}
|
||||
|
||||
int proc_match_t::assign_mem(NetAssignMem*)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int NetAssignMem::match_proc(proc_match_t*that)
|
||||
{
|
||||
return that->assign_mem(this);
|
||||
}
|
||||
|
||||
int proc_match_t::assign_mem_nb(NetAssignMemNB*)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int NetAssignMemNB::match_proc(proc_match_t*that)
|
||||
{
|
||||
return that->assign_mem_nb(this);
|
||||
}
|
||||
|
||||
int proc_match_t::block(NetBlock*)
|
||||
{
|
||||
cerr << "default (failing) match for block" << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int NetBlock::match_proc(proc_match_t*that)
|
||||
{
|
||||
cerr << "NetBlock::match_proc" << endl;
|
||||
return that->block(this);
|
||||
}
|
||||
|
||||
@@ -288,6 +267,25 @@ int proc_match_t::event_wait(NetEvWait*)
|
||||
|
||||
/*
|
||||
* $Log: functor.cc,v $
|
||||
* Revision 1.31 2002/08/16 05:18:27 steve
|
||||
* Fix intermix of node functors and node delete.
|
||||
*
|
||||
* Revision 1.30 2002/08/12 01:34:59 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.29 2002/08/10 22:07:38 steve
|
||||
* Remove useless error messages.
|
||||
*
|
||||
* Revision 1.28 2002/06/05 03:44:25 steve
|
||||
* Add support for memory words in l-value of
|
||||
* non-blocking assignments, and remove the special
|
||||
* NetAssignMem_ and NetAssignMemNB classes.
|
||||
*
|
||||
* Revision 1.27 2002/06/04 05:38:44 steve
|
||||
* Add support for memory words in l-value of
|
||||
* blocking assignments, and remove the special
|
||||
* NetAssignMem class.
|
||||
*
|
||||
* Revision 1.26 2001/10/19 21:53:24 steve
|
||||
* Support multiple root modules (Philip Blundell)
|
||||
*
|
||||
@@ -306,77 +304,5 @@ int proc_match_t::event_wait(NetEvWait*)
|
||||
*
|
||||
* Revision 1.21 2000/08/01 02:48:41 steve
|
||||
* Support <= in synthesis of DFF and ram devices.
|
||||
*
|
||||
* Revision 1.20 2000/07/16 04:56:07 steve
|
||||
* Handle some edge cases during node scans.
|
||||
*
|
||||
* Revision 1.19 2000/07/15 05:13:43 steve
|
||||
* Detect muxing Vz as a bufufN.
|
||||
*
|
||||
* Revision 1.18 2000/05/02 00:58:12 steve
|
||||
* Move signal tables to the NetScope class.
|
||||
*
|
||||
* Revision 1.17 2000/04/20 00:28:03 steve
|
||||
* Catch some simple identity compareoptimizations.
|
||||
*
|
||||
* Revision 1.16 2000/04/18 04:50:19 steve
|
||||
* Clean up unneeded NetEvent objects.
|
||||
*
|
||||
* Revision 1.15 2000/04/16 23:32:18 steve
|
||||
* Synthesis of comparator in expressions.
|
||||
*
|
||||
* Connect the NetEvent and related classes
|
||||
* together better.
|
||||
*
|
||||
* Revision 1.14 2000/04/12 20:02:53 steve
|
||||
* Finally remove the NetNEvent and NetPEvent classes,
|
||||
* Get synthesis working with the NetEvWait class,
|
||||
* and get started supporting multiple events in a
|
||||
* wait in vvm.
|
||||
*
|
||||
* Revision 1.13 2000/04/01 21:40:22 steve
|
||||
* Add support for integer division.
|
||||
*
|
||||
* Revision 1.12 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.11 2000/02/13 04:35:43 steve
|
||||
* Include some block matching from Larry.
|
||||
*
|
||||
* Revision 1.10 2000/01/13 03:35:35 steve
|
||||
* Multiplication all the way to simulation.
|
||||
*
|
||||
* Revision 1.9 2000/01/02 17:57:20 steve
|
||||
* Handle nodes running out during node scan.
|
||||
*
|
||||
* Revision 1.8 1999/12/30 04:19:12 steve
|
||||
* Propogate constant 0 in low bits of adders.
|
||||
*
|
||||
* Revision 1.7 1999/12/17 06:18:16 steve
|
||||
* Rewrite the cprop functor to use the functor_t interface.
|
||||
*
|
||||
* Revision 1.6 1999/12/05 02:24:08 steve
|
||||
* Synthesize LPM_RAM_DQ for writes into memories.
|
||||
*
|
||||
* Revision 1.5 1999/12/01 06:06:16 steve
|
||||
* Redo synth to use match_proc_t scanner.
|
||||
*
|
||||
* Revision 1.4 1999/11/18 03:52:19 steve
|
||||
* Turn NetTmp objects into normal local NetNet objects,
|
||||
* and add the nodangle functor to clean up the local
|
||||
* symbols generated by elaboration and other steps.
|
||||
*
|
||||
* Revision 1.3 1999/11/01 02:07:40 steve
|
||||
* Add the synth functor to do generic synthesis
|
||||
* and add the LPM_FF device to handle rows of
|
||||
* flip-flops.
|
||||
*
|
||||
* Revision 1.2 1999/07/18 05:52:46 steve
|
||||
* xnfsyn generates DFF objects for XNF output, and
|
||||
* properly rewrites the Design netlist in the process.
|
||||
*
|
||||
* Revision 1.1 1999/07/17 22:01:13 steve
|
||||
* Add the functor interface for functor transforms.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: functor.h,v 1.17 2000/09/17 21:26:15 steve Exp $"
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: functor.h,v 1.20 2002/08/12 01:34:59 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -83,9 +83,7 @@ struct proc_match_t {
|
||||
virtual ~proc_match_t();
|
||||
|
||||
virtual int assign(class NetAssign*);
|
||||
virtual int assign_mem(class NetAssignMem*);
|
||||
virtual int assign_nb(class NetAssignNB*);
|
||||
virtual int assign_mem_nb(class NetAssignMemNB*);
|
||||
virtual int condit(class NetCondit*);
|
||||
virtual int event_wait(class NetEvWait*);
|
||||
virtual int block(class NetBlock*);
|
||||
@@ -94,6 +92,19 @@ struct proc_match_t {
|
||||
|
||||
/*
|
||||
* $Log: functor.h,v $
|
||||
* Revision 1.20 2002/08/12 01:34:59 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.19 2002/06/05 03:44:25 steve
|
||||
* Add support for memory words in l-value of
|
||||
* non-blocking assignments, and remove the special
|
||||
* NetAssignMem_ and NetAssignMemNB classes.
|
||||
*
|
||||
* Revision 1.18 2002/06/04 05:38:44 steve
|
||||
* Add support for memory words in l-value of
|
||||
* blocking assignments, and remove the special
|
||||
* NetAssignMem class.
|
||||
*
|
||||
* Revision 1.17 2000/09/17 21:26:15 steve
|
||||
* Add support for modulus (Eric Aardoom)
|
||||
*
|
||||
@@ -108,32 +119,5 @@ struct proc_match_t {
|
||||
*
|
||||
* Revision 1.13 2000/04/20 00:28:03 steve
|
||||
* Catch some simple identity compareoptimizations.
|
||||
*
|
||||
* Revision 1.12 2000/04/18 04:50:19 steve
|
||||
* Clean up unneeded NetEvent objects.
|
||||
*
|
||||
* Revision 1.11 2000/04/12 20:02:53 steve
|
||||
* Finally remove the NetNEvent and NetPEvent classes,
|
||||
* Get synthesis working with the NetEvWait class,
|
||||
* and get started supporting multiple events in a
|
||||
* wait in vvm.
|
||||
*
|
||||
* Revision 1.10 2000/04/01 21:40:22 steve
|
||||
* Add support for integer division.
|
||||
*
|
||||
* Revision 1.9 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.8 2000/02/13 04:35:43 steve
|
||||
* Include some block matching from Larry.
|
||||
*
|
||||
* Revision 1.7 2000/01/13 03:35:35 steve
|
||||
* Multiplication all the way to simulation.
|
||||
*
|
||||
* Revision 1.6 1999/12/30 04:19:12 steve
|
||||
* Propogate constant 0 in low bits of adders.
|
||||
*
|
||||
* Revision 1.5 1999/12/17 06:18:16 steve
|
||||
* Rewrite the cprop functor to use the functor_t interface.
|
||||
*/
|
||||
#endif
|
||||
|
||||
+106
-5
@@ -86,7 +86,7 @@ tool so it is not clear that the standard really is at fault. It is
|
||||
clear, however, that somebody goofed somewhere.
|
||||
|
||||
My personal opinion is that there is no logical need to require that
|
||||
all module_item_declarations preceed any other module items. I
|
||||
all module_item_declarations precede any other module items. I
|
||||
personally would oppose such a restriction. It may make sense to
|
||||
require that declarations of variables within a module be preceded by
|
||||
their use, although even that is not necessary for the implementation
|
||||
@@ -97,7 +97,7 @@ sample2 can have implications that affect any declaration order
|
||||
rules. When reaching into a module with a hierarchical name, the
|
||||
module being referenced is already completely declared (or not
|
||||
declared at all, as in sample2) so module_item order is completely
|
||||
irrelevent. But a "declare before use" rule would infect module
|
||||
irrelevant. But a "declare before use" rule would infect module
|
||||
ordering, by requiring that modules that are used be first defined.
|
||||
|
||||
|
||||
@@ -141,7 +141,7 @@ ports.
|
||||
|
||||
With the above in mind, I have decided to *allow* function and task
|
||||
ports to be declared with types, as long as the types are variable
|
||||
types, such ag reg or integer. Without this, there would be no
|
||||
types, such as reg or integer. Without this, there would be no
|
||||
portable way to pass integers into functions/tasks. The standard does
|
||||
not say it is allowed, but it doesn't *disallow* it, and other
|
||||
commercial tools seem to work similarly.
|
||||
@@ -172,7 +172,7 @@ take it that x is allowed, as that is what Verilog-XL does.
|
||||
|
||||
There seems to be ambiguity in how code like this should be parsed:
|
||||
|
||||
repeat (5) @(posedge clk) <statment>;
|
||||
repeat (5) @(posedge clk) <statement>;
|
||||
|
||||
There are two valid interpretations of this code, from the
|
||||
IEEE1364-1995 standard. One looks like this:
|
||||
@@ -318,8 +318,109 @@ the right length, and will therefore flag instances u5 and u6 as
|
||||
errors. The IEEE1364 standard should be more specific one way or the
|
||||
other.
|
||||
|
||||
$Id: ieee1364-notes.txt,v 1.8 2001/08/01 05:17:31 steve Exp $
|
||||
* UNKNOWN VALUES IN L-VALUE BIT SELECTS
|
||||
|
||||
Consider this example:
|
||||
|
||||
reg [7:0] vec;
|
||||
wire [4:0] idx = <expr>;
|
||||
[...]
|
||||
vec[idx] = 1;
|
||||
|
||||
So long as the value of idx is a valid bit select address, the
|
||||
behavior of this assignment is obvious. However, there is no explicit
|
||||
word in the standard as to what happens if the value is out of
|
||||
range. The standard clearly states the value of an expression when the
|
||||
bit-select or part select is out of range (the value is x) but does
|
||||
not address the behavior when the expression is an l-value.
|
||||
|
||||
Icarus Verilog will take the position that bit select expressions in
|
||||
the l-value will select oblivion if it is out of range. That is, if
|
||||
idx has a value that is not a valid bit select of vec, then the
|
||||
assignment will have no effect.
|
||||
|
||||
|
||||
* SCHEDULING VALUES IN LOGIC
|
||||
|
||||
The interaction between blocking assignments in procedural code and
|
||||
logic gates in gate-level code and expressions is poorly defined in
|
||||
Verilog. Consider this example:
|
||||
|
||||
reg a;
|
||||
reg b;
|
||||
wire q = a & b;
|
||||
|
||||
initial begin
|
||||
a = 1;
|
||||
b = 0;
|
||||
#1 b = 1;
|
||||
if (q !== 0) begin
|
||||
$display("FAILED -- q changed too soon? %b", q);
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
|
||||
This is a confusing situation. It is clear from the Verilog standard
|
||||
that an assignment to a variable using a blocking assign causes the
|
||||
l-value to receive the value before the assignment completes. This
|
||||
means that a subsequent read of the assigned variable *must* read back
|
||||
what was blocking-assigned.
|
||||
|
||||
However, in the example above, the "wire q = a & b" expresses some
|
||||
gate logic between a/b and q. The standard does not say whether a read
|
||||
out of logic should read the value computed from previous assigns to
|
||||
the input from the same thread. Specifically, when "a" and "b" are
|
||||
assigned by blocking assignments, will a read of "q" get the computed
|
||||
value or the existing value?
|
||||
|
||||
In fact, existing commercial tools do it both ways. Some tools print
|
||||
the FAILED message in the above example, and some do not. Icarus
|
||||
Verilog does not print the FAILED message in the above example,
|
||||
because the gate value change is *scheduled* when inputs are assigned,
|
||||
but not propagated until the thread gives up the processor.
|
||||
|
||||
Icarus Verilog chooses this behavior in order to filter out zero-width
|
||||
pulses as early as possible. The implication of this is that a read of
|
||||
the output of combinational logic will most likely *not* reflect the
|
||||
changes in inputs until the thread that changed the inputs yields
|
||||
execution.
|
||||
|
||||
|
||||
* BIT AND PART SELECTS OF PARAMETERS
|
||||
|
||||
Bit and part selects are supposed to only be supported on vector nets
|
||||
and variables (wires, regs, etc.) However, it is common for Verilog
|
||||
compilers to also support bit and part select on parameters. Icarus
|
||||
Verilog also chooses to support bit and part selects on parameter
|
||||
names, but we need to define what that means.
|
||||
|
||||
A bit or a part select on a parameter expression returns an unsigned
|
||||
value with a defined size. The parameter value is considered be a
|
||||
constant vector of bits foo[X:0]. That is, zero based. The bit and
|
||||
part selects operate from that assumption.
|
||||
|
||||
Verilog 2001 adds syntax to allow the user to explicitly declare the
|
||||
parameter range (i.e. parameter [5:0] foo = 9;) so Icarus Verilog will
|
||||
(or should) use the explicitly declared vector dimensions to interpret
|
||||
bit and part selects.
|
||||
|
||||
$Id: ieee1364-notes.txt,v 1.13 2002/08/20 04:11:53 steve Exp $
|
||||
$Log: ieee1364-notes.txt,v $
|
||||
Revision 1.13 2002/08/20 04:11:53 steve
|
||||
Support parameters with defined ranges.
|
||||
|
||||
Revision 1.12 2002/06/11 03:34:33 steve
|
||||
Spelling patch (Larry Doolittle)
|
||||
|
||||
Revision 1.11 2002/04/27 02:38:04 steve
|
||||
Support selecting bits from parameters.
|
||||
|
||||
Revision 1.10 2002/03/31 01:54:13 steve
|
||||
Notes about scheduling
|
||||
|
||||
Revision 1.9 2002/01/26 02:08:07 steve
|
||||
Handle x in l-value of set/x
|
||||
|
||||
Revision 1.8 2001/08/01 05:17:31 steve
|
||||
Accept empty port lists to module instantiation.
|
||||
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
.TH iverilog-vpi 1 "$Date: 2002/07/05 17:17:20 $" Version "$Date: 2002/07/05 17:17:20 $"
|
||||
.SH NAME
|
||||
iverilog-vpi - Compile front end for VPI modules
|
||||
|
||||
.SH SYNOPSIS
|
||||
.B iverilog-vpi
|
||||
[--name=\fIname\fP]
|
||||
\fIsourcefile\fP...
|
||||
|
||||
.SH DESCRIPTION
|
||||
.PP
|
||||
\fIiverilog-vpi\fP is a tool to simplify the compilation of VPI
|
||||
modules for use with Icarus Verilog. It takes on the command line a
|
||||
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.
|
||||
|
||||
.SH OPTIONS
|
||||
.l
|
||||
\fIiverilog-vpi\fP accepts the following options:
|
||||
.TP 8
|
||||
.B -l\fIlibrary\fP
|
||||
Include the named library in the link of the VPI module. This allows
|
||||
VPI modules to further reference external libraries.
|
||||
|
||||
.TP 8
|
||||
.B --name=\fIname\fP
|
||||
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.
|
||||
.SH "AUTHOR"
|
||||
.nf
|
||||
Steve Williams ([email protected])
|
||||
|
||||
.SH SEE ALSO
|
||||
iverilog(1), vvp(1),
|
||||
.BR "<http://www.icarus.com/eda/verilog/>"
|
||||
|
||||
.SH COPYRIGHT
|
||||
.nf
|
||||
Copyright \(co 2002 Stephen Williams
|
||||
|
||||
This document can be freely redistributed according to the terms of the
|
||||
GNU General Public License version 2.0
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# This source code is free software; you can redistribute it
|
||||
# and/or modify it in source code form under the terms of the GNU
|
||||
# Library General Public License as published by the Free Software
|
||||
# Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Library General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Library General Public
|
||||
# License along with this program; if not, write to the Free
|
||||
# Software Foundation, Inc.,
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: iverilog-vpi.sh,v 1.9 2002/10/19 23:18:52 steve Exp $"
|
||||
|
||||
# These are the variables used for compiling files
|
||||
CC=gcc
|
||||
CXX=gcc
|
||||
CFLAGS="@PIC@ -O -I@INCLUDEDIR@"
|
||||
|
||||
# These are used for linking...
|
||||
LD=gcc
|
||||
LDFLAGS="@SHARED@"
|
||||
LDLIBS="-L@LIBDIR@ -lveriuser -lvpi"
|
||||
|
||||
CCSRC=
|
||||
CXSRC=
|
||||
OBJ=
|
||||
LIB=
|
||||
OUT=
|
||||
|
||||
# --
|
||||
# parse the command line switches. This collects the source files
|
||||
# and precompiled object files, and maybe user libraries. As we are
|
||||
# going, guess an output file name.
|
||||
for parm
|
||||
do
|
||||
case $parm
|
||||
in
|
||||
|
||||
*.c) CCSRC="$CCSRC $parm"
|
||||
if [ x$OUT = x ]; then
|
||||
OUT=`basename $parm .c`
|
||||
fi
|
||||
;;
|
||||
|
||||
*.cc) CXSRC="$CXSRC $parm"
|
||||
if [ x$OUT = x ]; then
|
||||
OUT=`basename $parm .cc`
|
||||
fi
|
||||
;;
|
||||
|
||||
*.o) OBJ="$OBJ $parm"
|
||||
if [ x$OUT = x ]; then
|
||||
OUT=`basename $parm .o`
|
||||
fi
|
||||
;;
|
||||
|
||||
--name=*)
|
||||
OUT=`echo $parm | cut -b8-`
|
||||
;;
|
||||
|
||||
-l*) LIB="$LIB $parm"
|
||||
;;
|
||||
|
||||
esac
|
||||
|
||||
done
|
||||
|
||||
if [ x$OUT = x ]; then
|
||||
echo "Usage: $0 [src and obj files]..."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Put the .vpi on the result file.
|
||||
OUT=$OUT".vpi"
|
||||
|
||||
compile_errors=0
|
||||
|
||||
# Compile all the source files into object files
|
||||
for src in $CCSRC
|
||||
do
|
||||
base=`basename $src .c`
|
||||
obj=$base".o"
|
||||
|
||||
echo "Compiling $src..."
|
||||
$CC -c -o $obj $CFLAGS $src || compile_errors=`expr $compile_errors + 1`
|
||||
OBJ="$OBJ $obj"
|
||||
done
|
||||
|
||||
for src in $CXSRC
|
||||
do
|
||||
base=`basename $src .cc`
|
||||
obj=$base".o"
|
||||
|
||||
echo "Compiling $src..."
|
||||
$CXX -c -o $obj $CFLAGS $src || compile_errors=`expr $compile_errors + 1`
|
||||
OBJ="$OBJ $obj"
|
||||
done
|
||||
|
||||
if test $compile_errors -gt 0
|
||||
then
|
||||
echo "Some ($compile_errors) files failed to compile."
|
||||
exit $compile_errors
|
||||
fi
|
||||
|
||||
echo "Making $OUT from $OBJ..."
|
||||
exec $LD -o $OUT $LDFLAGS $OBJ $LIB $LDLIBS
|
||||
+13
-20
@@ -28,10 +28,16 @@
|
||||
#
|
||||
# %B Substitute the base libdir, -B flag of iverilog.
|
||||
#
|
||||
# %C Substitute the path to the temporary config file.
|
||||
#
|
||||
# %f Substitute the -f flags from the command line.
|
||||
#
|
||||
# %g Substitule the -g flag
|
||||
#
|
||||
# %s Substitute the start module (-s flag) from the user.
|
||||
#
|
||||
# %M Substitute the value of the -M<depfile> flag.
|
||||
#
|
||||
# %N Substitute the value of the -N<path> flag.
|
||||
#
|
||||
# %o Substitute the value of the -o<path> flag, or the default
|
||||
@@ -43,9 +49,6 @@
|
||||
#
|
||||
# %W Substitute the ivl warning flags.
|
||||
#
|
||||
# %y Substitute all the -y flags here.
|
||||
# %Y Substitute all the -Y flags here.
|
||||
#
|
||||
# %[<c><text>]
|
||||
# This substitution pattern is magical, and is the only
|
||||
# multicharacter pattern. This tests the code <c>, and
|
||||
@@ -59,42 +62,32 @@
|
||||
# be useful and interesting if the -N flag is included.
|
||||
|
||||
[-tnull -S]
|
||||
<ivl>%B/ivl %[v-v] %y %Y %W %s %[N-N%N] %[T-T%T] -tdll -fDLL=%B/null.tgt -Fsynth -Fsyn-rules -- -
|
||||
<ivl>%B/ivl %[v-v] -C%C %g %W %s %[M-M%M] %[N-N%N] %[T-T%T] -tdll -fDLL=%B/null.tgt -Fsynth -Fsyn-rules -- -
|
||||
|
||||
[-tnull]
|
||||
<ivl>%B/ivl %[v-v] %y %Y %W %s %[N-N%N] %[T-T%T] -tdll -fDLL=%B/null.tgt -- -
|
||||
<ivl>%B/ivl %[v-v] -C%C %g %W %s %[M-M%M] %[N-N%N] %[T-T%T] -tdll -fDLL=%B/null.tgt -- -
|
||||
|
||||
# --
|
||||
# The vvp target generates code that the vvp simulation engine can execute.
|
||||
# These rules support synthesized and non-synthesized variants.
|
||||
|
||||
[-tvvp -S]
|
||||
<ivl>%B/ivl %[v-v] %y %Y %W %s %[N-N%N] %[T-T%T] -tdll -fDLL=%B/vvp.tgt -fVVP_EXECUTABLE=%B/../../bin/vvp -Fsynth -Fsyn-rules -Fcprop -Fnodangle %f %m -o%o -- -
|
||||
<ivl>%B/ivl %[v-v] -C%C %g %W %s %[M-M%M] %[N-N%N] %[T-T%T] -tdll -fDLL=%B/vvp.tgt -fVVP_EXECUTABLE=%B/../../bin/vvp -Fsynth2 -Fsynth -Fsyn-rules -Fcprop -Fnodangle %f %m -o%o -- -
|
||||
|
||||
[-tvvp]
|
||||
<ivl>%B/ivl %[v-v] %y %Y %W %s %[N-N%N] %[T-T%T] -tdll -fDLL=%B/vvp.tgt -fVVP_EXECUTABLE=%B/../../bin/vvp -Fcprop -Fnodangle %f %m -o%o -- -
|
||||
|
||||
# --
|
||||
# The vvm target uses the <ivl> string to take the preprocessed code from
|
||||
# standard input, compile it with the vvm code generator and write the
|
||||
# result to %o.cc. The driver assumes this when invoking the C++ compiler
|
||||
# on the result.
|
||||
|
||||
[-tvvm]
|
||||
<ivl>%B/ivl %[v-v] %y %Y %W %s %[N-N%N] %[T-T%T] -tvvm -Fcprop -Fnodangle -fVPI_MODULE_PATH=%B %f %m -o%o.cc -- -
|
||||
|
||||
<ivl>%B/ivl %[v-v] -C%C %g %W %s %[M-M%M] %[N-N%N] %[T-T%T] -tdll -fDLL=%B/vvp.tgt -fVVP_EXECUTABLE=%B/../../bin/vvp -Fcprop -Fnodangle %f %m -o%o -- -
|
||||
|
||||
# This is the XNF code generator.
|
||||
|
||||
[-txnf]
|
||||
<ivl>%B/ivl %y %Y %[v-v] %s %[N-N%N] %[T-T%T] -txnf -Fsynth -Fsyn-rules -Fxnfio -Fcprop -Fnodangle -o%o -- -
|
||||
<ivl>%B/ivl -C%C %[v-v] %g %s %[M-M%M] %[N-N%N] %[T-T%T] -txnf -Fsynth2 -Fsynth -Fsyn-rules -Fxnfio -Fcprop -Fnodangle -o%o -- -
|
||||
|
||||
# And this is another XNF code generator, under development.
|
||||
[-tfpga]
|
||||
<ivl>%B/ivl %y %Y %[v-v] %s %[N-N%N] %[T-T%T] %f -tdll -fDLL=%B/fpga.tgt -Fsynth -Fsyn-rules -Fcprop -Fnodangle -o%o -- -
|
||||
<ivl>%B/ivl -C%C %[v-v] %g %s %[M-M%M] %[N-N%N] %[T-T%T] %f -tdll -fDLL=%B/fpga.tgt -Fsynth2 -Fsynth -Fsyn-rules -Fcprop -Fnodangle -o%o -- -
|
||||
|
||||
# --
|
||||
# This is the pal code generator. The target module requires the -fpart=<type>
|
||||
# flag to specify the part type.
|
||||
[-tpal]
|
||||
<ivl>%B/ivl %y %Y %[v-v] %s %[N-N%N] %[T-T%T] -tdll -fDLL=%B/pal.tgt -Fsynth -Fsyn-rules -Fcprop -Fnodangle -o%o -- -
|
||||
<ivl>%B/ivl -C%C %[v-v] %g %s %[M-M%M] %[N-N%N] %[T-T%T] %f -tdll -fDLL=%B/pal.tgt -Fsynth -Fsyn-rules -Fcprop -Fnodangle -o%o -- -
|
||||
|
||||
@@ -43,6 +43,8 @@ ivl_expr_uvalue
|
||||
ivl_expr_width
|
||||
|
||||
ivl_logic_attr
|
||||
ivl_logic_attr_cnt
|
||||
ivl_logic_attr_val
|
||||
ivl_logic_delay
|
||||
ivl_logic_name
|
||||
ivl_logic_basename
|
||||
@@ -52,11 +54,16 @@ ivl_logic_pin
|
||||
ivl_logic_pins
|
||||
ivl_logic_udp
|
||||
|
||||
ivl_lpm_aset_value
|
||||
ivl_lpm_async_clr
|
||||
ivl_lpm_async_set
|
||||
ivl_lpm_basename
|
||||
ivl_lpm_clk
|
||||
ivl_lpm_data
|
||||
ivl_lpm_datab
|
||||
ivl_lpm_data2
|
||||
ivl_lpm_data2_width
|
||||
ivl_lpm_define
|
||||
ivl_lpm_enable
|
||||
ivl_lpm_memory
|
||||
ivl_lpm_name
|
||||
@@ -77,8 +84,8 @@ ivl_lval_pins
|
||||
ivl_lval_sig
|
||||
|
||||
ivl_memory_basename
|
||||
ivl_memory_name
|
||||
ivl_memory_root
|
||||
ivl_memory_scope
|
||||
ivl_memory_size
|
||||
ivl_memory_width
|
||||
|
||||
@@ -117,6 +124,10 @@ ivl_scope_type
|
||||
ivl_scope_tname
|
||||
|
||||
ivl_signal_attr
|
||||
ivl_signal_attr_cnt
|
||||
ivl_signal_attr_val
|
||||
ivl_signal_integer
|
||||
ivl_signal_local
|
||||
ivl_signal_pin
|
||||
ivl_signal_pins
|
||||
ivl_signal_port
|
||||
@@ -125,6 +136,8 @@ ivl_signal_type
|
||||
ivl_signal_name
|
||||
ivl_signal_basename
|
||||
|
||||
ivl_process_attr_cnt
|
||||
ivl_process_attr_val
|
||||
ivl_process_scope
|
||||
ivl_process_stmt
|
||||
ivl_process_type
|
||||
@@ -132,6 +145,7 @@ ivl_process_type
|
||||
ivl_statement_type
|
||||
|
||||
ivl_stmt_block_count
|
||||
ivl_stmt_block_scope
|
||||
ivl_stmt_block_stmt
|
||||
ivl_stmt_call
|
||||
ivl_stmt_case_count
|
||||
|
||||
+210
-280
@@ -18,8 +18,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: ivl_target.h,v 1.90 2001/12/15 02:13:17 steve Exp $"
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: ivl_target.h,v 1.108 2002/10/23 01:47:17 steve Exp $"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -98,7 +98,7 @@ _BEGIN_DECL
|
||||
* ivl_process_t
|
||||
* A Verilog process is represented by one of these. A process may
|
||||
* be an "initial" or an "always" process. These come from initial
|
||||
* or always statements from the verilog source.
|
||||
* or always statements from the Verilog source.
|
||||
*
|
||||
* ivl_scope_t
|
||||
* Elaborated scopes within a design are represented by this
|
||||
@@ -164,6 +164,7 @@ typedef enum ivl_expr_type_e {
|
||||
IVL_EX_MEMORY,
|
||||
IVL_EX_NUMBER,
|
||||
IVL_EX_SCOPE,
|
||||
IVL_EX_SELECT,
|
||||
IVL_EX_SFUNC,
|
||||
IVL_EX_SIGNAL,
|
||||
IVL_EX_STRING,
|
||||
@@ -210,12 +211,14 @@ typedef enum ivl_lpm_type_e {
|
||||
IVL_LPM_CMP_NE = 11,
|
||||
IVL_LPM_DIVIDE = 12,
|
||||
IVL_LPM_FF = 3,
|
||||
IVL_LPM_MOD = 13,
|
||||
IVL_LPM_MULT = 4,
|
||||
IVL_LPM_MUX = 5,
|
||||
IVL_LPM_SHIFTL = 6,
|
||||
IVL_LPM_SHIFTR = 7,
|
||||
IVL_LPM_SUB = 8,
|
||||
IVL_LPM_RAM = 9
|
||||
IVL_LPM_RAM = 9,
|
||||
IVL_LPM_UFUNC = 14
|
||||
} ivl_lpm_type_t;
|
||||
|
||||
/* Processes are initial or always blocks with a statement. This is
|
||||
@@ -297,6 +300,24 @@ typedef int (*ivl_process_f)(ivl_process_t net, void*cd);
|
||||
the user passes to the scanner. */
|
||||
typedef int (ivl_scope_f)(ivl_scope_t net, void*cd);
|
||||
|
||||
/* Attributes, which can be attached to various object types, have
|
||||
this form. */
|
||||
typedef enum ivl_attribute_type_e {
|
||||
IVL_ATT_VOID = 0,
|
||||
IVL_ATT_STR,
|
||||
IVL_ATT_NUM
|
||||
} ivl_attribute_type_t;
|
||||
|
||||
struct ivl_attribute_s {
|
||||
const char*key;
|
||||
ivl_attribute_type_t type;
|
||||
union val_ {
|
||||
const char*str;
|
||||
long num;
|
||||
} val;
|
||||
};
|
||||
typedef const struct ivl_attribute_s*ivl_attribute_t;
|
||||
|
||||
|
||||
/* DESIGN
|
||||
* When handed a design (ivl_design_t) there are a few things that you
|
||||
@@ -316,7 +337,7 @@ typedef int (ivl_scope_f)(ivl_scope_t net, void*cd);
|
||||
*
|
||||
* ivl_design_process
|
||||
* This function scans the processes (threads) in the design. It
|
||||
* calls the user suplied function on each of the processes until
|
||||
* calls the user supplied function on each of the processes until
|
||||
* one of the functors returns non-0 or all the processes are
|
||||
* scanned. This function will return 0, or the non-zero value that
|
||||
* was returned from the last scanned process.
|
||||
@@ -397,7 +418,15 @@ extern ivl_nexus_t ivl_event_pos(ivl_event_t net, unsigned idx);
|
||||
*
|
||||
* ivl_expr_width
|
||||
* This method returns the bit width of the expression at this
|
||||
* node. It can be applied to any expression node.
|
||||
* node. It can be applied to any expression node, and returns the
|
||||
* *output* width of the expression node.
|
||||
*
|
||||
* ivl_expr_opcode
|
||||
* IVL_EX_BINARY and IVL_EX_UNARY expression nodes include an
|
||||
* upcode from this table:
|
||||
* & -- AND
|
||||
* A -- NAND (~&)
|
||||
* X -- XNOR (~^)
|
||||
*/
|
||||
|
||||
extern ivl_expr_type_t ivl_expr_type(ivl_expr_t net);
|
||||
@@ -408,7 +437,7 @@ extern const char* ivl_expr_bits(ivl_expr_t net);
|
||||
extern ivl_scope_t ivl_expr_def(ivl_expr_t net);
|
||||
/* IVL_EX_SIGNAL */
|
||||
extern unsigned ivl_expr_lsi(ivl_expr_t net);
|
||||
/* IVL_EX_SIGNAL, IVL_EX_SFUNC, IVL_EX_MEMORY */
|
||||
/* IVL_EX_SIGNAL, IVL_EX_SFUNC */
|
||||
extern const char* ivl_expr_name(ivl_expr_t net);
|
||||
/* IVL_EX_BINARY IVL_EX_UNARY */
|
||||
extern char ivl_expr_opcode(ivl_expr_t net);
|
||||
@@ -440,13 +469,28 @@ extern unsigned ivl_expr_width(ivl_expr_t net);
|
||||
/*
|
||||
* Memory.
|
||||
*
|
||||
* ivl_memory_name (DEPRECATED)
|
||||
*
|
||||
* ivl_memory_basename
|
||||
* This returns the base name of the memory object. The base name
|
||||
* does not include the name of the scopes that contains the object.
|
||||
*
|
||||
* ivl_memory_size
|
||||
* ivl_memory_width
|
||||
* These functions return the dimensions of the memory. The size is
|
||||
* the number of words in the memory, and the width is the number
|
||||
* of bits in each word.
|
||||
*
|
||||
* ivl_memory_scope
|
||||
* This returns the scope that contains the memory.
|
||||
*/
|
||||
|
||||
extern const char*ivl_memory_name(ivl_memory_t net);
|
||||
extern const char*ivl_memory_basename(ivl_memory_t net);
|
||||
extern int ivl_memory_root(ivl_memory_t net);
|
||||
extern ivl_scope_t ivl_memory_scope(ivl_memory_t net);
|
||||
extern unsigned ivl_memory_size(ivl_memory_t net);
|
||||
extern unsigned ivl_memory_width(ivl_memory_t net);
|
||||
|
||||
extern ivl_memory_t ivl_expr_memory(ivl_expr_t net);
|
||||
|
||||
/* LOGIC
|
||||
@@ -477,6 +521,12 @@ extern ivl_memory_t ivl_expr_memory(ivl_expr_t net);
|
||||
* ivl_logic_attr
|
||||
* Return the value of a specific attribute, given the key name as
|
||||
* a string. If the key is not defined, then return 0 (null).
|
||||
*
|
||||
* ivl_logic_attr_cnt
|
||||
* ivl_logic_attr_val
|
||||
* These support iterating over logic attributes. The _cnt method
|
||||
* returns the number of attributes attached to the gate, and the
|
||||
* ivl_logic_attr_val returns the value of the attribute.
|
||||
*/
|
||||
|
||||
extern const char* ivl_logic_name(ivl_net_logic_t net);
|
||||
@@ -488,8 +538,12 @@ extern unsigned ivl_logic_pins(ivl_net_logic_t net);
|
||||
extern ivl_udp_t ivl_logic_udp(ivl_net_logic_t net);
|
||||
extern unsigned ivl_logic_delay(ivl_net_logic_t net, unsigned transition);
|
||||
|
||||
/* DEPRECATED */
|
||||
extern const char* ivl_logic_attr(ivl_net_logic_t net, const char*key);
|
||||
|
||||
extern unsigned ivl_logic_attr_cnt(ivl_net_logic_t net);
|
||||
extern ivl_attribute_t ivl_logic_attr_val(ivl_net_logic_t net, unsigned idx);
|
||||
|
||||
/* UDP
|
||||
*
|
||||
*/
|
||||
@@ -519,7 +573,7 @@ extern const char* ivl_udp_name(ivl_udp_t net);
|
||||
* this device.
|
||||
*
|
||||
* ivl_lpm_type
|
||||
* Return the ivl_lpm_type_t of the secific LPM device.
|
||||
* Return the ivl_lpm_type_t of the specific LPM device.
|
||||
*
|
||||
* ivl_lpm_width
|
||||
* Return the width of the LPM device. What this means depends on
|
||||
@@ -536,7 +590,7 @@ extern const char* ivl_udp_name(ivl_udp_t net);
|
||||
* vector for devices that have more inputs.
|
||||
*
|
||||
* ivl_lpm_datab
|
||||
* Return the input data nexis for device types that have a second
|
||||
* Return the input data nexus for device types that have a second
|
||||
* input vector. For example, arithmetic devices are like this.
|
||||
*
|
||||
* ivl_lpm_q
|
||||
@@ -549,7 +603,7 @@ extern const char* ivl_udp_name(ivl_udp_t net);
|
||||
*
|
||||
* ivl_lpm_size
|
||||
* In addition to a width, some devices have a size. The size is
|
||||
* often the number of inputs per out, i.e. the number of inputs
|
||||
* often the number of inputs per out, i.e., the number of inputs
|
||||
* per bit for a MUX.
|
||||
*/
|
||||
extern const char* ivl_lpm_name(ivl_lpm_t net);
|
||||
@@ -558,17 +612,26 @@ extern ivl_scope_t ivl_lpm_scope(ivl_lpm_t net);
|
||||
extern ivl_lpm_type_t ivl_lpm_type(ivl_lpm_t net);
|
||||
extern unsigned ivl_lpm_width(ivl_lpm_t net);
|
||||
|
||||
/* IVL_LPM_FF */
|
||||
extern ivl_nexus_t ivl_lpm_async_clr(ivl_lpm_t net);
|
||||
extern ivl_nexus_t ivl_lpm_async_set(ivl_lpm_t net);
|
||||
extern ivl_expr_t ivl_lpm_aset_value(ivl_lpm_t net);
|
||||
/* IVL_LPM_FF IVL_LPM_RAM */
|
||||
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);
|
||||
/* IVL_LPM_FF IVL_LPM_RAM */
|
||||
extern ivl_nexus_t ivl_lpm_enable(ivl_lpm_t net);
|
||||
/* IVL_LPM_ADD IVL_LPM_FF IVL_LPM_MULT IVL_LPM_RAM IVL_LPM_SUB */
|
||||
extern ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx);
|
||||
/* IVL_LPM_ADD IVL_LPM_MULT IVL_LPM_SUB */
|
||||
/* IVL_LPM_MUX IVL_LPM_UFUNC */
|
||||
extern ivl_nexus_t ivl_lpm_datab(ivl_lpm_t net, unsigned idx);
|
||||
/* IVL_LPM_MUX */
|
||||
extern ivl_nexus_t ivl_lpm_data2(ivl_lpm_t net, unsigned sdx, unsigned idx);
|
||||
/* IVL_LPM_ADD IVL_LPM_FF IVL_LPM_MULT IVL_LPM_RAM IVL_LPM_SUB */
|
||||
/* IVL_LPM_UFUNC */
|
||||
extern unsigned ivl_lpm_data2_width(ivl_lpm_t net, unsigned sdx);
|
||||
/* IVL_LPM_ADD IVL_LPM_FF IVL_LPM_MULT IVL_LPM_RAM IVL_LPM_SUB
|
||||
IVL_LPM_UFUNC */
|
||||
extern ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx);
|
||||
/* IVL_LPM_MUX IVL_LPM_RAM */
|
||||
extern unsigned ivl_lpm_selects(ivl_lpm_t net);
|
||||
@@ -669,7 +732,7 @@ extern ivl_signal_t ivl_lval_sig(ivl_lval_t net);
|
||||
* connected to the nexus.
|
||||
*
|
||||
* If the target is an LPM device, then this value is zero, and it
|
||||
* is up to the application to find the pin that referse to this
|
||||
* is up to the application to find the pin that refers to this
|
||||
* nexus. The problem is that LPM devices do not have a pinout per
|
||||
* se, the pins all have specific names.
|
||||
*
|
||||
@@ -724,8 +787,25 @@ extern ivl_signal_t ivl_nexus_ptr_sig(ivl_nexus_ptr_t net);
|
||||
* generally when a module is instantiated, though they also come from
|
||||
* named blocks, tasks and functions.
|
||||
*
|
||||
* (NOTE: Module scopes are *instances* of modules, and not the module
|
||||
* definition. A definition may apply to many instances.)
|
||||
* - module instances (IVL_SCT_MODULE)
|
||||
* A module instance scope may contain events, logic gates, lpm
|
||||
* nodes, signals, and possibly children. The children are further
|
||||
* instances, or function/task scopes. Module instances do *not*
|
||||
* contain a definition.
|
||||
*
|
||||
* - function scopes (IVL_SCT_FUNCTION)
|
||||
* These scopes represent functions. A function may not be a root,
|
||||
* so it is contained within a module instance scope. A function is
|
||||
* required to have a definition (in the form of a statement) and a
|
||||
* signal (IVL_SIG_REG) that is its return value.
|
||||
*
|
||||
* A single function scope is created each time the module with the
|
||||
* definition is instantiated.
|
||||
*
|
||||
*
|
||||
* - task scopes (IVL_SCT_TASK)
|
||||
* [...]
|
||||
*
|
||||
*
|
||||
* ivl_scope_children
|
||||
* A scope may in turn contain other scopes. This method iterates
|
||||
@@ -750,6 +830,11 @@ extern ivl_signal_t ivl_nexus_ptr_sig(ivl_nexus_ptr_t net);
|
||||
* Scopes have 0 or more logic devices in them. A logic device is
|
||||
* represented by ivl_logic_t.
|
||||
*
|
||||
* ivl_scope_lpm
|
||||
* ivl_scope_lpms
|
||||
* Scopes have 0 or more LPM devices in them. These functions access
|
||||
* those devices.
|
||||
*
|
||||
* ivl_scope_name
|
||||
* ivl_scope_basename
|
||||
* Every scope has a hierarchical name. This name is also a prefix
|
||||
@@ -810,7 +895,7 @@ extern const char* ivl_scope_tname(ivl_scope_t net);
|
||||
|
||||
/* SIGNALS
|
||||
* Signals are named things in the Verilog source, like wires and
|
||||
* regs, and also named things that are preated as temporaries during
|
||||
* regs, and also named things that are created as temporaries during
|
||||
* certain elaboration or optimization steps. A signal may also be a
|
||||
* port of a module or task.
|
||||
*
|
||||
@@ -820,7 +905,7 @@ extern const char* ivl_scope_tname(ivl_scope_t net);
|
||||
* ivl_signal_pins
|
||||
* ivl_signal_pin
|
||||
* The ivl_signal_pin function returns the nexus connected to the
|
||||
* signal. If the signal is a vectory, the idx can be a non-zero
|
||||
* signal. If the signal is a vector, the idx can be a non-zero
|
||||
* value, and the result is the nexus for the specified bit.
|
||||
*
|
||||
* ivl_signal_port
|
||||
@@ -833,16 +918,28 @@ extern const char* ivl_scope_tname(ivl_scope_t net);
|
||||
* net or variable may be signed. This function returns true if the
|
||||
* signal is signed.
|
||||
*
|
||||
* ivl_signal_type
|
||||
* Return the type of the signal, i.e. reg, wire, tri0, et al.
|
||||
* ivl_signal_local
|
||||
* A signal that was generated by the compiler as a place holder is
|
||||
* marked as local.
|
||||
*
|
||||
* ivl_signal_name
|
||||
* ivl_signal_type
|
||||
* Return the type of the signal, i.e., reg, wire, tri0, etc.
|
||||
*
|
||||
* ivl_signal_name (DEPRECATED)
|
||||
* This function returns the fully scoped hierarchical name for the
|
||||
* signal. The name refers to the entire vector that is the signal.
|
||||
*
|
||||
* NOTE: This function is deprecated. The heirarchical name is too
|
||||
* vague a construct when escaped names can have . characters in
|
||||
* them. Do no use this function in new code, it will disappear.
|
||||
*
|
||||
* ivl_signal_basename
|
||||
* This function returns the name of the signal, without the scope
|
||||
* information. This is the tail of the signal name.
|
||||
* information. This is the tail of the signal name. Since Verilog
|
||||
* has an escape syntax, this name can contain any ASCII
|
||||
* characters, except NULL or white space. The leading \ and
|
||||
* trailing ' ' of escaped names in Verilog source are not part of
|
||||
* the name, so not included here.
|
||||
*
|
||||
* ivl_signal_attr
|
||||
* Icarus Verilog supports attaching attributes to signals, with
|
||||
@@ -855,11 +952,16 @@ extern ivl_nexus_t ivl_signal_pin(ivl_signal_t net, unsigned idx);
|
||||
extern unsigned ivl_signal_pins(ivl_signal_t net);
|
||||
extern ivl_signal_port_t ivl_signal_port(ivl_signal_t net);
|
||||
extern int ivl_signal_signed(ivl_signal_t net);
|
||||
extern int ivl_signal_integer(ivl_signal_t net);
|
||||
extern int ivl_signal_local(ivl_signal_t net);
|
||||
extern ivl_signal_type_t ivl_signal_type(ivl_signal_t net);
|
||||
extern const char* ivl_signal_name(ivl_signal_t net);
|
||||
extern const char* ivl_signal_basename(ivl_signal_t net);
|
||||
extern const char* ivl_signal_attr(ivl_signal_t net, const char*key);
|
||||
|
||||
extern unsigned ivl_signal_attr_cnt(ivl_signal_t net);
|
||||
extern ivl_attribute_t ivl_signal_attr_val(ivl_signal_t net, unsigned idx);
|
||||
|
||||
|
||||
/*
|
||||
* These functions get information about a process. A process is
|
||||
@@ -868,7 +970,7 @@ extern const char* ivl_signal_attr(ivl_signal_t net, const char*key);
|
||||
* may be a compound statement.)
|
||||
*
|
||||
* The ivl_process_type function gets the type of the process,
|
||||
* an "inital" or "always" statement.
|
||||
* an "initial" or "always" statement.
|
||||
*
|
||||
* A process is placed in a scope. The statement within the process
|
||||
* operates within the scope of the process unless there are calls
|
||||
@@ -877,6 +979,9 @@ extern const char* ivl_signal_attr(ivl_signal_t net, const char*key);
|
||||
* The ivl_process_stmt function gets the statement that forms the
|
||||
* process. See the statement related functions for how to manipulate
|
||||
* statements.
|
||||
*
|
||||
* Processes can have attributes attached to them. the attr_cnt and
|
||||
* attr_val methods return those attributes.
|
||||
*/
|
||||
extern ivl_process_type_t ivl_process_type(ivl_process_t net);
|
||||
|
||||
@@ -884,6 +989,9 @@ extern ivl_scope_t ivl_process_scope(ivl_process_t net);
|
||||
|
||||
extern ivl_statement_t ivl_process_stmt(ivl_process_t net);
|
||||
|
||||
extern unsigned ivl_process_attr_cnt(ivl_process_t net);
|
||||
extern ivl_attribute_t ivl_process_attr_val(ivl_process_t net, unsigned idx);
|
||||
|
||||
/*
|
||||
* These functions manage statements of various type. This includes
|
||||
* all the different kinds of statements (as enumerated in
|
||||
@@ -891,7 +999,7 @@ extern ivl_statement_t ivl_process_stmt(ivl_process_t net);
|
||||
*
|
||||
* The ivl_statement_type() function returns the type code for the
|
||||
* statement. This is the major type, and implies which of the later
|
||||
* functions are applicable to the statemnt.
|
||||
* functions are applicable to the statement.
|
||||
*/
|
||||
extern ivl_statement_type_t ivl_statement_type(ivl_statement_t net);
|
||||
|
||||
@@ -901,11 +1009,18 @@ extern ivl_statement_type_t ivl_statement_type(ivl_statement_t net);
|
||||
* make up the statement. Many of these functions apply to more then
|
||||
* one type of statement, so the comment in front of them tells which
|
||||
* statement types can be passed to the function.
|
||||
*
|
||||
* ivl_stmt_block_scope
|
||||
* If the block is named, then there is a scope associated with
|
||||
* this. The code generator may need to know this in order to
|
||||
* handle disable statements.
|
||||
*/
|
||||
|
||||
/* IVL_ST_BLOCK, IVL_ST_FORK */
|
||||
extern unsigned ivl_stmt_block_count(ivl_statement_t net);
|
||||
/* IVL_ST_BLOCK, IVL_ST_FORK */
|
||||
extern ivl_scope_t ivl_stmt_block_scope(ivl_statement_t net);
|
||||
/* IVL_ST_BLOCK, IVL_ST_FORK */
|
||||
extern ivl_statement_t ivl_stmt_block_stmt(ivl_statement_t net, unsigned i);
|
||||
/* IVL_ST_UTASK IVL_ST_DISABLE */
|
||||
extern ivl_scope_t ivl_stmt_call(ivl_statement_t net);
|
||||
@@ -976,6 +1091,77 @@ _END_DECL
|
||||
|
||||
/*
|
||||
* $Log: ivl_target.h,v $
|
||||
* Revision 1.108 2002/10/23 01:47:17 steve
|
||||
* Fix synth2 handling of aset/aclr signals where
|
||||
* flip-flops are split by begin-end blocks.
|
||||
*
|
||||
* Revision 1.107 2002/09/26 03:18:04 steve
|
||||
* Generate vvp code for asynch set/reset of NetFF.
|
||||
*
|
||||
* Revision 1.106 2002/09/12 15:49:43 steve
|
||||
* Add support for binary nand operator.
|
||||
*
|
||||
* Revision 1.105 2002/08/24 05:03:40 steve
|
||||
* Missing declaration of ivl_memory_scope.
|
||||
*
|
||||
* Revision 1.104 2002/08/12 01:34:59 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.103 2002/08/05 04:18:45 steve
|
||||
* Store only the base name of memories.
|
||||
*
|
||||
* Revision 1.102 2002/08/04 18:28:14 steve
|
||||
* Do not use hierarchical names of memories to
|
||||
* generate vvp labels. -tdll target does not
|
||||
* used hierarchical name string to look up the
|
||||
* memory objects in the design.
|
||||
*
|
||||
* Revision 1.101 2002/07/05 21:26:17 steve
|
||||
* Avoid emitting to vvp local net symbols.
|
||||
*
|
||||
* Revision 1.100 2002/06/21 04:59:35 steve
|
||||
* Carry integerness throughout the compilation.
|
||||
*
|
||||
* Revision 1.99 2002/06/11 03:34:33 steve
|
||||
* Spelling patch (Larry Doolittle)
|
||||
*
|
||||
* Revision 1.98 2002/05/27 00:08:45 steve
|
||||
* Support carrying the scope of named begin-end
|
||||
* blocks down to the code generator, and have
|
||||
* the vvp code generator use that to support disable.
|
||||
*
|
||||
* Revision 1.97 2002/05/26 01:39:02 steve
|
||||
* Carry Verilog 2001 attributes with processes,
|
||||
* all the way through to the ivl_target API.
|
||||
*
|
||||
* Divide signal reference counts between rval
|
||||
* and lval references.
|
||||
*
|
||||
* Revision 1.96 2002/05/24 04:36:23 steve
|
||||
* Verilog 2001 attriubtes on nets/wires.
|
||||
*
|
||||
* Revision 1.95 2002/05/23 03:08:51 steve
|
||||
* Add language support for Verilog-2001 attribute
|
||||
* syntax. Hook this support into existing $attribute
|
||||
* handling, and add number and void value types.
|
||||
*
|
||||
* Add to the ivl_target API new functions for access
|
||||
* of complex attributes attached to gates.
|
||||
*
|
||||
* Revision 1.94 2002/03/17 19:30:20 steve
|
||||
* Add API to support user defined function.
|
||||
*
|
||||
* Revision 1.93 2002/03/09 02:10:22 steve
|
||||
* Add the NetUserFunc netlist node.
|
||||
*
|
||||
* Revision 1.92 2002/01/28 00:52:41 steve
|
||||
* Add support for bit select of parameters.
|
||||
* This leads to a NetESelect node and the
|
||||
* vvp code generator to support that.
|
||||
*
|
||||
* Revision 1.91 2002/01/03 04:19:01 steve
|
||||
* Add structural modulus support down to vvp.
|
||||
*
|
||||
* Revision 1.90 2001/12/15 02:13:17 steve
|
||||
* The IVL_SIT_WIRE type does not exist, it is a
|
||||
* synonym for IVL_SIT_TRI.
|
||||
@@ -985,261 +1171,5 @@ _END_DECL
|
||||
*
|
||||
* Revision 1.88 2001/11/14 03:28:49 steve
|
||||
* DLL target support for force and release.
|
||||
*
|
||||
* Revision 1.87 2001/11/01 04:25:31 steve
|
||||
* ivl_target support for cassign.
|
||||
*
|
||||
* Revision 1.86 2001/10/31 05:24:52 steve
|
||||
* ivl_target support for assign/deassign.
|
||||
*
|
||||
* Revision 1.85 2001/10/19 21:53:24 steve
|
||||
* Support multiple root modules (Philip Blundell)
|
||||
*
|
||||
* Revision 1.84 2001/10/16 02:19:27 steve
|
||||
* Support IVL_LPM_DIVIDE for structural divide.
|
||||
*
|
||||
* Revision 1.83 2001/09/30 16:45:10 steve
|
||||
* Fix some Cygwin DLL handling. (Venkat Iyer)
|
||||
*
|
||||
* Revision 1.82 2001/09/16 22:19:42 steve
|
||||
* Support attributes to logic gates.
|
||||
*
|
||||
* Revision 1.81 2001/09/09 22:21:57 steve
|
||||
* pin down some enumerated constants.
|
||||
*
|
||||
* Revision 1.80 2001/09/01 01:57:31 steve
|
||||
* Make constants available through the design root
|
||||
*
|
||||
* Revision 1.79 2001/08/31 22:58:39 steve
|
||||
* Support DFF CE inputs.
|
||||
*
|
||||
* Revision 1.78 2001/08/28 04:07:17 steve
|
||||
* Add some ivl_target convenience functions.
|
||||
*
|
||||
* Revision 1.77 2001/08/25 23:50:03 steve
|
||||
* Change the NetAssign_ class to refer to the signal
|
||||
* instead of link into the netlist. This is faster
|
||||
* and uses less space. Make the NetAssignNB carry
|
||||
* the delays instead of the NetAssign_ lval objects.
|
||||
*
|
||||
* Change the vvp code generator to support multiple
|
||||
* l-values, i.e. concatenations of part selects.
|
||||
*
|
||||
* Revision 1.76 2001/08/10 00:40:45 steve
|
||||
* tgt-vvp generates code that skips nets as inputs.
|
||||
*
|
||||
* Revision 1.75 2001/07/27 04:51:44 steve
|
||||
* Handle part select expressions as variants of
|
||||
* NetESignal/IVL_EX_SIGNAL objects, instead of
|
||||
* creating new and useless temporary signals.
|
||||
*
|
||||
* Revision 1.74 2001/07/27 02:41:55 steve
|
||||
* Fix binding of dangling function ports. do not elide them.
|
||||
*
|
||||
* Revision 1.73 2001/07/22 00:17:49 steve
|
||||
* Support the NetESubSignal expressions in vvp.tgt.
|
||||
*
|
||||
* Revision 1.72 2001/07/19 04:55:06 steve
|
||||
* Support calculated delays in vvp.tgt.
|
||||
*
|
||||
* Revision 1.71 2001/07/04 22:59:25 steve
|
||||
* handle left shifter in dll output.
|
||||
*
|
||||
* Revision 1.70 2001/06/30 23:03:16 steve
|
||||
* support fast programming by only writing the bits
|
||||
* that are listed in the input file.
|
||||
*
|
||||
* Revision 1.69 2001/06/19 03:01:10 steve
|
||||
* Add structural EEQ gates (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.68 2001/06/16 23:45:05 steve
|
||||
* Add support for structural multiply in t-dll.
|
||||
* Add code generators and vvp support for both
|
||||
* structural and behavioral multiply.
|
||||
*
|
||||
* Revision 1.67 2001/06/16 02:41:41 steve
|
||||
* Generate code to support memory access in continuous
|
||||
* assignment statements. (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.66 2001/06/15 04:14:18 steve
|
||||
* Generate vvp code for GT and GE comparisons.
|
||||
*
|
||||
* Revision 1.65 2001/06/07 03:09:37 steve
|
||||
* support subtraction in tgt-vvp.
|
||||
*
|
||||
* Revision 1.64 2001/06/07 02:12:43 steve
|
||||
* Support structural addition.
|
||||
*
|
||||
* Revision 1.63 2001/05/20 01:06:16 steve
|
||||
* stub ivl_expr_parms for sfunctions.
|
||||
*
|
||||
* Revision 1.62 2001/05/17 04:37:02 steve
|
||||
* Behavioral ternary operators for vvp.
|
||||
*
|
||||
* Revision 1.61 2001/05/12 03:18:44 steve
|
||||
* Make sure LPM devices have drives on outputs.
|
||||
*
|
||||
* Revision 1.60 2001/05/08 23:59:33 steve
|
||||
* Add ivl and vvp.tgt support for memories in
|
||||
* expressions and l-values. (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.59 2001/05/08 04:13:12 steve
|
||||
* sort enumeration values.
|
||||
*
|
||||
* Revision 1.58 2001/05/06 17:48:20 steve
|
||||
* Support memory objects. (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.57 2001/04/29 23:17:38 steve
|
||||
* Carry drive strengths in the ivl_nexus_ptr_t, and
|
||||
* handle constant devices in targets.'
|
||||
*
|
||||
* Revision 1.56 2001/04/29 20:19:10 steve
|
||||
* Add pullup and pulldown devices.
|
||||
*
|
||||
* Revision 1.55 2001/04/26 05:12:02 steve
|
||||
* Implement simple MUXZ for ?: operators.
|
||||
*
|
||||
* Revision 1.54 2001/04/22 23:09:46 steve
|
||||
* More UDP consolidation from Stephan Boettcher.
|
||||
*
|
||||
* Revision 1.53 2001/04/21 00:55:46 steve
|
||||
* Generate code for disable.
|
||||
*
|
||||
* Revision 1.52 2001/04/15 02:58:11 steve
|
||||
* vvp support for <= with internal delay.
|
||||
*
|
||||
* Revision 1.51 2001/04/07 19:24:36 steve
|
||||
* Add the disable statemnent.
|
||||
*
|
||||
* Revision 1.50 2001/04/06 02:28:02 steve
|
||||
* Generate vvp code for functions with ports.
|
||||
*
|
||||
* Revision 1.49 2001/04/05 03:20:57 steve
|
||||
* Generate vvp code for the repeat statement.
|
||||
*
|
||||
* Revision 1.48 2001/04/05 01:12:27 steve
|
||||
* Get signed compares working correctly in vvp.
|
||||
*
|
||||
* Revision 1.47 2001/04/04 04:50:35 steve
|
||||
* Support forever loops in the tgt-vvp target.
|
||||
*
|
||||
* Revision 1.46 2001/04/03 04:50:37 steve
|
||||
* Support non-blocking assignments.
|
||||
*
|
||||
* Revision 1.45 2001/04/02 02:28:12 steve
|
||||
* Generate code for task calls.
|
||||
*
|
||||
* Revision 1.44 2001/04/02 00:28:35 steve
|
||||
* Support the scope expression node.
|
||||
*
|
||||
* Revision 1.43 2001/04/01 06:52:27 steve
|
||||
* support the NetWhile statement.
|
||||
*
|
||||
* Revision 1.42 2001/04/01 04:38:17 steve
|
||||
* dead cruft.
|
||||
*
|
||||
* Revision 1.41 2001/04/01 01:48:21 steve
|
||||
* Redesign event information to support arbitrary edge combining.
|
||||
*
|
||||
* Revision 1.40 2001/03/31 17:36:38 steve
|
||||
* Generate vvp code for case statements.
|
||||
*
|
||||
* Revision 1.39 2001/03/30 05:49:52 steve
|
||||
* Generate code for fork/join statements.
|
||||
*
|
||||
* Revision 1.38 2001/03/29 02:52:39 steve
|
||||
* Add unary ~ operator to tgt-vvp.
|
||||
*
|
||||
* Revision 1.37 2001/03/28 06:07:39 steve
|
||||
* Add the ivl_event_t to ivl_target, and use that to generate
|
||||
* .event statements in vvp way ahead of the thread that uses it.
|
||||
*
|
||||
* Revision 1.36 2001/03/27 06:27:40 steve
|
||||
* Generate code for simple @ statements.
|
||||
*
|
||||
* Revision 1.35 2001/03/20 01:44:13 steve
|
||||
* Put processes in the proper scope.
|
||||
*
|
||||
* Revision 1.34 2001/01/15 22:05:14 steve
|
||||
* Declare ivl_scope_type functions.
|
||||
*
|
||||
* Revision 1.33 2001/01/15 00:47:01 steve
|
||||
* Pass scope type information to the target module.
|
||||
*
|
||||
* Revision 1.32 2001/01/15 00:05:39 steve
|
||||
* Add client data pointer for scope and process scanners.
|
||||
*
|
||||
* Revision 1.31 2001/01/06 06:31:58 steve
|
||||
* declaration initialization for time variables.
|
||||
*
|
||||
* Revision 1.30 2000/12/05 06:29:33 steve
|
||||
* Make signal attributes available to ivl_target API.
|
||||
*
|
||||
* Revision 1.29 2000/11/12 17:47:29 steve
|
||||
* flip-flop pins for ivl_target API.
|
||||
*
|
||||
* Revision 1.28 2000/11/11 01:52:09 steve
|
||||
* change set for support of nmos, pmos, rnmos, rpmos, notif0, and notif1
|
||||
* change set to correct behavior of bufif0 and bufif1
|
||||
* (Tim Leight)
|
||||
*
|
||||
* Also includes fix for PR#27
|
||||
*
|
||||
* Revision 1.27 2000/11/11 00:03:36 steve
|
||||
* Add support for the t-dll backend grabing flip-flops.
|
||||
*
|
||||
* Revision 1.26 2000/10/31 17:49:02 steve
|
||||
* Support time variables.
|
||||
*
|
||||
* Revision 1.25 2000/10/28 22:32:34 steve
|
||||
* API for concatenation expressions.
|
||||
*
|
||||
* Revision 1.24 2000/10/28 17:55:03 steve
|
||||
* stub for the concat operator.
|
||||
*
|
||||
* Revision 1.23 2000/10/25 05:41:24 steve
|
||||
* Get target signal from nexus_ptr.
|
||||
*
|
||||
* Revision 1.22 2000/10/21 16:49:45 steve
|
||||
* Reduce the target entry points to the target_design.
|
||||
*
|
||||
* Revision 1.21 2000/10/18 20:04:39 steve
|
||||
* Add ivl_lval_t and support for assignment l-values.
|
||||
*
|
||||
* Revision 1.20 2000/10/15 04:46:23 steve
|
||||
* Scopes and processes are accessible randomly from
|
||||
* the design, and signals and logic are accessible
|
||||
* from scopes. Remove the target calls that are no
|
||||
* longer needed.
|
||||
*
|
||||
* Add the ivl_nexus_ptr_t and the means to get at
|
||||
* them from nexus objects.
|
||||
*
|
||||
* Give names to methods that manipulate the ivl_design_t
|
||||
* type more consistent names.
|
||||
*
|
||||
* Revision 1.19 2000/10/13 03:39:27 steve
|
||||
* Include constants in nexus targets.
|
||||
*
|
||||
* Revision 1.18 2000/10/08 04:01:54 steve
|
||||
* Back pointers in the nexus objects into the devices
|
||||
* that point to it.
|
||||
*
|
||||
* Collect threads into a list in the design.
|
||||
*
|
||||
* Revision 1.17 2000/10/07 19:45:43 steve
|
||||
* Put logic devices into scopes.
|
||||
*
|
||||
* Revision 1.16 2000/10/06 23:46:50 steve
|
||||
* ivl_target updates, including more complete
|
||||
* handling of ivl_nexus_t objects. Much reduced
|
||||
* dependencies on pointers to netlist objects.
|
||||
*
|
||||
* Revision 1.15 2000/10/05 05:03:01 steve
|
||||
* xor and constant devices.
|
||||
*
|
||||
* Revision 1.14 2000/09/30 02:18:15 steve
|
||||
* ivl_expr_t support for binary operators,
|
||||
* Create a proper ivl_scope_t object.
|
||||
*/
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
|
||||
Icarus Verilog LOADABLE TARGET API (ivl_target)
|
||||
|
||||
Copyright 2002 Stephen Williams <[email protected]>
|
||||
$Id: ivl_target.txt,v 1.3 2002/06/11 03:34:33 steve Exp $
|
||||
|
||||
|
||||
The ivl_target API is the interface available to modules that the
|
||||
Icarus Verilog compiler loads to act as a code generator. The API
|
||||
provides an interface to the elaborated, possibly synthesized, design
|
||||
for code generators that are intended to write netlist files or
|
||||
executable programs.
|
||||
|
||||
The functions and types of the API are summarized in the ivl_target.h
|
||||
header file. This document describes how the functions and types of
|
||||
the API are used to access and interpret the netlist of the design.
|
||||
|
||||
|
||||
LPM DEVICES
|
||||
|
||||
All LPM devices support a small set of common LPM functions, as
|
||||
described in the ivl_target header file. The ivl_lpm_t object has a
|
||||
type enumerated by ivl_lpm_type_t, and that type is accessible via the
|
||||
ivl_lpm_type function.
|
||||
|
||||
The following are type specific aspects of LPM devices.
|
||||
|
||||
* IVL_LPM_UFUNC
|
||||
|
||||
This LPM represents a user defined function. It is a way to connect
|
||||
behavioral code into a structural network. The UFUNC device has a
|
||||
vector output and a set of inputs. The ivl_lpm_define function returns
|
||||
the definition as an ivl_scope_t object.
|
||||
|
||||
The output vector is accessible through the ivl_lpm_q, and the output
|
||||
has the width defined by ivl_lpm_width. This similar to most every
|
||||
other LPM device with outputs.
|
||||
|
||||
There are ivl_lpm_size() input ports, each with the width
|
||||
ivl_lpm_data2_width(). The actual nexus is indexed by ivl_lpm_data2().
|
||||
|
||||
$Log: ivl_target.txt,v $
|
||||
Revision 1.3 2002/06/11 03:34:33 steve
|
||||
Spelling patch (Larry Doolittle)
|
||||
|
||||
Revision 1.2 2002/03/17 19:31:17 steve
|
||||
Add API to support user defined function.
|
||||
|
||||
Revision 1.1 2002/03/09 02:10:22 steve
|
||||
Add the NetUserFunc netlist node.
|
||||
|
||||
+10
-2
@@ -18,8 +18,8 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: globals.h,v 1.5 2000/09/13 22:33:13 steve Exp $"
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: globals.h,v 1.7 2002/08/12 01:35:02 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <stdio.h>
|
||||
@@ -37,11 +37,19 @@ extern int line_direct_flag;
|
||||
|
||||
extern unsigned error_count;
|
||||
|
||||
extern FILE *depend_file;
|
||||
|
||||
/* This is the entry to the parser. */
|
||||
extern int yyparse();
|
||||
|
||||
/*
|
||||
* $Log: globals.h,v $
|
||||
* Revision 1.7 2002/08/12 01:35:02 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.6 2002/04/04 05:26:13 steve
|
||||
* Add dependency generation.
|
||||
*
|
||||
* Revision 1.5 2000/09/13 22:33:13 steve
|
||||
* undefined macros are null (with warnings.)
|
||||
*
|
||||
|
||||
+155
-38
@@ -1,7 +1,7 @@
|
||||
|
||||
%{
|
||||
/*
|
||||
* Copyright (c) 1999 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1999-2002 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: lexor.lex,v 1.28 2001/11/29 02:26:25 steve Exp $"
|
||||
#ident "$Id: lexor.lex,v 1.35 2002/09/25 02:23:08 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -43,6 +43,7 @@ static void def_start();
|
||||
static void def_finish();
|
||||
static void def_undefine();
|
||||
static void do_define();
|
||||
static int def_is_done();
|
||||
static int is_defined(const char*name);
|
||||
|
||||
static void include_filename();
|
||||
@@ -66,6 +67,8 @@ struct include_stack_t {
|
||||
struct include_stack_t*next;
|
||||
};
|
||||
|
||||
static void emit_pathline(struct include_stack_t *isp);
|
||||
|
||||
static struct include_stack_t*file_queue = 0;
|
||||
static struct include_stack_t*istack = 0;
|
||||
static struct include_stack_t*standby = 0;
|
||||
@@ -89,6 +92,7 @@ static int comment_enter = 0;
|
||||
%x PPINCLUDE
|
||||
%x PPDEFINE
|
||||
%x CCOMMENT
|
||||
%x PCOMENT
|
||||
%x CSTRING
|
||||
%x ERROR_LINE
|
||||
|
||||
@@ -111,6 +115,15 @@ W [ \t\b\f]+
|
||||
<CCOMMENT>\n { istack->lineno += 1; ECHO; }
|
||||
<CCOMMENT>"*/" { BEGIN(comment_enter); ECHO; }
|
||||
|
||||
/* Detect and pass multiline pragma comments. As with C-style
|
||||
comments, pragma comments are passed through, and CPP directives
|
||||
contained within are ignored. */
|
||||
|
||||
"(*" { comment_enter = YY_START; BEGIN(PCOMENT); ECHO; }
|
||||
<PCOMENT>. { ECHO; }
|
||||
<PCOMENT>\n { istack->lineno += 1; ECHO; }
|
||||
<PCOMENT>"*)" { BEGIN(comment_enter); ECHO; }
|
||||
|
||||
/* Strings do not contain macros or preprocessor directives. */
|
||||
\" { comment_enter = YY_START; BEGIN(CSTRING); ECHO; }
|
||||
<CSTRING>\\\" { yymore(); }
|
||||
@@ -124,6 +137,7 @@ W [ \t\b\f]+
|
||||
|
||||
^{W}?`include { yy_push_state(PPINCLUDE); }
|
||||
|
||||
<PPINCLUDE>`[a-zA-Z][a-zA-Z0-9_]* { def_match(); }
|
||||
<PPINCLUDE>\"[^\"]*\" { include_filename(); }
|
||||
|
||||
<PPINCLUDE>[ \t\b\f] { ; }
|
||||
@@ -145,9 +159,9 @@ W [ \t\b\f]+
|
||||
/* Anything that is not matched by the above is an error of some
|
||||
sort. Print and error message and absorb the rest of the line. */
|
||||
<PPINCLUDE>. {
|
||||
fprintf(stderr, "%s:%u: error: malformed `include directive."
|
||||
" Did you quote the file name?\n", istack->path,
|
||||
istack->lineno+1);
|
||||
emit_pathline(istack);
|
||||
fprintf(stderr, "error: malformed `include directive."
|
||||
" Did you quote the file name?\n");
|
||||
error_count += 1;
|
||||
BEGIN(ERROR_LINE); }
|
||||
|
||||
@@ -156,17 +170,23 @@ W [ \t\b\f]+
|
||||
directive and the name, go into PPDEFINE mode and prepare to
|
||||
collect the defined value. */
|
||||
|
||||
`define{W}[a-zA-Z_][a-zA-Z0-9_]*{W}? { yy_push_state(PPDEFINE); def_start(); }
|
||||
`define{W}[a-zA-Z_][a-zA-Z0-9_$]*{W}? { yy_push_state(PPDEFINE); def_start(); }
|
||||
|
||||
<PPDEFINE>.* { do_define(); }
|
||||
|
||||
<PPDEFINE>(\n|"\r\n"|"\n\r") {
|
||||
def_finish();
|
||||
istack->lineno += 1;
|
||||
fputc('\n', yyout);
|
||||
yy_pop_state();
|
||||
<PPDEFINE>.* {
|
||||
do_define();
|
||||
}
|
||||
|
||||
<PPDEFINE>(\n|"\r\n"|"\n\r") {
|
||||
if (def_is_done()) {
|
||||
def_finish();
|
||||
istack->lineno += 1;
|
||||
yy_pop_state();
|
||||
}
|
||||
fputc('\n', yyout);
|
||||
}
|
||||
|
||||
/* If the define is terminated by an EOF, then finish the define
|
||||
whether there was a continuation or not. */
|
||||
<PPDEFINE><<EOF>> {
|
||||
def_finish();
|
||||
istack->lineno += 1;
|
||||
@@ -174,7 +194,7 @@ W [ \t\b\f]+
|
||||
yy_pop_state();
|
||||
}
|
||||
|
||||
`undef{W}[a-zA-Z_][a-zA-Z0-9_]*{W}?.* { def_undefine(); }
|
||||
`undef{W}[a-zA-Z_][a-zA-Z0-9_$]*{W}?.* { def_undefine(); }
|
||||
|
||||
|
||||
/* Detect conditional compilation directives, and parse them. If I
|
||||
@@ -186,7 +206,7 @@ W [ \t\b\f]+
|
||||
condition that stacks on top of the IFDEF_FALSE so that output is
|
||||
not accidentally turned on within nested ifdefs. */
|
||||
|
||||
^{W}?`ifdef{W}[a-zA-Z_][a-zA-Z0-9_]* {
|
||||
`ifdef{W}[a-zA-Z_][a-zA-Z0-9_$]* {
|
||||
char*name = strchr(yytext, '`');
|
||||
assert(name);
|
||||
name += 6;
|
||||
@@ -199,7 +219,7 @@ W [ \t\b\f]+
|
||||
}
|
||||
}
|
||||
|
||||
^{W}?`ifndef{W}[a-zA-Z_][a-zA-Z0-9_]* {
|
||||
`ifndef{W}[a-zA-Z_][a-zA-Z0-9_$]* {
|
||||
char*name = strchr(yytext, '`');
|
||||
assert(name);
|
||||
name += 7;
|
||||
@@ -212,22 +232,22 @@ W [ \t\b\f]+
|
||||
}
|
||||
}
|
||||
|
||||
<IFDEF_FALSE,IFDEF_SUPR>^{W}?`ifdef{W}.* { yy_push_state(IFDEF_SUPR); }
|
||||
<IFDEF_FALSE,IFDEF_SUPR>^{W}?`ifndef{W}.* { yy_push_state(IFDEF_SUPR); }
|
||||
<IFDEF_FALSE,IFDEF_SUPR>`ifdef{W} { yy_push_state(IFDEF_SUPR); }
|
||||
<IFDEF_FALSE,IFDEF_SUPR>`ifndef{W} { yy_push_state(IFDEF_SUPR); }
|
||||
|
||||
<IFDEF_TRUE>{W}?`else { BEGIN(IFDEF_FALSE); }
|
||||
<IFDEF_FALSE>{W}?`else { BEGIN(IFDEF_TRUE); }
|
||||
<IFDEF_SUPR>{W}?`else { }
|
||||
<IFDEF_TRUE>`else { BEGIN(IFDEF_FALSE); }
|
||||
<IFDEF_FALSE>`else { BEGIN(IFDEF_TRUE); }
|
||||
<IFDEF_SUPR>`else { }
|
||||
|
||||
<IFDEF_FALSE,IFDEF_SUPR>. { }
|
||||
<IFDEF_FALSE,IFDEF_SUPR>\n { istack->lineno += 1; fputc('\n', yyout); }
|
||||
|
||||
<IFDEF_FALSE,IFDEF_TRUE,IFDEF_SUPR>^{W}?`endif {
|
||||
<IFDEF_FALSE,IFDEF_TRUE,IFDEF_SUPR>`endif {
|
||||
yy_pop_state();
|
||||
}
|
||||
|
||||
/* This pattern notices macros and arranges for them to be replaced. */
|
||||
`[a-zA-Z][a-zA-Z0-9_]* { def_match(); }
|
||||
`[a-zA-Z][a-zA-Z0-9_$]* { def_match(); }
|
||||
|
||||
/* Any text that is not a directive just gets passed through to the
|
||||
output. Very easy. */
|
||||
@@ -302,9 +322,9 @@ static void def_match()
|
||||
yy_switch_to_buffer(yy_new_buffer(istack->file, YY_BUF_SIZE));
|
||||
|
||||
} else {
|
||||
fprintf(stderr, "%s:%u: warning: macro %s undefined "
|
||||
"(and assumed null) at this point.\n",
|
||||
istack->path, istack->lineno, yytext);
|
||||
emit_pathline(istack);
|
||||
fprintf(stderr, "warning: macro %s undefined "
|
||||
"(and assumed null) at this point.\n", yytext);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -361,33 +381,98 @@ void define_macro(const char*name, const char*value, int keyword)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The do_define function accumulates the defined value in these
|
||||
* variables. When the define is over, the def_finish() function
|
||||
* executes the define and clears this text. The define_continue_flag
|
||||
* is set if do_define detects that the definition is to be continued
|
||||
* on the next line.
|
||||
*/
|
||||
static char* define_text = 0;
|
||||
static size_t define_cnt = 0;
|
||||
|
||||
static int define_continue_flag = 0;
|
||||
|
||||
/*
|
||||
* Collect the definition. Normally, this returns 0. If there is a
|
||||
* continuation, then return 1 and this function may be called again
|
||||
* to collect another line of the definition.
|
||||
*/
|
||||
static void do_define()
|
||||
{
|
||||
char *cp;
|
||||
|
||||
define_continue_flag = 0;
|
||||
|
||||
/* FIXME: This strips trailing line comments out of the
|
||||
definition. It's not adequate as the "//" may have been
|
||||
quoted or commented, but it'll do for now. */
|
||||
char *cp;
|
||||
if(cp = strstr(yytext, "//"))
|
||||
*cp = 0;
|
||||
|
||||
/* Trim trailing white space. */
|
||||
cp = yytext + strlen(yytext);
|
||||
while (cp > yytext) {
|
||||
cp -= 1;
|
||||
if (!isspace(*cp))
|
||||
if (!isspace(cp[-1]))
|
||||
break;
|
||||
|
||||
cp -= 1;
|
||||
*cp = 0;
|
||||
}
|
||||
|
||||
define_macro(def_name, yytext, 0);
|
||||
def_name[0] = 0;
|
||||
/* Detect the continuation sequence. If I find it, remove it
|
||||
and the white space that preceeds it, then replace all that
|
||||
with a single newline. */
|
||||
if ((cp > yytext) && (cp[-1] == '\\')) {
|
||||
|
||||
cp -= 1;
|
||||
cp[0] = 0;
|
||||
while ((cp > yytext) && isspace(cp[-1])) {
|
||||
cp -= 1;
|
||||
*cp = 0;
|
||||
}
|
||||
|
||||
*cp++ = '\n';
|
||||
*cp = 0;
|
||||
define_continue_flag = 1;
|
||||
}
|
||||
|
||||
/* Accumulate this text into the define_text string. */
|
||||
define_text = realloc(define_text, define_cnt + (cp-yytext) + 1);
|
||||
strcpy(define_text+define_cnt, yytext);
|
||||
define_cnt += cp-yytext;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return true if the definition text is done. This is the opposite of
|
||||
* the define_continue_flag.
|
||||
*/
|
||||
static int def_is_done()
|
||||
{
|
||||
return define_continue_flag? 0 : 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* After some number of calls to do_define, this function is called to
|
||||
* assigned value to the parsed name. If there is no value, then
|
||||
* assign the string "1"
|
||||
*/
|
||||
static void def_finish()
|
||||
{
|
||||
if (def_name[0])
|
||||
define_macro(def_name, "1", 0);
|
||||
define_continue_flag = 0;
|
||||
|
||||
if (def_name[0]) {
|
||||
if (define_text) {
|
||||
define_macro(def_name, define_text, 0);
|
||||
free(define_text);
|
||||
define_text = 0;
|
||||
define_cnt = 0;
|
||||
|
||||
} else {
|
||||
define_macro(def_name, "1", 0);
|
||||
}
|
||||
def_name[0] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void def_undefine()
|
||||
@@ -498,7 +583,11 @@ static void output_init()
|
||||
|
||||
static void include_filename()
|
||||
{
|
||||
assert(standby == 0);
|
||||
if(standby) {
|
||||
emit_pathline(istack);
|
||||
fprintf(stderr, "error: malformed `include directive. Extra junk on line?\n");
|
||||
exit(1);
|
||||
}
|
||||
standby = malloc(sizeof(struct include_stack_t));
|
||||
standby->path = strdup(yytext+1);
|
||||
standby->path[strlen(standby->path)-1] = 0;
|
||||
@@ -510,7 +599,9 @@ static void do_include()
|
||||
|
||||
if (standby->path[0] == '/') {
|
||||
standby->file = fopen(standby->path, "r");
|
||||
|
||||
if(depend_file && standby->file) {
|
||||
fprintf(depend_file, "%s\n", istack->path);
|
||||
}
|
||||
} else {
|
||||
unsigned idx = 0;
|
||||
standby->file = 0;
|
||||
@@ -518,14 +609,18 @@ static void do_include()
|
||||
char path[4096];
|
||||
sprintf(path, "%s/%s", include_dir[idx], standby->path);
|
||||
standby->file = fopen(path, "r");
|
||||
if (standby->file)
|
||||
if (standby->file) {
|
||||
if(depend_file) {
|
||||
fprintf(depend_file, "%s\n", path);
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (standby->file == 0) {
|
||||
perror(standby->path);
|
||||
fprintf(stderr, "%s:%u: Include file %s not found\n",
|
||||
istack->path, istack->lineno, standby->path);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -541,6 +636,22 @@ static void do_include()
|
||||
istack->lineno+1, istack->path);
|
||||
}
|
||||
|
||||
/* walk the include stack until we find an entry with a valid pathname,
|
||||
* and print the file and line from that entry for use in an error message.
|
||||
* The istack entries created by def_match() for macro expansions do not
|
||||
* contain pathnames. This finds instead the real file in which the outermost
|
||||
* macro was used.
|
||||
*/
|
||||
static void emit_pathline(struct include_stack_t*isp)
|
||||
{
|
||||
while(isp && (isp->path == NULL)) {
|
||||
isp = isp->next;
|
||||
}
|
||||
assert(isp);
|
||||
fprintf(stderr, "%s:%u: ",
|
||||
isp->path, isp->lineno+1);
|
||||
}
|
||||
|
||||
/*
|
||||
* The lexical analyzer calls this function when the current file
|
||||
* ends. Here I pop the include stack and resume the previous file. If
|
||||
@@ -591,6 +702,9 @@ static int yywrap()
|
||||
|
||||
if (line_direct_flag)
|
||||
fprintf(yyout, "\n`line 1 \"%s\" 0\n", istack->path);
|
||||
if(depend_file) {
|
||||
fprintf(depend_file, "%s\n", istack->path);
|
||||
}
|
||||
|
||||
yyrestart(istack->file);
|
||||
return 0;
|
||||
@@ -626,6 +740,9 @@ void reset_lexor(FILE*out, char*paths[])
|
||||
perror(paths[0]);
|
||||
exit(1);
|
||||
}
|
||||
if(depend_file) {
|
||||
fprintf(depend_file, "%s\n", paths[0]);
|
||||
}
|
||||
|
||||
yyout = out;
|
||||
|
||||
|
||||
+32
-3
@@ -16,8 +16,8 @@ const char COPYRIGHT[] =
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: main.c,v 1.14 2001/11/21 02:59:27 steve Exp $"
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: main.c,v 1.16 2002/08/12 01:35:02 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -86,6 +86,7 @@ unsigned include_cnt = 0;
|
||||
int line_direct_flag = 0;
|
||||
|
||||
unsigned error_count = 0;
|
||||
FILE *depend_file = NULL;
|
||||
|
||||
/*
|
||||
* This function reads from a file a list of file names. Each name
|
||||
@@ -125,6 +126,7 @@ int main(int argc, char*argv[])
|
||||
const char*flist_path = 0;
|
||||
unsigned flag_errors = 0;
|
||||
char*out_path = 0;
|
||||
char *dep_path = NULL;
|
||||
FILE*out;
|
||||
|
||||
/* Define preprocessor keywords that I plan to just pass. */
|
||||
@@ -150,7 +152,7 @@ int main(int argc, char*argv[])
|
||||
include_dir[0] = strdup(".");
|
||||
include_cnt = 1;
|
||||
|
||||
while ((opt = getopt(argc, argv, "D:f:I:K:Lo:v")) != EOF) switch (opt) {
|
||||
while ((opt = getopt(argc, argv, "D:f:I:K:LM:o:v")) != EOF) switch (opt) {
|
||||
|
||||
case 'D': {
|
||||
char*tmp = strdup(optarg);
|
||||
@@ -192,6 +194,14 @@ int main(int argc, char*argv[])
|
||||
line_direct_flag = 1;
|
||||
break;
|
||||
|
||||
case 'M':
|
||||
if (dep_path) {
|
||||
fprintf(stderr, "duplicate -M flag.\n");
|
||||
} else {
|
||||
dep_path = optarg;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
if (out_path) {
|
||||
fprintf(stderr, "duplicate -o flag.\n");
|
||||
@@ -219,6 +229,7 @@ int main(int argc, char*argv[])
|
||||
" -I<dir> - Add an include file search directory\n"
|
||||
" -K<def> - Define a keyword macro that I just pass\n"
|
||||
" -L - Emit line number directives\n"
|
||||
" -M<fil> - Write dependencies to <fil>\n"
|
||||
" -o<fil> - Send the output to <fil>\n"
|
||||
" -v - Print version information\n",
|
||||
argv[0]);
|
||||
@@ -250,6 +261,14 @@ int main(int argc, char*argv[])
|
||||
out = stdout;
|
||||
}
|
||||
|
||||
if(dep_path) {
|
||||
depend_file = fopen(dep_path, "w");
|
||||
if (depend_file == 0) {
|
||||
perror(dep_path);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (source_cnt == 0) {
|
||||
fprintf(stderr, "%s: No input files given.\n", argv[0]);
|
||||
return 1;
|
||||
@@ -260,11 +279,21 @@ int main(int argc, char*argv[])
|
||||
reset_lexor(out, source_list);
|
||||
if (yyparse()) return -1;
|
||||
|
||||
if(depend_file) {
|
||||
fclose(depend_file);
|
||||
}
|
||||
|
||||
return error_count;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: main.c,v $
|
||||
* Revision 1.16 2002/08/12 01:35:02 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.15 2002/04/04 05:26:13 steve
|
||||
* Add dependency generation.
|
||||
*
|
||||
* Revision 1.14 2001/11/21 02:59:27 steve
|
||||
* Remove diag print.
|
||||
*
|
||||
|
||||
+3
-1
@@ -19,9 +19,11 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: parse.y,v 1.2 2000/08/20 17:49:05 steve Exp $"
|
||||
#ident "$Id: parse.y,v 1.3 2002/01/24 03:57:45 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <stdio.h>
|
||||
|
||||
static void yyerror(const char*msg);
|
||||
%}
|
||||
|
||||
|
||||
@@ -19,14 +19,14 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: lexor.lex,v 1.67 2001/12/03 04:47:15 steve Exp $"
|
||||
#ident "$Id: lexor.lex,v 1.73 2002/06/06 18:57:18 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
//# define YYSTYPE lexval
|
||||
|
||||
# include <iostream.h>
|
||||
# include <iostream>
|
||||
# include "compiler.h"
|
||||
# include "parse_misc.h"
|
||||
# include "parse_api.h"
|
||||
@@ -74,7 +74,7 @@ static const char* set_file_name(char*text)
|
||||
}
|
||||
|
||||
|
||||
extern void pform_set_timescale(int, int);
|
||||
extern void pform_set_timescale(int, int, const char*file, unsigned line);
|
||||
|
||||
void reset_lexor();
|
||||
static void line_directive();
|
||||
@@ -89,12 +89,15 @@ static verinum*make_unsized_dec(const char*txt);
|
||||
static verinum*make_unsized_octal(const char*txt);
|
||||
static verinum*make_unsized_hex(const char*txt);
|
||||
|
||||
static int dec_buf_div2(char *buf);
|
||||
|
||||
static void process_timescale(const char*txt);
|
||||
|
||||
static int comment_enter;
|
||||
%}
|
||||
|
||||
%x CCOMMENT
|
||||
%x PCOMMENT
|
||||
%x LCOMMENT
|
||||
%x CSTRING
|
||||
%s UDPTABLE
|
||||
@@ -110,15 +113,24 @@ W [ \t\b\f\r]+
|
||||
[ \t\b\f\r] { ; }
|
||||
\n { yylloc.first_line += 1; }
|
||||
|
||||
/* C++ style comments start with / / and run to the ene of the
|
||||
current line. These are very easy to handle. */
|
||||
|
||||
"//".* { comment_enter = YY_START; BEGIN(LCOMMENT); }
|
||||
<LCOMMENT>. { yymore(); }
|
||||
<LCOMMENT>\n { yylloc.first_line += 1; BEGIN(comment_enter); }
|
||||
|
||||
|
||||
/* The contents of C-style comments are ignored, like white space. */
|
||||
|
||||
"/*" { comment_enter = YY_START; BEGIN(CCOMMENT); }
|
||||
<CCOMMENT>. { yymore(); }
|
||||
<CCOMMENT>\n { yylloc.first_line += 1; yymore(); }
|
||||
<CCOMMENT>"*/" { BEGIN(comment_enter); }
|
||||
|
||||
|
||||
"(*" { return K_PSTAR; }
|
||||
"*)" { return K_STARP; }
|
||||
"<<" { return K_LS; }
|
||||
">>" { return K_RS; }
|
||||
"<=" { return K_LE; }
|
||||
@@ -193,7 +205,7 @@ W [ \t\b\f\r]+
|
||||
}
|
||||
|
||||
|
||||
\\[^ \t\b\f\r]+ {
|
||||
\\[^ \t\b\f\r\n]+ {
|
||||
yylval.text = strdup(yytext+1);
|
||||
return IDENTIFIER; }
|
||||
|
||||
@@ -238,19 +250,38 @@ W [ \t\b\f\r]+
|
||||
return NUMBER; }
|
||||
|
||||
[0-9][0-9_]* {
|
||||
/* Handle the special case of the unsized decimal number. */
|
||||
unsigned long value = 0;
|
||||
for (const char*cp = yytext ; *cp ; cp += 1) {
|
||||
if (*cp != '_')
|
||||
value = 10 * value + (*cp - '0');
|
||||
char buf[4096];
|
||||
|
||||
if (strlen(yytext) >= sizeof(buf)-2){
|
||||
fprintf(stderr, "Ridicilously long decimal constant will be truncated!\n");
|
||||
}
|
||||
|
||||
assert(INTEGER_WIDTH <= (8*sizeof(value)));
|
||||
unsigned nbits = INTEGER_WIDTH;
|
||||
verinum::V*bits = new verinum::V[8 * sizeof value];
|
||||
strncpy(buf, yytext, sizeof(buf)-2);
|
||||
buf[sizeof(buf)-1] = 0;
|
||||
|
||||
for (unsigned idx = 0 ; idx < nbits ; idx += 1, value >>= 1) {
|
||||
bits[idx] = (value&1) ? verinum::V1 : verinum::V0;
|
||||
/* Convert the decimal number to a binary value, one digit at
|
||||
a time. Watch out for overflow. */
|
||||
verinum::V*bits = new verinum::V[INTEGER_WIDTH];
|
||||
unsigned idx=0;
|
||||
unsigned nbits=INTEGER_WIDTH;
|
||||
|
||||
while(idx<nbits){
|
||||
int rem = dec_buf_div2(buf);
|
||||
|
||||
bits[idx] = (rem==1) ? verinum::V1 : verinum::V0;
|
||||
++idx;
|
||||
}
|
||||
|
||||
for(; idx<nbits; ++idx){
|
||||
bits[idx] = verinum::V0;
|
||||
}
|
||||
|
||||
/* If we run out of bits to hold the value, but there are
|
||||
still valueable bits in the number, print a warning. */
|
||||
if (strcmp(buf, "0") != 0){
|
||||
cerr << yylloc.text << ":" << yylloc.first_line <<
|
||||
": warning: Numeric decimal constant ``" << yytext <<
|
||||
"'' truncated to " << nbits << " bits." << endl;
|
||||
}
|
||||
|
||||
yylval.number = new verinum(bits, nbits, false);
|
||||
@@ -821,13 +852,65 @@ static verinum*make_unsized_hex(const char*txt)
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
/* Divide the integer given by the string by 2. Return the remainder bit. */
|
||||
static int dec_buf_div2(char *buf)
|
||||
{
|
||||
int partial;
|
||||
int len = strlen(buf);
|
||||
char *dst_ptr;
|
||||
int pos;
|
||||
|
||||
partial = 0;
|
||||
pos = 0;
|
||||
|
||||
/* dst_ptr overwrites buf, but all characters that are overwritten
|
||||
were already used by the reader. */
|
||||
dst_ptr = buf;
|
||||
|
||||
while(buf[pos] == '0')
|
||||
++pos;
|
||||
|
||||
for(; pos<len; ++pos){
|
||||
if (buf[pos]=='_')
|
||||
continue;
|
||||
|
||||
assert(isdigit(buf[pos]));
|
||||
|
||||
partial= partial*10 + (buf[pos]-'0');
|
||||
|
||||
if (partial >= 2){
|
||||
*dst_ptr = partial/2 + '0';
|
||||
partial = partial & 1;
|
||||
|
||||
++dst_ptr;
|
||||
}
|
||||
else{
|
||||
*dst_ptr = '0';
|
||||
++dst_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
// If result of division was zero string, it should remain that way.
|
||||
// Don't eat the last zero...
|
||||
if (dst_ptr == buf){
|
||||
*dst_ptr = '0';
|
||||
++dst_ptr;
|
||||
}
|
||||
*dst_ptr = 0;
|
||||
|
||||
return partial;
|
||||
}
|
||||
|
||||
/*
|
||||
* Making a decimal number is much easier then the other base numbers
|
||||
* because there are no z or x values to worry about.
|
||||
*/
|
||||
static verinum*make_dec_with_size(unsigned size, bool fixed, const char*ptr)
|
||||
{
|
||||
char buf[4096];
|
||||
bool signed_flag = false;
|
||||
|
||||
if (tolower(*ptr) == 's') {
|
||||
signed_flag = true;
|
||||
ptr += 1;
|
||||
@@ -838,40 +921,36 @@ static verinum*make_dec_with_size(unsigned size, bool fixed, const char*ptr)
|
||||
while (*ptr && ((*ptr == ' ') || (*ptr == '\t')))
|
||||
ptr += 1;
|
||||
|
||||
const char*digits = ptr;
|
||||
|
||||
/* Convert the decimal number to a binary value, one digit at
|
||||
a time. Watch out for overflow. */
|
||||
|
||||
unsigned long value = 0;
|
||||
for ( ; *ptr ; ptr += 1)
|
||||
if (isdigit(*ptr)) {
|
||||
unsigned long tmp = value * 10 + (*ptr - '0');
|
||||
if (tmp < value)
|
||||
cerr << yylloc.text << ":" << yylloc.first_line <<
|
||||
": warning: Numeric decimal constant ``"
|
||||
<< digits << "'' is too large." << endl;
|
||||
value *= 10;
|
||||
value += *ptr - '0';
|
||||
} else {
|
||||
assert(*ptr == '_');
|
||||
}
|
||||
|
||||
|
||||
verinum::V*bits = new verinum::V[size];
|
||||
|
||||
for (unsigned idx = 0 ; idx < size ; idx += 1) {
|
||||
bits[idx] = (value&1)? verinum::V1 : verinum::V0;
|
||||
value /= 2;
|
||||
if (strlen(ptr) >= sizeof(buf)-2){
|
||||
fprintf(stderr, "Ridicilously long decimal constant will be truncated!\n");
|
||||
}
|
||||
|
||||
/* If we run out of bits to hold the value, but there are
|
||||
still valueable bits in the number, print a warning. */
|
||||
strncpy(buf, ptr, sizeof(buf)-2);
|
||||
buf[sizeof(buf)-1] = 0;
|
||||
|
||||
if (value != 0)
|
||||
/* Convert the decimal number to a binary value, one digit at
|
||||
a time. Watch out for overflow. */
|
||||
verinum::V*bits = new verinum::V[size];
|
||||
unsigned idx=0;
|
||||
|
||||
while(idx<size){
|
||||
int rem = dec_buf_div2(buf);
|
||||
|
||||
bits[idx] = (rem==1) ? verinum::V1 : verinum::V0;
|
||||
++idx;
|
||||
}
|
||||
|
||||
for(; idx<size; ++idx){
|
||||
bits[idx] = verinum::V0;
|
||||
}
|
||||
|
||||
/* If we run out of bits to hold the value, but there are
|
||||
still valueable bits in the number, print a warning. */
|
||||
if (strcmp(buf, "0") != 0){
|
||||
cerr << yylloc.text << ":" << yylloc.first_line <<
|
||||
": warning: Numeric decimal constant ``" << digits <<
|
||||
": warning: Numeric decimal constant ``" << ptr <<
|
||||
"'' truncated to " << size << " bits." << endl;
|
||||
}
|
||||
|
||||
verinum*out = new verinum(bits, size, fixed);
|
||||
out->has_sign(signed_flag);
|
||||
@@ -999,7 +1078,7 @@ static void process_timescale(const char*txt)
|
||||
return;
|
||||
}
|
||||
|
||||
pform_set_timescale(unit, prec);
|
||||
pform_set_timescale(unit, prec, yylloc.text, yylloc.first_line);
|
||||
}
|
||||
|
||||
int yywrap()
|
||||
|
||||
+1
-1
@@ -82,7 +82,7 @@ rpmos, K_rpmos
|
||||
rtran, K_rtran
|
||||
rtranif0, K_rtranif0
|
||||
rtranif1, K_rtranif1
|
||||
scalered, K_scalered
|
||||
scalared, K_scalared
|
||||
signed, K_signed
|
||||
small, K_small
|
||||
specify, K_specify
|
||||
|
||||
+5
-2
@@ -18,14 +18,17 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#if !defined(WINNT) && !defined(macintosh)
|
||||
#ident "$Id: lexor_keyword.h,v 1.1 2000/03/12 17:09:41 steve Exp $"
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: lexor_keyword.h,v 1.2 2002/08/12 01:34:59 steve Exp $"
|
||||
#endif
|
||||
|
||||
extern int lexor_keyword_code (const char*str, unsigned len);
|
||||
|
||||
/*
|
||||
* $Log: lexor_keyword.h,v $
|
||||
* Revision 1.2 2002/08/12 01:34:59 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.1 2000/03/12 17:09:41 steve
|
||||
* Support localparam.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
Makefile
|
||||
configure
|
||||
config.*
|
||||
dep
|
||||
@@ -0,0 +1,89 @@
|
||||
#
|
||||
# This source code is free software; you can redistribute it
|
||||
# and/or modify it in source code form under the terms of the GNU
|
||||
# Library General Public License as published by the Free Software
|
||||
# Foundation; either version 2 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Library General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Library General Public
|
||||
# License along with this program; if not, write to the Free
|
||||
# Software Foundation, Inc.,
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.14 2002/06/11 15:19:12 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
srcdir = @srcdir@
|
||||
|
||||
VPATH = $(srcdir)
|
||||
|
||||
bindir = @bindir@
|
||||
libdir = @libdir@
|
||||
includedir = $(prefix)/include
|
||||
|
||||
CC = @CC@ -I$(srcdir) -I$(srcdir)/..
|
||||
CXX = @CXX@ -I$(srcdir) -I$(srcdir)/..
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
|
||||
CPPFLAGS = @CPPFLAGS@ @DEFS@
|
||||
CXXFLAGS = @CXXFLAGS@
|
||||
CFLAGS = @CFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
STRIP = @STRIP@
|
||||
|
||||
A = a_close.o a_fetch_argc.o a_fetch_argv.o a_fetch_fullname.o \
|
||||
a_fetch_tfarg.o a_handle_tfarg.o \
|
||||
a_initialize.o a_next_topmod.o a_object_of_type.o a_product_version.o \
|
||||
a_set_value.o a_version.o
|
||||
O = asynch.o finish.o getcstringp.o getinstance.o getlongp.o \
|
||||
getp.o getsimtime.o io_print.o mc_scan_plusargs.o nump.o putlongp.o \
|
||||
putp.o veriusertfs.o $A
|
||||
|
||||
all: libveriuser.a
|
||||
|
||||
check: all
|
||||
|
||||
Makefile: Makefile.in config.status
|
||||
./config.status
|
||||
|
||||
libveriuser.a: $O
|
||||
rm -f $@
|
||||
ar cvq $@ $O
|
||||
|
||||
%.o: %.c
|
||||
@[ -d dep ] || mkdir dep
|
||||
$(CC) -Wall $(CPPFLAGS) $(CFLAGS) -MD -c $< -o $*.o
|
||||
mv $*.d dep
|
||||
|
||||
|
||||
clean:
|
||||
rm -f *.o dep/*.d libveriuser.a
|
||||
|
||||
distclean: clean
|
||||
rm -f Makefile config.status config.log config.cache
|
||||
|
||||
install:: all installdirs $(libdir)/libveriuser.a
|
||||
|
||||
$(libdir)/libveriuser.a: ./libveriuser.a
|
||||
$(INSTALL_DATA) ./libveriuser.a $(libdir)/libveriuser.a
|
||||
|
||||
installdirs: mkinstalldirs
|
||||
$(srcdir)/mkinstalldirs $(includedir) $(libdir)
|
||||
|
||||
uninstall::
|
||||
rm -f $(libdir)/libveriuser.a
|
||||
|
||||
-include $(patsubst %.o, dep/%.d, $O)
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2002 Michael Ruff (mruff at chiaro.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: a_close.c,v 1.2 2002/08/12 01:35:02 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <acc_user.h>
|
||||
|
||||
void acc_close(void) { }
|
||||
|
||||
/*
|
||||
* $Log: a_close.c,v $
|
||||
* Revision 1.2 2002/08/12 01:35:02 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.1 2002/05/23 03:46:42 steve
|
||||
* Add the acc_user.h header file.
|
||||
*
|
||||
*/
|
||||
@@ -0,0 +1,49 @@
|
||||
/* vi:sw=6
|
||||
* Copyright (c) 2002 Michael Ruff (mruff at chiaro.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: a_fetch_argc.c,v 1.2 2002/08/12 01:35:02 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <vpi_user.h>
|
||||
# include <veriuser.h>
|
||||
|
||||
/*
|
||||
* acc_fetch_argc implemented using VPI interface
|
||||
*/
|
||||
int acc_fetch_argc(void)
|
||||
{
|
||||
s_vpi_vlog_info vpi_vlog_info;
|
||||
|
||||
/* get command line info */
|
||||
if (! vpi_get_vlog_info(&vpi_vlog_info))
|
||||
return 0;
|
||||
|
||||
/* return argc */
|
||||
return vpi_vlog_info.argc;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: a_fetch_argc.c,v $
|
||||
* Revision 1.2 2002/08/12 01:35:02 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.1 2002/06/11 15:19:12 steve
|
||||
* Add acc_fetch_argc/argv/version (mruff)
|
||||
*
|
||||
*/
|
||||
@@ -0,0 +1,49 @@
|
||||
/* vi:sw=6
|
||||
* Copyright (c) 2002 Michael Ruff (mruff at chiaro.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: a_fetch_argv.c,v 1.2 2002/08/12 01:35:02 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <vpi_user.h>
|
||||
# include <veriuser.h>
|
||||
|
||||
/*
|
||||
* acc_fetch_argv implemented using VPI interface
|
||||
*/
|
||||
char **acc_fetch_argv(void)
|
||||
{
|
||||
s_vpi_vlog_info vpi_vlog_info;
|
||||
|
||||
/* get command line info */
|
||||
if (! vpi_get_vlog_info(&vpi_vlog_info))
|
||||
return (char **)0;
|
||||
|
||||
/* return argc */
|
||||
return vpi_vlog_info.argv;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: a_fetch_argv.c,v $
|
||||
* Revision 1.2 2002/08/12 01:35:02 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.1 2002/06/11 15:19:12 steve
|
||||
* Add acc_fetch_argc/argv/version (mruff)
|
||||
*
|
||||
*/
|
||||
@@ -0,0 +1,42 @@
|
||||
/* vi:sw=6
|
||||
* Copyright (c) 2002 Michael Ruff (mruff at chiaro.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: a_fetch_fullname.c,v 1.2 2002/08/12 01:35:02 steve Exp $"
|
||||
#endif
|
||||
|
||||
#include <vpi_user.h>
|
||||
#include <acc_user.h>
|
||||
|
||||
/*
|
||||
* acc_fetch_fullname implemented using VPI interface
|
||||
*/
|
||||
char *acc_fetch_fullname(handle object)
|
||||
{
|
||||
return vpi_get_str(vpiFullName, object);
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: a_fetch_fullname.c,v $
|
||||
* Revision 1.2 2002/08/12 01:35:02 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.1 2002/06/07 02:58:58 steve
|
||||
* Add a bunch of acc/tf functions. (mruff)
|
||||
*
|
||||
*/
|
||||
@@ -0,0 +1,83 @@
|
||||
/* vi:sw=6
|
||||
* Copyright (c) 2002 Michael Ruff (mruff at chiaro.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: a_fetch_tfarg.c,v 1.2 2002/08/12 01:35:02 steve Exp $"
|
||||
#endif
|
||||
|
||||
#include <vpi_user.h>
|
||||
#include <acc_user.h>
|
||||
|
||||
/*
|
||||
* acc_fetch_tfarg routines implemented using VPI interface
|
||||
*/
|
||||
int acc_fetch_tfarg_int(int n)
|
||||
{
|
||||
vpiHandle sys_h, sys_i, arg_h = 0;
|
||||
s_vpi_value value;
|
||||
int rtn;
|
||||
|
||||
sys_h = vpi_handle(vpiSysTfCall, 0);
|
||||
sys_i = vpi_iterate(vpiArgument, sys_h);
|
||||
|
||||
/* scan to nth argument */
|
||||
while (n > 0 && (arg_h = vpi_scan(sys_i))) n--;
|
||||
|
||||
if (arg_h) {
|
||||
value.format=vpiIntVal;
|
||||
vpi_get_value(arg_h, &value);
|
||||
rtn = value.value.integer;
|
||||
} else {
|
||||
rtn = 0;
|
||||
}
|
||||
|
||||
return rtn;
|
||||
}
|
||||
|
||||
char *acc_fetch_tfarg_str(int n)
|
||||
{
|
||||
vpiHandle sys_h, sys_i, arg_h = 0;
|
||||
s_vpi_value value;
|
||||
char *rtn;
|
||||
|
||||
sys_h = vpi_handle(vpiSysTfCall, 0);
|
||||
sys_i = vpi_iterate(vpiArgument, sys_h);
|
||||
|
||||
/* scan to nth argument */
|
||||
while (n > 0 && (arg_h = vpi_scan(sys_i))) n--;
|
||||
|
||||
if (arg_h) {
|
||||
value.format=vpiStringVal;
|
||||
vpi_get_value(arg_h, &value);
|
||||
rtn = value.value.str;
|
||||
} else {
|
||||
rtn = (char *) 0;
|
||||
}
|
||||
|
||||
return rtn;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: a_fetch_tfarg.c,v $
|
||||
* Revision 1.2 2002/08/12 01:35:02 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.1 2002/06/07 02:58:58 steve
|
||||
* Add a bunch of acc/tf functions. (mruff)
|
||||
*
|
||||
*/
|
||||
@@ -0,0 +1,57 @@
|
||||
/* vi:sw=6
|
||||
* Copyright (c) 2002 Michael Ruff (mruff at chiaro.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: a_handle_tfarg.c,v 1.2 2002/08/12 01:35:02 steve Exp $"
|
||||
#endif
|
||||
|
||||
#include <acc_user.h>
|
||||
#include <vpi_user.h>
|
||||
|
||||
/*
|
||||
* acc_handle_tfarg implemented using VPI interface
|
||||
*/
|
||||
handle acc_handle_tfarg(int n)
|
||||
{
|
||||
vpiHandle sys_h, sys_i, rtn_h;
|
||||
|
||||
if (n > 0) {
|
||||
sys_h = vpi_handle(vpiSysTfCall, 0 /* NULL */);
|
||||
sys_i = vpi_iterate(vpiArgument, sys_h);
|
||||
|
||||
/* find nth arg */
|
||||
while (n > 0) {
|
||||
rtn_h = vpi_scan(sys_i);
|
||||
n--;
|
||||
}
|
||||
} else {
|
||||
rtn_h = (vpiHandle) 0;
|
||||
}
|
||||
|
||||
return rtn_h;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: a_handle_tfarg.c,v $
|
||||
* Revision 1.2 2002/08/12 01:35:02 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.1 2002/06/02 19:03:58 steve
|
||||
* Add acc_handle_tfarg and acc_next_topmode
|
||||
*
|
||||
*/
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 2002 Michael Ruff (mruff at chiaro.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: a_initialize.c,v 1.2 2002/08/12 01:35:02 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <acc_user.h>
|
||||
|
||||
int acc_error_flag;
|
||||
|
||||
int acc_initialize()
|
||||
{
|
||||
acc_error_flag = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: a_initialize.c,v $
|
||||
* Revision 1.2 2002/08/12 01:35:02 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.1 2002/05/23 03:46:42 steve
|
||||
* Add the acc_user.h header file.
|
||||
*
|
||||
*/
|
||||
@@ -0,0 +1,58 @@
|
||||
/* vi:sw=6
|
||||
* Copyright (c) 2002 Michael Ruff (mruff at chiaro.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: a_next_topmod.c,v 1.2 2002/08/12 01:35:02 steve Exp $"
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <vpi_user.h>
|
||||
#include <acc_user.h>
|
||||
|
||||
#undef NULL
|
||||
#define NULL 0
|
||||
|
||||
/*
|
||||
* acc_next_topmod implemented using VPI interface
|
||||
*/
|
||||
handle acc_next_topmod(handle prev_topmod)
|
||||
{
|
||||
static vpiHandle last = NULL;
|
||||
static vpiHandle mod_i = NULL;
|
||||
|
||||
if (!prev_topmod) {
|
||||
/* start over */
|
||||
mod_i = vpi_iterate(vpiModule, NULL);
|
||||
} else {
|
||||
/* subsequent time through */
|
||||
assert(prev_topmod == last);
|
||||
}
|
||||
|
||||
last = vpi_scan(mod_i);
|
||||
return last;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: a_next_topmod.c,v $
|
||||
* Revision 1.2 2002/08/12 01:35:02 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.1 2002/06/02 19:03:58 steve
|
||||
* Add acc_handle_tfarg and acc_next_topmode
|
||||
*
|
||||
*/
|
||||
@@ -0,0 +1,68 @@
|
||||
/* vi:sw=6
|
||||
* Copyright (c) 2002 Michael Ruff (mruff at chiaro.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: a_object_of_type.c,v 1.2 2002/08/12 01:35:02 steve Exp $"
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <vpi_user.h>
|
||||
#include <acc_user.h>
|
||||
|
||||
/*
|
||||
* acc_object_of_type implemented using VPI interface
|
||||
*/
|
||||
int acc_object_of_type(handle object, int type)
|
||||
{
|
||||
int vtype;
|
||||
int rtn = 0; /* false */
|
||||
|
||||
/* get VPI type of object */
|
||||
vtype = vpi_get(vpiType, object);
|
||||
|
||||
switch (type) {
|
||||
case accScope:
|
||||
if (vtype == vpiModule || vtype == vpiNamedBegin ||
|
||||
vtype == vpiNamedFork || vtype == vpiTask ||
|
||||
vtype == vpiFunction) rtn = 1;
|
||||
break;
|
||||
case accScalar:
|
||||
if (vtype == vpiReg || vtype == vpiNet)
|
||||
rtn = vpi_get(vpiSize, object) == 1;
|
||||
break;
|
||||
case accVector:
|
||||
if (vtype == vpiReg || vtype == vpiNet)
|
||||
rtn = vpi_get(vpiSize, object) > 1;
|
||||
break;
|
||||
default:
|
||||
vpi_printf("acc_object_of_type: Unknown type %d\n", type);
|
||||
assert(0);
|
||||
}
|
||||
|
||||
return rtn;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: a_object_of_type.c,v $
|
||||
* Revision 1.2 2002/08/12 01:35:02 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.1 2002/06/07 02:58:58 steve
|
||||
* Add a bunch of acc/tf functions. (mruff)
|
||||
*
|
||||
*/
|
||||
@@ -0,0 +1,43 @@
|
||||
/* vi:sw=6
|
||||
* Copyright (c) 2002 Michael Ruff (mruff at chiaro.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: a_product_version.c,v 1.2 2002/08/12 01:35:02 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <vpi_user.h>
|
||||
# include <acc_user.h>
|
||||
|
||||
char *acc_product_version(void)
|
||||
{
|
||||
s_vpi_vlog_info info;
|
||||
|
||||
if (! vpi_get_vlog_info(&info)) return (char *)0;
|
||||
|
||||
return info.version;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: a_product_version.c,v $
|
||||
* Revision 1.2 2002/08/12 01:35:02 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.1 2002/05/30 02:06:05 steve
|
||||
* Implement acc_product_version.
|
||||
*
|
||||
*/
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user