Compare commits

..
163 Commits
Author SHA1 Message Date
Stephen Williams 2fc5f4f7d8 Prepare for v0.8.5 release.
Signed-off-by: Stephen Williams <[email protected]>
2007-07-24 16:12:40 -07:00
Stephen Williams d16a0bdb3a Unary minus size assertion
Fix errors with unary subtraction producing logic gates with
inconsistent widths.

Signed-off-by: Stephen Williams <[email protected]>
2007-07-19 15:41:42 -07:00
Stephen Williams 6eaf0c231c No system functions in continuous assignments.
Do not support (in 0.8) system functions in continuous assignments.
Make a better error message.

Signed-off-by: Stephen Williams <[email protected]>
2007-07-18 12:45:04 -07:00
Stephen Williams cd8eb8776e Fix comparison of two negative numbers
Pairs of negative numbers that are equal do not set
the LT flag correctly at runtime.
2007-07-03 16:12:55 -07:00
Alan Feldstein 3d0a2aba2c Add code generator hooks for latches
Add code generator hooks missing from the previous
patches that add latch synthesis support.
2007-06-27 14:39:06 -07:00
steve f600e774d5 Add support for NAND gates. (Chris H) 2007-06-06 15:46:22 +00:00
steve d16dd26660 Support Latch synthesis (Alan Feldstein) 2007-05-30 17:48:53 +00:00
steve 8c04d669f9 DEBUG aids. (Alan Feldstein) 2007-05-30 17:48:26 +00:00
steve 5d2dcfd7f7 Fix uninitilized line number. 2007-05-25 18:35:45 +00:00
steve 0b3f1e4119 Better configuration messages (Alan Feldstein) 2007-05-16 23:51:42 +00:00
steve 8bd9fc7128 Supress error about types for default rule. 2007-04-26 00:50:54 +00:00
steve 1b551aaf94 Update to v0.8.4 release. 2007-03-23 23:26:51 +00:00
steve a3dda80fb2 Properly support signed task/function arguments. 2007-03-23 23:22:57 +00:00
steve 9e9d5ccfdd Fix compile time eval of <= comparison. 2007-03-23 23:02:31 +00:00
steve 07daee9438 Fix compile time evaluation of < operator. 2007-03-23 20:59:25 +00:00
steve 82808d8b5d Parse attribute attached to block items. 2007-03-23 19:31:22 +00:00
steve c045f51a7f Spelling fixes (larry doolittle) 2007-02-26 19:51:38 +00:00
steve d72eadb885 Get page size from sysconf. 2007-02-16 23:29:17 +00:00
steve e99f0a8f51 Comment about 10.3. 2007-02-09 05:30:22 +00:00
steve ed2cb380cd fix lexical handling of slashes in strings. 2007-02-09 05:29:24 +00:00
steve dc8e941260 Fix parse of bit select in notifier expression, 2006-12-03 04:58:20 +00:00
steve d486b81f23 Fix crash handling constant true conditional. 2006-11-27 01:47:14 +00:00
steve 59c2f16a5f Fix evaluate of constant condition expressions. 2006-11-27 01:32:24 +00:00
steve 1470a061fd Add synthesis of user defined functions. 2006-11-26 01:54:05 +00:00
steve c1333a21ef Prevent constant mux outputs from confusing itself. 2006-11-12 01:20:45 +00:00
steve 04ef0b7d80 Fix async blocks to take accumulated input. 2006-11-11 23:10:20 +00:00
steve 2fc9413d1f More detailed BuildRequires settings. 2006-11-11 21:21:50 +00:00
steve c94bdbcdb0 Make signal lookup use extended names. 2006-11-11 21:21:21 +00:00
steve 1820cd0244 Fix compile on Mac OS X 2006-11-02 17:47:52 +00:00
steve aa3cbbdf99 Error message for condit expression not synthesized. 2006-11-02 02:13:15 +00:00
steve 0a9b6f34ae Detect and synthesize enables using condit false. 2006-10-30 02:03:30 +00:00
steve 5c2c5453ac Fix code generation for signed numbers in real expressions. 2006-10-11 00:19:04 +00:00
steve 0c6bb476ea Get rounding of conversion correct. 2006-10-11 00:17:35 +00:00
steve 568924dcb5 Version stamp update 2006-10-04 17:08:59 +00:00
steve 33b3f7bdda Detect delay precision overflow. 2006-10-04 00:37:03 +00:00
steve 3a04e0a051 Fix a dangling reference to NetEParam objects in defparams. 2006-10-04 00:34:45 +00:00
steve 66ae377801 Snapshot v0.8.3 2006-10-03 21:34:40 +00:00
steve 898db57405 Describe the preconfigure steps. 2006-09-28 23:42:14 +00:00
steve 0fe45b5046 Fix host type detection in some configure scripts. 2006-09-22 03:29:02 +00:00
steve 20cfe99457 Fix left shift of small unsized constants. 2006-09-20 20:27:02 +00:00
steve 4ec8b38a5c Special handling of exploded memory arguments. 2006-09-15 23:56:05 +00:00
steve 79add47002 Build instruction typos and minor corrections. 2006-09-15 23:53:24 +00:00
steve c429f4c9a7 missing sig diagnostics. 2006-08-23 04:09:14 +00:00
steve 7f6a0b652a Do not count self as signifincant in nodangle. 2006-08-23 04:08:55 +00:00
steve 9f3f9154eb Fix missing sig on certain mux outputs.
Ignore condit statements (for synthesis) with no outputs.
2006-08-23 04:08:19 +00:00
steve 498fd06412 Add synthesis for casez statements. 2006-08-22 04:22:45 +00:00
steve 6d3b780791 Improve performance of unlink of heavily connected nexa. 2006-08-15 03:41:24 +00:00
steve a0ec981c50 Improved nexus management performance. 2006-08-08 02:17:48 +00:00
steve 930cd598a0 Typo clearing an event cell. 2006-08-06 18:09:42 +00:00
steve 77adab0f33 Remove excess PEString:: prefix for stubborn compilers. 2006-07-28 16:26:17 +00:00
steve 0e3768f829 Handle statement output override better in blocks. 2006-07-23 19:42:33 +00:00
steve 22884f2e64 Add support for full_case attribute. 2006-07-10 00:21:49 +00:00
steve 62da6aca28 Root dir variable does not include lib/ivl components. 2006-07-07 21:31:50 +00:00
steve 525ebddb0c Properly synthesize casex statements. 2006-07-02 00:50:15 +00:00
steve 521750c007 Fix ambiguity warnings. 2006-06-27 01:47:25 +00:00
steve 85d2833a62 Fix const/non-const warnings. 2006-06-27 01:37:14 +00:00
steve e2cc258283 Cure exit from main warning. 2006-06-27 01:33:17 +00:00
steve f09cf85c76 Fix unused var warning for mingw32 build. 2006-06-27 01:30:20 +00:00
steve c32de1dba0 Handle case where case output appears to be internal. 2006-06-26 00:05:46 +00:00
steve 628b866c36 Change Copyright tag to License. 2006-06-24 05:22:55 +00:00
steve 08dbe801c1 synthesis of NetCondit handles partial resets. 2006-06-23 03:49:46 +00:00
steve 101810df21 Handle simple memory addressing in expression synthesis. 2006-06-15 01:57:26 +00:00
steve 3877b636df synthesis for NetEBitSel. 2006-06-14 03:02:54 +00:00
steve 9d028a63f2 Remove redundant call to get_root_dir. 2006-06-14 03:01:49 +00:00
steve 35e5cea9df Add support for -Wunused warnings. 2006-06-12 00:16:50 +00:00
steve ec510071f1 Fix partial use of NetMux in sync condit statements. 2006-06-07 03:17:39 +00:00
steve 7413c533f6 Compilation warnings. 2006-06-02 23:42:48 +00:00
steve dde69cebb6 Handle condit clauses with unassigned outputs. 2006-06-01 03:01:48 +00:00
steve f942657ad5 NetESignal input is only selected bits. 2006-05-21 21:58:46 +00:00
steve fad1620828 Replace assertions with error messages. 2006-05-20 16:06:48 +00:00
steve a9931e7a58 Fix synthesis of l-value bit select in block. 2006-05-18 01:47:12 +00:00
steve 6cd4adb135 Fix synthesis of expressions with land of vectors. 2006-05-15 03:55:22 +00:00
steve 9643b86ab3 Update to use only Mingw for build. 2006-05-08 04:33:35 +00:00
steve 452eaeaea8 Handle memory assignments out of range during synthesis 2006-05-05 01:56:36 +00:00
steve 3a6e2df958 Fix uninitialized mem_lref_ member. 2006-05-02 02:00:15 +00:00
steve e73b7e2656 parse.cc and parse.h are made by the same steps. 2006-05-01 20:11:56 +00:00
steve 469ec11190 Merge fixes from devel tree. 2006-04-25 05:11:14 +00:00
steve e0bbfa512c Constant propagate addresses through NetRamDq read ports. 2006-04-23 04:26:13 +00:00
steve 94c9af2a5d Add cprop debugging. 2006-04-23 04:25:45 +00:00
steve 9f2e7df0ff vpp.conf is generated, so add it to cvsignore. 2006-04-23 02:44:29 +00:00
steve f02b2c9d7a Fix handling of exploded memories with partial or missing resets. 2006-04-16 19:26:37 +00:00
steve 058dac4290 Exploded memories accessed by constant indices. 2006-04-10 03:43:39 +00:00
steve ce4e21a962 Punt on set/reset if some sources are unconnected. 2006-04-01 01:37:58 +00:00
steve 065d6bc1e3 Add synth debug flag 2006-04-01 01:37:24 +00:00
steve 312d09dc1d Handle asynchronous demux/bit replacements. 2006-03-26 23:09:21 +00:00
steve faf7f30283 Add the .demux device. 2006-03-26 23:09:00 +00:00
steve 5d41e98c1f More installation directory flexibility. 2006-03-26 21:47:26 +00:00
steve 5e8330a4ff Better error messages when synthesis fails. 2006-03-18 18:43:21 +00:00
steve ef8964c65a Fix crash when memory exploding doesnot work 2006-03-16 05:40:18 +00:00
steve aa42ec381c Fix a spelling error in an error message. 2006-03-16 05:39:43 +00:00
steve c9d4aab9cb Right shifts really are allowed. 2006-03-16 05:39:20 +00:00
steve b8bc531f05 Fix the memsynth1 case. 2006-03-12 07:34:16 +00:00
steve 79cb8c883a Add support for negedge FFs by using attributes. 2006-02-25 05:03:28 +00:00
steve 27e633410c Add change callback to vpiMemory objects. 2006-02-19 16:57:31 +00:00
steve 7527c466ed Handle synthesis of FF vectors with l-value decoder. 2006-02-19 00:11:31 +00:00
steve 3ea1214160 More robust test for concat constant-ness. 2006-02-07 22:46:23 +00:00
steve 782542922d Detect nul arguments to concat expressions. 2006-02-07 22:45:54 +00:00
steve 1f8102c4dc Speed up processing of connect when one side is empty. 2006-01-27 02:05:46 +00:00
steve c4b34e8720 Document how the default statement handling works. 2006-01-27 01:58:53 +00:00
steve e494be7cbf Fix pin_Sel overrun. 2006-01-22 00:13:59 +00:00
steve eb0a78e9ce When mux has wide select but sparse choices, use 1hot translation. 2006-01-21 21:42:31 +00:00
steve e80138ec8c Restrict DFF to only one of Sset and Sclr. 2006-01-18 06:16:11 +00:00
steve 943316c6f6 Support DFF with synchronous inputs. 2006-01-18 06:15:45 +00:00
steve 52b8ed9077 Rework l-value handling to allow for more l-value type flexibility. 2006-01-18 01:23:23 +00:00
steve fc227aa3e1 Remember to set DLL= flag. 2006-01-14 20:13:38 +00:00
steve 41993815e9 Show synchronous set/clr of FF. 2006-01-14 20:13:22 +00:00
steve c5063f5d2f Case statement handles partial outputs. 2006-01-01 02:25:07 +00:00
steve f28aa11936 Allow for implicit case default in synchronous processes. 2006-01-01 01:30:39 +00:00
steve 3131fa68b7 Fix crashes caused bu synthesis of sqrt32.v. 2005-12-31 04:28:14 +00:00
steve def3809b3f Handle DFF definitions spread out within a block. 2005-12-19 01:13:47 +00:00
steve 3429c24a6a Properly fail when concat is not actually constant. 2005-12-18 21:06:01 +00:00
steve f47627d752 Fix missing outputs from synchronous conditionals to get out from in. 2005-12-15 02:38:51 +00:00
steve 9468f3d06f Handle both asynchronous set and reset. 2005-12-14 01:53:39 +00:00
steve b997de63a5 Account for sync vs async muxes. 2005-12-14 00:54:29 +00:00
steve f50f06ab4e Handle concatenations in l-values. 2005-12-10 04:26:32 +00:00
steve d5d03812cd Fix crash on block with assignments that assign lval to self. 2005-12-10 03:30:50 +00:00
steve b6d5a0675e Support constant concatenation of constants. 2005-12-07 03:28:44 +00:00
steve e63e830d62 Error messages for missing else clauses. 2005-12-07 02:14:37 +00:00
steve 74ca34bd82 Handle partial sets of conditional clauses. 2005-11-16 00:38:26 +00:00
steve c9d480028e Allow for block output to be set throughout the statements. 2005-11-13 22:28:48 +00:00
steve cc89ba66af Do not panic if case statement is nul. 2005-11-13 22:28:14 +00:00
steve 05e6d51004 Snapshot 0.8.2 2005-09-30 15:13:37 +00:00
steve ae583204e3 Snapshot 0.8.2 2005-09-30 15:01:44 +00:00
steve 018476f7cd More predictable ordering of items in NexusSet. 2005-09-25 23:30:31 +00:00
steve bfabeab6b9 Add Xilinx virtex as a reference EDIF device. 2005-09-25 16:35:36 +00:00
steve 4a3f1a3641 Attach line numbers to NetMux devices. 2005-09-11 02:56:37 +00:00
steve d97560caa7 Fix overly agressive constant propagation through MUX causing lost Z bits. 2005-09-11 02:50:51 +00:00
steve 393102d43a Evaluate magnitude compare with real operands. 2005-09-09 02:17:08 +00:00
steve 8e97a0e4d4 Support b1 edge in primitive tables. 2005-09-09 02:13:15 +00:00
steve 4ea789a2d7 More explicit internal error message. 2005-09-04 15:41:54 +00:00
steve 354f7ad920 More explicit internal error message. 2005-09-04 15:39:19 +00:00
steve f4a6206790 Handle b0 edges in primitives. 2005-09-04 15:33:19 +00:00
steve fd29ba3398 Reduce mux slices that are constant throughout range. 2005-08-28 22:00:39 +00:00
steve 44fbf60885 More thorough constant propagation through MUX devices. 2005-08-28 19:51:02 +00:00
steve a0d69113c3 More thorough constant propagation through MUX devices. 2005-08-28 19:50:03 +00:00
steve 86942ac592 Dump CMP_GE devices. 2005-08-28 17:37:28 +00:00
steve 075f9cbc4b Back-port edif_nexus_to_joint from tgt-edif. 2005-08-27 22:29:30 +00:00
steve 9dab368880 fix configure and build instructions for mingw build. 2005-08-27 22:19:37 +00:00
steve 5f6027fb66 Join cell0 and cell1 instances in LPM target. 2005-08-25 18:52:32 +00:00
steve 53156793fe Add support for implicit defaults in case and conditions. 2005-08-22 01:00:41 +00:00
steve 4644c220e8 Handle statements in blocks overriding previous statement outputs. 2005-08-21 22:49:54 +00:00
steve c30cd9afea Display NOR gates. 2005-08-21 22:27:57 +00:00
steve a8f45a18f0 Fix the comment in the EDIT header. 2005-08-21 22:25:51 +00:00
steve 6828e3e2ea Generate LPM for the CMP_EQ device. 2005-08-21 14:39:33 +00:00
steve 75eb372adf configure tgt-edif subdir. 2005-08-21 02:20:16 +00:00
steve 3b753fe52b Add the tgt-edif target. 2005-08-17 01:17:28 +00:00
steve 8c73fa7840 Fix compilation warnings/errors with newer compilers. 2005-08-13 00:45:53 +00:00
steve d310e656c7 Fix parse errors related to pr766. 2005-07-27 14:48:34 +00:00
steve 0510367b70 Fix compile errors with g++-4. 2005-07-06 22:41:34 +00:00
steve 3e11207a56 Fix gcc4 build issues. 2005-06-14 15:33:54 +00:00
steve 665f31271f popen must be matched by pclose. 2005-03-22 15:53:12 +00:00
steve 9a2b56675c Fix set_width to allow binary logical operands to be self determined. 2005-03-05 01:36:16 +00:00
steve c9f38f5ffa Improve distclean targets. 2005-02-23 18:40:23 +00:00
steve 5ea4152162 Spelling fixes from Larry. 2005-02-23 18:37:52 +00:00
steve 327c897d7e Spellig fixes. 2005-02-19 16:39:30 +00:00
steve 29ebe486b7 Fix multiple delete of an expression. 2005-02-19 16:38:14 +00:00
steve 4af0acb3be Fix (from Tony) for clock compression detection 2005-02-11 17:04:22 +00:00
steve 8435774c26 Fix evaluate of constants in netlist concatenation repeats. 2005-01-29 00:18:23 +00:00
steve 6172748c65 Add stub config files to CVS. 2005-01-28 18:30:11 +00:00
steve ca0ae9040a Add ability to compile real values into index registers. 2005-01-28 18:29:29 +00:00
steve d9cdbde3f6 More robust handling of file name argument to $fopen. 2005-01-01 20:07:41 +00:00
steve 307a97116f Fix leak of word registers in code generator. 2004-12-12 04:25:10 +00:00
steve 83d2c6dfd1 Update for 0.8 files. 2004-10-14 01:12:41 +00:00
300 changed files with 29337 additions and 39126 deletions
-1
View File
@@ -17,7 +17,6 @@ configure
Makefile
check
check.cc
check.vvp
config.status
config.log
config.cache
+2 -5
View File
@@ -104,7 +104,7 @@ module may not be needed as long as the ``-s <name>'' switch is
given.
So when you send a test case, ask yourself "Can poor overworked Steve
invoke the error without any Verilog other than what is included?" And
invoke the error without any Verilog other then what is included?" And
while we are at it, please place a copyright notice in your test
program and include a GPL license statement if you can. Your test
program may find its way into the test suite, and the notices will
@@ -160,11 +160,8 @@ I must insist that any copyright material submitted for inclusion
include the GPL license notice as shown in the rest of the source.
$Id: BUGS.txt,v 1.5 2007/03/22 16:08:14 steve Exp $
$Id: BUGS.txt,v 1.4 2003/02/19 04:36:31 steve Exp $
$Log: BUGS.txt,v $
Revision 1.5 2007/03/22 16:08:14 steve
Spelling fixes from Larry
Revision 1.4 2003/02/19 04:36:31 steve
Notes on hte bug database.
+186 -58
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: HName.cc,v 1.8 2007/06/02 03:42:12 steve Exp $"
#ident "$Id: HName.cc,v 1.5 2002/11/02 03:27:52 steve Exp $"
#endif
# include "config.h"
@@ -29,107 +29,235 @@
# include <malloc.h>
#endif
hname_t::hname_t()
{
number_ = INT_MIN;
item_ = 0;
count_ = 0;
}
hname_t::hname_t(perm_string text)
hname_t::hname_t(const char*text)
{
name_ = text;
number_ = INT_MIN;
}
hname_t::hname_t(perm_string text, int num)
{
name_ = text;
number_ = num;
item_ = strdup(text);
count_ = 1;
}
hname_t::hname_t(const hname_t&that)
{
name_ = that.name_;
number_ = that.number_;
}
hname_t& hname_t::operator = (const hname_t&that)
{
name_ = that.name_;
number_ = that.number_;
return *this;
count_ = that.count_;
switch (count_) {
case 0:
item_ = 0;
break;
case 1:
item_ = strdup(that.item_);
break;
default:
array_ = new char*[count_];
for (unsigned idx = 0 ; idx < count_ ; idx += 1)
array_[idx] = strdup(that.array_[idx]);
break;
}
}
hname_t::~hname_t()
{
switch (count_) {
case 0:
break;
case 1:
free(item_);
break;
default:
for (unsigned idx = 0 ; idx < count_ ; idx += 1)
free(array_[idx]);
delete[]array_;
break;
}
}
perm_string hname_t::peek_name(void) const
unsigned hname_t::component_count() const
{
return name_;
return count_;
}
bool hname_t::has_number() const
void hname_t::append(const char*text)
{
return number_ != INT_MIN;
char**tmp;
switch (count_) {
case 0:
count_ = 1;
item_ = strdup(text);
break;
case 1:
count_ = 2;
tmp = new char*[2];
tmp[0] = item_;
tmp[1] = strdup(text);
array_ = tmp;
break;
default:
tmp = new char*[count_+1];
for (unsigned idx = 0 ; idx < count_ ; idx += 1)
tmp[idx] = array_[idx];
delete[]array_;
array_ = tmp;
array_[count_] = strdup(text);
count_ += 1;
}
}
int hname_t::peek_number() const
void hname_t::prepend(const char*text)
{
return number_;
char**tmp;
switch (count_) {
case 0:
count_ = 1;
item_ = strdup(text);
break;
case 1:
count_ = 2;
tmp = new char*[2];
tmp[0] = strdup(text);
tmp[1] = item_;
array_ = tmp;
break;
default:
tmp = new char*[count_+1];
tmp[0] = strdup(text);
for (unsigned idx = 0 ; idx < count_ ; idx += 1)
tmp[idx+1] = array_[idx];
delete[]array_;
array_ = tmp;
count_ += 1;
}
}
char* hname_t::remove_tail_name()
{
if (count_ == 0)
return 0;
if (count_ == 1) {
char*tmp = item_;
count_ = 0;
item_ = 0;
return tmp;
}
if (count_ == 2) {
char*tmp1 = array_[0];
char*tmp2 = array_[1];
delete[]array_;
count_ = 1;
item_ = tmp1;
return tmp2;
}
char*tmpo = array_[count_-1];
char**tmpa = new char*[count_-1];
for (unsigned idx = 0 ; idx < count_-1 ; idx += 1)
tmpa[idx] = array_[idx];
delete[]array_;
array_ = tmpa;
count_ -= 1;
return tmpo;
}
const char* hname_t::peek_name(unsigned idx) const
{
if (idx >= count_)
return 0;
if (count_ == 1)
return item_;
return array_[idx];
}
const char* hname_t::peek_tail_name() const
{
switch (count_) {
case 0:
return 0;
case 1:
return item_;
default:
return array_[count_-1];
}
}
bool operator < (const hname_t&l, const hname_t&r)
{
int cmp = strcmp(l.peek_name(), r.peek_name());
if (cmp < 0) return true;
if (cmp > 0) return false;
if (l.has_number() && r.has_number())
return l.peek_number() < r.peek_number();
else
unsigned idx = 0;
const char*lc = l.peek_name(idx);
const char*rc = r.peek_name(idx);
while (lc && rc) {
int cmp = strcmp(lc, rc);
if (cmp < 0)
return true;
if (cmp > 0)
return false;
idx += 1;
lc = l.peek_name(idx);
rc = r.peek_name(idx);
}
if (lc && !rc)
return false;
if (rc && !lc)
return true;
// Must be ==
return false;
}
bool operator == (const hname_t&l, const hname_t&r)
{
if (l.peek_name() == r.peek_name()) {
if (l.has_number() && r.has_number())
return l.peek_number() == r.peek_number();
else
return true;
unsigned idx = 0;
const char*lc = l.peek_name(idx);
const char*rc = r.peek_name(idx);
while (lc && rc) {
int cmp = strcmp(lc, rc);
if (cmp != 0)
return false;
idx += 1;
lc = l.peek_name(idx);
rc = r.peek_name(idx);
}
return false;
}
if (lc || rc)
return false;
bool operator != (const hname_t&l, const hname_t&r)
{ return ! (l==r); }
// Must be ==
return true;
}
ostream& operator<< (ostream&out, const hname_t&that)
{
if (that.peek_name() == 0) {
switch (that.count_) {
case 0:
out << "";
return out;
case 1:
out << that.item_;
return out;
default:
out << that.array_[0];
for (unsigned idx = 1 ; idx < that.count_ ; idx += 1)
out << "." << that.array_[idx];
return out;
}
out << that.peek_name();
if (that.has_number())
out << "[" << that.peek_number() << "]";
return out;
}
/*
* $Log: HName.cc,v $
* Revision 1.8 2007/06/02 03:42:12 steve
* Properly evaluate scope path expressions.
*
* Revision 1.7 2007/05/16 19:12:33 steve
* Fix hname_t use of space for 1 perm_string.
*
* Revision 1.6 2007/04/26 03:06:21 steve
* Rework hname_t to use perm_strings.
*
* Revision 1.5 2002/11/02 03:27:52 steve
* Allow named events to be referenced by
* hierarchical names.
+33 -31
View File
@@ -1,7 +1,7 @@
#ifndef __HName_H
#define __HName_H
/*
* Copyright (c) 2001-2007 Stephen Williams ([email protected])
* Copyright (c) 2001 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -19,11 +19,10 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: HName.h,v 1.7 2007/06/02 03:42:12 steve Exp $"
#ident "$Id: HName.h,v 1.4 2002/11/02 03:27:51 steve Exp $"
#endif
# include <iostream>
# include "StringHeap.h"
#ifdef __GNUC__
#if __GNUC__ > 2
using namespace std;
@@ -31,56 +30,59 @@ using namespace std;
#endif
/*
* This class represents a component of a Verilog hierarchical name. A
* hierarchical component contains a name string (prepresented here
* with a perm_string) and an optional signed number. This signed
* number is used if the scope is part of an array, for example an
* array of module instances or a loop generated scope.
* This class represents a Verilog hierarchical name. A hierarchical
* name is an ordered list of simple names.
*/
class hname_t {
public:
hname_t ();
explicit hname_t (perm_string text);
explicit hname_t (perm_string text, int num);
explicit hname_t (const char*text);
hname_t (const hname_t&that);
~hname_t();
hname_t& operator= (const hname_t&);
// This method adds a name to the end of the hierarchical
// path. This becomes a new base name.
void append(const char*text);
// Return the string part of the hname_t.
perm_string peek_name(void) const;
// This method adds a name to the *front* of the hierarchical
// path. The base name remains the same, unless this is the
// only component.
void prepend(const char*text);
bool has_number() const;
int peek_number() const;
// This method removes the tail name from the hierarchy, and
// returns a pointer to that tail name. That tail name now
// must be removed by the caller.
char* remove_tail_name();
// Return the given component in the hierarchical name. If the
// idx is too large, return 0.
const char*peek_name(unsigned idx) const;
const char*peek_tail_name() const;
// Return the number of components in the hierarchical
// name. If this is a simple name, this will return 1.
unsigned component_count() const;
friend ostream& operator<< (ostream&, const hname_t&);
private:
perm_string name_;
// If the number is anything other then INT_MIN, then this is
// the numeric part of the name. Otherwise, it is not part of
// the name at all.
int number_;
union {
char**array_;
char* item_;
};
unsigned count_;
private: // not implemented
hname_t& operator= (const hname_t&);
};
extern bool operator < (const hname_t&, const hname_t&);
extern bool operator == (const hname_t&, const hname_t&);
extern bool operator != (const hname_t&, const hname_t&);
extern ostream& operator<< (ostream&, const hname_t&);
/*
* $Log: HName.h,v $
* Revision 1.7 2007/06/02 03:42:12 steve
* Properly evaluate scope path expressions.
*
* Revision 1.6 2007/05/16 19:12:33 steve
* Fix hname_t use of space for 1 perm_string.
*
* Revision 1.5 2007/04/26 03:06:21 steve
* Rework hname_t to use perm_strings.
*
* Revision 1.4 2002/11/02 03:27:51 steve
* Allow named events to be referenced by
* hierarchical names.
+7 -4
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: LineInfo.cc,v 1.4 2003/01/17 05:49:03 steve Exp $"
#ident "$Id: LineInfo.cc,v 1.4.2.1 2005/08/13 00:45:53 steve Exp $"
#endif
# include "config.h"
@@ -34,12 +34,12 @@ LineInfo::~LineInfo()
{
}
string LineInfo::get_line() const
std::string LineInfo::get_line() const
{
ostringstream buf;
std::ostringstream buf;
buf << (file_? file_ : "") << ":" << lineno_;
string res = buf.str();
std::string res = buf.str();
return res;
}
@@ -61,6 +61,9 @@ void LineInfo::set_lineno(unsigned n)
/*
* $Log: LineInfo.cc,v $
* Revision 1.4.2.1 2005/08/13 00:45:53 steve
* Fix compilation warnings/errors with newer compilers.
*
* Revision 1.4 2003/01/17 05:49:03 steve
* Use stringstream in place of sprintf.
*
+7 -4
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: LineInfo.h,v 1.8 2005/06/14 19:13:43 steve Exp $"
#ident "$Id: LineInfo.h,v 1.7.2.2 2005/08/13 00:45:53 steve Exp $"
#endif
# include <string>
@@ -40,7 +40,7 @@ class LineInfo {
LineInfo();
~LineInfo();
string get_line() const;
std::string get_line() const;
void set_line(const LineInfo&that);
@@ -54,8 +54,11 @@ class LineInfo {
/*
* $Log: LineInfo.h,v $
* Revision 1.8 2005/06/14 19:13:43 steve
* gcc3/4 compile errors.
* Revision 1.7.2.2 2005/08/13 00:45:53 steve
* Fix compilation warnings/errors with newer compilers.
*
* Revision 1.7.2.1 2005/06/14 15:33:54 steve
* Fix gcc4 build issues.
*
* Revision 1.7 2003/01/17 05:49:03 steve
* Use stringstream in place of sprintf.
+50 -30
View File
@@ -16,7 +16,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.181 2007/05/24 04:07:11 steve Exp $"
#ident "$Id: Makefile.in,v 1.169.2.7 2007/05/30 17:48:53 steve Exp $"
#
#
SHELL = /bin/sh
@@ -25,7 +25,7 @@ SHELL = /bin/sh
# by the compiler. It reflects the assigned version number for the
# product as a whole. Most components also print the CVS Name: token
# in order to get a more automatic version stamp as well.
VERSION = 0.9.devel
VERSION = 0.8.5
prefix = @prefix@
exec_prefix = @exec_prefix@
@@ -43,6 +43,7 @@ mandir = @mandir@
libdir64 = @libdir64@
dllib=@DLLIB@
strip_dynamic=@strip_dynamic@
CC = @CC@
CXX = @CXX@
@@ -50,23 +51,32 @@ INSTALL = @INSTALL@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
STRIP = @STRIP@
LEX = @LEX@
YACC = @YACC@
MAN = @MAN@
PS2PDF = @PS2PDF@
CPPFLAGS = @ident_support@ @DEFS@ -I. -I$(srcdir) @CPPFLAGS@
CXXFLAGS = -Wall @CXXFLAGS@
PICFLAGS = @PICFLAG@
LDFLAGS = @rdynamic@ @LDFLAGS@
# The TARGETS variable lists the target modules that can be build and
# installed. Some of them depend on external things, so are only
# compiled if the prerequisites are installed.
TARGETS = tgt-null
all: dep ivl@EXEEXT@
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) $@); done
for dir in ivlpp ; \
for tgt in $(TARGETS); do (cd $$tgt ; $(MAKE) $@); done
for dir in ivlpp tgt-verilog tgt-stub; \
do (cd $$dir ; $(MAKE) $@); done
cd driver ; $(MAKE) VERSION=$(VERSION) $@
# In the windows world, the installer will need a dosify program to
# dosify text files.
ifeq (@MING32@,yes)
ifeq (@WIN32@,yes)
all: dep dosify.exe
dosify.exe: dosify.c
$(CC) -o dosify.exe dosify.c
@@ -82,37 +92,37 @@ check: all
clean:
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) $@); done
for dir in vpi ivlpp tgt-verilog tgt-pal driver driver-vpi; \
for tgt in $(TARGETS); do (cd $$tgt ; $(MAKE) $@); done
for dir in vpi ivlpp tgt-verilog tgt-stub driver; \
do (cd $$dir ; $(MAKE) $@); done
rm -f *.o parse.cc parse.cc.output parse.h lexor.cc
rm -f ivl.exp iverilog-vpi.pdf iverilog-vpi.ps parse.output
rm -f syn-rules.output dosify.exe ivl@EXEEXT@ check.vvp
rm -f lexor_keyword.cc libivl.a libvpi.a iverilog-vpi syn-rules.cc*
rm -rf dep
rm -rf dep ivl@EXEEXT@
distclean: clean
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) $@); done
for dir in vpi ivlpp tgt-verilog tgt-pal driver driver-vpi; \
for tgt in $(TARGETS); do (cd $$tgt ; $(MAKE) $@); done
for dir in vpi ivlpp tgt-verilog tgt-stub driver; \
do (cd $$dir ; $(MAKE) $@); done
rm -f Makefile config.status config.log config.cache config.h
rm -f _pli_types.h
rm -rf autom4te.cache
TT = t-dll.o t-dll-api.o t-dll-expr.o t-dll-proc.o
FF = cprop.o nodangle.o synth.o synth2.o syn-rules.o
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 async.o design_dump.o dup_expr.o elaborate.o elab_expr.o \
elab_lval.o elab_net.o elab_pexpr.o elab_scope.o \
elab_lval.o elab_net.o elab_anet.o elab_pexpr.o elab_scope.o \
elab_sig.o emit.o eval.o eval_attrib.o \
eval_tree.o expr_synth.o functor.o lexor.o lexor_keyword.o link_const.o \
load_module.o netlist.o netmisc.o net_assign.o \
load_module.o netlist.o NetLatch.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 pform_types.o \
net_proc.o net_scope.o net_udp.o net_variable.o pad_to_width.o \
parse.o parse_misc.o pform.o pform_dump.o \
set_width.o symbol_search.o sync.o sys_funcs.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 PGenerate.o PSpec.o \
Attrib.o HName.o LineInfo.o Module.o PData.o PDelays.o PEvent.o \
PExpr.o PGate.o \
PTask.o PUdp.o PFunction.o PWire.o Statement.o StringHeap.o \
$(FF) $(TT)
@@ -129,10 +139,11 @@ ivl@EXEEXT@: $O ivl.def
$(CXX) -o ivl@EXEEXT@ $O $(dllib) @EXTRALIBS@
dlltool --dllname ivl@EXEEXT@ --def ivl.def \
--output-lib libivl.a --output-exp ivl.exp
$(CXX) $(LDFLAGS) -o ivl@EXEEXT@ ivl.exp $O $(dllib) @EXTRALIBS@
$(CXX) -o ivl@EXEEXT@ ivl.exp $O $(dllib) @EXTRALIBS@
else
ivl@EXEEXT@: $O
$(CXX) $(LDFLAGS) -o ivl@EXEEXT@ $O $(dllib)
endif
ifeq (@MINGW32@,yes)
@@ -142,9 +153,6 @@ all: dep iverilog-vpi
iverilog-vpi: iverilog-vpi.sh
sed -e 's;@SHARED@;@shared@;' -e 's;@PIC@;@PICFLAG@;' \
-e 's;@IVCC@;$(CC);' \
-e 's;@IVCXX@;$(CXX);' \
-e 's;@IVCFLAGS@;$(CXXFLAGS);' \
-e 's;@INCLUDEDIR@;@includedir@;' \
-e 's;@LIBDIR64@;@libdir64@;' \
-e 's;@VPIDIR1@;@vpidir1@;' -e 's;@VPIDIR2@;@vpidir2@;' \
@@ -156,7 +164,7 @@ dep:
mkdir dep
%.o: %.cc
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -MD -c $< -o $*.o
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -MD -c $< -o $*.o $(DEBUGFLAGS)
mv $*.d dep/$*.d
@@ -180,15 +188,25 @@ 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
$(MAN) -t $(srcdir)/iverilog-vpi.man > iverilog-vpi.ps
iverilog-vpi.pdf: iverilog-vpi.ps
ps2pdf iverilog-vpi.ps iverilog-vpi.pdf
$(PS2PDF) iverilog-vpi.ps iverilog-vpi.pdf
ifeq (@MING32@,yes)
# Build and install the iverilog-vpi.pdf only if there is a man
# program *and* a ps2pdf program.
ifeq (@WIN32@,yes)
ifeq ($(MAN),none)
INSTALL_DOC = $(mandir)/man1/iverilog-vpi.1
else
ifeq ($(PS2PDF),none)
INSTALL_DOC = $(mandir)/man1/iverilog-vpi.1
else
INSTALL_DOC = $(prefix)/iverilog-vpi.pdf $(mandir)/man1/iverilog-vpi.1
INSTALL_DOCDIR = $(mandir)/man1
all: dep iverilog-vpi.pdf
endif
endif
INSTALL_DOCDIR = $(mandir)/man1
else
INSTALL_DOC = $(mandir)/man1/iverilog-vpi.1
INSTALL_DOCDIR = $(mandir)/man1
@@ -202,8 +220,9 @@ endif
XNF_INSTALL = $(libdir)/ivl/xnf.conf $(libdir)/ivl/xnf-s.conf
install: all installdirs $(libdir)/ivl/ivl@EXEEXT@ $(includedir)/ivl_target.h $(includedir)/_pli_types.h $(includedir)/vpi_user.h $(includedir)/acc_user.h $(includedir)/veriuser.h $(WIN32_INSTALL) $(INSTALL_DOC)
install: all installdirs $(libdir)/ivl/ivl@EXEEXT@ $(includedir)/ivl_target.h $(includedir)/_pli_types.h $(includedir)/vpi_user.h $(includedir)/acc_user.h $(includedir)/veriuser.h $(WIN32_INSTALL) $(INSTALL_DOC) $(XNF_INSTALL)
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) $@); done
for tgt in $(TARGETS); do (cd $$tgt ; $(MAKE) $@); done
for dir in vpi ivlpp driver; \
do (cd $$dir ; $(MAKE) $@); done
@@ -266,16 +285,17 @@ installdirs: mkinstalldirs
uninstall:
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) $@); done
for tgt in $(TARGETS); do (cd $$tgt ; $(MAKE) $@); done
for dir in vpi ivlpp driver; \
do (cd $$dir ; $(MAKE) $@); done
for f in xnf.conf xnf-s.conf ivl@EXEEXT@; \
for f in xnf.conf xnf-s.conf ivl; \
do rm -f $(libdir)/ivl/$$f; done
-rmdir $(libdir)/ivl
for f in verilog iverilog-vpi gverilog@EXEEXT@; \
do rm -f $(bindir)/$$f; done
for f in ivl_target.h vpi_user.h _pli_types.h acc_user.h veriuser.h; \
do rm -f $(includedir)/$$f; done
rm -f $(mandir)/man1/iverilog-vpi.1 $(prefix)/iverilog-vpi.pdf
rm -f $(mandir)/man1/iverilog-vpi.1
-include $(patsubst %.o, dep/%.d, $O)
+8 -11
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: Module.cc,v 1.27 2007/05/24 04:07:11 steve Exp $"
#ident "$Id: Module.cc,v 1.25 2004/10/04 01:10:51 steve Exp $"
#endif
# include "config.h"
@@ -31,7 +31,6 @@
Module::Module(perm_string n)
: name_(n)
{
library_flag = false;
default_nettype = NetNet::NONE;
}
@@ -111,9 +110,9 @@ unsigned Module::find_port(const char*name) const
}
PWire* Module::get_wire(const pform_name_t&name) const
PWire* Module::get_wire(const hname_t&name) const
{
map<pform_name_t,PWire*>::const_iterator obj = wires_.find(name);
map<hname_t,PWire*>::const_iterator obj = wires_.find(name);
if (obj == wires_.end())
return 0;
else
@@ -133,6 +132,11 @@ PGate* Module::get_gate(perm_string name)
return 0;
}
const map<hname_t,PWire*>& Module::get_wires() const
{
return wires_;
}
const list<PGate*>& Module::get_gates() const
{
return gates_;
@@ -146,13 +150,6 @@ const list<PProcess*>& Module::get_behaviors() const
/*
* $Log: Module.cc,v $
* Revision 1.27 2007/05/24 04:07:11 steve
* Rework the heirarchical identifier parse syntax and pform
* to handle more general combinations of heirarch and bit selects.
*
* Revision 1.26 2007/04/19 02:52:53 steve
* Add support for -v flag in command file.
*
* Revision 1.25 2004/10/04 01:10:51 steve
* Clean up spurious trailing white space.
*
+45 -38
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: Module.h,v 1.43 2007/05/24 04:07:11 steve Exp $"
#ident "$Id: Module.h,v 1.37 2004/06/13 04:56:53 steve Exp $"
#endif
# include <list>
@@ -30,13 +30,11 @@
# include "named.h"
# include "LineInfo.h"
# include "netlist.h"
# include "pform_types.h"
class PData;
class PEvent;
class PExpr;
class PEIdent;
class PGate;
class PGenerate;
class PSpecPath;
class PTask;
class PFunction;
class PWire;
@@ -69,12 +67,6 @@ class Module : public LineInfo {
explicit Module(perm_string name);
~Module();
/* Initially false. This is set to true if the module has been
declared as a library module. This makes the module
ineligible for being chosen as an implicit root. It has no
other effect. */
bool library_flag;
NetNet::Type default_nettype;
/* The module has parameters that are evaluated when the
@@ -99,7 +91,7 @@ class Module : public LineInfo {
new parameters within the module, but may be used to set
values within this module (when instantiated) or in other
instantiated modules. */
map<pform_name_t,PExpr*>defparms;
map<hname_t,PExpr*>defparms;
/* Parameters may be overridden at instantiation time;
the overrides do not contain explicit parameter names,
@@ -116,22 +108,15 @@ class Module : public LineInfo {
/* Keep a table of named events declared in the module. */
map<perm_string,PEvent*>events;
/* Keep a table of datum variables declared in the module. */
map<hname_t,PData*>datum;
map<perm_string,PExpr*> attributes;
/* These are the timescale for this module. The default is
set by the `timescale directive. */
int time_unit, time_precision;
/* The module has a list of genvars that may be used in
various generate schemes. */
list<perm_string> genvars;
/* the module has a list of generate schemes that appear in
the module definition. These are used at elaboration time. */
list<PGenerate*> generate_schemes;
list<PSpecPath*> specify_paths;
perm_string mod_name() const { return name_; }
void add_gate(PGate*gate);
@@ -151,24 +136,24 @@ class Module : public LineInfo {
// Find a wire by name. This is used for connecting gates to
// existing wires, etc.
PWire* get_wire(const pform_name_t&name) const;
PWire* get_wire(const hname_t&name) const;
PGate* get_gate(perm_string name);
const map<hname_t,PWire*>& get_wires() const;
const list<PGate*>& get_gates() const;
const list<PProcess*>& get_behaviors() const;
void dump(ostream&out) const;
bool elaborate(Design*, NetScope*scope) const;
typedef map<perm_string,NetExpr*> replace_t;
bool elaborate_scope(Design*, NetScope*scope, const replace_t&rep) const;
bool elaborate_scope(Design*, NetScope*scope) const;
bool elaborate_sig(Design*, NetScope*scope) const;
private:
perm_string name_;
map<pform_name_t,PWire*> wires_;
map<hname_t,PWire*> wires_;
list<PGate*> gates_;
list<PProcess*> behaviors_;
map<perm_string,PTask*> tasks_;
@@ -182,23 +167,45 @@ class Module : public LineInfo {
/*
* $Log: Module.h,v $
* Revision 1.43 2007/05/24 04:07:11 steve
* Rework the heirarchical identifier parse syntax and pform
* to handle more general combinations of heirarch and bit selects.
* Revision 1.37 2004/06/13 04:56:53 steve
* Add support for the default_nettype directive.
*
* Revision 1.42 2007/04/19 02:52:53 steve
* Add support for -v flag in command file.
* Revision 1.36 2004/05/25 19:21:06 steve
* More identifier lists use perm_strings.
*
* Revision 1.41 2006/09/23 04:57:19 steve
* Basic support for specify timing.
* Revision 1.35 2004/02/20 18:53:33 steve
* Addtrbute keys are perm_strings.
*
* Revision 1.40 2006/04/10 00:37:42 steve
* Add support for generate loops w/ wires and gates.
* Revision 1.34 2004/02/20 06:22:56 steve
* parameter keys are per_strings.
*
* Revision 1.39 2006/03/30 01:49:07 steve
* Fix instance arrays indexed by overridden parameters.
* Revision 1.33 2004/02/18 17:11:54 steve
* Use perm_strings for named langiage items.
*
* Revision 1.38 2005/07/11 16:56:50 steve
* Remove NetVariable and ivl_variable_t structures.
* Revision 1.32 2003/06/20 00:53:19 steve
* Module attributes from the parser
* through to elaborated form.
*
* Revision 1.31 2003/06/13 19:10:45 steve
* Properly manage real variables in subscopes.
*
* Revision 1.30 2003/03/06 04:37:12 steve
* lex_strings.add module names earlier.
*
* Revision 1.29 2003/02/27 06:45:11 steve
* specparams as far as pform.
*
* Revision 1.28 2003/01/26 21:15:58 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
* 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.
*/
#endif
+43
View File
@@ -0,0 +1,43 @@
// NetLatch.cc
// Author: Alan M. Feldstein
// Class NetLatch member-function definitions
#include "NetLatch.h" // NetLatch class definition
#include "target.h" // target_t structure definition
// constructor
NetLatch::NetLatch( NetScope *scope, perm_string name, unsigned width )
// explicitly call base-class constructor
: NetNode( scope, name, 2U * width + 1U )
{
} // end NetLatch constructor
unsigned NetLatch::width() const
{
return ( pin_count() - 1U ) / 2U;
} // end function width
Link &NetLatch::pin_Data( unsigned w )
{
unsigned pn = 1 + 2 * w;
assert( pn < pin_count() );
return pin( pn );
} // end function pin_Data
Link &NetLatch::pin_Q( unsigned w )
{
unsigned pn = 2 + 2 * w;
assert( pn < pin_count() );
return pin( pn );
} // end function pin_Q
Link &NetLatch::pin_Gate()
{
return pin( 0 );
} // end function pin_Q
bool NetLatch::emit_node( target_t *driverPtr ) const
{
driverPtr->lpm_latch( this );
return true;
} // end function emit_node
+34
View File
@@ -0,0 +1,34 @@
// NetLatch.h
// Author: Alan M. Feldstein
// This class represents an LPM_LATCH device. In Verilog, storage components of this type can be inferred.
// The pinout is assigned like so:
// 0 -- Gate
//
// 1 -- Data[0]
// 2 -- Q[0]
// ...
#ifndef NETLATCH_H
#define NETLATCH_H
#include "netlist.h" // NetNode, NetScope, Link class definitions
#include "StringHeap.h" // perm_string class definition
class NetLatch : public NetNode
{
public:
NetLatch( NetScope *, perm_string, unsigned );
unsigned width() const;
Link &pin_Data( unsigned );
Link &pin_Q( unsigned );
Link &pin_Gate();
const Link &pin_Data( unsigned ) const;
const Link &pin_Q( unsigned ) const;
const Link &pin_Gate() const;
virtual bool emit_node( target_t * ) const;
}; // end class NetLatch
#endif
+24 -8
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2006 Stephen Williams <steve@icarus.com>
* Copyright (c) 2003 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -17,18 +17,34 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: PSpec.cc,v 1.2 2007/02/12 01:52:21 steve Exp $"
#ident "$Id: PData.cc,v 1.2 2003/11/10 20:11:01 steve Exp $"
#endif
# include "PSpec.h"
# include "config.h"
# include "PData.h"
PSpecPath::PSpecPath(unsigned src_cnt, unsigned dst_cnt)
: conditional(false), condition(0), edge(0),
src(src_cnt), dst(dst_cnt),
data_source_expression(0)
PData::PData(const hname_t&h)
: hname_(h)
{
}
PSpecPath::~PSpecPath()
PData::~PData()
{
}
const hname_t&PData::name() const
{
return hname_;
}
/*
* $Log: PData.cc,v $
* Revision 1.2 2003/11/10 20:11:01 steve
* missing include of config.h
*
* Revision 1.1 2003/01/26 21:15:58 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
*/
+63
View File
@@ -0,0 +1,63 @@
#ifndef __PData_H
#define __PData_H
/*
* Copyright (c) 2003 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: PData.h,v 1.1 2003/01/26 21:15:58 steve Exp $"
#endif
# include "HName.h"
# include "netlist.h"
# include "LineInfo.h"
/*
* The PData object represents declaration of atomic datum such as
* real and realtime variables. These are variables that cannot be bit
* or part selected, but can be used in expressions.
*/
class PData : public LineInfo {
public:
PData(const hname_t&hname);
~PData();
// Return a hierarchical name.
const hname_t&name() const;
void elaborate_scope(Design*des, NetScope*scope) const;
map<string,PExpr*> attributes;
private:
hname_t hname_;
private:
PData(const PData&);
PData& operator= (const PData&);
};
/*
* $Log: PData.h,v $
* Revision 1.1 2003/01/26 21:15:58 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
*/
#endif
+31 -52
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: PDelays.cc,v 1.15 2006/07/08 21:48:46 steve Exp $"
#ident "$Id: PDelays.cc,v 1.11.2.1 2006/10/04 00:37:03 steve Exp $"
#endif
# include "config.h"
@@ -62,15 +62,30 @@ void PDelays::set_delays(const svector<PExpr*>*del, bool df)
delete_flag_ = df;
}
static NetExpr*calculate_val(Design*des, NetScope*scope, const PExpr*expr)
static unsigned long calculate_val(Design*des, NetScope*scope,
const PExpr*expr)
{
NetExpr*dex = expr->elaborate_expr(des, scope, -1, false);
NetExpr*dex = expr->elaborate_expr(des, scope);
if (NetExpr*tmp = dex->eval_tree()) {
delete dex;
dex = tmp;
}
int shift = scope->time_unit() - des->get_precision();
if (sizeof(unsigned) <= 4 && shift > 9) {
cerr << expr->get_line() << ": error: Precision overflow"
<< " in scope " << scope->name() << "." << endl;
cerr << expr->get_line() << ": :"
<< " Units are 10e" << scope->time_unit()
<< " minus precision 10e" << des->get_precision()
<< " is 10e" << shift << "." << endl;
cerr << expr->get_line() << ": : Perhaps a timescale "
<< "is missing or incorrect?" << endl;
des->errors += 1;
return 0;
}
/* If the delay expression is a real constant or vector
constant, then evaluate it, scale it to the local time
units, and return an adjusted value. */
@@ -78,15 +93,12 @@ static NetExpr*calculate_val(Design*des, NetScope*scope, const PExpr*expr)
if (NetECReal*tmp = dynamic_cast<NetECReal*>(dex)) {
verireal fn = tmp->value();
int shift = scope->time_unit() - des->get_precision();
long delay = fn.as_long(shift);
if (delay < 0)
delay = 0;
delete tmp;
NetEConst*tmp2 = new NetEConst(verinum(delay));
tmp2->set_line(*expr);
return tmp2;
return delay;
}
@@ -97,57 +109,35 @@ static NetExpr*calculate_val(Design*des, NetScope*scope, const PExpr*expr)
des->scale_to_precision(fn.as_ulong(), scope);
delete tmp;
NetEConst*tmp2 = new NetEConst(verinum(delay));
tmp2->set_line(*expr);
return tmp2;
return delay;
}
/* Oops, cannot evaluate down to a constant. */
return dex;
}
/* Oops, cannot evaluate down to a constant. Error message. */
delete dex;
static NetExpr* make_delay_nets(Design*des, NetExpr*expr)
{
if (dynamic_cast<NetESignal*> (expr))
return expr;
cerr << expr->get_line() << ": sorry: non-constant "
<< "delays not supported here: " << *expr << endl;
des->errors += 1;
return 0;
if (dynamic_cast<NetEConst*> (expr))
return expr;
NetNet*sig = expr->synthesize(des);
if (sig == 0) {
cerr << expr->get_line() << ": error: Expression " << *expr
<< " is not suitable for delay expression." << endl;
return 0;
}
expr = new NetESignal(sig);
return expr;
}
void PDelays::eval_delays(Design*des, NetScope*scope,
NetExpr*&rise_time,
NetExpr*&fall_time,
NetExpr*&decay_time,
bool as_nets_flag) const
unsigned long&rise_time,
unsigned long&fall_time,
unsigned long&decay_time) const
{
assert(scope);
if (delay_[0]) {
rise_time = calculate_val(des, scope, delay_[0]);
if (as_nets_flag)
rise_time = make_delay_nets(des, rise_time);
if (delay_[1]) {
fall_time = calculate_val(des, scope, delay_[1]);
if (as_nets_flag)
fall_time = make_delay_nets(des, fall_time);
if (delay_[2]) {
decay_time = calculate_val(des, scope, delay_[2]);
if (as_nets_flag)
decay_time = make_delay_nets(des, decay_time);
} else {
if (rise_time < fall_time)
@@ -169,19 +159,8 @@ void PDelays::eval_delays(Design*des, NetScope*scope,
/*
* $Log: PDelays.cc,v $
* Revision 1.15 2006/07/08 21:48:46 steve
* Handle real valued literals in net contexts.
*
* Revision 1.14 2006/06/02 04:48:49 steve
* Make elaborate_expr methods aware of the width that the context
* requires of it. In the process, fix sizing of the width of unary
* minus is context determined sizes.
*
* Revision 1.13 2006/01/03 05:22:14 steve
* Handle complex net node delays.
*
* Revision 1.12 2006/01/02 05:33:19 steve
* Node delays can be more general expressions in structural contexts.
* Revision 1.11.2.1 2006/10/04 00:37:03 steve
* Detect delay precision overflow.
*
* Revision 1.11 2003/06/21 01:21:42 steve
* Harmless fixup of warnings.
+4 -12
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: PDelays.h,v 1.9 2006/01/03 05:22:14 steve Exp $"
#ident "$Id: PDelays.h,v 1.7 2002/08/12 01:34:58 steve Exp $"
#endif
# include "svector.h"
@@ -34,7 +34,6 @@ using namespace std;
class Design;
class NetScope;
class NetExpr;
class PExpr;
/*
@@ -54,10 +53,9 @@ class PDelays {
void set_delays(const svector<PExpr*>*del, bool delete_flag=true);
void eval_delays(Design*des, NetScope*scope,
NetExpr*&rise_time,
NetExpr*&fall_time,
NetExpr*&decay_time,
bool as_nets_flag =false) const;
unsigned long&rise_time,
unsigned long&fall_time,
unsigned long&decay_time) const;
void dump_delays(ostream&out) const;
@@ -74,12 +72,6 @@ ostream& operator << (ostream&o, const PDelays&);
/*
* $Log: PDelays.h,v $
* Revision 1.9 2006/01/03 05:22:14 steve
* Handle complex net node delays.
*
* Revision 1.8 2006/01/02 05:33:19 steve
* Node delays can be more general expressions in structural contexts.
*
* Revision 1.7 2002/08/12 01:34:58 steve
* conditional ident string using autoconfig.
*
+20 -66
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: PExpr.cc,v 1.39 2007/05/24 04:07:11 steve Exp $"
#ident "$Id: PExpr.cc,v 1.35.2.1 2006/02/07 22:46:23 steve Exp $"
#endif
# include "config.h"
@@ -53,14 +53,6 @@ NetNet* PExpr::elaborate_lnet(Design*des, NetScope*, bool) const
return 0;
}
NetNet* PExpr::elaborate_bi_net(Design*des, NetScope*) const
{
cerr << get_line() << ": error: "
<< "expression not valid as argument to inout port: "
<< *this << endl;
return 0;
}
PEBinary::PEBinary(char op, PExpr*l, PExpr*r)
: op_(op), left_(l), right_(r)
{
@@ -75,44 +67,13 @@ bool PEBinary::is_constant(Module*mod) const
return left_->is_constant(mod) && right_->is_constant(mod);
}
PEBComp::PEBComp(char op, PExpr*l, PExpr*r)
: PEBinary(op, l, r)
{
}
PEBComp::~PEBComp()
{
}
PEBShift::PEBShift(char op, PExpr*l, PExpr*r)
: PEBinary(op, l, r)
{
}
PEBShift::~PEBShift()
{
}
PECallFunction::PECallFunction(const pform_name_t&n, const svector<PExpr *> &parms)
PECallFunction::PECallFunction(const hname_t&n, const svector<PExpr *> &parms)
: path_(n), parms_(parms)
{
}
static pform_name_t pn_from_ps(perm_string n)
{
name_component_t tmp_name (n);
pform_name_t tmp;
tmp.push_back(tmp_name);
return tmp;
}
PECallFunction::PECallFunction(perm_string n, const svector<PExpr*>&parms)
: path_(pn_from_ps(n)), parms_(parms)
{
}
PECallFunction::PECallFunction(perm_string n)
: path_(pn_from_ps(n))
PECallFunction::PECallFunction(const hname_t&n)
: path_(n)
{
}
@@ -129,6 +90,8 @@ bool PEConcat::is_constant(Module *mod) const
{
bool constant = repeat_? repeat_->is_constant(mod) : true;
for (unsigned i = 0; constant && i < parms_.count(); ++i) {
if (parms_[i] == 0)
continue;
constant = constant && parms_[i]->is_constant(mod);
}
return constant;
@@ -178,32 +141,33 @@ bool PEFNumber::is_constant(Module*) const
return true;
}
PEIdent::PEIdent(const pform_name_t&that)
: path_(that)
PEIdent::PEIdent(const hname_t&s)
: path_(s), msb_(0), lsb_(0), idx_(0)
{
}
PEIdent::PEIdent(perm_string s)
{
path_.push_back(name_component_t(s));
}
PEIdent::~PEIdent()
{
}
const hname_t& PEIdent::path() const
{
return path_;
}
/*
* An identifier can be in a constant expression if (and only if) it is
* a parameter.
*
* NOTE: This test does not work if the name is hierarchical!
*/
bool PEIdent::is_constant(Module*mod) const
{
if (mod == 0) return false;
/* */
perm_string tmp = path_.back().name;
/* This is a work-around for map not matching < even when
there is a perm_string operator that can do the comprare.
The real fix is to make the path_ carry perm_strings. */
perm_string tmp = perm_string::literal(path_.peek_name(0));
{ map<perm_string,Module::param_expr_t>::const_iterator cur;
cur = mod->parameters.find(tmp);
@@ -300,18 +264,8 @@ bool PEUnary::is_constant(Module*m) const
/*
* $Log: PExpr.cc,v $
* Revision 1.39 2007/05/24 04:07:11 steve
* Rework the heirarchical identifier parse syntax and pform
* to handle more general combinations of heirarch and bit selects.
*
* Revision 1.38 2006/10/30 05:44:49 steve
* Expression widths with unsized literals are pseudo-infinite width.
*
* Revision 1.37 2005/10/04 04:09:25 steve
* Add support for indexed select attached to parameters.
*
* Revision 1.36 2005/08/06 17:58:16 steve
* Implement bi-directional part selects.
* Revision 1.35.2.1 2006/02/07 22:46:23 steve
* More robust test for concat constant-ness.
*
* Revision 1.35 2004/10/04 01:10:51 steve
* Clean up spurious trailing white space.
+120 -366
View File
@@ -19,15 +19,13 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: PExpr.h,v 1.90 2007/06/04 19:14:06 steve Exp $"
#ident "$Id: PExpr.h,v 1.66.2.2 2006/07/28 16:26:17 steve Exp $"
#endif
# include <string>
# include <vector>
# include "netlist.h"
# include "verinum.h"
# include "LineInfo.h"
# include "pform_types.h"
class Design;
class Module;
@@ -52,38 +50,11 @@ class PExpr : public LineInfo {
virtual void dump(ostream&) const;
// This method tests the width that the expression wants to
// be. It is used by elaboration of assignments to figure out
// the width of the expression.
//
// The "min" is the width of the local context, so it the
// minimum width that this function should return. Initially
// this is the same as the lval width.
//
// The "lval" is the width of the destination where this
// result is going to go. This can be used to constrain the
// amount that an expression can reasonably expand. For
// example, there is no point expanding an addition to beyond
// the lval. This extra bit of information allows the
// expression to optimize itself a bit. If the lval==0, then
// the subexpression should not make l-value related
// optimizations.
//
// The unsigned_flag is set to true if the expression is
// unsized and therefore expandable. This happens if a
// sub-expression is an unsized literal. Some expressions make
// special use of that.
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
bool&unsized_flag) const;
// Procedural elaboration of the expression. The expr_width is
// the width of the context of the expression (i.e. the
// l-value width of an assignment) or -1 if the expression is
// self-determinted. The sys_task_arg flag is true if
// expressions are allowed to be incomplete.
// Procedural elaboration of the expression. Set the
// bare_memory_ok flag if the result is allowed to be a
// NetEMemory without an index.
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
int expr_width, bool sys_task_arg) const;
bool sys_task_arg =false) const;
// Elaborate expressions that are the r-value of parameter
// assignments. This elaboration follows the restrictions of
@@ -95,37 +66,30 @@ class PExpr : public LineInfo {
// continuous assign or other wholly structural context.
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
unsigned long rise,
unsigned long fall,
unsigned long decay,
Link::strength_t drive0 =Link::STRONG,
Link::strength_t drive1 =Link::STRONG)
const;
// This method elaborates the expression as NetNet objects. It
// only allows regs suitable for procedural continuous assignments.
virtual NetNet* elaborate_anet(Design*des, NetScope*scope) const;
// This method elaborates the expression as gates, but
// restricted for use as l-values of continuous assignments.
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope,
bool implicit_net_ok =false) const;
// This is similar to elaborate_lnet, except that the
// expression is evaluated to be bi-directional. This is
// useful for arguments to inout ports of module instances and
// ports of tran primitives.
virtual NetNet* elaborate_bi_net(Design*des, NetScope*scope) const;
// Expressions that can be in the l-value of procedural
// assignments can be elaborated with this method. If the
// is_force flag is true, then the set of valid l-value types
// is slightly modified to accomodate the Verilog force
// statement
virtual NetAssign_* elaborate_lval(Design*des,
NetScope*scope,
bool is_force) const;
// assignments can be elaborated with this method.
virtual NetAssign_* elaborate_lval(Design*des, NetScope*scope) const;
// This attempts to evaluate a constant expression, and return
// a verinum as a result. If the expression cannot be
// evaluated, return 0.
virtual verinum* eval_const(Design*des, NetScope*sc) const;
virtual verinum* eval_const(const Design*des, const NetScope*sc) const;
// This method returns true if that expression is the same as
// this expression. This method is used for comparing
@@ -151,31 +115,29 @@ class PEConcat : public PExpr {
PEConcat(const svector<PExpr*>&p, PExpr*r =0);
~PEConcat();
virtual verinum* eval_const(Design*des, NetScope*sc) const;
virtual verinum* eval_const(const Design*des, const NetScope*sc) const;
virtual void dump(ostream&) const;
// Concatenated Regs can be on the left of procedural
// continuous assignments.
virtual NetNet* elaborate_anet(Design*des, NetScope*scope) const;
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope,
bool implicit_net_ok =false) const;
virtual NetNet* elaborate_bi_net(Design*des, NetScope*scope) const;
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned width,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
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*,
int expr_width, bool sys_task_arg) const;
bool sys_task_arg =false) const;
virtual NetEConcat*elaborate_pexpr(Design*des, NetScope*) const;
virtual NetAssign_* elaborate_lval(Design*des,
NetScope*scope,
bool is_force) const;
virtual NetAssign_* elaborate_lval(Design*des, NetScope*scope) const;
virtual bool is_constant(Module*) const;
private:
NetNet* elaborate_lnet_common_(Design*des, NetScope*scope,
bool implicit_net_ok,
bool bidirectional_flag) const;
private:
svector<PExpr*>parms_;
PExpr*repeat_;
@@ -222,23 +184,15 @@ class PEFNumber : public PExpr {
/* The eval_const method as applied to a floating point number
gets the *integer* value of the number. This accounts for
any rounding that is needed to get the value. */
virtual verinum* eval_const(Design*des, NetScope*sc) const;
virtual verinum* eval_const(const Design*des, const NetScope*sc) const;
/* A PEFNumber is a constant, so this returns true. */
virtual bool is_constant(Module*) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
int expr_width, bool sys_task_arg) const;
bool sys_task_arg =false) const;
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
virtual void dump(ostream&) const;
private:
@@ -248,41 +202,32 @@ class PEFNumber : public PExpr {
class PEIdent : public PExpr {
public:
explicit PEIdent(perm_string);
explicit PEIdent(const pform_name_t&);
explicit PEIdent(const hname_t&s);
~PEIdent();
// Add another name to the string of heirarchy that is the
// current identifier.
void append_name(perm_string);
virtual void dump(ostream&) const;
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
bool&unsized_flag) const;
// Regs can be on the left of procedural continuous assignments
virtual NetNet* elaborate_anet(Design*des, NetScope*scope) const;
// Identifiers are allowed (with restrictions) is assign l-values.
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope,
bool implicit_net_ok =false) const;
virtual NetNet* elaborate_bi_net(Design*des, NetScope*scope) const;
// Identifiers are also allowed as procedural assignment l-values.
virtual NetAssign_* elaborate_lval(Design*des,
NetScope*scope,
bool is_force) const;
virtual NetAssign_* elaborate_lval(Design*des, NetScope*scope) const;
// Structural r-values are OK.
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
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*,
int expr_width, bool sys_task_arg) const;
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
@@ -290,86 +235,39 @@ class PEIdent : public PExpr {
NetNet* elaborate_port(Design*des, NetScope*sc) const;
virtual bool is_constant(Module*) const;
verinum* eval_const(Design*des, NetScope*sc) const;
verinum* eval_const(const Design*des, const NetScope*sc) const;
const pform_name_t& path() const { return path_; }
const hname_t& path() const;
private:
pform_name_t path_;
private:
// Common functions to calculate parts of part/bit selects.
bool calculate_parts_(Design*, NetScope*, long&msb, long&lsb) const;
bool calculate_up_do_width_(Design*, NetScope*, unsigned long&wid) const;
private:
NetAssign_*elaborate_lval_net_word_(Design*, NetScope*, NetNet*) const;
bool elaborate_lval_net_part_(Design*, NetScope*, NetAssign_*) const;
bool elaborate_lval_net_idx_up_(Design*, NetScope*, NetAssign_*) const;
bool elaborate_lval_net_idx_do_(Design*, NetScope*, NetAssign_*) const;
private:
NetExpr*elaborate_expr_param(Design*des,
NetScope*scope,
const NetExpr*par,
NetScope*found,
const NetExpr*par_msb,
const NetExpr*par_lsb) const;
NetExpr*elaborate_expr_net(Design*des,
NetScope*scope,
NetNet*net,
NetScope*found,
bool sys_task_arg) const;
NetExpr*elaborate_expr_net_word_(Design*des,
NetScope*scope,
NetNet*net,
NetScope*found,
bool sys_task_arg) const;
NetExpr*elaborate_expr_net_part_(Design*des,
NetScope*scope,
NetESignal*net,
NetScope*found) const;
NetExpr*elaborate_expr_net_idx_up_(Design*des,
NetScope*scope,
NetESignal*net,
NetScope*found) const;
NetExpr*elaborate_expr_net_idx_do_(Design*des,
NetScope*scope,
NetESignal*net,
NetScope*found) const;
NetExpr*elaborate_expr_net_bit_(Design*des,
NetScope*scope,
NetESignal*net,
NetScope*found) const;
hname_t path_;
public:
// Use these to support bit- and part-select operators.
PExpr*msb_;
PExpr*lsb_;
NetNet* elaborate_net_array_(Design*des, NetScope*scope,
NetNet*sig, unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
// If this is a reference to a memory, this is the index
// expression.
PExpr*idx_;
NetNet* elaborate_net_ram_(Design*des, NetScope*scope,
NetMemory*mem, unsigned lwidth,
unsigned long rise,
unsigned long fall,
unsigned long decay) const;
NetNet* elaborate_net_bitmux_(Design*des, NetScope*scope,
NetNet*sig,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
unsigned long rise,
unsigned long fall,
unsigned long decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
private:
NetNet* elaborate_lnet_common_(Design*des, NetScope*scope,
bool implicit_net_ok,
bool bidirectional_flag) const;
NetNet*make_implicit_net_(Design*des, NetScope*scope) const;
bool eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
unsigned&midx, unsigned&lidx) const;
NetNet*process_select_(Design*des, NetScope*scope, NetNet*sig) const;
NetAssign_* elaborate_mem_lval_(Design*des, NetScope*scope,
NetMemory*mem) const;
};
@@ -382,25 +280,19 @@ class PENumber : public PExpr {
const verinum& value() const;
virtual void dump(ostream&) const;
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
bool&unsized_flag) const;
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
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*,
int expr_width, bool) const;
bool sys_task_arg =false) const;
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
virtual NetAssign_* elaborate_lval(Design*des,
NetScope*scope,
bool is_force) const;
virtual NetAssign_* elaborate_lval(Design*des, NetScope*scope) const;
virtual verinum* eval_const(Design*des, NetScope*sc) const;
virtual verinum* eval_const(const Design*des, const NetScope*sc) const;
virtual bool is_the_same(const PExpr*that) const;
virtual bool is_constant(Module*) const;
@@ -424,22 +316,17 @@ class PEString : public PExpr {
string value() const;
virtual void dump(ostream&) const;
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
bool&unsized_flag) const;
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned width,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
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*,
int expr_width, bool) const;
bool sys_task_arg =false) const;
virtual NetEConst*elaborate_pexpr(Design*des, NetScope*sc) const;
verinum* eval_const(Design*, NetScope*) const;
verinum* eval_const(const Design*, const NetScope*) const;
virtual bool is_constant(Module*) const;
@@ -454,18 +341,17 @@ class PEUnary : public PExpr {
~PEUnary();
virtual void dump(ostream&out) const;
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned width,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
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*,
int expr_width, bool sys_task_arg) const;
bool sys_task_arg =false) const;
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
virtual verinum* eval_const(Design*des, NetScope*sc) const;
virtual verinum* eval_const(const Design*des, const NetScope*sc) const;
virtual bool is_constant(Module*) const;
@@ -483,100 +369,65 @@ class PEBinary : public PExpr {
virtual bool is_constant(Module*) const;
virtual void dump(ostream&out) const;
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
bool&unsized_flag) const;
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned width,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
unsigned long rise,
unsigned long fall,
unsigned long decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
virtual NetEBinary*elaborate_expr(Design*des, NetScope*,
int expr_width, bool sys_task_arg) const;
bool sys_task_arg =false) const;
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
virtual verinum* eval_const(Design*des, NetScope*sc) const;
virtual verinum* eval_const(const Design*des, const NetScope*sc) const;
protected:
private:
char op_;
PExpr*left_;
PExpr*right_;
NetEBinary*elaborate_expr_base_(Design*, NetExpr*lp, NetExpr*rp, int use_wid) const;
NetEBinary*elaborate_eval_expr_base_(Design*, NetExpr*lp, NetExpr*rp, int use_wid) const;
NetEBinary*elaborate_expr_base_(Design*, NetExpr*lp, NetExpr*rp) const;
private:
NetNet* elaborate_net_add_(Design*des, NetScope*scope,
unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay) const;
unsigned long rise,
unsigned long fall,
unsigned long decay) const;
NetNet* elaborate_net_bit_(Design*des, NetScope*scope,
unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay) const;
unsigned long rise,
unsigned long fall,
unsigned long decay) const;
NetNet* elaborate_net_cmp_(Design*des, NetScope*scope,
unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay) const;
unsigned long rise,
unsigned long fall,
unsigned long decay) const;
NetNet* elaborate_net_div_(Design*des, NetScope*scope,
unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay) const;
unsigned long rise,
unsigned long fall,
unsigned long decay) const;
NetNet* elaborate_net_mod_(Design*des, NetScope*scope,
unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay) const;
unsigned long rise,
unsigned long fall,
unsigned long decay) const;
NetNet* elaborate_net_log_(Design*des, NetScope*scope,
unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay) const;
unsigned long rise,
unsigned long fall,
unsigned long decay) const;
NetNet* elaborate_net_mul_(Design*des, NetScope*scope,
unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay) const;
unsigned long rise,
unsigned long fall,
unsigned long decay) const;
NetNet* elaborate_net_shift_(Design*des, NetScope*scope,
unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay) const;
};
/*
* Here are a few specilized classes for handling specific binary
* operators.
*/
class PEBComp : public PEBinary {
public:
explicit PEBComp(char op, PExpr*l, PExpr*r);
~PEBComp();
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
bool&flag) const;
NetEBinary* elaborate_expr(Design*des, NetScope*scope,
int expr_width, bool sys_task_arg) const;
};
class PEBShift : public PEBinary {
public:
explicit PEBShift(char op, PExpr*l, PExpr*r);
~PEBShift();
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval, bool&flag) const;
unsigned long rise,
unsigned long fall,
unsigned long decay) const;
};
/*
@@ -592,21 +443,17 @@ class PETernary : public PExpr {
virtual bool is_constant(Module*) const;
virtual void dump(ostream&out) const;
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
bool&unsized_flag) const;
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned width,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
unsigned long rise,
unsigned long fall,
unsigned long decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
virtual NetETernary*elaborate_expr(Design*des, NetScope*,
int expr_width, bool sys_task_arg) const;
bool sys_task_arg =false) const;
virtual NetETernary*elaborate_pexpr(Design*des, NetScope*sc) const;
virtual verinum* eval_const(Design*des, NetScope*sc) const;
virtual verinum* eval_const(const Design*des, const NetScope*sc) const;
private:
PExpr*expr_;
@@ -621,130 +468,37 @@ class PETernary : public PExpr {
*/
class PECallFunction : public PExpr {
public:
explicit PECallFunction(const pform_name_t&n, const svector<PExpr *> &parms);
// Call of system function (name is not heirarchical)
explicit PECallFunction(perm_string n, const svector<PExpr *> &parms);
explicit PECallFunction(perm_string n);
explicit PECallFunction(const hname_t&n, const svector<PExpr *> &parms);
explicit PECallFunction(const hname_t&n);
~PECallFunction();
virtual void dump(ostream &) const;
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned width,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
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,
int expr_wid, bool sys_task_arg) const;
bool sys_task_arg =false) const;
private:
pform_name_t path_;
hname_t path_;
svector<PExpr *> parms_;
bool check_call_matches_definition_(Design*des, NetScope*dscope) const;
NetExpr* elaborate_sfunc_(Design*des, NetScope*scope) const;
NetNet* elaborate_net_sfunc_(Design*des, NetScope*scope,
unsigned width,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
};
/*
* $Log: PExpr.h,v $
* Revision 1.90 2007/06/04 19:14:06 steve
* Build errors in picky GCC compilers.
* Revision 1.66.2.2 2006/07/28 16:26:17 steve
* Remove excess PEString:: prefix for stubborn compilers.
*
* Revision 1.89 2007/06/04 02:19:07 steve
* Handle bit/part select of array words in nets.
*
* Revision 1.88 2007/05/24 04:07:11 steve
* Rework the heirarchical identifier parse syntax and pform
* to handle more general combinations of heirarch and bit selects.
*
* Revision 1.87 2007/01/16 05:44:14 steve
* Major rework of array handling. Memories are replaced with the
* more general concept of arrays. The NetMemory and NetEMemory
* classes are removed from the ivl core program, and the IVL_LPM_RAM
* lpm type is removed from the ivl_target API.
*
* Revision 1.86 2006/11/10 04:54:26 steve
* Add test_width methods for PETernary and PEString.
*
* Revision 1.85 2006/11/04 06:19:24 steve
* Remove last bits of relax_width methods, and use test_width
* to calculate the width of an r-value expression that may
* contain unsized numbers.
*
* Revision 1.84 2006/10/30 05:44:49 steve
* Expression widths with unsized literals are pseudo-infinite width.
*
* Revision 1.83 2006/06/18 04:15:50 steve
* Add support for system functions in continuous assignments.
*
* Revision 1.82 2006/06/02 04:48:49 steve
* Make elaborate_expr methods aware of the width that the context
* requires of it. In the process, fix sizing of the width of unary
* minus is context determined sizes.
*
* Revision 1.81 2006/04/28 04:28:35 steve
* Allow concatenations as arguments to inout ports.
*
* Revision 1.80 2006/04/16 00:54:04 steve
* Cleanup lval part select handling.
*
* Revision 1.79 2006/04/16 00:15:43 steve
* Fix part selects in l-values.
*
* Revision 1.78 2006/03/25 02:36:26 steve
* Get rid of excess PESTring:: prefix within class declaration.
*
* Revision 1.77 2006/02/02 02:43:57 steve
* Allow part selects of memory words in l-values.
*
* Revision 1.76 2006/01/02 05:33:19 steve
* Node delays can be more general expressions in structural contexts.
*
* Revision 1.75 2005/12/07 04:04:23 steve
* Allow constant concat expressions.
*
* Revision 1.74 2005/11/27 17:01:56 steve
* Fix for stubborn compiler.
*
* Revision 1.73 2005/11/27 05:56:20 steve
* Handle bit select of parameter with ranges.
*
* Revision 1.72 2005/11/10 13:28:11 steve
* Reorganize signal part select handling, and add support for
* indexed part selects.
*
* Expand expression constant propagation to eliminate extra
* sums in certain cases.
*
* Revision 1.71 2005/10/04 04:09:25 steve
* Add support for indexed select attached to parameters.
*
* Revision 1.70 2005/08/06 17:58:16 steve
* Implement bi-directional part selects.
*
* Revision 1.69 2005/07/07 16:22:49 steve
* Generalize signals to carry types.
*
* Revision 1.68 2005/01/09 20:16:00 steve
* Use PartSelect/PV and VP to handle part selects through ports.
*
* Revision 1.67 2004/12/29 23:55:43 steve
* Unify elaboration of l-values for all proceedural assignments,
* including assing, cassign and force.
*
* Generate NetConcat devices for gate outputs that feed into a
* vector results. Use this to hande gate arrays. Also let gate
* arrays handle vectors of gates when the outputs allow for it.
* Revision 1.66.2.1 2005/12/07 03:28:44 steve
* Support constant concatenation of constants.
*
* Revision 1.66 2004/10/04 01:10:51 steve
* Clean up spurious trailing white space.
+2 -65
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: PGate.cc,v 1.18 2006/01/03 05:22:14 steve Exp $"
#ident "$Id: PGate.cc,v 1.16 2004/02/18 17:11:54 steve Exp $"
#endif
# include "config.h"
@@ -90,69 +90,12 @@ void PGate::elaborate_scope(Design*, NetScope*) const
* parameters. This method understands how to handle the different
* numbers of expressions.
*/
void PGate::eval_delays(Design*des, NetScope*scope,
NetExpr*&rise_expr,
NetExpr*&fall_expr,
NetExpr*&decay_expr,
bool as_net_flag) const
{
delay_.eval_delays(des, scope,
rise_expr, fall_expr, decay_expr,
as_net_flag);
}
void PGate::eval_delays(Design*des, NetScope*scope,
unsigned long&rise_time,
unsigned long&fall_time,
unsigned long&decay_time) const
{
NetExpr*rise_expr, *fall_expr, *decay_expr;
delay_.eval_delays(des, scope, rise_expr, fall_expr, decay_expr);
if (rise_expr == 0) {
rise_time = 0;
fall_time = 0;
decay_time = 0;
}
if (NetEConst*tmp = dynamic_cast<NetEConst*> (rise_expr)) {
rise_time = tmp->value().as_ulong();
} else {
cerr << get_line() << ": error: Delay expressions must be "
<< "constant here." << endl;
cerr << get_line() << ": : Cannot calculate "
<< *rise_expr << endl;
des->errors += 1;
rise_time = 0;
}
if (NetEConst*tmp = dynamic_cast<NetEConst*> (fall_expr)) {
fall_time = tmp->value().as_ulong();
} else {
if (fall_expr != rise_expr) {
cerr << get_line() << ": error: Delay expressions must be "
<< "constant here." << endl;
cerr << get_line() << ": : Cannot calculate "
<< *rise_expr << endl;
}
des->errors += 1;
fall_time = 0;
}
if (NetEConst*tmp = dynamic_cast<NetEConst*> (decay_expr)) {
decay_time = tmp->value().as_ulong();
} else {
cerr << get_line() << ": error: Delay expressions must be "
<< "constant here." << endl;
cerr << get_line() << ": : Cannot calculate "
<< *rise_expr << endl;
des->errors += 1;
decay_time = 0;
}
delay_.eval_delays(des, scope, rise_time, fall_time, decay_time);
}
PGAssign::PGAssign(svector<PExpr*>*pins)
@@ -248,12 +191,6 @@ perm_string PGModule::get_type()
/*
* $Log: PGate.cc,v $
* Revision 1.18 2006/01/03 05:22:14 steve
* Handle complex net node delays.
*
* Revision 1.17 2006/01/02 05:33:19 steve
* Node delays can be more general expressions in structural contexts.
*
* Revision 1.16 2004/02/18 17:11:54 steve
* Use perm_strings for named langiage items.
*
+5 -26
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: PGate.h,v 1.32 2006/04/10 00:37:42 steve Exp $"
#ident "$Id: PGate.h,v 1.29 2004/10/04 01:10:52 steve Exp $"
#endif
# include "svector.h"
@@ -66,23 +66,11 @@ class PGate : public LineInfo {
perm_string get_name() const { return name_; }
// This method evaluates the delays all the way to an
// integer. If the delay is non-constant, then set the times
// to 0, print an error message and mark an error to the
// design.
void eval_delays(Design*des, NetScope*scope,
unsigned long&rise_time,
unsigned long&fall_time,
unsigned long&decay_time) const;
// This evaluates the delays as far as possible, but returns
// an expression, and do not signal errors.
void eval_delays(Design*des, NetScope*scope,
NetExpr*&rise_time,
NetExpr*&fall_time,
NetExpr*&decay_time,
bool as_net_flag =false) const;
unsigned pin_count() const { return pins_? pins_->count() : 0; }
const PExpr*pin(unsigned idx) const { return (*pins_)[idx]; }
@@ -94,7 +82,7 @@ class PGate : public LineInfo {
map<perm_string,PExpr*> attributes;
virtual void dump(ostream&out, unsigned ind =4) const;
virtual void dump(ostream&out) const;
virtual void elaborate(Design*des, NetScope*scope) const;
virtual void elaborate_scope(Design*des, NetScope*sc) const;
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
@@ -128,7 +116,7 @@ class PGAssign : public PGate {
explicit PGAssign(svector<PExpr*>*pins, svector<PExpr*>*dels);
~PGAssign();
void dump(ostream&out, unsigned ind =4) const;
void dump(ostream&out) const;
virtual void elaborate(Design*des, NetScope*scope) const;
private:
@@ -165,7 +153,7 @@ class PGBuiltin : public PGate {
Type type() const { return type_; }
void set_range(PExpr*msb, PExpr*lsb);
virtual void dump(ostream&out, unsigned ind =4) const;
virtual void dump(ostream&out) const;
virtual void elaborate(Design*, NetScope*scope) const;
private:
@@ -208,7 +196,7 @@ class PGModule : public PGate {
// method to pass the range to the pform.
void set_range(PExpr*msb, PExpr*lsb);
virtual void dump(ostream&out, unsigned ind =4) const;
virtual void dump(ostream&out) const;
virtual void elaborate(Design*, NetScope*scope) const;
virtual void elaborate_scope(Design*des, NetScope*sc) const;
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
@@ -239,15 +227,6 @@ class PGModule : public PGate {
/*
* $Log: PGate.h,v $
* Revision 1.32 2006/04/10 00:37:42 steve
* Add support for generate loops w/ wires and gates.
*
* Revision 1.31 2006/01/03 05:22:14 steve
* Handle complex net node delays.
*
* Revision 1.30 2006/01/02 05:33:19 steve
* Node delays can be more general expressions in structural contexts.
*
* Revision 1.29 2004/10/04 01:10:52 steve
* Clean up spurious trailing white space.
*
-63
View File
@@ -1,63 +0,0 @@
/*
* Copyright (c) 2006 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: PGenerate.cc,v 1.4 2007/06/02 03:42:12 steve Exp $"
#endif
# include "PGenerate.h"
# include "PWire.h"
PGenerate::PGenerate(unsigned id)
: id_number(id)
{
parent = 0;
}
PGenerate::~PGenerate()
{
}
PWire* PGenerate::add_wire(PWire*wire)
{
PWire*&ep = wires[wire->path()];
if (ep) return ep;
assert(ep == 0);
ep = wire;
return wire;
}
PWire* PGenerate::get_wire(const pform_name_t&name) const
{
map<pform_name_t,PWire*>::const_iterator obj = wires.find(name);
if (obj == wires.end())
return 0;
else
return (*obj).second;
}
void PGenerate::add_gate(PGate*gate)
{
gates.push_back(gate);
}
void PGenerate::add_behavior(PProcess*proc)
{
behaviors.push_back(proc);
}
-100
View File
@@ -1,100 +0,0 @@
#ifndef __PGenerate_H
#define __PGenerate_H
/*
* Copyright (c) 2006 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: PGenerate.h,v 1.4 2007/06/02 03:42:12 steve Exp $"
#endif
# include "LineInfo.h"
# include "StringHeap.h"
# include "HName.h"
# include <list>
# include <map>
# include "pform_types.h"
class Design;
class NetScope;
class PExpr;
class PProcess;
class PGate;
class PWire;
/*
* This represents a generate scheme.
*/
class PGenerate : public LineInfo {
public:
PGenerate(unsigned id_number);
~PGenerate();
// Generate schemes have an ID number, for when the scope is
// implicit.
const unsigned id_number;
perm_string scope_name;
enum scheme_t {GS_NONE, GS_LOOP, GS_CONDIT};
scheme_t scheme_type;
// generate loops have an index variable and three
// expressions: for (index = <init>; <test>; index=<step>)
perm_string loop_index;
PExpr*loop_init;
PExpr*loop_test;
PExpr*loop_step;
map<pform_name_t,PWire*>wires;
PWire* add_wire(PWire*);
PWire* get_wire(const pform_name_t&name) const;
list<PGate*> gates;
void add_gate(PGate*);
list<PProcess*> behaviors;
void add_behavior(PProcess*behave);
list<PGenerate*> generates;
PGenerate*parent;
// This method is called by the elaboration of a module to
// generate scopes. the container is the scope that is to
// contain the generated scope.
bool generate_scope(Design*des, NetScope*container);
bool elaborate_sig(Design*des) const;
bool elaborate(Design*des) const;
void dump(ostream&out, unsigned indent) const;
private:
bool generate_scope_loop_(Design*des, NetScope*container);
// These are the scopes created by generate_scope.
list<NetScope*>scope_list_;
// internal function called on each scope generated by this scheme.
bool elaborate_sig_(Design*des, NetScope*scope) const;
bool elaborate_(Design*des, NetScope*scope) const;
private: // not implemented
PGenerate(const PGenerate&);
PGenerate& operator= (const PGenerate&);
};
#endif
-79
View File
@@ -1,79 +0,0 @@
#ifndef __PSpec_H
#define __PSpec_H
/*
* Copyright (c) 2006 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: PSpec.h,v 1.3 2007/04/13 02:34:35 steve Exp $"
#endif
# include "LineInfo.h"
# include "StringHeap.h"
# include <vector>
class PExpr;
/*
* The PSpecPath is the parse of a specify path, which is in its most
* general form <path> = <delays>. The <delays> are collected into the
* "delays" vector in all cases, and the variety is in the other
* members.
*
* All paths also have a list of source names in the src vector, and a
* list of destination names in the dst vector. These pairs are the
* actual paths.
*
* If the path is a simple path, then:
* condition == nil
* edge == 0
* data_source_expression == nil
*
* If the path is conditional, then conditional == true and condition
* is the condition expression. If the condition expression is nil,
* then this is an ifnone conditional path.
*
* If data_source_expression != nil, then the path is edge sensitive
* and the edge might not be 0.
*/
class PSpecPath : public LineInfo {
public:
PSpecPath(unsigned src_cnt, unsigned dst_cnt);
~PSpecPath();
void elaborate(class Design*des, class NetScope*scope) const;
void dump(std::ostream&out, unsigned ind) const;
public:
// Condition expression, if present.
bool conditional;
class PExpr* condition;
// Edge specification (-1==negedge, 0 = no edge, 1==posedge)
int edge;
// Ordered set of source nodes of a path
std::vector<perm_string> src;
// Ordered set of destination nodes of a path
std::vector<perm_string> dst;
// Data source expression
class PExpr* data_source_expression;
std::vector<class PExpr*>delays;
};
#endif
+5 -6
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: PTask.h,v 1.14 2007/03/06 05:22:49 steve Exp $"
#ident "$Id: PTask.h,v 1.13.2.1 2005/08/13 00:45:53 steve Exp $"
#endif
# include "LineInfo.h"
@@ -35,7 +35,6 @@ class PExpr;
enum PTaskFuncEnum {
PTF_NONE,
PTF_REG,
PTF_REG_S,
PTF_INTEGER,
PTF_REAL,
PTF_REALTIME,
@@ -71,7 +70,7 @@ class PTask : public LineInfo {
// Elaborate the statement to finish off the task definition.
void elaborate(Design*des, NetScope*scope) const;
void dump(ostream&, unsigned) const;
void dump(std::ostream&, unsigned) const;
private:
svector<PWire*>*ports_;
@@ -107,7 +106,7 @@ class PFunction : public LineInfo {
/* Elaborate the behavioral statement. */
void elaborate(Design *des, NetScope*) const;
void dump(ostream&, unsigned) const;
void dump(std::ostream&, unsigned) const;
private:
perm_string name_;
@@ -118,8 +117,8 @@ class PFunction : public LineInfo {
/*
* $Log: PTask.h,v $
* Revision 1.14 2007/03/06 05:22:49 steve
* Support signed function return values.
* Revision 1.13.2.1 2005/08/13 00:45:53 steve
* Fix compilation warnings/errors with newer compilers.
*
* Revision 1.13 2004/05/31 23:34:36 steve
* Rewire/generalize parsing an elaboration of
+8 -5
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: PUdp.h,v 1.12 2004/03/08 00:47:44 steve Exp $"
#ident "$Id: PUdp.h,v 1.12.2.1 2005/08/13 00:45:53 steve Exp $"
#endif
# include <map>
@@ -55,20 +55,20 @@ class PUdp {
public:
explicit PUdp(perm_string n, unsigned nports);
svector<string>ports;
svector<std::string>ports;
unsigned find_port(const char*name);
bool sequential;
svector<string>tinput;
svector<std::string>tinput;
svector<char> tcurrent;
svector<char> toutput;
verinum::V initial;
map<string,PExpr*> attributes;
std::map<std::string,PExpr*> attributes;
void dump(ostream&out) const;
void dump(std::ostream&out) const;
perm_string name_;
private:
@@ -80,6 +80,9 @@ class PUdp {
/*
* $Log: PUdp.h,v $
* Revision 1.12.2.1 2005/08/13 00:45:53 steve
* Fix compilation warnings/errors with newer compilers.
*
* Revision 1.12 2004/03/08 00:47:44 steve
* primitive ports can bind bi name.
*
+17 -38
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2007 Stephen Williams ([email protected])
* Copyright (c) 1999 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -17,19 +17,26 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: PWire.cc,v 1.14 2007/05/24 04:07:11 steve Exp $"
#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 pform_name_t&n,
NetNet::Type t,
NetNet::PortType pt,
ivl_variable_type_t dt)
: hname_(n), type_(t), port_type_(pt), data_type_(dt),
signed_(false), isint_(false),
PWire::PWire(const hname_t&n, NetNet::Type t, NetNet::PortType pt)
: 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), isint_(false),
lidx_(0), ridx_(0)
{
if (t == NetNet::INTEGER) {
@@ -44,7 +51,7 @@ NetNet::Type PWire::get_wire_type() const
return type_;
}
const pform_name_t& PWire::path() const
const hname_t& PWire::path() const
{
return hname_;
}
@@ -101,19 +108,6 @@ bool PWire::set_port_type(NetNet::PortType pt)
}
}
bool PWire::set_data_type(ivl_variable_type_t dt)
{
if (data_type_ != IVL_VT_NO_TYPE)
if (data_type_ != dt)
return false;
else
return true;
assert(data_type_ == IVL_VT_NO_TYPE);
data_type_ = dt;
return true;
}
void PWire::set_signed(bool flag)
{
signed_ = flag;
@@ -139,28 +133,13 @@ void PWire::set_memory_idx(PExpr*ldx, PExpr*rdx)
{
assert(lidx_ == 0);
assert(ridx_ == 0);
assert(type_ == NetNet::REG);
lidx_ = ldx;
ridx_ = rdx;
}
/*
* $Log: PWire.cc,v $
* Revision 1.14 2007/05/24 04:07:11 steve
* Rework the heirarchical identifier parse syntax and pform
* to handle more general combinations of heirarch and bit selects.
*
* Revision 1.13 2007/04/26 03:06:21 steve
* Rework hname_t to use perm_strings.
*
* Revision 1.12 2007/01/16 05:44:14 steve
* Major rework of array handling. Memories are replaced with the
* more general concept of arrays. The NetMemory and NetEMemory
* classes are removed from the ivl core program, and the IVL_LPM_RAM
* lpm type is removed from the ivl_target API.
*
* Revision 1.11 2005/07/07 16:22:49 steve
* Generalize signals to carry types.
*
* Revision 1.10 2002/08/12 01:34:58 steve
* conditional ident string using autoconfig.
*
+46 -32
View File
@@ -1,7 +1,7 @@
#ifndef __PWire_H
#define __PWire_H
/*
* Copyright (c) 1998-2007 Stephen Williams ([email protected])
* Copyright (c) 1998-2000 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -19,14 +19,13 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: PWire.h,v 1.21 2007/05/24 04:07:11 steve Exp $"
#ident "$Id: PWire.h,v 1.17 2004/02/20 18:53:33 steve Exp $"
#endif
# include "netlist.h"
# include "LineInfo.h"
# include <map>
# include "svector.h"
# include "StringHeap.h"
#ifdef HAVE_IOSFWD
# include <iosfwd>
@@ -43,21 +42,18 @@ class Design;
* identifies a port by keeping it in its port list.
*
* The hname parameter to the constructor is a hierarchical name. It
* is the name of the wire within a module, so does not include the
* current scope or any instances. Modules contain all the wires, so
* from that perspective, sub-scopes within the module are a part of
* the wire name.
* is an array of strings starting with the root, running towards
* the base name, and terminated by a null pointer. The environment
* allocates the memory for me.
*/
class PWire : public LineInfo {
public:
PWire(const pform_name_t&hname,
NetNet::Type t,
NetNet::PortType pt,
ivl_variable_type_t dt);
PWire(const hname_t&hname, NetNet::Type t, NetNet::PortType pt);
PWire(char*name, NetNet::Type t, NetNet::PortType pt);
// Return a hierarchical name.
const pform_name_t&path() const;
const hname_t&path() const;
NetNet::Type get_wire_type() const;
bool set_wire_type(NetNet::Type);
@@ -69,9 +65,6 @@ class PWire : public LineInfo {
bool get_signed() const;
bool get_isint() const;
bool set_data_type(ivl_variable_type_t dt);
ivl_variable_type_t get_data_type() const;
void set_range(PExpr*msb, PExpr*lsb);
void set_memory_idx(PExpr*ldx, PExpr*rdx);
@@ -79,15 +72,14 @@ class PWire : public LineInfo {
map<perm_string,PExpr*> attributes;
// Write myself to the specified stream.
void dump(ostream&out, unsigned ind=4) const;
void dump(ostream&out) const;
NetNet* elaborate_sig(Design*, NetScope*scope) const;
void elaborate_sig(Design*, NetScope*scope) const;
private:
pform_name_t hname_;
hname_t hname_;
NetNet::Type type_;
NetNet::PortType port_type_;
ivl_variable_type_t data_type_;
bool signed_;
bool isint_; // original type of integer
@@ -108,19 +100,6 @@ class PWire : public LineInfo {
/*
* $Log: PWire.h,v $
* Revision 1.21 2007/05/24 04:07:11 steve
* Rework the heirarchical identifier parse syntax and pform
* to handle more general combinations of heirarch and bit selects.
*
* Revision 1.20 2007/04/26 03:06:22 steve
* Rework hname_t to use perm_strings.
*
* Revision 1.19 2006/04/10 00:37:42 steve
* Add support for generate loops w/ wires and gates.
*
* Revision 1.18 2005/07/07 16:22:49 steve
* Generalize signals to carry types.
*
* Revision 1.17 2004/02/20 18:53:33 steve
* Addtrbute keys are perm_strings.
*
@@ -151,5 +130,40 @@ class PWire : public LineInfo {
*
* Revision 1.10 2001/01/16 02:44:18 steve
* Use the iosfwd header if available.
*
* Revision 1.9 2000/12/11 00:31:43 steve
* Add support for signed reg variables,
* simulate in t-vvm signed comparisons.
*
* Revision 1.8 2000/05/02 16:27:38 steve
* Move signal elaboration to a seperate pass.
*
* Revision 1.7 2000/02/23 02:56:54 steve
* Macintosh compilers do not support ident.
*
* Revision 1.6 1999/11/27 19:07:57 steve
* Support the creation of scopes.
*
* Revision 1.5 1999/06/17 05:34:42 steve
* Clean up interface of the PWire class,
* Properly match wire ranges.
*
* Revision 1.4 1999/06/02 15:38:46 steve
* Line information with nets.
*
* Revision 1.3 1999/04/19 01:59:36 steve
* Add memories to the parse and elaboration phases.
*
* Revision 1.2 1998/11/23 00:20:22 steve
* NetAssign handles lvalues as pin links
* instead of a signal pointer,
* Wire attributes added,
* Ability to parse UDP descriptions added,
* XNF generates EXT records for signals with
* the PAD attribute.
*
* Revision 1.1 1998/11/03 23:28:55 steve
* Introduce verilog to CVS.
*
*/
#endif
+51 -17
View File
@@ -114,7 +114,7 @@ configure script that modify its behavior:
If you are building for Linux/AMD64 (a.k.a x86_64) then to get the
most out of your install, first make sure you have both 64bit and
32bit development libraries installed. Then configure with this
somewhat more complicated command:
somewhat more complex command:
./configure libdir64='$(prefix)/lib64' vpidir1=vpi64 vpidir2=. --enable-vvp32
@@ -359,8 +359,7 @@ constructs.
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. See the "extensions.txt" documentation for
more details.
language that are defined.
$is_signed(<expr>)
This system function returns 1 if the expression contained is
@@ -471,20 +470,6 @@ more details.
combinational always blocks to be triggered when the values in
the sensitivity list are initialized by initial threads.
Nets with Types
Icarus Verilog support an extension syntax that allows nets
and regs to be explicitly typed. The currently supported types
are logic, bool and real. This implies that "logic" and "bool"
are new keywords. Typical syntax is:
wire real foo = 1.0;
reg logic bar, bat;
... and so forth. The syntax can be turned off by using the
-g2 flag to iverilog, and turned on explicitly with the -g2x
flag to iverilog.
6.0 CREDITS
Except where otherwise noted, Icarus Verilog, ivl and ivlpp are
@@ -494,3 +479,52 @@ Verilog guidance, and especially testing from many people. Testers in
particular include a larger community of people interested in a GPL
Verilog for Linux.
6.1 PORT MAINTAINERS
This is a list of people who have created ports and precompiled
packages for various operating systems. These folks have graciously
taken on the task of building Icarus Verilog on their systems and
bundled it into neat packages.(+) If you want to be added to the list (or
removed from the list) send e-mail to me.
FreeBSD/{Intel,alpha}
Ying-Chieh Liao <[email protected]>
Linux/{alpha,AMD64,Intel} (RPMS)
Stephen Williams <[email protected]>
Linux/* (.debs)
Hamish Moffatt <[email protected]>
Macintosh -- MacO/S
Yasuhisa Kato <[email protected]>
Mac O/S X
Timothy J. Wood <[email protected]>
NetBSD/*
Dan McMahill <[email protected]>
Solaris/SPARC packages (.pkg)
Dan McMahill <[email protected]>
Cygwin32/*
Venkat Iyer <[email protected]>
Mingw32
Venkat Iyer <[email protected]>
(+) These are not the only systems where Icarus Verilog has been run,
just the systems where precompiled binaries are publicly available.
6.2 TEST SUITE MANAGER
Steve Wilson <[email protected]> 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.
+5 -15
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: Statement.cc,v 1.30 2007/05/24 04:07:11 steve Exp $"
#ident "$Id: Statement.cc,v 1.29 2004/02/18 17:11:54 steve Exp $"
#endif
# include "config.h"
@@ -107,22 +107,16 @@ PBlock::~PBlock()
delete list_[idx];
}
PCallTask::PCallTask(const pform_name_t&n, const svector<PExpr*>&p)
PCallTask::PCallTask(const hname_t&n, const svector<PExpr*>&p)
: path_(n), parms_(p)
{
}
PCallTask::PCallTask(perm_string n, const svector<PExpr*>&p)
: parms_(p)
{
path_.push_back(name_component_t(n));
}
PCallTask::~PCallTask()
{
}
const pform_name_t& PCallTask::path() const
const hname_t& PCallTask::path() const
{
return path_;
}
@@ -184,7 +178,7 @@ PDelayStatement::~PDelayStatement()
{
}
PDisable::PDisable(const pform_name_t&sc)
PDisable::PDisable(const hname_t&sc)
: scope_(sc)
{
}
@@ -279,7 +273,7 @@ PRepeat::~PRepeat()
delete statement_;
}
PTrigger::PTrigger(const pform_name_t&e)
PTrigger::PTrigger(const hname_t&e)
: event_(e)
{
}
@@ -301,10 +295,6 @@ PWhile::~PWhile()
/*
* $Log: Statement.cc,v $
* Revision 1.30 2007/05/24 04:07:11 steve
* Rework the heirarchical identifier parse syntax and pform
* to handle more general combinations of heirarch and bit selects.
*
* Revision 1.29 2004/02/18 17:11:54 steve
* Use perm_strings for named langiage items.
*
+15 -29
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: Statement.h,v 1.44 2007/05/24 04:07:11 steve Exp $"
#ident "$Id: Statement.h,v 1.40.2.1 2006/07/10 00:21:49 steve Exp $"
#endif
# include <string>
@@ -36,7 +36,6 @@ class Design;
class NetAssign_;
class NetCAssign;
class NetDeassign;
class NetForce;
class NetScope;
/*
@@ -55,8 +54,6 @@ class PProcess : public LineInfo {
virtual ~PProcess();
bool elaborate(Design*des, NetScope*scope) const;
Type type() const { return type_; }
Statement*statement() { return statement_; }
@@ -74,12 +71,15 @@ class PProcess : public LineInfo {
* fact, the Statement class is abstract and represents all the
* possible kinds of statements that exist in Verilog.
*/
class Statement : public LineInfo {
class Statement : public LineInfo, public Attrib {
public:
Statement() { }
virtual ~Statement() =0;
map<perm_string,PExpr*> attributes;
void dump_attributes(ostream&out, unsigned ind) const;
virtual void dump(ostream&out, unsigned ind) const;
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void elaborate_scope(Design*des, NetScope*scope) const;
@@ -173,11 +173,10 @@ class PBlock : public Statement {
class PCallTask : public Statement {
public:
explicit PCallTask(const pform_name_t&n, const svector<PExpr*>&parms);
explicit PCallTask(perm_string n, const svector<PExpr*>&parms);
explicit PCallTask(const hname_t&n, const svector<PExpr*>&parms);
~PCallTask();
const pform_name_t& path() const;
const hname_t& path() const;
unsigned nparms() const { return parms_.count(); }
@@ -198,7 +197,7 @@ class PCallTask : public Statement {
NetProc* elaborate_sys(Design*des, NetScope*scope) const;
NetProc* elaborate_usr(Design*des, NetScope*scope) const;
pform_name_t path_;
hname_t path_;
svector<PExpr*> parms_;
};
@@ -297,14 +296,14 @@ class PDelayStatement : public Statement {
class PDisable : public Statement {
public:
explicit PDisable(const pform_name_t&sc);
explicit PDisable(const hname_t&sc);
~PDisable();
virtual void dump(ostream&out, unsigned ind) const;
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
private:
pform_name_t scope_;
hname_t scope_;
};
/*
@@ -349,7 +348,7 @@ class PForce : public Statement {
explicit PForce(PExpr*l, PExpr*r);
~PForce();
virtual NetForce* elaborate(Design*des, NetScope*scope) const;
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void dump(ostream&out, unsigned ind) const;
private:
@@ -397,7 +396,6 @@ class PNoop : public Statement {
public:
PNoop() { }
~PNoop() { }
};
class PRepeat : public Statement {
@@ -434,14 +432,14 @@ class PRelease : public Statement {
class PTrigger : public Statement {
public:
explicit PTrigger(const pform_name_t&ev);
explicit PTrigger(const hname_t&ev);
~PTrigger();
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void dump(ostream&out, unsigned ind) const;
private:
pform_name_t event_;
hname_t event_;
};
class PWhile : public Statement {
@@ -461,20 +459,8 @@ class PWhile : public Statement {
/*
* $Log: Statement.h,v $
* Revision 1.44 2007/05/24 04:07:11 steve
* Rework the heirarchical identifier parse syntax and pform
* to handle more general combinations of heirarch and bit selects.
*
* Revision 1.43 2007/03/05 05:59:10 steve
* Handle processes within generate loops.
*
* Revision 1.42 2005/12/05 21:21:18 steve
* Fixes for stubborn compilers.
*
* Revision 1.41 2004/12/11 02:31:25 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
* Revision 1.40.2.1 2006/07/10 00:21:49 steve
* Add support for full_case attribute.
*
* Revision 1.40 2004/02/20 18:53:33 steve
* Addtrbute keys are perm_strings.
+5 -2
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: StringHeap.cc,v 1.6 2004/02/18 17:11:54 steve Exp $"
#ident "$Id: StringHeap.cc,v 1.6.2.1 2005/08/13 00:45:53 steve Exp $"
#endif
# include "StringHeap.h"
@@ -131,7 +131,7 @@ perm_string StringHeapLex::make(const char*text)
return perm_string(add(text));
}
perm_string StringHeapLex::make(const string&text)
perm_string StringHeapLex::make(const std::string&text)
{
return perm_string(add(text.c_str()));
}
@@ -181,6 +181,9 @@ bool operator < (perm_string a, perm_string b)
/*
* $Log: StringHeap.cc,v $
* Revision 1.6.2.1 2005/08/13 00:45:53 steve
* Fix compilation warnings/errors with newer compilers.
*
* Revision 1.6 2004/02/18 17:11:54 steve
* Use perm_strings for named langiage items.
*
+7 -4
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: StringHeap.h,v 1.6 2005/06/14 19:13:43 steve Exp $"
#ident "$Id: StringHeap.h,v 1.5.2.2 2005/08/13 00:45:53 steve Exp $"
#endif
# include "config.h"
@@ -103,7 +103,7 @@ class StringHeapLex : private StringHeap {
const char*add(const char*);
perm_string make(const char*);
perm_string make(const string&);
perm_string make(const std::string&);
unsigned add_count() const;
unsigned add_hit_count() const;
@@ -122,8 +122,11 @@ class StringHeapLex : private StringHeap {
/*
* $Log: StringHeap.h,v $
* Revision 1.6 2005/06/14 19:13:43 steve
* gcc3/4 compile errors.
* Revision 1.5.2.2 2005/08/13 00:45:53 steve
* Fix compilation warnings/errors with newer compilers.
*
* Revision 1.5.2.1 2005/06/14 15:33:54 steve
* Fix gcc4 build issues.
*
* Revision 1.5 2004/02/18 17:11:54 steve
* Use perm_strings for named langiage items.
+3 -6
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: _pli_types.h.in,v 1.8 2007/06/05 21:32:30 steve Exp $"
#ident "$Id: _pli_types.h.in,v 1.7 2003/11/12 02:38:44 steve Exp $"
#endif
# undef HAVE_INTTYPES_H
@@ -42,7 +42,7 @@ typedef int32_t PLI_INT32;
typedef signed short PLI_INT16;
typedef unsigned short PLI_UINT16;
typedef char PLI_BYTE8;
typedef signed char PLI_BYTE8;
typedef unsigned char PLI_UBYTE8;
# define PLI_UINT64_FMT PRIu64
@@ -84,15 +84,12 @@ typedef signed int PLI_INT32;
typedef unsigned int PLI_UINT32;
typedef signed short PLI_INT16;
typedef unsigned short PLI_UINT16;
typedef char PLI_BYTE8;
typedef signed char PLI_BYTE8;
typedef unsigned char PLI_UBYTE8;
#endif
/*
* $Log: _pli_types.h.in,v $
* Revision 1.8 2007/06/05 21:32:30 steve
* More standard PLI_BYTE8.
*
* Revision 1.7 2003/11/12 02:38:44 steve
* Clean up manual definitions of PLI_UINT64_FMT.
*
Vendored
+7 -11
View File
@@ -14,7 +14,7 @@
AC_DEFUN([AX_CPP_IDENT],
[AC_CACHE_CHECK([for ident support in C compiler], ax_cv_cpp_ident,
[AC_TRY_COMPILE([
#ident "$Id: aclocal.m4,v 1.7 2007/05/16 23:59:12 steve Exp $"
#ident "$Id: aclocal.m4,v 1.6.2.2 2007/05/16 23:51:42 steve Exp $"
],[while (0) {}],
[AS_VAR_SET(ax_cv_cpp_ident, yes)],
[AS_VAR_SET(ax_cv_cpp_ident, no)])])
@@ -91,13 +91,9 @@ AC_MSG_RESULT($WIN32)
AC_DEFUN([AX_LD_EXTRALIBS],
[AC_MSG_CHECKING([for extra libs needed])
EXTRALIBS=
case "${host}" in
*-*-cygwin* )
if test "$MINGW32" = "yes"; then
EXTRALIBS="-liberty"
fi
;;
esac
if test "$MINGW32" = "yes"; then
EXTRALIBS="-liberty"
fi
AC_SUBST(EXTRALIBS)
AC_MSG_RESULT($EXTRALIBS)
])# AX_LD_EXTRALIBS
@@ -109,7 +105,7 @@ AC_DEFUN([AX_LD_SHAREDLIB_OPTS],
[AC_MSG_CHECKING([for shared library link flag])
shared=-shared
case "${host}" in
*-*-cygwin*)
*-*-cygwin* | *-*-mingw32*)
shared="-shared -Wl,--enable-auto-image-base"
;;
@@ -138,7 +134,7 @@ AC_DEFUN([AX_C_PICFLAG],
PICFLAG=-fPIC
case "${host}" in
*-*-cygwin*)
*-*-cygwin* | *-*-mingw32*)
PICFLAG=
;;
@@ -173,7 +169,7 @@ case "${host}" in
rdynamic=""
;;
*-*-cygwin*)
*-*-cygwin* | *-*-mingw32*)
rdynamic=""
;;
+12 -2
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: async.cc,v 1.7 2004/01/18 23:26:54 steve Exp $"
#ident "$Id: async.cc,v 1.7.2.2 2007/05/30 17:48:53 steve Exp $"
#endif
# include "config.h"
@@ -66,6 +66,10 @@ bool NetEvWait::is_asynchronous()
NexusSet*inputs = statement_->nex_input();
/* All the inputs of the statement must be accounted for in
the sensitivity list. Otherwise, there are inputs that can
change without the event being triggered, and that implies
a latch, not a combinational circuit. */
if (! sense->contains(*inputs)) {
delete sense;
delete inputs;
@@ -85,7 +89,7 @@ bool NetProc::is_asynchronous()
return false;
}
bool NetProcTop::is_asynchronous()
bool NetProcTop::is_asynchronous() const
{
if (type_ == NetProcTop::KINITIAL)
return false;
@@ -95,6 +99,12 @@ bool NetProcTop::is_asynchronous()
/*
* $Log: async.cc,v $
* Revision 1.7.2.2 2007/05/30 17:48:53 steve
* Support Latch synthesis (Alan Feldstein)
*
* Revision 1.7.2.1 2006/05/21 21:58:46 steve
* NetESignal input is only selected bits.
*
* Revision 1.7 2004/01/18 23:26:54 steve
* The is_combinational function really need not recurse.
*
+8
View File
@@ -70,6 +70,14 @@ warning.)
* Other Attributes
(* ivl_full_case *)
This attribute only has meaning when attached to case statements,
and only when doing synthesis. The statement means to ignore the
possibility that some cases are not defined. Presume that the
device really is fully specified and do not emit any warnings
about missing guards.
[ none defined yet ]
+2 -2
View File
@@ -7,9 +7,9 @@
# to just run this script to autoconf wherever needed.
#
echo "Autoconf in root..."
autoconf -f
autoconf
for dir in vpip vpi vvp tgt-vvp tgt-fpga tgt-stub libveriuser cadpli
for dir in vpip vpi vvp tgt-vvp tgt-edif tgt-fpga libveriuser cadpli
do
echo "Autoconf in $dir..."
( cd ./$dir ; autoconf -f --include=.. )
+7 -5
View File
@@ -16,7 +16,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.13 2007/02/06 05:07:31 steve Exp $"
#ident "$Id: Makefile.in,v 1.11.2.1 2005/02/23 18:40:23 steve Exp $"
#
#
SHELL = /bin/sh
@@ -35,6 +35,8 @@ includedir = $(prefix)/include
vpidir = @libdir@/ivl/@vpidir1@
strip_dynamic=@strip_dynamic@
CC = @CC@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
@@ -43,6 +45,7 @@ INSTALL_DATA = @INSTALL_DATA@
CPPFLAGS = @ident_support@ -I$(srcdir) -I$(srcdir)/.. -I.. @CPPFLAGS@ @DEFS@ @PICFLAG@
CFLAGS = -Wall @CFLAGS@
LDFLAGS = @LDFLAGS@
STRIP = @STRIP@
SHARED = @shared@
@@ -52,7 +55,7 @@ ifeq (@enable_vvp32@,yes)
vpidir32 = $(libdir)/ivl/@vpidir2@
ALL32 = all32
INSTALL32 = install32
UNINSTALL32 = uninstall32
UNINSTALL32 = uninistall32
include $(srcdir)/enable_vvp32.mk
endif
@@ -71,7 +74,7 @@ dep:
O = cadpli.o
SYSTEM_VPI_LDFLAGS = -L../vvp -lvpi
ifeq (@MING32@,yes)
ifeq (@WIN32@,yes)
SYSTEM_VPI_LDFLAGS += @EXTRALIBS@
endif
@@ -83,6 +86,7 @@ clean:
distclean: clean
rm -f Makefile config.status config.log config.cache
rm -rf autom4te.cache
install: all installdirs $(vpidir)/cadpli.vpl $(INSTALL32)
@@ -95,8 +99,6 @@ installdirs: ../mkinstalldirs
uninstall: $(UNINSTALL32)
rm -f $(vpidir)/cadpli.vpl
uninstall32:
ifeq (@enable_vvp32@,yes)
include $(srcdir)/enable_vvp32.mk
endif
+21 -44
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: compiler.h,v 1.33 2007/04/19 02:52:53 steve Exp $"
#ident "$Id: compiler.h,v 1.26.2.3 2006/06/12 00:16:50 steve Exp $"
#endif
# include <list>
@@ -32,8 +32,11 @@
*/
/* The integer_width is the width of integer variables. */
extern unsigned integer_width;
/* The INTEGER_WIDTH is the default width of integer variables, and
the presumed width of unsigned literal numbers. */
#ifndef INTEGER_WIDTH
# define INTEGER_WIDTH 32
#endif
/* The TIME_WIDTH is the width of time variables. */
#ifndef TIME_WIDTH
@@ -75,13 +78,17 @@ extern bool warn_timescale;
/* Warn about legal but questionable module port bindings. */
extern bool warn_portbinding;
/* Warn about unused or unassigned variables. */
extern bool warn_unused;
/* This is true if verbose output is requested. */
extern bool verbose_flag;
extern bool debug_scopes;
extern bool debug_eval_tree;
extern bool debug_elaborate;
extern bool debug_synth2;
extern bool debug_synth;
extern bool debug_cprop;
/* Path to a directory useful for finding subcomponents. */
extern const char*basedir;
@@ -91,46 +98,28 @@ 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. Then there are also more detailed controls for more
specific language features. */
support. */
enum generation_t {
GN_VER1995 = 1,
GN_VER2001 = 2,
GN_VER2001X = 3,
GN_SYSVER30 = 3,
GN_DEFAULT = 3
};
extern generation_t generation_flag;
extern bool gn_cadence_types_flag;
/* These functions test that specific features are enabled. */
inline bool gn_cadence_types_enabled()
{ return gn_cadence_types_flag && generation_flag==GN_VER2001X; }
/* If this flag is true, then elaborate specify blocks. If this flag
is false, then skip elaboration of specify behavior. */
extern bool gn_specify_blocks_flag;
/* This is the string to use to invoke the preprocessor. */
extern char*ivlpp_string;
extern map<perm_string,unsigned> missing_modules;
/* Files that are library files are in this map. The lexor compares
file names as it processes `line directives, and if the file name
matches an entry in this table, it will turn on the
library_active_flag so that modules know that they are in a
library. */
extern map<string,bool> library_file_map;
/*
* the lex_strings are perm_strings made up of tokens from the source
* file. Identifiers are so likely to be used many times that it makes
* much sense to use a StringHeapLex to hold them.
*/
extern StringHeapLex lex_strings;
extern StringHeap misc_strings;
/*
* system task/function listings.
@@ -142,7 +131,7 @@ extern StringHeap misc_strings;
*/
struct sfunc_return_type {
const char* name;
ivl_variable_type_t type;
NetExpr::TYPE type;
unsigned wid;
int signed_flag;
};
@@ -152,26 +141,14 @@ extern int load_sys_func_table(const char*path);
/*
* $Log: compiler.h,v $
* Revision 1.33 2007/04/19 02:52:53 steve
* Add support for -v flag in command file.
* Revision 1.26.2.3 2006/06/12 00:16:50 steve
* Add support for -Wunused warnings.
*
* Revision 1.32 2007/03/07 04:24:59 steve
* Make integer width controllable.
* Revision 1.26.2.2 2006/04/23 04:25:45 steve
* Add cprop debugging.
*
* Revision 1.31 2006/09/28 04:35:18 steve
* Support selective control of specify and xtypes features.
*
* Revision 1.30 2005/07/11 16:56:50 steve
* Remove NetVariable and ivl_variable_t structures.
*
* Revision 1.29 2005/07/07 16:22:49 steve
* Generalize signals to carry types.
*
* Revision 1.28 2005/06/28 04:25:55 steve
* Remove reference to SystemVerilog.
*
* Revision 1.27 2005/04/24 23:44:01 steve
* Update DFF support to new data flow.
* Revision 1.26.2.1 2006/04/01 01:37:24 steve
* Add synth debug flag
*
* Revision 1.26 2004/10/04 01:10:52 steve
* Clean up spurious trailing white space.
+1 -9
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: config.h.in,v 1.12 2007/02/02 04:33:00 steve Exp $"
#ident "$Id: config.h.in,v 1.11 2004/10/04 01:10:52 steve Exp $"
#endif
#if defined(__cplusplus)
@@ -37,7 +37,6 @@
# undef HAVE_TIMES
# undef HAVE_IOSFWD
# undef HAVE_GETOPT_H
# undef HAVE_INTTYPES_H
# undef HAVE_LIBIBERTY_H
# undef HAVE_MALLOC_H
# undef HAVE_DLFCN_H
@@ -49,15 +48,8 @@
# undef HAVE_SYS_WAIT_H
# undef WORDS_BIGENDIAN
#ifdef HAVE_INTTYPES_H
# include <inttypes.h>
#endif
/*
* $Log: config.h.in,v $
* Revision 1.12 2007/02/02 04:33:00 steve
* Use inttypes.h instead of stdint.h for portability.
*
* Revision 1.11 2004/10/04 01:10:52 steve
* Clean up spurious trailing white space.
*
+5 -3
View File
@@ -9,6 +9,9 @@ AC_PROG_CC
AC_PROG_CXX
AC_CHECK_TOOL(STRIP, strip, true)
AC_CHECK_PROGS(XGPERF,gperf,none)
AC_CHECK_PROGS(MAN,man,none)
AC_CHECK_PROGS(PS2PDF,ps2pdf,none)
if test "$XGPERF" = "none"
then
echo ""
@@ -141,7 +144,6 @@ AC_SUBST(vpidir1)
AC_SUBST(vpidir2)
AC_MSG_RESULT(${vpidir1} ${vpidir2})
# XXX disable tgt-fpga for the moment
AC_CONFIG_SUBDIRS(vvp vpi tgt-stub tgt-null tgt-vvp libveriuser cadpli)
AC_CONFIG_SUBDIRS(vvp vpi tgt-vvp tgt-edif tgt-fpga libveriuser cadpli)
AC_OUTPUT(Makefile ivlpp/Makefile driver/Makefile driver-vpi/Makefile tgt-null/Makefile tgt-verilog/Makefile tgt-pal/Makefile)
AC_OUTPUT(Makefile ivlpp/Makefile driver/Makefile driver-vpi/Makefile tgt-null/Makefile tgt-stub/Makefile tgt-verilog/Makefile tgt-pal/Makefile)
+509 -136
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2005 Stephen Williams ([email protected])
* Copyright (c) 1998-2006 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
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: cprop.cc,v 1.56 2007/03/07 00:38:15 steve Exp $"
#ident "$Id: cprop.cc,v 1.47.2.7 2007/02/26 19:51:38 steve Exp $"
#endif
# include "config.h"
@@ -25,6 +25,7 @@
# include "netlist.h"
# include "netmisc.h"
# include "functor.h"
# include "compiler.h"
# include <assert.h>
@@ -47,6 +48,9 @@ struct cprop_functor : public functor_t {
virtual void lpm_ff(Design*des, NetFF*obj);
virtual void lpm_logic(Design*des, NetLogic*obj);
virtual void lpm_mux(Design*des, NetMux*obj);
virtual void lpm_mux_large(Design*des, NetMux*obj);
virtual void lpm_ram_dq(Design*des, NetRamDq*obj);
bool lpm_ram_dq_const_address_(Design*des, NetRamDq*obj);
};
void cprop_functor::signal(Design*des, NetNet*obj)
@@ -55,6 +59,86 @@ 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(perm_string::literal("LPM_Direction")) != verinum("ADD"))
return;
// If the low bit on the A side is 0, then eliminate it from
// the adder, and pass the B side directly to the
// result. Don't reduce the adder smaller then a 1-bit
// adder. These will be eliminated later.
while ((obj->width() > 1)
&& 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);
//connect(tmp->pin_Aclr(), obj->pin_Aclr());
//connect(tmp->pin_Add_Sub(), obj->pin_Add_Sub());
//connect(tmp->pin_Clock(), obj->pin_Clock());
//connect(tmp->pin_Cin(), obj->pin_Cin());
connect(tmp->pin_Cout(), obj->pin_Cout());
//connect(tmp->pin_Overflow(), obj->pin_Overflow());
for (unsigned idx = 0 ; idx < tmp->width() ; idx += 1) {
connect(tmp->pin_DataA(idx), obj->pin_DataA(idx+1));
connect(tmp->pin_DataB(idx), obj->pin_DataB(idx+1));
connect(tmp->pin_Result(idx), obj->pin_Result(idx+1));
}
connect(obj->pin_Result(0), obj->pin_DataB(0));
delete obj;
des->add_node(tmp);
obj = tmp;
count += 1;
}
// Now do the same thing on the B side.
while ((obj->width() > 1)
&& 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);
//connect(tmp->pin_Aclr(), obj->pin_Aclr());
//connect(tmp->pin_Add_Sub(), obj->pin_Add_Sub());
//connect(tmp->pin_Clock(), obj->pin_Clock());
//connect(tmp->pin_Cin(), obj->pin_Cin());
connect(tmp->pin_Cout(), obj->pin_Cout());
//connect(tmp->pin_Overflow(), obj->pin_Overflow());
for (unsigned idx = 0 ; idx < tmp->width() ; idx += 1) {
connect(tmp->pin_DataA(idx), obj->pin_DataA(idx+1));
connect(tmp->pin_DataB(idx), obj->pin_DataB(idx+1));
connect(tmp->pin_Result(idx), obj->pin_Result(idx+1));
}
connect(obj->pin_Result(0), obj->pin_DataA(0));
delete obj;
des->add_node(tmp);
obj = tmp;
count += 1;
}
// If the adder is only 1 bit wide, then replace it with the
// simple logic gate.
if (obj->width() == 1) {
NetLogic*tmp;
if (obj->pin_Cout().is_linked()) {
tmp = new NetLogic(obj->scope(),
obj->scope()->local_symbol(),
3, NetLogic::AND);
connect(tmp->pin(0), obj->pin_Cout());
connect(tmp->pin(1), obj->pin_DataA(0));
connect(tmp->pin(2), obj->pin_DataB(0));
des->add_node(tmp);
}
tmp = new NetLogic(obj->scope(), obj->name(), 3, NetLogic::XOR);
connect(tmp->pin(0), obj->pin_Result(0));
connect(tmp->pin(1), obj->pin_DataA(0));
connect(tmp->pin(2), obj->pin_DataB(0));
delete obj;
des->add_node(tmp);
count += 1;
return;
}
}
void cprop_functor::lpm_compare(Design*des, NetCompare*obj)
@@ -73,8 +157,6 @@ void cprop_functor::lpm_compare(Design*des, NetCompare*obj)
void cprop_functor::lpm_compare_eq_(Design*des, NetCompare*obj)
{
#if 0
/* XXXX Need to reimplement this code to account for vectors. */
NetScope*scope = obj->scope();
unsigned const_count = 0;
@@ -170,7 +252,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::XNOR, 1);
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));
@@ -193,7 +275,6 @@ void cprop_functor::lpm_compare_eq_(Design*des, NetCompare*obj)
delete obj;
des->add_node(tmp);
count += 1;
#endif
}
void cprop_functor::lpm_ff(Design*des, NetFF*obj)
@@ -201,30 +282,63 @@ void cprop_functor::lpm_ff(Design*des, NetFF*obj)
// Look for and count unlinked FF outputs. Note that if the
// Data and Q pins are connected together, they can be removed
// from the circuit, since it doesn't do anything.
unsigned unlinked_count = 0;
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) {
if (connected(obj->pin_Data(idx), obj->pin_Q(idx))
&& (! obj->pin_Sclr().is_linked())
&& (! obj->pin_Sset().is_linked())
&& (! obj->pin_Aclr().is_linked())
&& (! obj->pin_Aset().is_linked())) {
obj->pin_Data(idx).unlink();
obj->pin_Q(idx).unlink();
}
if (! obj->pin_Q(idx).is_linked())
unlinked_count += 1;
}
if (connected(obj->pin_Data(), obj->pin_Q())
&& (! obj->pin_Sclr().is_linked())
&& (! obj->pin_Sset().is_linked())
&& (! obj->pin_Aclr().is_linked())
&& (! obj->pin_Aset().is_linked())) {
obj->pin_Data().unlink();
obj->pin_Q().unlink();
// If the entire FF is unlinked, remove the whole thing.
if (unlinked_count == obj->width()) {
delete obj;
count += 1;
return;
}
// If some of the FFs are unconnected, make a new FF array
// that does not include the useless FF devices.
if (unlinked_count > 0) {
NetFF*tmp = new NetFF(obj->scope(), obj->name(),
obj->width()-unlinked_count);
connect(tmp->pin_Clock(), obj->pin_Clock());
connect(tmp->pin_Enable(), obj->pin_Enable());
connect(tmp->pin_Aload(), obj->pin_Aload());
connect(tmp->pin_Aset(), obj->pin_Aset());
connect(tmp->pin_Aclr(), obj->pin_Aclr());
connect(tmp->pin_Sload(), obj->pin_Sload());
connect(tmp->pin_Sset(), obj->pin_Sset());
connect(tmp->pin_Sclr(), obj->pin_Sclr());
unsigned tidx = 0;
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1)
if (obj->pin_Q(idx).is_linked()) {
connect(tmp->pin_Data(tidx), obj->pin_Data(idx));
connect(tmp->pin_Q(tidx), obj->pin_Q(idx));
tidx += 1;
}
assert(tidx == obj->width() - unlinked_count);
delete obj;
des->add_node(tmp);
count += 1;
return;
}
}
void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
{
#if 0
NetScope*scope = obj->scope();
#endif
switch (obj->type()) {
#if 0
/* XXXX This old code assumed that the individual bit
slices could be replaced with different gates. They
cannot when the device takes atomic vectors, so this
needs to be rewritten. XXXX */
case NetLogic::NAND:
case NetLogic::AND: {
unsigned top = obj->pin_count();
@@ -339,12 +453,12 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
case NetLogic::AND:
tmp = new NetLogic(scope,
obj->name(), 2,
NetLogic::BUF, 1);
NetLogic::BUF);
break;
case NetLogic::NAND:
tmp = new NetLogic(scope,
obj->name(), 2,
NetLogic::NOT, 1);
NetLogic::NOT);
break;
default:
assert(0);
@@ -370,7 +484,7 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
if (top < obj->pin_count()) {
NetLogic*tmp = new NetLogic(scope,
obj->name(), top,
obj->type(), 1);
obj->type());
tmp->rise_time(obj->rise_time());
tmp->fall_time(obj->fall_time());
tmp->decay_time(obj->decay_time());
@@ -387,12 +501,7 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
}
break;
}
#endif
#if 0
/* XXXX This old code assumed that the individual bit
slices could be replaced with different gates. They
cannot when the device takes atomic vectors, so this
needs to be rewritten. XXXX */
case NetLogic::NOR:
case NetLogic::OR: {
@@ -492,12 +601,12 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
case NetLogic::OR:
tmp = new NetLogic(scope,
obj->name(), 2,
NetLogic::BUF, 1);
NetLogic::BUF);
break;
case NetLogic::NOR:
tmp = new NetLogic(scope,
obj->name(), 2,
NetLogic::NOT, 1);
NetLogic::NOT);
break;
default:
assert(0);
@@ -514,7 +623,7 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
delete obj;
count += 1;
return;
v }
}
/* Finally, this cleans up the gate by creating a
new [N]OR gate that has the right number of
@@ -522,7 +631,7 @@ v }
if (top < obj->pin_count()) {
NetLogic*tmp = new NetLogic(scope,
obj->name(), top,
obj->type(), 1);
obj->type());
tmp->rise_time(obj->rise_time());
tmp->fall_time(obj->fall_time());
tmp->decay_time(obj->decay_time());
@@ -539,12 +648,7 @@ v }
}
break;
}
#endif
#if 0
/* XXXX This old code assumed that the individual bit
slices could be replaced with different gates. They
cannot when the device takes atomic vectors, so this
needs to be rewritten. XXXX */
case NetLogic::XNOR:
case NetLogic::XOR: {
unsigned top = obj->pin_count();
@@ -666,11 +770,11 @@ v }
if (obj->type() == NetLogic::XOR)
tmp = new NetLogic(scope,
obj->name(), 2,
NetLogic::NOT, 1);
NetLogic::NOT);
else
tmp = new NetLogic(scope,
obj->name(), 2,
NetLogic::BUF, 1);
NetLogic::BUF);
tmp->rise_time(obj->rise_time());
tmp->fall_time(obj->fall_time());
@@ -695,11 +799,11 @@ v }
if (obj->type() == NetLogic::XOR)
tmp = new NetLogic(scope,
obj->name(), 2,
NetLogic::BUF, 1);
NetLogic::BUF);
else
tmp = new NetLogic(scope,
obj->name(), 2,
NetLogic::NOT, 1);
NetLogic::NOT);
tmp->rise_time(obj->rise_time());
tmp->fall_time(obj->fall_time());
@@ -721,7 +825,7 @@ v }
if (top < obj->pin_count()) {
NetLogic*tmp = new NetLogic(scope,
obj->name(), top,
obj->type(), 1);
obj->type());
des->add_node(tmp);
tmp->pin(0).drive0(obj->pin(0).drive0());
tmp->pin(0).drive1(obj->pin(0).drive1());
@@ -734,54 +838,12 @@ v }
}
break;
}
#endif
default:
break;
}
}
static void replace_with_bufif(Design*des, NetMux*obj, NetLogic::TYPE type)
{
NetScope*scope = obj->scope();
NetLogic*tmp = new NetLogic(obj->scope(),
scope->local_symbol(),
3, type, obj->width());
des->add_node(tmp);
connect(obj->pin_Result(), tmp->pin(0));
connect(obj->pin_Data(type==NetLogic::BUFIF0? 0 : 1), tmp->pin(1));
if (obj->width() == 1) {
/* Special case that the expression is 1 bit
wide. Connect the select directly to the enable. */
connect(obj->pin_Sel(), tmp->pin(2));
} else {
/* General case that the expression is arbitrarily
wide. Replicate the enable signal (which we
assume is 1 bit wide) to match the expression,
and connect the enable vector to the enable
input of the gate. */
NetReplicate*rtmp = new NetReplicate(scope,
scope->local_symbol(),
obj->width(),
obj->width());
des->add_node(rtmp);
connect(obj->pin_Sel(), rtmp->pin(1));
connect(tmp->pin(2), rtmp->pin(0));
NetNet*rsig = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, obj->width());
rsig->local_flag(true);
rsig->data_type(IVL_VT_LOGIC);
connect(tmp->pin(2), rsig->pin(0));
}
delete obj;
}
/*
* This detects the case where the mux selects between a value and
* Vz. In this case, replace the device with a bufif with the sel
@@ -789,49 +851,373 @@ static void replace_with_bufif(Design*des, NetMux*obj, NetLogic::TYPE type)
*/
void cprop_functor::lpm_mux(Design*des, NetMux*obj)
{
if (obj->size() > 2) {
lpm_mux_large(des, obj);
return;
}
if (obj->size() != 2)
return;
if (obj->sel_width() != 1)
return;
/* If the first input is all constant Vz, then replace the
NetMux with an array of BUFIF1 devices, with the enable
connected to the select input. */
NetScope*scope = obj->scope();
bool flag = true;
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) {
bool cflag_a = obj->pin_Data(idx, 0).nexus()->drivers_constant();
bool cflag_b = obj->pin_Data(idx, 1).nexus()->drivers_constant();
if (! obj->pin_Data(0).nexus()->drivers_constant()) {
/* If both data inputs are constant, we'll be able to do
a substitution. */
if (cflag_a && cflag_b)
continue;
verinum::V va = cflag_a
? obj->pin_Data(idx, 0).nexus()->driven_value()
: verinum::Vx;
verinum::V vb = cflag_b
? obj->pin_Data(idx, 1).nexus()->driven_value()
: verinum::Vx;
/* If only one Data input is constant, but a constant
HiZ, then we will be able to to a bufif
substitution. */
if (cflag_a && va==verinum::Vz)
continue;
if (cflag_b && vb==verinum::Vz)
continue;
/* Otherwise, we cannot accurately do a substitution. If
one input is non-constant, then that input may have a
HiZ value, and there is no Verilog logic other then a
MUX that can pass a HiZ value. */
flag = false;
}
if (flag && obj->pin_Data(0).nexus()->driven_value() != verinum::Vz) {
flag = false;
}
if (flag) {
replace_with_bufif(des, obj, NetLogic::BUFIF1);
count += 1;
if (! flag) {
return;
}
/* Create a temporary net to hold the result value that we
build up. When we are done, we will connect this to the
Result pins of the mux, then delete the mux *and* this
net. That will cause all the proper connectivity to
happen. */
NetNet result_tmp(scope, scope->local_symbol(),
NetNet::WIRE, obj->width());
/* We know that every slice has at least one constant. Run
through the slices again, creating boolean devices to
replace the MUX slice. */
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) {
/* If the Sel==0 input is constant Z, make a bufif1. */
if (obj->pin_Data(idx, 0).nexus()->drivers_constant()
&& obj->pin_Data(idx, 0).nexus()->driven_value()==verinum::Vz) {
NetLogic*tmp = new NetLogic(scope,
scope->local_symbol(),
3, NetLogic::BUFIF1);
connect(result_tmp.pin(idx), tmp->pin(0));
connect(obj->pin_Data(idx,1), tmp->pin(1));
connect(obj->pin_Sel(0), tmp->pin(2));
des->add_node(tmp);
continue;
}
/* If the Sel==1 input is constant Z, make a bufif0. */
if (obj->pin_Data(idx, 1).nexus()->drivers_constant()
&& obj->pin_Data(idx, 1).nexus()->driven_value()==verinum::Vz) {
NetLogic*tmp = new NetLogic(scope,
scope->local_symbol(),
3, NetLogic::BUFIF0);
connect(result_tmp.pin(idx), tmp->pin(0));
connect(obj->pin_Data(idx,0), tmp->pin(1));
connect(obj->pin_Sel(0), tmp->pin(2));
des->add_node(tmp);
continue;
}
/* At this point, the only cases that are left are where
the data inputs are both constant, and neither are
HiZ. From this we know how to generate the output
from only the S input. */
if (! (obj->pin_Data(idx, 0).nexus()->drivers_constant()
&& obj->pin_Data(idx, 1).nexus()->drivers_constant())) {
cerr << obj->get_line() << ": internal error: "
<< "Drivers not constant where expected?"
<< " obj->width()=" << obj->width()
<< " idx=" << idx
<< endl;
obj->dump_node(cerr, 4);
}
assert(obj->pin_Data(idx, 0).nexus()->drivers_constant()
&& obj->pin_Data(idx, 1).nexus()->drivers_constant());
verinum::V a = obj->pin_Data(idx, 0).nexus()->driven_value();
verinum::V b = obj->pin_Data(idx, 1).nexus()->driven_value();
if (a == b) {
connect(result_tmp.pin(idx), obj->pin_Data(idx,0));
continue;
}
if (a == verinum::V0 && b == verinum::V1) {
connect(result_tmp.pin(idx), obj->pin_Sel(0));
continue;
}
if (a == verinum::V1 && b == verinum::V0) {
NetLogic*tmp = new NetLogic(scope,
scope->local_symbol(),
2, NetLogic::NOT);
connect(result_tmp.pin(idx), tmp->pin(0));
connect(obj->pin_Sel(0), tmp->pin(1));
des->add_node(tmp);
continue;
}
/* A==0: Q = B & S */
if (a == verinum::V0) {
NetLogic*tmp = new NetLogic(scope,
scope->local_symbol(),
3, NetLogic::AND);
connect(result_tmp.pin(idx), tmp->pin(0));
connect(obj->pin_Data(idx,1), tmp->pin(1));
connect(obj->pin_Sel(0), tmp->pin(2));
des->add_node(tmp);
continue;
}
/* B==1: Q = A | S */
if (b == verinum::V1) {
NetLogic*tmp = new NetLogic(scope,
scope->local_symbol(),
3, NetLogic::OR);
connect(result_tmp.pin(idx), tmp->pin(0));
connect(obj->pin_Data(idx,0), tmp->pin(1));
connect(obj->pin_Sel(0), tmp->pin(2));
des->add_node(tmp);
continue;
}
/* A==1: Q = B | ~S */
if (a == verinum::V1) {
NetLogic*inv = new NetLogic(scope,
scope->local_symbol(),
2, NetLogic::NOT);
NetNet*invs = new NetNet(scope,
scope->local_symbol(),
NetNet::TRI, 1);
invs->local_flag(true);
connect(inv->pin(0), invs->pin(0));
connect(inv->pin(1), obj->pin_Sel(0));
des->add_node(inv);
NetLogic*tmp = new NetLogic(scope,
scope->local_symbol(),
3, NetLogic::OR);
connect(result_tmp.pin(idx), tmp->pin(0));
connect(obj->pin_Data(idx,1), tmp->pin(1));
connect(inv->pin(0), tmp->pin(2));
des->add_node(tmp);
continue;
}
/* B==0: Q = A & ~S */
if (b == verinum::V0) {
NetLogic*inv = new NetLogic(scope,
scope->local_symbol(),
2, NetLogic::NOT);
NetNet*invs = new NetNet(scope,
scope->local_symbol(),
NetNet::TRI, 1);
invs->local_flag(true);
connect(inv->pin(0), invs->pin(0));
connect(inv->pin(1), obj->pin_Sel(0));
des->add_node(inv);
NetLogic*tmp = new NetLogic(scope,
scope->local_symbol(),
3, NetLogic::AND);
connect(result_tmp.pin(idx), tmp->pin(0));
connect(obj->pin_Data(idx,0), tmp->pin(1));
connect(inv->pin(0), tmp->pin(2));
des->add_node(tmp);
continue;
}
assert(0);
/* If instead the second input is all constant Vz, replace the
NetMux with an array of BUFIF0 devices. */
flag = true;
if (! obj->pin_Data(1).nexus()->drivers_constant()) {
flag = false;
}
if (flag && obj->pin_Data(1).nexus()->driven_value() != verinum::Vz) {
flag = false;
}
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1)
connect(result_tmp.pin(idx), obj->pin_Result(idx));
if (flag) {
replace_with_bufif(des, obj, NetLogic::BUFIF0);
count += 1;
return;
}
delete obj;
count += 1;
}
void cprop_functor::lpm_mux_large(Design*des, NetMux*obj)
{
NetScope*scope = obj->scope();
unsigned width = obj->width();
unsigned size = obj->size();
/* This test looks for bit slices that are constant
throughout. If we find any, we can reduce the width of the
MUX to eliminate the fixed value. */
/* After the following for loop, this array of bools will
contain "true" for each bit slice that is constant and
identical, and "false" otherwise. The reduce_width will
count the number of true entries in the flags array. */
bool*flags = new bool[width];
unsigned reduce_width = 0;
for (unsigned bit = 0 ; bit < width ; bit += 1) {
flags[bit] = true;
/* If not even the first selection is constant, then the
slice cannot be reduced. */
if (! obj->pin_Data(bit, 0).nexus()->drivers_constant()) {
flags[bit] = false;
continue;
}
/* If any of the remaining selections in non-consant, or
constant with a different value, then this slice
cannot be reduced. */
verinum::V val = obj->pin_Data(bit, 0).nexus()->driven_value();
for (unsigned idx = 1; flags[bit] && idx < size ; idx += 1) {
if (!obj->pin_Data(bit,idx).nexus()->drivers_constant()) {
flags[bit] = false;
break;
}
if (val != obj->pin_Data(bit,idx).nexus()->driven_value()) {
flags[bit] = false;
break;
}
}
if (! flags[bit]) {
/* This bit slice is too complex. Go on. */
continue;
}
reduce_width += 1;
}
/* If no slices can be reduced, then we are finished. */
if (reduce_width == 0) {
delete[]flags;
return;
}
/* Handle the very special case that all the slices can be
reduced. We don't need a MUX at all! */
if (reduce_width == width) {
for (unsigned idx = 0 ; idx < width ; idx += 1)
connect(obj->pin_Result(idx), obj->pin_Data(idx,0));
delete obj;
count += 1;
delete[]flags;
return;
}
/* Create a reduced mux with the same name and size, but fewer
slices. Connect all the slices that we are keeping. */
NetMux*tmp = new NetMux(scope, obj->name(),
width-reduce_width, size, obj->sel_width());
tmp->set_line(*obj);
for (unsigned idx = 0 ; idx < obj->sel_width() ; idx += 1)
connect(obj->pin_Sel(idx), tmp->pin_Sel(idx));
unsigned dst_bit = 0;
for (unsigned bit = 0 ; bit < width ; bit += 1) {
if (flags[bit]) {
connect(obj->pin_Result(bit), obj->pin_Data(bit,0));
continue;
}
connect(obj->pin_Result(bit), tmp->pin_Result(dst_bit));
for (unsigned idx = 0 ; idx < size ; idx += 1)
connect(obj->pin_Data(bit,idx), tmp->pin_Data(dst_bit,idx));
dst_bit += 1;
}
/* Add the new node. Delete the old node. Signal that we
change the design and may use a rescan. */
des->add_node(tmp);
delete obj;
delete[]flags;
count += 1;
}
void cprop_functor::lpm_ram_dq(Design*des, NetRamDq*obj)
{
if (lpm_ram_dq_const_address_(des,obj))
return;
}
/*
* Try to evaluate a constant address input. If we find it, then
* replace the NetRamDq with a direct link to the addressed word.
*/
bool cprop_functor::lpm_ram_dq_const_address_(Design*des, NetRamDq*obj)
{
NetMemory*mem = obj->mem();
NetNet* reg = mem->reg_from_explode();
/* I only know how to do this on exploded memories. */
if (reg == 0)
return false;
verinum sel (0UL, obj->awidth());
for (unsigned idx = 0 ; idx < obj->awidth() ; idx += 1) {
if (! obj->pin_Address(idx).nexus()->drivers_constant())
return false;
sel.set(idx, obj->pin_Address(idx).nexus()->driven_value());
}
unsigned long address = sel.as_ulong();
/* If the address is outside the ram, then leave this to the
code generator to figure out. */
if (address >= obj->size())
return false;
unsigned base = address * obj->width();
assert(base+obj->width() <= reg->pin_count());
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1)
connect(reg->pin(base+idx), obj->pin_Q(idx));
if (debug_cprop) {
cerr << obj->get_line() << ": debug: Replace read port with"
<< " fixed link to word " << address << "." << endl;
}
delete obj;
count += 1;
return true;
}
/*
* This functor looks to see if the constant is connected to nothing
* but signals. If that is the case, delete the dangling constant and
@@ -950,36 +1336,23 @@ void cprop(Design*des)
/*
* $Log: cprop.cc,v $
* Revision 1.56 2007/03/07 00:38:15 steve
* Lint fixes.
* Revision 1.47.2.7 2007/02/26 19:51:38 steve
* Spelling fixes (larry doolittle)
*
* Revision 1.55 2006/05/24 04:32:57 steve
* Fix handling of ternary-to-bufif0 constant propagation.
* Revision 1.47.2.6 2006/11/12 01:20:45 steve
* Prevent constant mux outputs from confusing itself.
*
* Revision 1.54 2005/07/15 19:22:52 steve
* bufif enable is LOGIC.
* Revision 1.47.2.5 2006/04/23 04:26:13 steve
* Constant propagate addresses through NetRamDq read ports.
*
* Revision 1.53 2005/05/15 04:44:30 steve
* Disable obsolete logic constant fixup code.
* Revision 1.47.2.4 2005/09/11 02:50:51 steve
* Fix overly agressive constant propagation through MUX causing lost Z bits.
*
* Revision 1.52 2005/04/24 23:44:01 steve
* Update DFF support to new data flow.
* Revision 1.47.2.3 2005/08/28 22:00:39 steve
* Reduce mux slices that are constant throughout range.
*
* Revision 1.51 2005/02/12 22:52:45 steve
* Fix copyright notice.
*
* Revision 1.50 2005/02/12 06:25:40 steve
* Restructure NetMux devices to pass vectors.
* Generate NetMux devices from ternary expressions,
* Reduce NetMux devices to bufif when appropriate.
*
* Revision 1.49 2005/01/16 04:20:32 steve
* Implement LPM_COMPARE nodes as two-input vector functors.
*
* Revision 1.48 2004/12/11 02:31:25 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
* Revision 1.47.2.2 2005/08/28 19:51:02 steve
* More thorough constant propagation through MUX devices.
*
* Revision 1.47 2004/02/20 18:53:34 steve
* Addtrbute keys are perm_strings.
+185 -351
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: design_dump.cc,v 1.176 2007/06/02 03:42:12 steve Exp $"
#ident "$Id: design_dump.cc,v 1.149.2.7 2006/08/23 04:09:14 steve Exp $"
#endif
# include "config.h"
@@ -29,8 +29,7 @@
# include <iostream>
# include <iomanip>
# include "netlist.h"
# include "compiler.h"
# include "ivl_assert.h"
static ostream& operator<< (ostream&o, NetBlock::Type t)
{
@@ -69,77 +68,13 @@ ostream& operator << (ostream&o, Link::strength_t str)
return o;
}
ostream& operator << (ostream&o, ivl_variable_type_t val)
{
switch (val) {
case IVL_VT_VOID:
o << "void";
break;
case IVL_VT_NO_TYPE:
o << "<no_type>";
break;
case IVL_VT_REAL:
o << "real";
break;
case IVL_VT_BOOL:
o << "bool";
break;
case IVL_VT_LOGIC:
o << "logic";
break;
}
return o;
}
static inline void dump_scope_path(ostream&o, const NetScope*scope)
{
if (const NetScope*parent = scope->parent()) {
dump_scope_path(o, parent);
o << ".";
}
const hname_t name = scope->fullname();
o << name.peek_name();
if (name.has_number())
o << "[" << name.peek_number() << "]";
}
ostream& operator <<(ostream&o, struct __ScopePathManip marg)
{
if (marg.scope != 0)
dump_scope_path(o, marg.scope);
return o;
}
void NetDelaySrc::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "specify delay";
if (posedge_) o << " posedge";
if (negedge_) o << " negedge";
o << " src "
<< "(" << transition_delays_[IVL_PE_01]
<< "," << transition_delays_[IVL_PE_10]
<< "," << transition_delays_[IVL_PE_0z]
<< "/" << transition_delays_[IVL_PE_z1]
<< "," << transition_delays_[IVL_PE_1z]
<< "," << transition_delays_[IVL_PE_z0]
<< "/" << transition_delays_[IVL_PE_0x]
<< "," << transition_delays_[IVL_PE_x1]
<< "," << transition_delays_[IVL_PE_1x]
<< "/" << transition_delays_[IVL_PE_x0]
<< "," << transition_delays_[IVL_PE_xz]
<< "," << transition_delays_[IVL_PE_zx]
<< "): " << endl;
dump_node_pins(o, ind+4);
}
/* Dump a net. This can be a wire or register. */
void NetNet::dump_net(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << type() << ": " << name()
<< "[" << s0_ << ":" << e0_ << " count=" << pin_count() << "]";
o << setw(ind) << "" << type() << ": " << name() << "[" <<
pin_count() << "]";
if (local_flag_)
o << " (local)";
o << " " << data_type_;
if (signed_)
o << " signed";
switch (port_type_) {
@@ -160,11 +95,9 @@ void NetNet::dump_net(ostream&o, unsigned ind) const
}
o << " (eref=" << peek_eref() << ", lref=" << peek_lref() << ")";
if (scope())
o << " scope=" << scope_path(scope());
o << " #(" << rise_time() << "," << fall_time() << ","
<< decay_time() << ") vector_width=" << vector_width()
<< " pin_count=" << pin_count()
<< " init=";
o << " scope=" << scope()->name();
o << " #(" << rise_time() << "," << fall_time() << "," <<
decay_time() << ") init=";
for (unsigned idx = pin_count() ; idx > 0 ; idx -= 1)
o << pin(idx-1).get_init();
@@ -181,15 +114,23 @@ void NetNet::dump_net(ostream&o, unsigned ind) const
o << setw(ind+4) << "" << "[" << idx << "]: " << nex
<< " " << nex->name() << endl;
}
for (unsigned idx = 0 ; idx < delay_paths_.size() ; idx += 1) {
const NetDelaySrc*cur = delay_paths_[idx];
cur->dump(o, ind+4);
}
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_ << "] " <<
"[" << idxh_ << ":" << idxl_ << "]" << endl;
}
/* Dump a NetNode and its pins. Dump what I know about the netnode on
the first line, then list all the pins, with the name of the
connected signal. */
@@ -230,7 +171,8 @@ void NetObj::dump_node_pins(ostream&o, unsigned ind) const
if (pin(idx).is_linked()) {
const Nexus*nex = pin(idx).nexus();
o << nex << " " << nex->name();
const char*nex_name = nex->name();
o << nex << " " << (nex_name? nex_name : "????");
}
o << endl;
@@ -248,20 +190,16 @@ void NetObj::dump_obj_attr(ostream&o, unsigned ind) const
void NetAddSub::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "Adder (NetAddSub): " << name()
<< " width=" << width() << " pin_count=" << pin_count()
<< endl;
o << setw(ind) << "" << "Adder (NetAddSub): " << name() << endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
void NetArrayDq::dump_node(ostream&o, unsigned ind) const
void NetCAssign::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "NetArrayDq: " << name()
<< " array=" << mem_->name()
<< endl;
o << setw(ind) << "" << "Procedural continuous assign (NetCAssign): "
<< name() << endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
void NetCLShift::dump_node(ostream&o, unsigned ind) const
@@ -279,12 +217,19 @@ void NetCompare::dump_node(ostream&o, unsigned ind) const
dump_obj_attr(o, ind+4);
}
void NetConcat::dump_node(ostream&o, unsigned ind) const
void NetDecode::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "NetConcat: "
<< name()
<< " scope=" << scope_path(scope())
<< " width=" << width_ << endl;
o << setw(ind) << "" << "LPM_DECODE (NetDecode): " << name()
<< " ff=" << ff_->name() << ", word width=" << width() << endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
void NetDemux::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "LPM_DEMUX (NetDemux): " << name()
<< " bus width=" << width() << ", address width=" << awidth()
<< ", word count=" << size() << endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
@@ -296,6 +241,12 @@ void NetDivide::dump_node(ostream&o, unsigned ind) const
dump_obj_attr(o, ind+4);
}
void NetForce::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "force " << lval_->name() << endl;
dump_node_pins(o, ind+4);
}
void NetMult::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "LPM_MULT (NetMult): " << name() << endl;
@@ -306,8 +257,8 @@ void NetMult::dump_node(ostream&o, unsigned ind) const
void NetMux::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "Multiplexer (NetMux): " << name()
<< " width=" << width_ << " swidth=" << swidth_ << " size=" << size_
<< " scope=" << scope_path(scope()) << endl;
<< " scope=" << scope()->name() << endl;
o << setw(ind+6) << "" << "source=" << get_line() << endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
@@ -315,26 +266,22 @@ void NetMux::dump_node(ostream&o, unsigned ind) const
void NetBUFZ::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "NetBUFZ: " << name()
<< " scope=" << scope_path(scope())
<< " scope=" << (scope()? scope()->name() : "")
<< " delay=(" << rise_time() << "," << fall_time() << "," <<
decay_time() << ") width=" << width() << endl;
decay_time() << ")" << endl;
dump_node_pins(o, ind+4);
}
void NetCaseCmp::dump_node(ostream&o, unsigned ind) const
{
if (eeq_)
o << setw(ind) << "" << "case compare === : " << name() << endl;
else
o << setw(ind) << "" << "case compare !== : " << name() << endl;
o << setw(ind) << "" << "case compare === : " << name() << endl;
dump_node_pins(o, ind+4);
}
void NetConst::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "constant " << width_ << "'b";
for (unsigned idx = width_ ; idx > 0 ; idx -= 1)
o << setw(ind) << "" << "constant ";
for (unsigned idx = pin_count() ; idx > 0 ; idx -= 1)
o << value_[idx-1];
o << ": " << name() << endl;
dump_node_pins(o, ind+4);
@@ -343,20 +290,18 @@ void NetConst::dump_node(ostream&o, unsigned ind) const
void NetFF::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "LPM_FF: " << name()
<< " scope=" << scope_path(scope())
<< " aset_value=" << aset_value_ << endl;
<< " scope=" << (scope()? scope()->name() : "")
<< " aset_value=" << aset_value_
<< " sset_value=" << sset_value_;
if (demux_) o << " demux=" << demux_->name();
o << endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
void NetLiteral::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "constant real " << real_
<< ": " << name() << endl;
dump_node_pins(o, ind+4);
}
void NetLogic::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "logic: ";
@@ -418,7 +363,7 @@ void NetLogic::dump_node(ostream&o, unsigned ind) const
}
o << " #(" << rise_time()
<< "," << fall_time() << "," << decay_time() << ") " << name()
<< " scope=" << scope_path(scope())
<< " scope=" << (scope()? scope()->name() : "")
<< endl;
dump_node_pins(o, ind+4);
@@ -432,88 +377,25 @@ void NetModulo::dump_node(ostream&o, unsigned ind) const
dump_obj_attr(o, ind+4);
}
void NetPartSelect::dump_node(ostream&o, unsigned ind) const
void NetRamDq::dump_node(ostream&o, unsigned ind) const
{
const char*pt = "";
switch (dir_) {
case VP:
pt = "VP";
break;
case PV:
pt = "PV";
break;
case BI:
pt = "BI";
break;
}
o << setw(ind) << "" << "NetPartSelect(" << pt << "): "
<< name() << " off=" << off_ << " wid=" << wid_ <<endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
o << setw(ind) << "" << "LPM_RAM_DQ (";
void NetReplicate::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "NetReplicate: "
<< name() << " wid=" << width_ << ", repeat_=" << repeat_
<< ", input wid=" << width_/repeat_ << endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
if (mem_)
if (NetNet*tmp = mem_->reg_from_explode())
o << "exploded mem=" << tmp->name();
else
o << "mem=" << mem_->name();
void NetSignExtend::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "NetSignExtend: "
<< name() << " output width=" << width_ << endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
o << "): " << name() << endl;
void NetUReduce::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "reduction logic: ";
switch (type_) {
case NONE:
o << "NONE";
break;
case AND:
o << "and";
break;
case OR:
o << "or";
break;
case XOR:
o << "xor";
break;
case NAND:
o << "nand";
break;
case NOR:
o << "nor";
break;
case XNOR:
o << "xnor";
break;
}
o << " #(" << rise_time()
<< "," << fall_time() << "," << decay_time() << ") " << name()
<< " scope=" << scope_path(scope())
<< endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
void NetSysFunc::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << def_->name << "(...)" << endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
void NetUserFunc::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << scope_path(def_) << "(";
o << setw(ind) << "" << def_->name() << "(";
o << ")" << endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
@@ -521,7 +403,7 @@ void NetUserFunc::dump_node(ostream&o, unsigned ind) const
void NetTaskDef::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "task " << scope_path(scope_) << ";" << endl;
o << setw(ind) << "" << "task " << name_ << ";" << endl;
for (unsigned idx = 0 ; idx < ports_.count() ; idx += 1) {
o << setw(ind+4) << "";
@@ -563,11 +445,11 @@ void NetProcTop::dump(ostream&o, unsigned ind) const
switch (type_) {
case NetProcTop::KINITIAL:
o << "initial /* " << get_line() << " in "
<< scope_path(scope_) << " */" << endl;
<< scope_->name() << " */" << endl;
break;
case NetProcTop::KALWAYS:
o << "always /* " << get_line() << " in "
<< scope_path(scope_) << " */" << endl;
<< scope_->name() << " */" << endl;
break;
}
@@ -583,12 +465,22 @@ void NetAssign_::dump_lval(ostream&o) const
{
if (sig_) {
o << sig_->name();
if (word_) {
o << "[word=" << *word_ << "]";
}
if (base_) {
o << "[" << *base_ << " +: " << lwid_ << "]";
if (bmux_) {
o << "[" << *bmux_ << "]";
} 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 if (var_) {
o << "<real " << var_->basename() << ">";
} else {
o << "";
}
@@ -614,10 +506,10 @@ void NetAssign::dump(ostream&o, unsigned ind) const
dump_lval(o);
o << " = ";
if (const NetExpr*de = get_delay())
o << "#(" << *de << ") ";
#if 0
if (l_val(0)->rise_time())
o << "#" << l_val(0)->rise_time() << " ";
#endif
o << *rval() << ";" << endl;
}
@@ -627,10 +519,10 @@ void NetAssignNB::dump(ostream&o, unsigned ind) const
dump_lval(o);
o << " <= ";
if (const NetExpr*de = get_delay())
o << "#(" << *de << ") ";
#if 0
if (l_val(0)->rise_time())
o << "#" << l_val(0)->rise_time() << " ";
#endif
o << *rval() << ";" << endl;
}
@@ -649,7 +541,7 @@ void NetBlock::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << type_;
if (subscope_)
o << " : " << scope_path(subscope_);
o << " : " << subscope_->name();
o << endl;
if (last_) {
@@ -677,6 +569,8 @@ void NetCase::dump(ostream&o, unsigned ind) const
break;
}
dump_proc_attr(o, ind+2);
for (unsigned idx = 0 ; idx < nitems_ ; idx += 1) {
o << setw(ind+2) << "";
if (items_[idx].guard)
@@ -697,9 +591,8 @@ void NetCase::dump(ostream&o, unsigned ind) const
void NetCAssign::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "cassign ";
dump_lval(o);
o << " = " << *rval() << "; /* " << get_line() << " */" << endl;
o << setw(ind) << "" << "cassign " << lval_->name() << " = "
<< name() << ";" << endl;
}
void NetCondit::dump(ostream&o, unsigned ind) const
@@ -719,14 +612,13 @@ void NetCondit::dump(ostream&o, unsigned ind) const
void NetDeassign::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "deassign ";
dump_lval(o);
o << "; /* " << get_line() << " */" << endl;
o << setw(ind) << "" << "deassign " << lval_->name() << "; "
<< "/* " << get_line() << " */" << endl;
}
void NetDisable::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "disable " << scope_path(target_) << "; "
o << setw(ind) << "" << "disable " << target_->name() << "; "
<< "/* " << get_line() << " */" << endl;
}
@@ -745,7 +637,7 @@ void NetEvProbe::dump_node(ostream&o, unsigned ind) const
o << "negedge ";
break;
}
o << setw(ind) << "" << "-> " << event_->name() << "; " << endl;
o << setw(ind) << "" << "-> " << event_->full_name() << "; " << endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
@@ -758,13 +650,11 @@ void NetEvTrig::dump(ostream&o, unsigned ind) const
void NetEvWait::dump(ostream&o, unsigned ind) const
{
o << setw(ind) <<"" << "@(";
if (nevents() > 0)
o << event(0)->name();
assert(nevents() > 0);
o << setw(ind) <<"" << "@(" << event(0)->full_name();
for (unsigned idx = 1 ; idx < nevents() ; idx += 1)
o << " or " << event(idx)->name();
o << " or " << event(idx)->full_name();
o << ") // " << get_line() << endl;
@@ -776,9 +666,8 @@ void NetEvWait::dump(ostream&o, unsigned ind) const
void NetForce::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "force ";
dump_lval(o);
o << " = " << *rval() << "; /* " << get_line() << " */" << endl;
o << setw(ind) << "" << "force " << lval_->name() << " = "
<< name() << ";" << endl;
}
void NetForever::dump(ostream&o, unsigned ind) const
@@ -789,10 +678,14 @@ void NetForever::dump(ostream&o, unsigned ind) const
void NetFuncDef::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "function " << scope_path(scope_) << endl;
o << setw(ind) << "" << "function " << scope_->name() << endl;
if (result_sig_)
o << setw(ind+2) << "" << "Return signal: "
<< result_sig_->name() << endl;
if (result_var_)
o << setw(ind+2) << "" << "Return variable: "
<< result_var_->basename() << endl;
if (statement_)
statement_->dump(o, ind+2);
else
@@ -818,9 +711,12 @@ void NetPDelay::dump(ostream&o, unsigned ind) const
void NetRelease::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "release ";
dump_lval(o);
o << "; /* " << 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
@@ -832,7 +728,7 @@ void NetRepeat::dump(ostream&o, unsigned ind) const
void NetScope::dump(ostream&o) const
{
/* This is a constructed hierarchical name. */
o << scope_path(this);
o << name();
switch (type_) {
case BEGIN_END:
@@ -850,9 +746,6 @@ void NetScope::dump(ostream&o) const
case TASK:
o << " task";
break;
case GENBLOCK:
o << " generate block";
break;
}
o << endl;
@@ -890,7 +783,7 @@ void NetScope::dump(ostream&o) const
/* Dump the saved defparam assignments here. */
{
map<pform_name_t,NetExpr*>::const_iterator pp;
map<hname_t,NetExpr*>::const_iterator pp;
for (pp = defparams.begin()
; pp != defparams.end() ; pp ++ ) {
o << " defparam " << (*pp).first << " = " <<
@@ -898,11 +791,15 @@ void NetScope::dump(ostream&o) const
}
}
for (NetVariable*cur = vars_ ; cur ; cur = cur->snext_) {
o << " real " << cur->basename() << " // "
<< cur->get_line() << endl;
}
/* Dump the events in this scope. */
for (NetEvent*cur = events_ ; cur ; cur = cur->snext_) {
o << " event " << cur->name() << "; nprobe="
<< cur->nprobe() << " scope=" << scope_path(cur->scope())
<< " // " << cur->get_line() << endl;
<< cur->nprobe() << " // " << cur->get_line() << endl;
}
// Dump the signals,
@@ -914,25 +811,13 @@ void NetScope::dump(ostream&o) const
} while (cur != signals_->sig_next_);
}
// Dump specparams
typedef map<perm_string,spec_val_t>::const_iterator specparam_it_t;
for (specparam_it_t cur = specparams.begin()
; cur != specparams.end() ; cur ++ ) {
o << " specparam " << (*cur).first
<< " = ";
spec_val_t value = (*cur).second;
switch (value.type) {
case IVL_VT_REAL:
o << "R:" << value.real_val;
break;
case IVL_VT_BOOL:
o << "I:" << value.integer;
break;
default:
o << "<bad type>";
break;
}
o << endl;
// Dump the memories,
if (memories_) {
NetMemory*cur = memories_->snext_;
do {
cur->dump(o, 4);
cur = cur->snext_;
} while (cur != memories_->snext_);
}
switch (type_) {
@@ -976,7 +861,7 @@ void NetSTask::dump(ostream&o, unsigned ind) const
void NetUTask::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << scope_path(task_) << ";" << endl;
o << setw(ind) << "" << task_->name() << ";" << endl;
}
void NetWhile::dump(ostream&o, unsigned ind) const
@@ -991,6 +876,15 @@ void NetProc::dump(ostream&o, unsigned ind) const
o << setw(ind) << "" << "// " << typeid(*this).name() << endl;
}
void NetProc::dump_proc_attr(ostream&o, unsigned ind) const
{
unsigned idx;
for (idx = 0 ; idx < attr_cnt() ; idx += 1) {
o << setw(ind) << "" << "(* " << attr_key(idx) << " = "
<< attr_value(idx) << " *)" << endl;
}
}
/* Dump an expression that no one wrote a dump method for. */
void NetExpr::dump(ostream&o) const
{
@@ -1036,9 +930,6 @@ void NetEBinary::dump(ostream&o) const
case 'O':
o << "~|";
break;
case 'p':
o << "**";
break;
case 'r':
o << ">>";
break;
@@ -1089,7 +980,7 @@ void NetEConstParam::dump(ostream&o) const
{
o << "<" << name_ << "=";
NetEConst::dump(o);
o << ", wid=" << expr_width() << ">";
o << ">";
}
void NetECReal::dump(ostream&o) const
@@ -1111,7 +1002,7 @@ void NetEEvent::dump(ostream&o) const
void NetEScope::dump(ostream&o) const
{
o << "<scope=" << scope_path(scope_) << ">";
o << "<scope=" << scope_->name() << ">";
}
void NetESelect::dump(ostream&o) const
@@ -1147,19 +1038,30 @@ void NetESignal::dump(ostream&o) const
{
if (has_sign())
o << "+";
o << name();
if (word_) o << "[word=" << *word_ << "]";
o << "[" << msi()<<":"<<lsi() << "]";
o << name() << "[" << msi_<<":"<<lsi_ << "]";
}
void NetEBitSel::dump(ostream&o) const
{
sig_->dump(o);
o << "[";
idx_->dump(o);
o << "]";
}
void NetEMemory::dump(ostream&o) const
{
o << mem_->name() << "[";
if (idx_) idx_->dump(o);
o << "]";
}
void NetEParam::dump(ostream&o) const
{
if (scope_ != 0)
o << "<" << scope_path(scope_) << "." << name_ << ">";
else if (name_)
o << "<" << name_ << ">";
o << "<" << scope_->name() << "." << name_ << ">";
else
o << "<" "???" ">";
o << "<" << name_ << ">";
}
void NetETernary::dump(ostream&o) const
@@ -1170,7 +1072,7 @@ void NetETernary::dump(ostream&o) const
void NetEUFunc::dump(ostream&o) const
{
o << func_->basename() << "(";
o << name() << "(";
if (parms_.count() > 0) {
parms_[0]->dump(o);
for (unsigned idx = 1 ; idx < parms_.count() ; idx += 1) {
@@ -1196,6 +1098,11 @@ void NetEUnary::dump(ostream&o) const
o << ")";
}
void NetEVariable::dump(ostream&o) const
{
o << var_->basename();
}
void Design::dump(ostream&o) const
{
o << "DESIGN TIME PRECISION: 10e" << get_precision() << endl;
@@ -1225,99 +1132,26 @@ void Design::dump(ostream&o) const
/*
* $Log: design_dump.cc,v $
* Revision 1.176 2007/06/02 03:42:12 steve
* Properly evaluate scope path expressions.
* Revision 1.149.2.7 2006/08/23 04:09:14 steve
* missing sig diagnostics.
*
* Revision 1.175 2007/05/24 04:07:11 steve
* Rework the heirarchical identifier parse syntax and pform
* to handle more general combinations of heirarch and bit selects.
* Revision 1.149.2.6 2006/07/10 00:21:50 steve
* Add support for full_case attribute.
*
* Revision 1.174 2007/03/02 06:13:22 steve
* Add support for edge sensitive spec paths.
* Revision 1.149.2.5 2006/04/16 19:26:37 steve
* Fix handling of exploded memories with partial or missing resets.
*
* Revision 1.173 2007/02/01 03:14:33 steve
* Detect and report arrays without index in net contexts.
* Revision 1.149.2.4 2006/03/26 23:09:21 steve
* Handle asynchronous demux/bit replacements.
*
* Revision 1.172 2007/01/16 05:44:14 steve
* Major rework of array handling. Memories are replaced with the
* more general concept of arrays. The NetMemory and NetEMemory
* classes are removed from the ivl core program, and the IVL_LPM_RAM
* lpm type is removed from the ivl_target API.
* Revision 1.149.2.3 2006/03/12 07:34:16 steve
* Fix the memsynth1 case.
*
* Revision 1.171 2006/10/30 05:44:49 steve
* Expression widths with unsized literals are pseudo-infinite width.
* Revision 1.149.2.2 2006/02/19 00:11:31 steve
* Handle synthesis of FF vectors with l-value decoder.
*
* Revision 1.170 2006/10/03 05:06:00 steve
* Support real valued specify delays, properly scaled.
*
* Revision 1.169 2006/09/26 19:48:40 steve
* Missing PSpec.cc file.
*
* Revision 1.168 2006/09/23 04:57:19 steve
* Basic support for specify timing.
*
* Revision 1.167 2006/07/31 03:50:17 steve
* Add support for power in constant expressions.
*
* Revision 1.166 2006/06/18 04:15:50 steve
* Add support for system functions in continuous assignments.
*
* Revision 1.165 2006/04/10 00:37:42 steve
* Add support for generate loops w/ wires and gates.
*
* Revision 1.164 2006/02/02 02:43:57 steve
* Allow part selects of memory words in l-values.
*
* Revision 1.163 2005/08/27 04:32:08 steve
* Handle synthesis of fully packed case statements.
*
* Revision 1.162 2005/07/11 16:56:50 steve
* Remove NetVariable and ivl_variable_t structures.
*
* Revision 1.161 2005/07/07 16:22:49 steve
* Generalize signals to carry types.
*
* Revision 1.160 2005/05/24 01:44:27 steve
* Do sign extension of structuran nets.
*
* Revision 1.159 2005/05/17 20:56:55 steve
* Parameters cannot have their width changed.
*
* Revision 1.158 2005/05/07 03:13:30 steve
* Include delay expressions for assignments in dump.
*
* Revision 1.157 2005/03/09 05:52:03 steve
* Handle case inequality in netlists.
*
* Revision 1.156 2005/02/08 00:12:36 steve
* Add the NetRepeat node, and code generator support.
*
* Revision 1.155 2005/02/03 04:56:20 steve
* laborate reduction gates into LPM_RED_ nodes.
*
* Revision 1.154 2005/01/24 05:28:30 steve
* Remove the NetEBitSel and combine all bit/part select
* behavior into the NetESelect node and IVL_EX_SELECT
* ivl_target expression type.
*
* Revision 1.153 2005/01/22 18:16:00 steve
* Remove obsolete NetSubnet class.
*
* Revision 1.152 2005/01/09 20:16:00 steve
* Use PartSelect/PV and VP to handle part selects through ports.
*
* Revision 1.151 2004/12/29 23:55:43 steve
* Unify elaboration of l-values for all proceedural assignments,
* including assing, cassign and force.
*
* Generate NetConcat devices for gate outputs that feed into a
* vector results. Use this to hande gate arrays. Also let gate
* arrays handle vectors of gates when the outputs allow for it.
*
* Revision 1.150 2004/12/11 02:31:25 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
* Revision 1.149.2.1 2006/01/18 01:23:23 steve
* Rework l-value handling to allow for more l-value type flexibility.
*
* Revision 1.149 2004/10/04 01:10:52 steve
* Clean up spurious trailing white space.
+2 -2
View File
@@ -16,12 +16,12 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.7 2004/10/13 22:01:34 steve Exp $"
#ident "$Id: Makefile.in,v 1.7.2.1 2006/10/04 17:08:59 steve Exp $"
#
#
SHELL = /bin/sh
VERSION = 0.8
VERSION = 0.8.3
prefix = @prefix@
exec_prefix = @exec_prefix@
+1 -8
View File
@@ -277,7 +277,6 @@ static int parse(int argc, char *argv[])
char dot_c_ext[] = ".c";
char dot_cc_ext[] = ".cc";
char dot_cpp_ext[] = ".cpp";
char dot_o_ext[] = ".o";
char name_option[] = "--name=";
char lib_option[] = "-l";
@@ -302,13 +301,6 @@ static int parse(int argc, char *argv[])
if (!*gstr.pOUT)
assignn(&gstr.pOUT,argv[idx],strlen(argv[idx])-strlen(dot_cc_ext));
}
else if (endsIn(dot_cpp_ext,argv[idx])) { /* check for C++ source files */
++srcFileCnt;
append(&gstr.pCXSRC,argv[idx]);
append(&gstr.pCXSRC," ");
if (!*gstr.pOUT)
assignn(&gstr.pOUT,argv[idx],strlen(argv[idx])-strlen(dot_cpp_ext));
}
else if (endsIn(dot_o_ext,argv[idx])) { /* check for compiled object files */
++srcFileCnt;
append(&gstr.pOBJ,argv[idx]);
@@ -570,4 +562,5 @@ int main(int argc, char *argv[])
compile_and_link();
myExit(0);
return 0; // eliminate warnings.
}
+19 -8
View File
@@ -16,7 +16,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.26 2007/02/06 05:07:31 steve Exp $"
#ident "$Id: Makefile.in,v 1.24.2.3 2007/05/30 17:48:26 steve Exp $"
#
#
SHELL = /bin/sh
@@ -40,6 +40,8 @@ CC = @CC@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
MAN = @MAN@
PS2PDF = @PS2PDF@
CPPFLAGS = @ident_support@ -I. -I.. -I$(srcdir)/.. -I$(srcdir) -DVERSION='"$(VERSION)"' @CPPFLAGS@ @DEFS@
CFLAGS = -Wall @CFLAGS@
@@ -50,10 +52,11 @@ all: iverilog@EXEEXT@
clean:
rm -f *.o lexor.c parse.c parse.h parse.output
rm -f cflexor.c cfparse.c cfparse.h cfparse.output
rm -f iverilog@EXEEXT@ iverilog.pdf iverilog.ps
rm -f iverilog@EXEEXT@
distclean: clean
rm -f Makefile
rm -rf autom4te.cache
O = main.o substit.o cflexor.o cfparse.o
@@ -68,22 +71,30 @@ cfparse.h cfparse.c: cfparse.y
main.o: main.c globals.h
$(CC) $(CPPFLAGS) $(CFLAGS) -c -DIVL_ROOT='"@libdir@/ivl"' -DIVL_INC='"@includedir@"' -DIVL_LIB='"@libdir@"' -DDLLIB='"@DLLIB@"' $(srcdir)/main.c
$(CC) $(CPPFLAGS) $(CFLAGS) -c -DIVL_ROOT='"@libdir@/ivl"' -DIVL_INC='"@includedir@"' -DIVL_LIB='"@libdir@"' -DDLLIB='"@DLLIB@"' $(DEBUGFLAGS) $(srcdir)/main.c
build_string.o: build_string.c globals.h
cflexor.o: cflexor.c cfparse.h cfparse_misc.h globals.h
cfparse.o: cfparse.c globals.h cfparse_misc.h
iverilog.ps: $(srcdir)/iverilog.man
man -t $(srcdir)/iverilog.man > iverilog.ps
$(MAN) -t $(srcdir)/iverilog.man > iverilog.ps
iverilog.pdf: iverilog.ps
ps2pdf iverilog.ps iverilog.pdf
$(PS2PDF) iverilog.ps iverilog.pdf
ifeq (@MING32@,yes)
ifeq (@WIN32@,yes)
ifeq ($(MAN),none)
INSTALL_DOC = $(mandir)/man1/iverilog.1
else
ifeq ($(PS2PDF),none)
INSTALL_DOC = $(mandir)/man1/iverilog.1
else
INSTALL_DOC = $(prefix)/iverilog.pdf $(mandir)/man1/iverilog.1
INSTALL_DOCDIR = $(mandir)/man1
all: iverilog.pdf
endif
endif
INSTALL_DOCDIR = $(mandir)/man1
else
INSTALL_DOC = $(mandir)/man1/iverilog.1
INSTALL_DOCDIR = $(mandir)/man1
@@ -105,4 +116,4 @@ installdirs: ../mkinstalldirs
uninstall:
rm -f $(bindir)/iverilog@EXEEXT@
rm -f $(mandir)/man1/iverilog.1 $(prefix)/iverilog.pdf
rm -f $(mandir)/man1/iverilog.1
+6 -42
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: cflexor.lex,v 1.11 2007/03/22 16:08:18 steve Exp $"
#ident "$Id: cflexor.lex,v 1.8 2004/10/04 01:10:56 steve Exp $"
#endif
# include "cfparse.h"
@@ -37,14 +37,12 @@
YYLTYPE yylloc;
static int comment_enter;
static char* trim_trailing_white(char*txt, int trim);
%}
%x CCOMMENT
%x LCOMMENT
%x PLUS_ARGS
%x FILE_NAME
%%
@@ -78,7 +76,6 @@ static int comment_enter;
"+libext+" { BEGIN(PLUS_ARGS); return TOK_LIBEXT; }
"+integer-width+" { BEGIN(PLUS_ARGS); return TOK_INTEGER_WIDTH; }
/* If it is not any known plus-flag, return the generic form. */
"+"[^\n \t\b\f\r+]* {
@@ -115,50 +112,17 @@ static int comment_enter;
/* This rule matches paths and strings that may be file names. This
is a little bit tricky, as we don't want to mistake a comment for
a string word. */
"/"[\r\n] { /* Special case of file name "/" */
cflval.text = trim_trailing_white(yytext, 0);
return TOK_STRING; }
"/"[^\*\/] { /* A file name that starts with "/". */
yymore();
BEGIN(FILE_NAME); }
[^/\n \t\b\r+-][^/\n\r]* { /* A file name that starts with other than "/" */
yymore();
BEGIN(FILE_NAME); }
"/"[^\*\/].* { cflval.text = strdup(yytext);
return TOK_STRING; }
[^/\n \t\b\r+-].* { cflval.text = strdup(yytext);
return TOK_STRING; }
<FILE_NAME>"//" {
/* Found a trailing comment. Returning the terminated name. */
cflval.text = trim_trailing_white(yytext, 2);
BEGIN(LCOMMENT);
return TOK_STRING; }
<FILE_NAME>"/"?[^/\n\r]* {
yymore();
/* not a comment... continuing */; }
<FILE_NAME>[\n\r] {
/* No trailing comment. Return the file name. */
cflval.text = trim_trailing_white(yytext, 0);
BEGIN(0);
return TOK_STRING; }
/* Fallback match. */
. { return yytext[0]; }
%%
static char* trim_trailing_white(char*text, int trim)
{
char*cp = text + strlen(text);
while (cp > text && trim > 0) {
trim -= 1;
cp -= 1;
*cp = 0;
}
while (cp > text && strchr("\n\r\t\b", cp[-1]))
cp -= 1;
cp[0] = 0;
return strdup(text);
}
int yywrap()
{
return 1;
+5 -13
View File
@@ -18,7 +18,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: cfparse.y,v 1.12 2007/04/19 02:52:53 steve Exp $"
#ident "$Id: cfparse.y,v 1.10 2003/09/26 21:25:58 steve Exp $"
#endif
@@ -62,7 +62,6 @@ static void translate_file_name(char*text)
%token TOK_Da TOK_Dv TOK_Dy
%token TOK_DEFINE TOK_INCDIR TOK_LIBDIR TOK_LIBDIR_NOCASE TOK_LIBEXT
%token TOK_INTEGER_WIDTH
%token <text> TOK_PLUSARG TOK_PLUSWORD TOK_STRING
%%
@@ -84,7 +83,7 @@ item
: TOK_STRING
{ char*tmp = substitutions($1);
translate_file_name(tmp);
process_file_name(tmp, 0);
process_file_name(tmp);
free($1);
free(tmp);
}
@@ -99,7 +98,9 @@ item
| TOK_Dv TOK_STRING
{ char*tmp = substitutions($2);
translate_file_name(tmp);
process_file_name(tmp, 1);
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);
}
@@ -144,15 +145,6 @@ item
| TOK_LIBEXT libext_args
/* These are various misc flags that are supported. */
| TOK_INTEGER_WIDTH TOK_PLUSARG
{ char*tmp = substitutions($2);
free($2);
integer_width = strtoul(tmp,0,10);
free(tmp);
}
/* The +<word> tokens that are not otherwise matched, are
ignored. The skip_args rule arranges for all the argument words
to be consumed. */
+2 -11
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: globals.h,v 1.21 2007/04/19 02:52:53 steve Exp $"
#ident "$Id: globals.h,v 1.19 2003/11/18 06:31:46 steve Exp $"
#endif
# include <stddef.h>
@@ -49,14 +49,11 @@ extern int synth_flag;
/* This is the name of the selected target. */
extern const char*targ;
/* This is the integer-width argument that will be passed to ivl. */
extern unsigned integer_width;
/* 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, int lib_flag);
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);
@@ -80,12 +77,6 @@ extern char* library_flags2;
/*
* $Log: globals.h,v $
* Revision 1.21 2007/04/19 02:52:53 steve
* Add support for -v flag in command file.
*
* Revision 1.20 2007/03/07 04:24:59 steve
* Make integer width controllable.
*
* Revision 1.19 2003/11/18 06:31:46 steve
* Remove the iverilog.conf file.
*
+13 -30
View File
@@ -1,10 +1,10 @@
.TH iverilog 1 "$Date: 2007/06/05 01:56:12 $" Version "$Date: 2007/06/05 01:56:12 $"
.TH iverilog 1 "$Date: 2006/06/12 00:16:53 $" Version "$Date: 2006/06/12 00:16:53 $"
.SH NAME
iverilog - Icarus Verilog compiler
.SH SYNOPSIS
.B iverilog
[-ESVv] [-Bpath] [-ccmdfile] [-g1|-g2|-g2x|-gspecify-gxtypes] [-Dmacro[=defn]] [-pflag=value]
[-ESVv] [-Bpath] [-ccmdfile] [-g1|-g2|-g3.0] [-Dmacro[=defn]] [-pflag=value]
[-Iincludedir] [-mmodule] [-Mfile] [-Nfile] [-ooutputfilename]
[-stopmodule] [-ttype] [-Tmin/typ/max] [-Wclass] [-ypath] sourcefile
@@ -48,30 +48,15 @@ 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-g2x
.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 \fIVerilog with extension\fP(2x). Normally,
\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 -gspecify\fI|\fP-gno-specify
Enable (default) or disable specify block support. When enabled,
specify block code is elaborated. When disabled, specify blocks are
parsed but ignored. Specify blocks are commonly not needed for RTL
simulation, and in fact can hurt performance of the
simulation. However, disabling specify blocks reduces accuracy of
full-timing simulations.
.TP 8
.B -gxtypes\fI|\fP-gno-xtypes
Enable (default) or disable support for extended types. Enabling
extended types allows for new types that are supported by Icarus
Verilog as extensions beyond the baseline Verilog. It may be necessary
to disable extended types if compiling code that clashes with the few
new keywords used to implement the type system.
.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
@@ -89,8 +74,6 @@ leading or trailing space.
Add this module to the list of VPI modules to be loaded by the
simulation. Many modules can be specified, and all will be loaded, in
the order specified. The system module is implicit and always included.
If a System Function Table file (<module>.sft) exists for the module it
will be loaded automatically.
.TP 8
.B -N\fIpath\fP
This is used for debugging the compiler proper. Dump the final netlist
@@ -201,7 +184,7 @@ implies the synthesis \fB-S\fP flag.
.SH "WARNING TYPES"
These are the types of warnings that can be selected by the \fB-W\fP
switch. All the warning types (other than \fBall\fP) can also be
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.
@@ -229,6 +212,12 @@ inherit timescale from another file. Both probably mean that
timescales are inconsistent, and simulation timing can be confusing
and dependent on compilation order.
.TP 8
.B unused
This enables warnings for unused variables. This may detect variables
that are not assigned, or variables and nets that are not used, or
similar possible misuses of variables and nets.
.SH "SYSTEM FUNCTION TABLE FILES"
If the source file name as a \fB.sft\fP suffix, then it is taken to be
a system function table file. A System function table file is used to
@@ -266,7 +255,7 @@ well as # comments, if the # starts the line.
.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. Variables are substituted in file names.
character. Variables are substitued in file names.
.TP 8
.B -y\ \fIlibdir\fP
@@ -321,19 +310,13 @@ become munged.
.B +tolower-filename\fP
This is similar to the \fB+toupper-filename\fP hack described above.
.TP 8
.B +integer-width+\fIvalue\fP
This allows the programmer to select the width for integer variables
in the Verilog source. The default is 32, the value can be any desired
integer value.
.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
substituted in contexts that explicitly support them, including file
substitued in contexts that explicitly support them, including file
and directory strings.
Variable values come from the operating system environment, and not
+195 -171
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2005 Stephen Williams ([email protected])
* Copyright (c) 2000-2001 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: main.c,v 1.76 2007/06/05 01:56:12 steve Exp $"
#ident "$Id: main.c,v 1.65.2.6 2007/05/30 17:48:26 steve Exp $"
#endif
# include "config.h"
@@ -39,7 +39,7 @@ const char NOTICE[] =
;
const char HELP[] =
"Usage: iverilog [-ESvV] [-B base] [-c cmdfile] [-g1|-g2|-g2x]\n"
"Usage: iverilog [-ESvV] [-B base] [-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"
@@ -88,6 +88,10 @@ extern const char*optarg;
# define IVL_ROOT "."
#endif
#ifndef IVL_ROOT_VARIABLE
# define IVL_ROOT_VARIABLE "IVERILOG_ROOT"
#endif
# include "globals.h"
#include "cfparse_misc.h" /* cfparse() */
@@ -107,14 +111,12 @@ const char*npath = 0;
const char*targ = "vvp";
const char*depfile = 0;
const char*generation = "2x";
const char*gen_specify = "specify";
const char*gen_xtypes = "xtypes";
const char*generation = "3.0";
char warning_flags[16] = "";
unsigned integer_width = 32;
char*inc_list = 0;
char*def_list = 0;
char*mod_list = 0;
char*command_filename = 0;
@@ -125,9 +127,6 @@ char*source_path = 0;
FILE*source_file = 0;
unsigned source_count = 0;
char*defines_path = 0;
FILE*defines_file = 0;
char*iconfig_path = 0;
FILE*iconfig_file = 0;
@@ -136,6 +135,7 @@ char*iconfig_common_path = iconfig_common_path_buf;
int synth_flag = 0;
int verbose_flag = 0;
int command_file = 0;
FILE *fp;
@@ -144,48 +144,6 @@ char tmp[MAXSIZE];
static char ivl_root[MAXSIZE];
/* Structure to keep a FIFO list of the command files */
typedef struct t_command_file {
char *filename;
struct t_command_file *next;
} s_command_file, *p_command_file;
p_command_file cmd_file_head = NULL; /* The FIFO head */
p_command_file cmd_file_tail = NULL; /* The FIFO tail */
/* Function to add a comamnd file name to the FIFO. */
void add_cmd_file(const char* filename)
{
p_command_file new;
new = (p_command_file) malloc(sizeof(s_command_file));
new->filename = strdup(filename);
new->next = NULL;
if (cmd_file_head == NULL) {
cmd_file_head = new;
cmd_file_tail = new;
} else {
cmd_file_tail->next = new;
cmd_file_tail = new;
}
}
/* Function to return the top comamnd file name from the FIFO. */
char *get_cmd_file()
{
char *filename;
if (cmd_file_head == NULL) filename = NULL;
else {
p_command_file head;
filename = cmd_file_head->filename;
head = cmd_file_head;
cmd_file_head = cmd_file_head->next;
free(head);
}
return filename;
}
#ifdef __MINGW32__
# include <io.h>
# include <fcntl.h>
@@ -308,18 +266,69 @@ static int t_default(char*cmd, unsigned ncmd)
}
#endif
#ifdef DEBUG
char *original_cmd = malloc( strlen( cmd ) + (size_t)1 );
strcpy( original_cmd, cmd );
cmd = realloc( cmd, strlen( original_cmd ) + (size_t)19 ); /* more than enough memory for the ivlpp command and ">/tmp/ivlpp_stdout" */
if( cmd == NULL ){
exit( EXIT_FAILURE );
}
char *debug_ivl = malloc( strlen( original_cmd ) + (size_t)5 ); /* more than enough memory for "gdb " and ivl program_name */
strcpy( debug_ivl, "gdb " );
static char whitespace[] = " \t\f\r\v\n";
char *token;
int found_pipe = 0;
unsigned long token_counter = 0UL;
strcpy( cmd, "" );
for( token = strtok( original_cmd, whitespace ); token != NULL; token = strtok( NULL, whitespace ) ){
if( strcmp( token, "|" ) == 0 ){
found_pipe = 1;
}
if( found_pipe ){
token_counter++;
}
if( token_counter == 0UL ){
strcat( cmd, token );
strcat( cmd, " " ); /* harmless space after last token, and it was already there anyway */
}
if( token_counter == 2UL ){
strcat( debug_ivl, token );
}
if( token_counter > 2UL ){
printf( "%s\n", token );
}
}
free( original_cmd );
strcat( cmd, ">/tmp/ivlpp_stdout" );
#endif
if (verbose_flag)
printf("translate: %s\n", cmd);
rc = system(cmd);
if ( ! getenv("IVERILOG_ICONFIG")) {
remove(source_path);
remove(iconfig_path);
remove(defines_path);
#ifdef DEBUG
if( verbose_flag ){
printf( "%s\n", debug_ivl );
}
system( debug_ivl ); /* For simplicity, ignore any return value, which is implementation dependent anyway. */
free( debug_ivl );
#endif
remove(source_path);
if ( ! getenv("IVERILOG_ICONFIG"))
remove(iconfig_path);
if (rc != 0) {
if (rc == 127) {
fprintf(stderr, "Failed to execute: %s\n", cmd);
@@ -340,7 +349,7 @@ static int t_default(char*cmd, unsigned ncmd)
static void process_warning_switch(const char*name)
{
if (strcmp(name,"all") == 0) {
strcat(warning_flags, "ipt");
strcat(warning_flags, "iptu");
} else if (strcmp(name,"implicit") == 0) {
if (! strchr(warning_flags+2, 'i'))
@@ -351,6 +360,9 @@ static void process_warning_switch(const char*name)
} else if (strcmp(name,"timescale") == 0) {
if (! strchr(warning_flags+2, 't'))
strcat(warning_flags, "t");
} else if (strcmp(name,"unused") == 0) {
if (! strchr(warning_flags+2, 'u'))
strcat(warning_flags, "u");
} else if (strcmp(name,"no-implicit") == 0) {
char*cp = strchr(warning_flags+2, 'i');
if (cp) while (*cp) {
@@ -369,6 +381,12 @@ static void process_warning_switch(const char*name)
cp[0] = cp[1];
cp += 1;
}
} else if (strcmp(name,"no-unused") == 0) {
char*cp = strchr(warning_flags+2, 'u');
if (cp) while (*cp) {
cp[0] = cp[1];
cp += 1;
}
}
}
@@ -389,12 +407,32 @@ void process_library2_switch(const char *name)
void process_include_dir(const char *name)
{
fprintf(defines_file, "I:%s\n", name);
if (inc_list == 0) {
inc_list = malloc(strlen(" -I")+strlen(name)+1);
strcpy(inc_list, " -I");
strcat(inc_list, name);
} else {
inc_list = realloc(inc_list, strlen(inc_list)
+ strlen(" -I")
+ strlen(name) + 1);
strcat(inc_list, " -I");
strcat(inc_list, name);
}
}
void process_define(const char*name)
{
fprintf(defines_file,"D:%s\n", name);
if (def_list == 0) {
def_list = malloc(strlen(" -D")+strlen(name)+1);
strcpy(def_list, " -D");
strcat(def_list, name);
} else {
def_list = realloc(def_list, strlen(def_list)
+ strlen(" -D")
+ strlen(name) + 1);
strcat(def_list, " -D");
strcat(def_list, name);
}
}
/*
@@ -403,7 +441,7 @@ void process_define(const char*name)
* .sft suffix, and if so pass that as a sys_func file. Otherwise, it
* is a Verilog source file to be written into the file list.
*/
void process_file_name(const char*name, int lib_flag)
void process_file_name(const char*name)
{
if (strlen(name) > 4 && strcasecmp(".sft", name+strlen(name)-4) == 0) {
fprintf(iconfig_file,"sys_func:%s\n", name);
@@ -411,8 +449,6 @@ void process_file_name(const char*name, int lib_flag)
} else {
fprintf(source_file, "%s\n", name);
source_count += 1;
if (lib_flag)
fprintf(iconfig_file,"library_file:%s\n", name);
}
}
@@ -424,20 +460,8 @@ int process_generation(const char*name)
else if (strcmp(name,"2") == 0)
generation = "2";
else if (strcmp(name,"2x") == 0)
generation = "2x";
else if (strcmp(name,"xtypes") == 0)
gen_xtypes = "xtypes";
else if (strcmp(name,"no-xtypes") == 0)
gen_xtypes = "no-xtypes";
else if (strcmp(name,"specify") == 0)
gen_specify = "specify";
else if (strcmp(name,"no-specify") == 0)
gen_specify = "no-specify";
else if (strcmp(name,"3.0") == 0)
generation = "3.0";
else {
fprintf(stderr, "Unknown/Unsupported Language generation "
@@ -445,10 +469,7 @@ int process_generation(const char*name)
fprintf(stderr, "Supported generations are:\n");
fprintf(stderr, " 1 -- IEEE1364-1995 (Verilog 1)\n"
" 2 -- IEEE1364-2001 (Verilog 2001)\n"
" 2x -- Verilog with extensions\n"
"Other generation flags:\n"
" specify | no-specify\n"
" xtypes | no-xtypes\n");
" 3.0 -- SystemVerilog 3.0\n");
return 1;
}
@@ -456,27 +477,12 @@ int process_generation(const char*name)
}
/*
* If it exists add the SFT file for the given module.
* This function fills in th ivl_root directory with the appropriate
* path, based on operating system, build time configuration, and
* environment.
*/
void add_sft_file(const char *module)
static char* get_root_dir()
{
char *file;
file = (char *) malloc(strlen(base)+1+strlen(module)+4+1);
sprintf(file, "%s%c%s.sft", base, sep, module);
if (access(file, R_OK) == 0)
fprintf(iconfig_file, "sys_func:%s\n", file);
free(file);
}
int main(int argc, char **argv)
{
char*cmd;
unsigned ncmd;
int e_flag = 0;
int version_flag = 0;
int opt, idx, rc;
#ifdef __MINGW32__
{ char * s;
char basepath[1024];
@@ -503,16 +509,56 @@ int main(int argc, char **argv)
s = strrchr(ivl_root, sep);
if (s) *s = 0;
strcat(ivl_root, "\\lib\\ivl");
base = ivl_root;
}
#else
/* In a UNIX environment, the IVL_ROOT from the Makefile is
dependable. It points to the $prefix/lib/ivl directory,
where the sub-parts are installed. */
strcpy(ivl_root, IVL_ROOT);
base = ivl_root;
{ char*var = 0;
/* In other systems, use the configured root. */
strcpy(ivl_root, IVL_ROOT);
/* In any case, the IVL_ROOT variable can be used to override
the install location at run time. If it is set, use that
value instead. */
if ( (var = getenv(IVL_ROOT_VARIABLE)) ) {
strncpy(ivl_root, var, MAXSIZE);
strcat(ivl_root, "/lib/ivl");
}
}
#endif
return ivl_root;
}
int main(int argc, char **argv)
{
char*cmd;
unsigned ncmd;
int e_flag = 0;
int version_flag = 0;
int opt, idx, rc;
base = get_root_dir();
#ifdef __MINGW32__
/* Under Windows, there is no point checking the root
directory. */
#else
/* On other systems, check that the root directory seems
reasonable. */
{ size_t tmp_len = strlen(base) + 16;
char* tmp = malloc(tmp_len);
snprintf(tmp, tmp_len, "%s%civl", base, sep);
if (0 != access(tmp, F_OK)) {
fprintf(stderr, "%s: INSTALLATION ERROR: Directory %s"
" does not contain ivl files.\n", argv[0], base);
fprintf(stderr, "%s: : Check installation"
" or set " IVL_ROOT_VARIABLE " correctly.\n", argv[0]);
return 1;
}
free(tmp);
}
#endif
/* Create a temporary file for communicating input parameters
@@ -525,19 +571,6 @@ int main(int argc, char **argv)
return 1;
}
defines_path = strdup(my_tempfile("ivrlg2", &defines_file));
if (NULL == defines_file) {
fprintf(stderr, "%s: Error opening temporary file %s\n",
argv[0], defines_path);
fprintf(stderr, "%s: Please check TMP or TMPDIR.\n", argv[0]);
fclose(source_file);
remove(source_path);
return 1;
}
fprintf(defines_file, "D:__ICARUS__=1\n");
/* Create another temporary file for passing configuration
information to ivl. */
@@ -558,9 +591,6 @@ int main(int argc, char **argv)
fprintf(stderr, "%s: Please check TMP or TMPDIR.\n", argv[0]);
fclose(source_file);
remove(source_path);
fclose(defines_file);
remove(defines_path);
return 1;
}
@@ -579,7 +609,8 @@ int main(int argc, char **argv)
}
break;
case 'c':
add_cmd_file(optarg);
command_filename = malloc(strlen(optarg)+1);
strcpy(command_filename, optarg);
break;
case 'D':
process_define(optarg);
@@ -612,7 +643,6 @@ int main(int argc, char **argv)
case 'm':
fprintf(iconfig_file, "module:%s\n", optarg);
add_sft_file(optarg);
break;
case 'N':
@@ -692,13 +722,11 @@ int main(int argc, char **argv)
if (mtm != 0) fprintf(iconfig_file, "-T:%s\n", mtm);
fprintf(iconfig_file, "generation:%s\n", generation);
fprintf(iconfig_file, "generation:%s\n", gen_specify);
fprintf(iconfig_file, "generation:%s\n", gen_xtypes);
fprintf(iconfig_file, "warnings:%s\n", warning_flags);
fprintf(iconfig_file, "out:%s\n", opath);
if (depfile) fprintf(iconfig_file, "depfile:%s\n", depfile);
while ( (command_filename = get_cmd_file()) ) {
if (command_filename) {
int rc;
if (( fp = fopen(command_filename, "r")) == NULL ) {
@@ -714,25 +742,17 @@ int main(int argc, char **argv)
command_filename);
return 1;
}
free(command_filename);
}
if (depfile) {
fprintf(defines_file, "M:%s\n", depfile);
}
/* Finally, process all the remaining words on the command
line as file names. */
for (idx = optind ; idx < argc ; idx += 1)
process_file_name(argv[idx], 0);
process_file_name(argv[idx]);
fclose(source_file);
source_file = 0;
fclose(defines_file);
defines_file = 0;
if (source_count == 0) {
fprintf(stderr, "%s: No input files.\n", argv[0]);
fprintf(stderr, "%s\n", HELP);
@@ -742,14 +762,33 @@ int main(int argc, char **argv)
/* Start building the preprocess command line. */
sprintf(tmp, "%s%civlpp %s%s -F%s -f%s ", pbase,sep,
sprintf(tmp, "%s%civlpp %s%s -D__ICARUS__=1 -f%s ", pbase,sep,
verbose_flag?" -v":"",
e_flag?"":" -L", defines_path, source_path);
e_flag?"":" -L", source_path);
ncmd = strlen(tmp);
cmd = malloc(ncmd + 1);
strcpy(cmd, tmp);
if (inc_list) {
cmd = realloc(cmd, ncmd + strlen(inc_list) + 1);
strcat(cmd, inc_list);
ncmd += strlen(inc_list);
}
if (def_list) {
cmd = realloc(cmd, ncmd + strlen(def_list) + 1);
strcat(cmd, def_list);
ncmd += strlen(def_list);
}
if (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
user wants it. */
@@ -784,13 +823,13 @@ int main(int argc, char **argv)
return 0;
}
fprintf(iconfig_file, "iwidth:%u\n", integer_width);
/* Write the preprocessor command needed to preprocess a
single file. This may be used to preprocess library
files. */
fprintf(iconfig_file, "ivlpp:%s%civlpp -L -F%s\n",
pbase, sep, defines_path);
fprintf(iconfig_file, "ivlpp:%s%civlpp -D__ICARUS__ -L %s %s\n",
pbase, sep,
inc_list? inc_list : "",
def_list? def_list : "");
/* Done writing to the iconfig file. Close it now. */
fclose(iconfig_file);
@@ -802,38 +841,23 @@ int main(int argc, char **argv)
/*
* $Log: main.c,v $
* Revision 1.76 2007/06/05 01:56:12 steve
* Bring in .SFT file automatically if -m used.
* Revision 1.65.2.6 2007/05/30 17:48:26 steve
* DEBUG aids. (Alan Feldstein)
*
* Revision 1.75 2007/04/19 02:52:53 steve
* Add support for -v flag in command file.
* Revision 1.65.2.5 2006/07/07 21:31:50 steve
* Root dir variable does not include lib/ivl components.
*
* Revision 1.74 2007/04/18 03:23:38 steve
* Add support for multiple command files. (Cary R.)
* Revision 1.65.2.4 2006/06/27 01:30:20 steve
* Fix unused var warning for mingw32 build.
*
* Revision 1.73 2007/03/07 04:24:59 steve
* Make integer width controllable.
* Revision 1.65.2.3 2006/06/14 03:01:49 steve
* Remove redundant call to get_root_dir.
*
* Revision 1.72 2006/10/02 18:15:47 steve
* Fix handling of dep path in new argument passing method.
* Revision 1.65.2.2 2006/06/12 00:16:53 steve
* Add support for -Wunused warnings.
*
* Revision 1.71 2006/09/28 04:35:18 steve
* Support selective control of specify and xtypes features.
*
* Revision 1.70 2006/09/20 22:30:52 steve
* Do not pass -D__ICARUS__ to ivlpp.
*
* Revision 1.69 2006/07/26 00:11:40 steve
* Pass depfiles through temp defines file.
*
* Revision 1.68 2006/07/26 00:02:48 steve
* Pass defines and includes through temp file.
*
* Revision 1.67 2005/07/14 23:38:44 steve
* Display as version 0.9.devel
*
* Revision 1.66 2005/06/28 04:25:55 steve
* Remove reference to SystemVerilog.
* Revision 1.65.2.1 2006/03/26 21:47:26 steve
* More installation directory flexibility.
*
* Revision 1.65 2004/06/17 14:47:22 steve
* Add a .sft file for the system functions.
+21 -14
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: dup_expr.cc,v 1.21 2006/11/04 06:10:13 steve Exp $"
#ident "$Id: dup_expr.cc,v 1.18.2.2 2006/11/02 02:13:15 steve Exp $"
#endif
# include "config.h"
@@ -29,6 +29,7 @@ NetEBComp* NetEBComp::dup_expr() const
{
NetEBComp*result = new NetEBComp(op_, left_->dup_expr(),
right_->dup_expr());
result->set_line(*this);
return result;
}
@@ -67,8 +68,7 @@ NetEScope* NetEScope::dup_expr() const
NetESelect* NetESelect::dup_expr() const
{
return new NetESelect(expr_->dup_expr(),
base_? base_->dup_expr() : 0,
return new NetESelect(expr_->dup_expr(), base_->dup_expr(),
expr_width());
}
@@ -88,9 +88,10 @@ NetESFunc* NetESFunc::dup_expr() const
NetESignal* NetESignal::dup_expr() const
{
NetESignal*tmp = new NetESignal(net_);
NetESignal*tmp = new NetESignal(net_, msi_, lsi_);
assert(tmp);
tmp->expr_width(expr_width());
tmp->set_line(*this);
return tmp;
}
@@ -112,9 +113,14 @@ NetEUFunc* NetEUFunc::dup_expr() const
tmp_parms[idx] = parms_[idx]->dup_expr();
}
tmp = new NetEUFunc(func_, result_sig_->dup_expr(), tmp_parms);
tmp = 0;
if (result_sig_)
tmp = new NetEUFunc(func_, result_sig_->dup_expr(), tmp_parms);
if (result_var_)
tmp = new NetEUFunc(func_, result_var_->dup_expr(), tmp_parms);
assert(tmp);
tmp->set_line(*this);
return tmp;
}
@@ -132,18 +138,19 @@ NetEUReduce* NetEUReduce::dup_expr() const
return tmp;
}
NetEVariable* NetEVariable::dup_expr() const
{
NetEVariable*tmp = new NetEVariable(var_);
return tmp;
}
/*
* $Log: dup_expr.cc,v $
* Revision 1.21 2006/11/04 06:10:13 steve
* Handle dup of pad as well as normal select.
* Revision 1.18.2.2 2006/11/02 02:13:15 steve
* Error message for condit expression not synthesized.
*
* Revision 1.20 2005/07/11 16:56:50 steve
* Remove NetVariable and ivl_variable_t structures.
*
* Revision 1.19 2004/12/11 02:31:25 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
* Revision 1.18.2.1 2006/06/12 00:16:50 steve
* Add support for -Wunused warnings.
*
* Revision 1.18 2004/06/17 16:06:18 steve
* Help system function signedness survive elaboration.
+4 -15
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: elab_anet.cc,v 1.13 2007/03/22 16:08:14 steve Exp $"
#ident "$Id: elab_anet.cc,v 1.10 2004/10/04 01:10:52 steve Exp $"
#endif
# include "config.h"
@@ -84,18 +84,15 @@ NetNet* PEConcat::elaborate_anet(Design*des, NetScope*scope) const
concat operator from least significant to most significant,
which is opposite from how they are given in the list.
Allow for a repeat count other than 1 by repeating the
Allow for a repeat count other then 1 by repeating the
connect loop as many times as necessary. */
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT_REG, pins);
/* Assume that all the data types are the same. */
osig->data_type(nets[0]->data_type());
pins = 0;
for (unsigned idx = nets.count() ; idx > 0 ; idx -= 1) {
NetNet*cur = nets[idx-1];
assert(cur->data_type() == osig->data_type());
for (unsigned pin = 0; pin < cur->pin_count(); pin += 1) {
connect(osig->pin(pins), cur->pin(pin));
pins += 1;
@@ -112,10 +109,11 @@ NetNet* PEIdent::elaborate_anet(Design*des, NetScope*scope) const
NetNet* sig = 0;
NetMemory* mem = 0;
NetVariable* var = 0;
const NetExpr*par = 0;
NetEvent* eve = 0;
symbol_search(des, scope, path_, sig, mem, par, eve);
symbol_search(des, scope, path_, sig, mem, var, par, eve);
if (mem != 0) {
@@ -169,15 +167,6 @@ NetNet* PEIdent::elaborate_anet(Design*des, NetScope*scope) const
/*
* $Log: elab_anet.cc,v $
* Revision 1.13 2007/03/22 16:08:14 steve
* Spelling fixes from Larry
*
* Revision 1.12 2006/05/01 20:47:58 steve
* More explicit datatype setup.
*
* Revision 1.11 2005/07/11 16:56:50 steve
* Remove NetVariable and ivl_variable_t structures.
*
* Revision 1.10 2004/10/04 01:10:52 steve
* Clean up spurious trailing white space.
*
+379 -1173
View File
File diff suppressed because it is too large Load Diff
+196 -314
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2006 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: elab_lval.cc,v 1.44 2007/06/02 03:42:12 steve Exp $"
#ident "$Id: elab_lval.cc,v 1.29 2004/10/04 01:10:52 steve Exp $"
#endif
# include "config.h"
@@ -25,9 +25,8 @@
# include "PExpr.h"
# include "netlist.h"
# include "netmisc.h"
# include "compiler.h"
# include <iostream>
# include "ivl_assert.h"
/*
* These methods generate a NetAssign_ object for the l-value of the
@@ -67,9 +66,7 @@
* is to try to make a net elaboration, and see if the result is
* suitable for assignment.
*/
NetAssign_* PExpr::elaborate_lval(Design*des,
NetScope*scope,
bool is_force) const
NetAssign_* PExpr::elaborate_lval(Design*des, NetScope*scope) const
{
NetNet*ll = 0;
if (ll == 0) {
@@ -95,9 +92,7 @@ NetAssign_* PExpr::elaborate_lval(Design*des,
* a is the MSB and b the LSB. Connect the LSB to the low pins of the
* NetAssign_ object.
*/
NetAssign_* PEConcat::elaborate_lval(Design*des,
NetScope*scope,
bool is_force) const
NetAssign_* PEConcat::elaborate_lval(Design*des, NetScope*scope) const
{
if (repeat_) {
cerr << get_line() << ": error: Repeat concatenations make "
@@ -117,7 +112,7 @@ NetAssign_* PEConcat::elaborate_lval(Design*des,
continue;
}
NetAssign_*tmp = parms_[idx]->elaborate_lval(des, scope, is_force);
NetAssign_*tmp = parms_[idx]->elaborate_lval(des, scope);
/* If the l-value doesn't elaborate, the error was
already detected and printed. We just skip it and let
@@ -145,68 +140,41 @@ NetAssign_* PEConcat::elaborate_lval(Design*des,
* Handle the ident as an l-value. This includes bit and part selects
* of that ident.
*/
NetAssign_* PEIdent::elaborate_lval(Design*des,
NetScope*scope,
bool is_force) const
NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope) const
{
NetNet* reg = 0;
NetMemory* mem = 0;
NetVariable* var = 0;
const NetExpr*par = 0;
NetEvent* eve = 0;
symbol_search(des, scope, path_, reg, par, eve);
symbol_search(des, scope, path_, reg, mem, var, par, eve);
if (mem) {
return elaborate_mem_lval_(des, scope, mem);
}
if (var) {
NetAssign_*cur = new NetAssign_(var);
return cur;
}
if (reg == 0) {
cerr << get_line() << ": error: Could not find variable ``"
<< path_ << "'' in ``" << scope_path(scope) <<
<< path_ << "'' in ``" << scope->name() <<
"''" << endl;
des->errors += 1;
return 0;
}
ivl_assert(*this, reg);
const name_component_t&name_tail = path_.back();
index_component_t::ctype_t use_sel = index_component_t::SEL_NONE;
if (!name_tail.index.empty())
use_sel = name_tail.index.back().sel;
// This is the special case that the l-value is an entire
// memory. This is, in fact, an error.
if (reg->array_dimensions() > 0 && name_tail.index.empty()) {
cerr << get_line() << ": error: Cannot assign to array "
<< path_ << ". Did you forget a word index?" << endl;
des->errors += 1;
return 0;
}
if (reg->array_dimensions() > 0)
return elaborate_lval_net_word_(des, scope, reg);
if (use_sel == index_component_t::SEL_PART) {
NetAssign_*lv = new NetAssign_(reg);
elaborate_lval_net_part_(des, scope, lv);
return lv;
}
if (use_sel == index_component_t::SEL_IDX_UP) {
NetAssign_*lv = new NetAssign_(reg);
elaborate_lval_net_idx_up_(des, scope, lv);
return lv;
}
if (use_sel == index_component_t::SEL_IDX_DO) {
NetAssign_*lv = new NetAssign_(reg);
elaborate_lval_net_idx_do_(des, scope, lv);
return lv;
}
assert(reg);
/* Get the signal referenced by the identifier, and make sure
it is a register. Wires are not allows in this context,
unless this is the l-value of a force. */
if ((reg->type() != NetNet::REG) && !is_force) {
it is a register. (Wires are not allows in this context. */
if (reg->type() != NetNet::REG) {
cerr << get_line() << ": error: " << path_ <<
" is not a valid l-value in " << scope_path(scope) <<
" is not a reg/integer/time in " << scope->name() <<
"." << endl;
cerr << reg->get_line() << ": : " << path_ <<
" is declared here as " << reg->type() << "." << endl;
@@ -217,29 +185,57 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
long msb, lsb;
NetExpr*mux;
if (use_sel == index_component_t::SEL_BIT) {
if (msb_ && lsb_) {
/* This handles part selects. In this case, there are
two bit select expressions, and both must be
constant. Evaluate them and pass the results back to
the caller. */
verinum*vl = lsb_->eval_const(des, scope);
if (vl == 0) {
cerr << lsb_->get_line() << ": error: "
"Part select expressions must be constant."
<< endl;
cerr << lsb_->get_line() << ": : This lsb expression "
"violates the rule: " << *lsb_ << endl;
des->errors += 1;
return 0;
}
verinum*vm = msb_->eval_const(des, scope);
if (vm == 0) {
cerr << msb_->get_line() << ": error: "
"Part select expressions must be constant."
<< endl;
cerr << msb_->get_line() << ": : This msb expression "
"violates the rule: " << *msb_ << endl;
des->errors += 1;
return 0;
}
const index_component_t&index_tail = name_tail.index.back();
ivl_assert(*this, index_tail.msb != 0);
ivl_assert(*this, index_tail.lsb == 0);
msb = vm->as_long();
lsb = vl->as_long();
mux = 0;
} else if (msb_) {
/* If there is only a single select expression, it is a
bit select. Evaluate the constant value and treat it
as a part select with a bit width of 1. If the
expression it not constant, then return the
expression as a mux. */
NetExpr*index_expr = elab_and_eval(des, scope, index_tail.msb, -1);
if (NetEConst*index_con = dynamic_cast<NetEConst*> (index_expr)) {
msb = index_con->value().as_long();
lsb = index_con->value().as_long();
mux = 0;
} else {
assert(lsb_ == 0);
verinum*v = msb_->eval_const(des, scope);
if (v == 0) {
NetExpr*m = msb_->elaborate_expr(des, scope);
assert(m);
msb = 0;
lsb = 0;
mux = index_expr;
mux = m;
} else {
msb = v->as_long();
lsb = v->as_long();
mux = 0;
}
} else {
@@ -247,6 +243,8 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
/* No select expressions, so presume a part select the
width of the register. */
assert(msb_ == 0);
assert(lsb_ == 0);
msb = reg->msb();
lsb = reg->lsb();
mux = 0;
@@ -261,19 +259,7 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
bmux to select the target bit. */
lv = new NetAssign_(reg);
/* Correct the mux for the range of the vector. */
if (reg->msb() < reg->lsb())
mux = make_sub_expr(reg->lsb(), mux);
else if (reg->lsb() != 0)
mux = make_add_expr(mux, - reg->lsb());
lv->set_part(mux, 1);
} else if (msb == reg->msb() && lsb == reg->lsb()) {
/* No bit select, and part select covers the entire
vector. Simplest case. */
lv = new NetAssign_(reg);
lv->set_bmux(mux);
} else {
@@ -297,7 +283,7 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
converted to normalized form so is relative the
variable pins. */
if ((wid + loff) > reg->vector_width()) {
if ((wid + loff) > reg->pin_count()) {
cerr << get_line() << ": error: bit/part select "
<< reg->name() << "[" << msb<<":"<<lsb<<"]"
<< " is out of range." << endl;
@@ -306,191 +292,57 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
}
lv = new NetAssign_(reg);
lv->set_part(new NetEConst(verinum(loff)), wid);
lv->set_part(loff, wid);
assert(moff < reg->pin_count());
}
return lv;
}
NetAssign_* PEIdent::elaborate_lval_net_word_(Design*des,
NetScope*scope,
NetNet*reg) const
NetAssign_* PEIdent::elaborate_mem_lval_(Design*des, NetScope*scope,
NetMemory*mem) const
{
const name_component_t&name_tail = path_.back();
ivl_assert(*this, !name_tail.index.empty());
const index_component_t&index_head = name_tail.index.front();
ivl_assert(*this, index_head.sel == index_component_t::SEL_BIT);
ivl_assert(*this, index_head.msb != 0);
ivl_assert(*this, index_head.lsb == 0);
NetExpr*word = elab_and_eval(des, scope, index_head.msb, -1);
// If there is a non-zero base to the memory, then build an
// expression to calculate the canonical address.
if (long base = reg->array_first()) {
word = make_add_expr(word, 0-base);
if (NetExpr*tmp = word->eval_tree()) {
word = tmp;
}
}
NetAssign_*lv = new NetAssign_(reg);
lv->set_word(word);
if (debug_elaborate)
cerr << get_line() << ": debug: Set array word=" << *word << endl;
// Test for the case that the index is a constant, and is out
// of bounds. The "word" expression is the word index already
// converted to canonical address, so this just needs to check
// that the address is not too big.
if (NetEConst*word_const = dynamic_cast<NetEConst*>(word)) {
verinum word_val = word_const->value();
long index = word_val.as_long();
if (index < 0 || index >= reg->array_count()) {
cerr << get_line() << ": warning: Constant array index "
<< (index + reg->array_first())
<< " is out of range for array "
<< reg->name() << "." << endl;
}
}
/* An array word may also have part selects applied to them. */
index_component_t::ctype_t use_sel = index_component_t::SEL_NONE;
if (name_tail.index.size() > 1)
use_sel = name_tail.index.back().sel;
if (use_sel == index_component_t::SEL_PART)
elaborate_lval_net_part_(des, scope, lv);
if (use_sel == index_component_t::SEL_IDX_UP)
elaborate_lval_net_idx_up_(des, scope, lv);
if (use_sel == index_component_t::SEL_IDX_DO)
elaborate_lval_net_idx_do_(des, scope, lv);
return lv;
}
bool PEIdent::elaborate_lval_net_part_(Design*des,
NetScope*scope,
NetAssign_*lv) const
{
long msb, lsb;
bool flag = calculate_parts_(des, scope, msb, lsb);
if (!flag)
return false;
NetNet*reg = lv->sig();
assert(reg);
if (msb == reg->msb() && lsb == reg->lsb()) {
/* No bit select, and part select covers the entire
vector. Simplest case. */
} else {
/* If the bit/part select is constant, then make the
NetAssign_ only as wide as it needs to be and connect
only to the selected bits of the reg. */
unsigned loff = reg->sb_to_idx(lsb);
unsigned moff = reg->sb_to_idx(msb);
unsigned wid = moff - loff + 1;
if (moff < loff) {
cerr << get_line() << ": error: part select "
<< reg->name() << "[" << msb<<":"<<lsb<<"]"
<< " is reversed." << endl;
des->errors += 1;
return false;
}
/* If the part select extends beyond the extreme of the
variable, then report an error. Note that loff is
converted to normalized form so is relative the
variable pins. */
if ((wid + loff) > reg->vector_width()) {
cerr << get_line() << ": error: bit/part select "
<< reg->name() << "[" << msb<<":"<<lsb<<"]"
<< " is out of range." << endl;
des->errors += 1;
return false;
}
lv->set_part(new NetEConst(verinum(loff)), wid);
}
return true;
}
bool PEIdent::elaborate_lval_net_idx_up_(Design*des,
NetScope*scope,
NetAssign_*lv) const
{
const name_component_t&name_tail = path_.back();;
ivl_assert(*this, !name_tail.index.empty());
const index_component_t&index_tail = name_tail.index.back();
ivl_assert(*this, index_tail.msb != 0);
ivl_assert(*this, index_tail.lsb != 0);
NetNet*reg = lv->sig();
assert(reg);
if (reg->type() != NetNet::REG) {
cerr << get_line() << ": error: " << path_ <<
" is not a reg/integer/time in " << scope_path(scope) <<
"." << endl;
cerr << reg->get_line() << ": : " << path_ <<
" is declared here as " << reg->type() << "." << endl;
if (msb_ == 0) {
cerr << get_line() << ": error: Assign to memory \""
<< mem->name() << "\" requires a word select index."
<< endl;
des->errors += 1;
return false;
return 0;
}
unsigned long wid;
calculate_up_do_width_(des, scope, wid);
if (msb_ && lsb_) {
cerr << get_line() << ": error: Cannot use part select on "
<< "memory \"" << mem->name() << ".\"" << endl;
des->errors += 1;
return 0;
}
NetExpr*base = elab_and_eval(des, scope, index_tail.msb, -1);
assert(msb_ && !lsb_);
/* Correct the mux for the range of the vector. */
if (reg->msb() < reg->lsb())
base = make_sub_expr(reg->lsb(), base);
else if (reg->lsb() != 0)
base = make_add_expr(base, - reg->lsb());
NetExpr*ix = msb_->elaborate_expr(des, scope);
if (ix == 0)
return 0;
if (debug_elaborate)
cerr << get_line() << ": debug: Set part select width="
<< wid << ", base=" << *base << endl;
/* Evaluate the memory index expression down as must as
possible. Ideally, we can get it down to a constant. */
if (! dynamic_cast<NetEConst*>(ix)) {
NetExpr*tmp = ix->eval_tree();
if (tmp) {
tmp->set_line(*ix);
delete ix;
ix = tmp;
}
}
lv->set_part(base, wid);
return true;
NetAssign_*lv = new NetAssign_(mem);
lv->set_bmux(ix);
lv->set_part(0, mem->width());
return lv;
}
bool PEIdent::elaborate_lval_net_idx_do_(Design*des,
NetScope*scope,
NetAssign_*lv) const
{
const name_component_t&name_tail = path_.back();;
ivl_assert(*this, !name_tail.index.empty());
const index_component_t&index_tail = name_tail.index.back();
ivl_assert(*this, index_tail.msb != 0);
ivl_assert(*this, index_tail.lsb != 0);
cerr << get_line() << ": internal error: don't know how to "
"deal with SEL_IDX_DO in lval?" << endl;
des->errors += 1;
return false;
}
NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*, bool) const
NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*) const
{
cerr << get_line() << ": error: Constant values not allowed "
<< "in l-value expressions." << endl;
@@ -500,66 +352,6 @@ NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*, bool) const
/*
* $Log: elab_lval.cc,v $
* Revision 1.44 2007/06/02 03:42:12 steve
* Properly evaluate scope path expressions.
*
* Revision 1.43 2007/05/24 04:07:11 steve
* Rework the heirarchical identifier parse syntax and pform
* to handle more general combinations of heirarch and bit selects.
*
* Revision 1.42 2007/03/14 05:06:49 steve
* Replace some asserts with ivl_asserts.
*
* Revision 1.41 2007/03/05 05:59:10 steve
* Handle processes within generate loops.
*
* Revision 1.40 2007/02/27 05:14:38 steve
* Detect and warn about lval array index out fo bounds.
*
* Revision 1.39 2007/02/01 05:25:26 steve
* Error message better reflects more general reality.
*
* Revision 1.38 2007/01/16 05:44:15 steve
* Major rework of array handling. Memories are replaced with the
* more general concept of arrays. The NetMemory and NetEMemory
* classes are removed from the ivl core program, and the IVL_LPM_RAM
* lpm type is removed from the ivl_target API.
*
* Revision 1.37 2006/11/04 06:19:25 steve
* Remove last bits of relax_width methods, and use test_width
* to calculate the width of an r-value expression that may
* contain unsized numbers.
*
* Revision 1.36 2006/06/02 04:48:50 steve
* Make elaborate_expr methods aware of the width that the context
* requires of it. In the process, fix sizing of the width of unary
* minus is context determined sizes.
*
* Revision 1.35 2006/04/16 00:54:04 steve
* Cleanup lval part select handling.
*
* Revision 1.34 2006/04/16 00:15:43 steve
* Fix part selects in l-values.
*
* Revision 1.33 2006/02/02 02:43:57 steve
* Allow part selects of memory words in l-values.
*
* Revision 1.32 2005/07/11 16:56:50 steve
* Remove NetVariable and ivl_variable_t structures.
*
* Revision 1.31 2004/12/29 23:55:43 steve
* Unify elaboration of l-values for all proceedural assignments,
* including assing, cassign and force.
*
* Generate NetConcat devices for gate outputs that feed into a
* vector results. Use this to hande gate arrays. Also let gate
* arrays handle vectors of gates when the outputs allow for it.
*
* Revision 1.30 2004/12/11 02:31:25 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.29 2004/10/04 01:10:52 steve
* Clean up spurious trailing white space.
*
@@ -568,5 +360,95 @@ NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*, bool) const
*
* Revision 1.27 2003/09/19 03:30:05 steve
* Fix name search in elab_lval.
*
* Revision 1.26 2003/01/27 05:09:17 steve
* Spelling fixes.
*
* Revision 1.25 2003/01/26 21:15:58 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
* Revision 1.24 2003/01/19 00:35:39 steve
* Detect null arguments to concatenation operator.
*
* Revision 1.23 2002/11/21 23:27:51 steve
* Precalculate indices to l-value arrays.
*
* Revision 1.22 2002/11/21 18:15:40 steve
* Fix const test of msb in assignment l-values.
*
* Revision 1.21 2002/11/02 01:10:49 steve
* Detect memories without work index in l-value.
*
* 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.
*
* Revision 1.16 2001/11/08 05:15:50 steve
* Remove string paths from PExpr elaboration.
*
* Revision 1.15 2001/11/07 04:01:59 steve
* eval_const uses scope instead of a string path.
*
* Revision 1.14 2001/08/25 23:50:02 steve
* Change the NetAssign_ class to refer to the signal
* instead of link into the netlist. This is faster
* and uses less space. Make the NetAssignNB carry
* the delays instead of the NetAssign_ lval objects.
*
* Change the vvp code generator to support multiple
* l-values, i.e. concatenations of part selects.
*
* Revision 1.13 2001/07/25 03:10:48 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.12 2001/02/09 03:16:48 steve
* Report bit/part select out of range errors. (PR#133)
*
* Revision 1.11 2001/01/10 03:13:23 steve
* Build task outputs as lval instead of nets. (PR#98)
*
* Revision 1.10 2001/01/06 06:31:58 steve
* declaration initialization for time variables.
*
* Revision 1.9 2001/01/06 02:29:36 steve
* Support arrays of integers.
*
* Revision 1.8 2000/12/12 06:14:51 steve
* sorry for concatenated memories in l-values. (PR#76)
*
* Revision 1.7 2000/12/01 02:55:37 steve
* Detect part select errors on l-values.
*
* Revision 1.6 2000/10/31 17:49:02 steve
* Support time variables.
*
* Revision 1.5 2000/10/26 17:09:46 steve
* Fix handling of errors in behavioral lvalues. (PR#28)
*
* Revision 1.4 2000/09/10 15:43:59 steve
* Some error checking.
*
* Revision 1.3 2000/09/10 03:59:59 steve
* Agressively merge NetAssign_ within concatenations.
*
* Revision 1.2 2000/09/10 02:18:16 steve
* elaborate complex l-values
*
* Revision 1.1 2000/09/09 15:21:26 steve
* move lval elaboration to PExpr virtual methods.
*
*/
+1115 -1648
View File
File diff suppressed because it is too large Load Diff
+20 -58
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: elab_pexpr.cc,v 1.28 2007/06/02 03:42:12 steve Exp $"
#ident "$Id: elab_pexpr.cc,v 1.21 2004/02/20 06:22:56 steve Exp $"
#endif
# include "config.h"
@@ -25,7 +25,6 @@
# include "PExpr.h"
# include "compiler.h"
# include "util.h"
# include "netmisc.h"
# include <iostream>
@@ -54,7 +53,7 @@ NetExpr*PEBinary::elaborate_pexpr (Design*des, NetScope*scope) const
return 0;
}
NetEBinary*tmp = elaborate_expr_base_(des, lp, rp, -1);
NetEBinary*tmp = elaborate_expr_base_(des, lp, rp);
return tmp;
}
@@ -120,7 +119,7 @@ NetEConcat* PEConcat::elaborate_pexpr(Design*des, NetScope*scope) const
NetExpr*PEFNumber::elaborate_pexpr(Design*des, NetScope*scope) const
{
return elaborate_expr(des, scope, -1, false);
return elaborate_expr(des, scope);
}
/*
@@ -131,53 +130,42 @@ NetExpr*PEFNumber::elaborate_pexpr(Design*des, NetScope*scope) const
*/
NetExpr*PEIdent::elaborate_pexpr(Design*des, NetScope*scope) const
{
pform_name_t path = path_;
name_component_t name_tail = path_.back();
path.pop_back();
hname_t path = path_;
char*name = path.remove_tail_name();
NetScope*pscope = scope;
if (path_.size() > 0) {
list<hname_t> tmp = eval_scope_path(des, scope, path);
pscope = des->find_scope(scope, tmp);
}
if (path.peek_name(0))
pscope = des->find_scope(scope, path);
const NetExpr*ex_msb;
const NetExpr*ex_lsb;
const NetExpr*ex = pscope->get_parameter(name_tail.name, ex_msb, ex_lsb);
perm_string perm_name = lex_strings.make(name);
delete name;
const NetExpr*ex = pscope->get_parameter(perm_name);
if (ex == 0) {
cerr << get_line() << ": error: identifier ``" << name_tail.name <<
"'' is not a parameter in "<< scope_path(scope)<< "." << endl;
cerr << get_line() << ": error: identifier ``" << path_ <<
"'' is not a parameter in " << scope->name() << "." << endl;
des->errors += 1;
return 0;
}
NetExpr*res = new NetEParam(des, pscope, name_tail.name);
NetExpr*res = new NetEParam(des, pscope, perm_name);
res->set_line(*this);
assert(res);
index_component_t::ctype_t use_sel = index_component_t::SEL_NONE;
if (!name_tail.index.empty())
use_sel = name_tail.index.back().sel;
switch (use_sel) {
case index_component_t::SEL_NONE:
break;
default:
case index_component_t::SEL_PART:
assert(idx_ == 0);
if (msb_ && lsb_) {
cerr << get_line() << ": sorry: Cannot part select "
"bits of parameters." << endl;
des->errors += 1;
break;
case index_component_t::SEL_BIT:
} else if (msb_) {
/* We have here a bit select. Insert a NetESelect node
to handle it. */
NetExpr*tmp = name_tail.index.back().msb->elaborate_pexpr(des, scope);
NetExpr*tmp = msb_->elaborate_pexpr(des, scope);
if (tmp != 0) {
res = new NetESelect(res, tmp, 1);
}
break;
}
return res;
@@ -188,13 +176,13 @@ NetExpr*PEIdent::elaborate_pexpr(Design*des, NetScope*scope) const
*/
NetExpr*PENumber::elaborate_pexpr(Design*des, NetScope*sc) const
{
return elaborate_expr(des, sc, -1, false);
return elaborate_expr(des, sc);
}
NetEConst* PEString::elaborate_pexpr(Design*des, NetScope*scope) const
{
return elaborate_expr(des, scope, -1, false);
return elaborate_expr(des, scope);
}
NetETernary* PETernary::elaborate_pexpr(Design*des, NetScope*scope) const
@@ -243,32 +231,6 @@ NetExpr*PEUnary::elaborate_pexpr (Design*des, NetScope*scope) const
/*
* $Log: elab_pexpr.cc,v $
* Revision 1.28 2007/06/02 03:42:12 steve
* Properly evaluate scope path expressions.
*
* Revision 1.27 2007/05/24 04:07:11 steve
* Rework the heirarchical identifier parse syntax and pform
* to handle more general combinations of heirarch and bit selects.
*
* Revision 1.26 2007/04/26 03:06:22 steve
* Rework hname_t to use perm_strings.
*
* Revision 1.25 2006/11/04 06:19:25 steve
* Remove last bits of relax_width methods, and use test_width
* to calculate the width of an r-value expression that may
* contain unsized numbers.
*
* Revision 1.24 2006/06/02 04:48:50 steve
* Make elaborate_expr methods aware of the width that the context
* requires of it. In the process, fix sizing of the width of unary
* minus is context determined sizes.
*
* Revision 1.23 2006/02/02 02:43:58 steve
* Allow part selects of memory words in l-values.
*
* Revision 1.22 2005/11/27 05:56:20 steve
* Handle bit select of parameter with ranges.
*
* Revision 1.21 2004/02/20 06:22:56 steve
* parameter keys are per_strings.
*
+75 -232
View File
@@ -17,12 +17,11 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: elab_scope.cc,v 1.46 2007/06/02 03:42:12 steve Exp $"
#ident "$Id: elab_scope.cc,v 1.35 2004/09/10 00:15:17 steve Exp $"
#endif
# include "config.h"
# include "compiler.h"
# include "netmisc.h"
# include <iostream>
# include <stdio.h>
@@ -34,10 +33,10 @@
*/
# include "Module.h"
# include "PData.h"
# include "PEvent.h"
# include "PExpr.h"
# include "PGate.h"
# include "PGenerate.h"
# include "PTask.h"
# include "PWire.h"
# include "Statement.h"
@@ -46,12 +45,11 @@
# include <typeinfo>
# include <assert.h>
bool Module::elaborate_scope(Design*des, NetScope*scope,
const replace_t&replacements) const
bool Module::elaborate_scope(Design*des, NetScope*scope) const
{
if (debug_scopes) {
cerr << get_line() << ": debug: Elaborate scope "
<< scope_path(scope) << "." << endl;
<< scope->name() << "." << endl;
}
// Generate all the parameters that this instance of this
@@ -66,7 +64,7 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
// place of the elaborated expression.
typedef map<perm_string,param_expr_t>::const_iterator mparm_it_t;
typedef map<pform_name_t,PExpr*>::const_iterator pform_parm_it_t;
typedef map<hname_t,PExpr*>::const_iterator hparm_it_t;
// This loop scans the parameters in the module, and creates
@@ -77,7 +75,8 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
NetEParam*tmp = new NetEParam;
tmp->set_line(*((*cur).second.expr));
tmp->cast_signed( (*cur).second.signed_flag );
if ((*cur).second.msb)
tmp->cast_signed( (*cur).second.signed_flag );
scope->set_parameter((*cur).first, tmp, 0, 0, false);
}
@@ -108,7 +107,7 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
NetExpr*val = ex->elaborate_pexpr(des, scope);
NetExpr*msb = 0;
NetExpr*lsb = 0;
bool signed_flag = (*cur).second.signed_flag;
bool signed_flag = false;
/* If the parameter declaration includes msb and lsb,
then use them to calculate a width for the
@@ -119,47 +118,16 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
msb = (*cur).second.msb ->elaborate_pexpr(des, scope);
assert(msb);
lsb = (*cur).second.lsb ->elaborate_pexpr(des, scope);
signed_flag = (*cur).second.signed_flag;
}
if (signed_flag) {
/* If explicitly signed, then say so. */
val->cast_signed(true);
} else if ((*cur).second.msb) {
/* If there is a range, then the signedness comes
from the type and not the expression. */
val->cast_signed(signed_flag);
} else {
/* otherwise, let the expression describe
itself. */
signed_flag = val->has_sign();
}
val->cast_signed(signed_flag);
val = scope->set_parameter((*cur).first, val,
msb, lsb, signed_flag);
assert(val);
delete val;
}
/* run parameter replacements that were collected from the
containing scope and meant for me. */
for (replace_t::const_iterator cur = replacements.begin()
; cur != replacements.end() ; cur ++) {
NetExpr*val = (*cur).second;
if (debug_scopes) {
cerr << get_line() << ": debug: "
<< "Replace " << (*cur).first
<< " with expression " << *val
<< " from " << val->get_line() << "." << endl;
}
bool flag = scope->replace_parameter((*cur).first, val);
if (! flag) {
cerr << val->get_line() << ": warning: parameter "
<< (*cur).first << " not found in "
<< scope_path(scope) << "." << endl;
}
}
for (mparm_it_t cur = localparams.begin()
; cur != localparams.end() ; cur ++) {
@@ -200,7 +168,7 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
// here because the parameter receiving the assignment may be
// in a scope not discovered by this pass.
for (pform_parm_it_t cur = defparms.begin()
for (hparm_it_t cur = defparms.begin()
; cur != defparms.end() ; cur ++ ) {
PExpr*ex = (*cur).second;
@@ -221,17 +189,6 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
delete[]attr;
// Generate schemes can create new scopes in the form of
// generated code. Scan the generate schemes, and *generate*
// new scopes, which is slightly different from simple
// elaboration.
typedef list<PGenerate*>::const_iterator generate_it_t;
for (generate_it_t cur = generate_schemes.begin()
; cur != generate_schemes.end() ; cur ++ ) {
(*cur) -> generate_scope(des, scope);
}
// Tasks introduce new scopes, so scan the tasks in this
// module. Create a scope for the task and pass that to the
@@ -243,8 +200,7 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
for (tasks_it_t cur = tasks_.begin()
; cur != tasks_.end() ; cur ++ ) {
hname_t use_name( (*cur).first );
NetScope*task_scope = new NetScope(scope, use_name,
NetScope*task_scope = new NetScope(scope, (*cur).first,
NetScope::TASK);
(*cur).second->elaborate_scope(des, task_scope);
}
@@ -259,8 +215,7 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
for (funcs_it_t cur = funcs_.begin()
; cur != funcs_.end() ; cur ++ ) {
hname_t use_name( (*cur).first );
NetScope*func_scope = new NetScope(scope, use_name,
NetScope*func_scope = new NetScope(scope, (*cur).first,
NetScope::FUNC);
(*cur).second->elaborate_scope(des, func_scope);
}
@@ -290,7 +245,7 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
}
// Scan through all the named events in this scope. We do not
// need anything more than the current scope to do this
// need anything more then the current scope to do this
// elaboration, so do it now. This allows for normal
// elaboration to reference these events.
@@ -300,119 +255,15 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
(*et).second->elaborate_scope(des, scope);
}
for (map<hname_t,PData*>::const_iterator cur = datum.begin()
; cur != datum.end() ; cur ++ ) {
(*cur).second->elaborate_scope(des, scope);
}
return des->errors == 0;
}
bool PGenerate::generate_scope(Design*des, NetScope*container)
{
switch (scheme_type) {
case GS_LOOP:
return generate_scope_loop_(des, container);
default:
cerr << get_line() << ": sorry: Generate of this sort"
<< " is not supported yet!" << endl;
return false;
}
}
/*
* This is the elaborate scope method for a generate loop.
*/
bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
{
// We're going to need a genvar...
int genvar;
// The initial value for the genvar does not need (nor can it
// use) the genvar itself, so we can evaluate this expression
// the same way any other paramter value is evaluated.
NetExpr*init_ex = elab_and_eval(des, container, loop_init, -1);
NetEConst*init = dynamic_cast<NetEConst*> (init_ex);
if (init == 0) {
cerr << get_line() << ": error: Cannot evaluate genvar"
<< " init expression: " << *loop_init << endl;
des->errors += 1;
return false;
}
genvar = init->value().as_long();
delete init_ex;
if (debug_elaborate)
cerr << get_line() << ": debug: genvar init = " << genvar << endl;
container->genvar_tmp = loop_index;
container->genvar_tmp_val = 0;
NetExpr*test_ex = elab_and_eval(des, container, loop_test, -1);
NetEConst*test = dynamic_cast<NetEConst*>(test_ex);
assert(test);
while (test->value().as_long()) {
// The actual name of the scope includes the genvar so
// that each instance has a unique name in the
// container. The format of using [] is part of the
// Verilog standard.
hname_t use_name (scope_name, genvar);
if (debug_elaborate)
cerr << get_line() << ": debug: "
<< "Create generated scope " << use_name << endl;
NetScope*scope = new NetScope(container, use_name,
NetScope::GENBLOCK);
// Set in the scope a localparam for the value of the
// genvar within this instance of the generate
// block. Code within this scope thus has access to the
// genvar as a constant.
{
verinum genvar_verinum(genvar);
genvar_verinum.has_sign(true);
NetEConstParam*gp = new NetEConstParam(scope,
loop_index,
genvar_verinum);
scope->set_localparam(loop_index, gp);
if (debug_elaborate)
cerr << get_line() << ": debug: "
<< "Create implicit localparam "
<< loop_index << " = " << genvar_verinum << endl;
}
// Scan the generated scope for gates that may create
// their own scopes.
typedef list<PGate*>::const_iterator pgate_list_it_t;
for (pgate_list_it_t cur = gates.begin()
; cur != gates.end() ; cur ++) {
(*cur) ->elaborate_scope(des, scope);
}
scope_list_.push_back(scope);
// Calculate the step for the loop variable.
NetExpr*step_ex = elab_and_eval(des, container, loop_step, -1);
NetEConst*step = dynamic_cast<NetEConst*>(step_ex);
assert(step);
if (debug_elaborate)
cerr << get_line() << ": debug: genvar step from "
<< genvar << " to " << step->value().as_long() << endl;
genvar = step->value().as_long();
container->genvar_tmp_val = genvar;
delete step;
delete test_ex;
test_ex = elab_and_eval(des, container, loop_test, -1);
test = dynamic_cast<NetEConst*>(test_ex);
assert(test);
}
// Clear the genvar_tmp field in the scope to reflect that the
// genvar is no longer value for evaluating expressions.
container->genvar_tmp = perm_string();
return true;
}
void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
{
if (get_name() == "") {
@@ -429,7 +280,7 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
// about to create, and if I find it then somebody beat me to
// it.
if (sc->child(hname_t(get_name()))) {
if (sc->child(get_name())) {
cerr << get_line() << ": error: Instance/Scope name " <<
get_name() << " already used in this context." <<
endl;
@@ -452,17 +303,15 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
<< "module " << mod->mod_name() << " within itself." << endl;
cerr << get_line() << ": : The offending instance is "
<< scope_path(sc) << "." << get_name() << " within "
<< scope_path(scn) << "." << endl;
<< sc->name() << "." << get_name() << " within "
<< scn->name() << "." << endl;
des->errors += 1;
return;
}
NetExpr*mse = msb_ ? elab_and_eval(des, sc, msb_, -1) : 0;
NetExpr*lse = lsb_ ? elab_and_eval(des, sc, lsb_, -1) : 0;
NetEConst*msb = dynamic_cast<NetEConst*> (mse);
NetEConst*lsb = dynamic_cast<NetEConst*> (lse);
verinum*msb = msb_ ? msb_->eval_const(des, sc) : 0;
verinum*lsb = lsb_ ? lsb_->eval_const(des, sc) : 0;
assert( (msb == 0) || (lsb != 0) );
@@ -473,15 +322,12 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
if (msb) {
instance_array = true;
instance_high = msb->value().as_long();
instance_low = lsb->value().as_long();
instance_high = msb->as_long();
instance_low = lsb->as_long();
if (instance_high > instance_low)
instance_count = instance_high - instance_low + 1;
else
instance_count = instance_low - instance_high + 1;
delete mse;
delete lse;
}
NetScope::scope_vec_t instances (instance_count);
@@ -496,21 +342,24 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
// instantiation line.
for (int idx = 0 ; idx < instance_count ; idx += 1) {
hname_t use_name (get_name());
perm_string use_name = get_name();
if (instance_array) {
char name_buf[128];
int instance_idx = idx;
if (instance_low < instance_high)
instance_idx = instance_low + idx;
else
instance_idx = instance_low - idx;
use_name = hname_t(get_name(), instance_idx);
snprintf(name_buf, sizeof name_buf,
"%s[%d]", get_name().str(), instance_idx);
use_name = lex_strings.make(name_buf);
}
if (debug_scopes) {
cerr << get_line() << ": debug: Module instance " << use_name
<< " becomes child of " << scope_path(sc)
<< " becomes child of " << sc->name()
<< "." << endl;
}
@@ -526,6 +375,13 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
my_scope->time_precision(mod->time_precision);
des->set_precision(mod->time_precision);
// This call actually arranges for the description of the
// module type to process this instance and handle parameters
// and sub-scopes that might occur. Parameters are also
// created in that scope, as they exist. (I'll override them
// later.)
mod->elaborate_scope(des, my_scope);
// Look for module parameter replacements. The "replace" map
// maps parameter name to replacement expression that is
// passed. It is built up by the ordered overrides or named
@@ -568,8 +424,6 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
}
Module::replace_t replace_net;
// And here we scan the replacements we collected. Elaborate
// the expression in my context, then replace the sub-scope
// parameter value with the new expression.
@@ -579,16 +433,13 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
PExpr*tmp = (*cur).second;
NetExpr*val = tmp->elaborate_pexpr(des, sc);
replace_net[(*cur).first] = 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;
}
}
// This call actually arranges for the description of the
// module type to process this instance and handle parameters
// and sub-scopes that might occur. Parameters are also
// created in that scope, as they exist. (I'll override them
// later.)
mod->elaborate_scope(des, my_scope, replace_net);
}
/* Stash the instance array of scopes into the parent
@@ -597,6 +448,34 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
sc->instance_arrays[get_name()] = instances;
}
/*
* Elaborate the datum within the module. This variable may be
* within a subscope (i.e., a function or task) so use the components
* of the name to find the precise scope where this item goes.
*/
void PData::elaborate_scope(Design*des, NetScope*scope) const
{
NetScope*sub_scope = scope;
for (unsigned idx = 0 ; idx < (hname_.component_count()-1); idx += 1) {
sub_scope = sub_scope->child(hname_.peek_name(idx));
if (sub_scope == 0) {
cerr << get_line() << ": internal error: "
<< "Could not find sub-scope "
<< hname_.peek_name(idx) << " of "
<< hname_ << " in module " << scope->name()
<< endl;
des->errors += 1;
return;
}
}
const char*basename = hname_.peek_tail_name();
NetVariable*tmp = new NetVariable(lex_strings.make(basename));
tmp->set_line(*this);
sub_scope->add_variable(tmp);
}
/*
* The isn't really able to create new scopes, but it does create the
* event name in the current scope, so can be done during the
@@ -647,7 +526,7 @@ void PBlock::elaborate_scope(Design*des, NetScope*scope) const
NetScope*my_scope = scope;
if (name_ != 0) {
my_scope = new NetScope(scope, hname_t(name_), bl_type_==BL_PAR
my_scope = new NetScope(scope, name_, bl_type_==BL_PAR
? NetScope::FORK_JOIN
: NetScope::BEGIN_END);
}
@@ -756,42 +635,6 @@ void PWhile::elaborate_scope(Design*des, NetScope*scope) const
/*
* $Log: elab_scope.cc,v $
* Revision 1.46 2007/06/02 03:42:12 steve
* Properly evaluate scope path expressions.
*
* Revision 1.45 2007/05/24 04:07:11 steve
* Rework the heirarchical identifier parse syntax and pform
* to handle more general combinations of heirarch and bit selects.
*
* Revision 1.44 2007/03/22 16:08:15 steve
* Spelling fixes from Larry
*
* Revision 1.43 2007/03/08 06:11:35 steve
* Elaborate scopes of modules instantated in generate loops.
*
* Revision 1.42 2007/03/05 05:59:10 steve
* Handle processes within generate loops.
*
* Revision 1.41 2006/06/02 04:48:50 steve
* Make elaborate_expr methods aware of the width that the context
* requires of it. In the process, fix sizing of the width of unary
* minus is context determined sizes.
*
* Revision 1.40 2006/04/12 05:05:03 steve
* Use elab_and_eval to evaluate genvar expressions.
*
* Revision 1.39 2006/04/10 00:37:42 steve
* Add support for generate loops w/ wires and gates.
*
* Revision 1.38 2006/03/30 01:49:07 steve
* Fix instance arrays indexed by overridden parameters.
*
* Revision 1.37 2006/03/18 22:53:38 steve
* Support more parameter syntax.
*
* Revision 1.36 2005/07/11 16:56:50 steve
* Remove NetVariable and ivl_variable_t structures.
*
* Revision 1.35 2004/09/10 00:15:17 steve
* Missing stdio.h header for warnings.
*
+90 -288
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: elab_sig.cc,v 1.52 2007/06/02 03:42:12 steve Exp $"
#ident "$Id: elab_sig.cc,v 1.36 2004/09/27 22:34:10 steve Exp $"
#endif
# include "config.h"
@@ -27,14 +27,12 @@
# include "Module.h"
# include "PExpr.h"
# include "PGate.h"
# include "PGenerate.h"
# include "PTask.h"
# include "PWire.h"
# include "compiler.h"
# include "netlist.h"
# include "netmisc.h"
# include "util.h"
# include "ivl_assert.h"
/*
* This local function checks if a named signal is connected to a
@@ -42,10 +40,8 @@
* within the port_t that have a matching name.
*/
static bool signal_is_in_port(const svector<Module::port_t*>&ports,
NetNet*sig)
const hname_t&name)
{
perm_string name = sig->name();
for (unsigned idx = 0 ; idx < ports.count() ; idx += 1) {
Module::port_t*pp = ports[idx];
@@ -56,15 +52,9 @@ static bool signal_is_in_port(const svector<Module::port_t*>&ports,
// This port has an internal connection. In this case,
// the port has 0 or more NetEIdent objects concatenated
// together that form the port.
// Note that module ports should not have any heirarchy
// in their names: they are in the root of the module
// scope by definition.
for (unsigned cc = 0 ; cc < pp->expr.count() ; cc += 1) {
perm_string pname = peek_tail_name(pp->expr[cc]->path());
assert(pp->expr[cc]);
if (pname == name)
if (pp->expr[cc]->path() == name)
return true;
}
}
@@ -72,28 +62,14 @@ static bool signal_is_in_port(const svector<Module::port_t*>&ports,
return false;
}
#if 0
static NetNet*find_signal_in_scope(NetScope*scope, const hname_t&path)
{
NetScope*cur = scope;
unsigned idx = 0;
while (path.peek_name(idx+1)) {
cur = cur->child(path.peek_name(idx));
if (cur == 0)
return 0;
idx += 1;
}
return cur->find_signal(path.peek_name(idx));
}
#endif
bool Module::elaborate_sig(Design*des, NetScope*scope) const
{
bool flag = true;
// Get all the explicitly declared wires of the module and
// start the signals list with them.
const map<hname_t,PWire*>&wl = get_wires();
// 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) {
@@ -101,12 +77,12 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
if (pp == 0)
continue;
map<pform_name_t,PWire*>::const_iterator wt;
map<hname_t,PWire*>::const_iterator wt;
for (unsigned cc = 0 ; cc < pp->expr.count() ; cc += 1) {
pform_name_t port_path (pp->expr[cc]->path());
wt = wires_.find(port_path);
hname_t port_path (pp->expr[cc]->path());
wt = wl.find(port_path);
if (wt == wires_.end()) {
if (wt == wl.end()) {
cerr << get_line() << ": error: "
<< "Port " << pp->expr[cc]->path() << " ("
<< (idx+1) << ") of module " << name_
@@ -126,11 +102,14 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
}
}
for (map<pform_name_t,PWire*>::const_iterator wt = wires_.begin()
; wt != wires_.end() ; wt ++ ) {
for (map<hname_t,PWire*>::const_iterator wt = wl.begin()
; wt != wl.end()
; wt ++ ) {
PWire*cur = (*wt).second;
NetNet*sig = cur->elaborate_sig(des, scope);
cur->elaborate_sig(des, scope);
NetNet*sig = scope->find_signal_in_child(cur->path());
// If this wire is a signal of the module (as opposed to
// a port of a function) and is a port, then check that
@@ -142,10 +121,12 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
if (sig && (sig->scope() == scope)
&& (cur->get_port_type() != NetNet::NOT_A_PORT)) {
if (! signal_is_in_port(ports, sig)) {
hname_t name = (*wt).first;
if (! signal_is_in_port(ports, name)) {
cerr << cur->get_line() << ": error: Signal "
<< sig->name() << " has a declared direction "
<< name << " has a declared direction "
<< "but is not a port." << endl;
des->errors += 1;
}
@@ -177,16 +158,6 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
des->errors += 1;
}
}
// Run through all the generate schemes to enaborate the
// signals that they hold. Note that the generate schemes hold
// the scopes that they instantiated, so we don't pass any
// scope in.
typedef list<PGenerate*>::const_iterator generate_it_t;
for (generate_it_t cur = generate_schemes.begin()
; cur != generate_schemes.end() ; cur ++ ) {
(*cur) -> elaborate_sig(des);
}
// Get all the gates of the module and elaborate them by
@@ -208,13 +179,11 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
for (mfunc_it_t cur = funcs_.begin()
; cur != funcs_.end() ; cur ++) {
hname_t use_name ( (*cur).first );
NetScope*fscope = scope->child(use_name);
NetScope*fscope = scope->child((*cur).first);
if (scope == 0) {
cerr << (*cur).second->get_line() << ": internal error: "
<< "Child scope for function " << (*cur).first
<< " missing in " << scope_path(scope) << "." << endl;
<< " missing in " << scope->name() << "." << endl;
des->errors += 1;
continue;
}
@@ -231,7 +200,7 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
for (mtask_it_t cur = tasks_.begin()
; cur != tasks_.end() ; cur ++) {
NetScope*tscope = scope->child( hname_t((*cur).first) );
NetScope*tscope = scope->child((*cur).first);
assert(tscope);
(*cur).second->elaborate_sig(des, tscope);
}
@@ -254,9 +223,9 @@ bool PGModule::elaborate_sig_mod_(Design*des, NetScope*scope,
if (my_scope->parent() != scope) {
cerr << get_line() << ": internal error: "
<< "Instance " << scope_path(my_scope)
<< " is in parent " << scope_path(my_scope->parent())
<< " instead of " << scope_path(scope)
<< "Instance " << my_scope->name()
<< " is in parent " << my_scope->parent()->name()
<< " instead of " << scope->name()
<< endl;
}
assert(my_scope->parent() == scope);
@@ -269,50 +238,6 @@ bool PGModule::elaborate_sig_mod_(Design*des, NetScope*scope,
return flag;
}
bool PGenerate::elaborate_sig(Design*des) const
{
bool flag = true;
typedef list<NetScope*>::const_iterator scope_list_it_t;
for (scope_list_it_t cur = scope_list_.begin()
; cur != scope_list_.end() ; cur ++ ) {
if (debug_elaborate)
cerr << get_line() << ": debug: Elaborate nets in "
<< "scope " << scope_path(*cur) << endl;
flag = elaborate_sig_(des, *cur) & flag;
}
return flag;
}
bool PGenerate::elaborate_sig_(Design*des, NetScope*scope) const
{
// Scan the declared PWires to elaborate the obvious signals
// in the current scope.
typedef map<pform_name_t,PWire*>::const_iterator wires_it_t;
for (wires_it_t wt = wires.begin()
; wt != wires.end() ; wt ++ ) {
PWire*cur = (*wt).second;
if (debug_elaborate)
cerr << get_line() << ": debug: Elaborate PWire "
<< cur->path() << " in scope " << scope_path(scope) << endl;
cur->elaborate_sig(des, scope);
}
typedef list<PGate*>::const_iterator pgate_list_it_t;
for (pgate_list_it_t cur = gates.begin()
; cur != gates.end() ; cur ++) {
(*cur) ->elaborate_sig(des, scope);
}
return true;
}
/*
* A function definition exists within an elaborated module. This
* matters when elaborating signals, as the ports of the function are
@@ -336,19 +261,19 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
}
NetNet*ret_sig = 0;
NetVariable*ret_real = 0;
/* Create the signals/variables of the return value and write
them into the function scope. */
switch (return_type_.type) {
case PTF_REG:
case PTF_REG_S:
if (return_type_.range) {
NetExpr*me = elab_and_eval(des, scope,
(*return_type_.range)[0], -1);
(*return_type_.range)[0]);
assert(me);
NetExpr*le = elab_and_eval(des, scope,
(*return_type_.range)[1], -1);
(*return_type_.range)[1]);
assert(le);
long mnum = 0, lnum = 0;
@@ -376,18 +301,15 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
ret_sig = new NetNet(scope, fname, NetNet::REG);
}
ret_sig->set_line(*this);
ret_sig->set_signed(return_type_.type == PTF_REG_S);
ret_sig->port_type(NetNet::POUTPUT);
ret_sig->data_type(IVL_VT_LOGIC);
break;
case PTF_INTEGER:
ret_sig = new NetNet(scope, fname, NetNet::REG, integer_width);
ret_sig = new NetNet(scope, fname, NetNet::REG, INTEGER_WIDTH);
ret_sig->set_line(*this);
ret_sig->set_signed(true);
ret_sig->set_isint(true);
ret_sig->port_type(NetNet::POUTPUT);
ret_sig->data_type(IVL_VT_LOGIC);
break;
case PTF_TIME:
@@ -396,17 +318,13 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
ret_sig->set_signed(false);
ret_sig->set_isint(false);
ret_sig->port_type(NetNet::POUTPUT);
ret_sig->data_type(IVL_VT_LOGIC);
break;
case PTF_REAL:
case PTF_REALTIME:
ret_sig = new NetNet(scope, fname, NetNet::REG, 1);
ret_sig->set_line(*this);
ret_sig->set_signed(true);
ret_sig->set_isint(false);
ret_sig->port_type(NetNet::POUTPUT);
ret_sig->data_type(IVL_VT_REAL);
ret_real = new NetVariable(fname);
ret_real->set_line(*this);
scope->add_variable(ret_real);
break;
default:
@@ -424,24 +342,22 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
name. We know by design that the port name is given
as two components: <func>.<port>. */
pform_name_t path = (*ports_)[idx]->path();
ivl_assert(*this, path.size() == 2);
perm_string pname = peek_tail_name(path);
perm_string ppath = peek_head_name(path);
hname_t path = (*ports_)[idx]->path();
perm_string pname = lex_strings.make(path.peek_name(1));
perm_string ppath = lex_strings.make(path.peek_name(0));
if (ppath != scope->basename()) {
cerr << get_line() << ": internal error: function "
<< "port " << (*ports_)[idx]->path()
<< " has wrong name for function "
<< scope_path(scope) << "." << endl;
<< scope->name() << "." << endl;
des->errors += 1;
}
NetNet*tmp = scope->find_signal(pname);
if (tmp == 0) {
cerr << get_line() << ": internal error: function "
<< scope_path(scope) << " is missing port "
<< scope->name() << " is missing port "
<< pname << "." << endl;
scope->dump(cerr);
cerr << get_line() << ": Continuing..." << endl;
@@ -454,6 +370,7 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
NetFuncDef*def = 0;
if (ret_sig) def = new NetFuncDef(scope, ret_sig, ports);
if (ret_real) def = new NetFuncDef(scope, ret_real, ports);
assert(def);
scope->set_func_def(def);
@@ -479,34 +396,36 @@ void PTask::elaborate_sig(Design*des, NetScope*scope) const
name. We know by design that the port name is given
as two components: <task>.<port>. */
pform_name_t path = (*ports_)[idx]->path();
ivl_assert(*this, path.size() == 2);
perm_string scope_name = peek_head_name(path);
perm_string port_name = peek_tail_name(path);
hname_t path = (*ports_)[idx]->path();
assert(path.peek_name(0) && path.peek_name(1));
/* check that the current scope really does have the
name of the first component of the task port name. Do
this by looking up the task scope in the parent of
the current scope. */
ivl_assert(*this, scope->basename() == scope_name);
if (scope->parent()->child(path.peek_name(0)) != scope) {
cerr << "internal error: task scope " << path
<< " not the same as scope " << scope->name()
<< "?!" << endl;
return;
}
/* Find the signal for the port. We know by definition
that it is in the scope of the task, so look only in
the scope. */
NetNet*tmp = scope->find_signal(port_name);
NetNet*tmp = scope->find_signal(path.peek_name(1));
if (tmp == 0) {
cerr << get_line() << ": internal error: "
<< "Could not find port " << port_name
<< " in scope " << scope_path(scope) << endl;
<< "Could not find port " << path.peek_name(1)
<< " in scope " << scope->name() << endl;
scope->dump(cerr);
}
ports[idx] = tmp;
}
NetTaskDef*def = new NetTaskDef(scope, ports);
NetTaskDef*def = new NetTaskDef(scope->name(), ports);
scope->set_task_def(def);
}
@@ -522,19 +441,16 @@ bool PGate::elaborate_sig(Design*des, NetScope*scope) const
* elaboration this creates an object in the design that represent the
* defined item.
*/
NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
void PWire::elaborate_sig(Design*des, NetScope*scope) const
{
/* The parser may produce hierarchical names for wires. I here
follow the scopes down to the base where I actually want to
elaborate the NetNet object. */
{ pform_name_t tmp_path = hname_;
tmp_path.pop_back();
while (! tmp_path.empty()) {
name_component_t cur = tmp_path.front();
tmp_path.pop_front();
scope = scope->child( hname_t(cur.name) );
{ hname_t tmp_path = hname_;
free(tmp_path.remove_tail_name());
for (unsigned idx = 0 ; tmp_path.peek_name(idx) ; idx += 1) {
scope = scope->child(tmp_path.peek_name(idx));
if (scope == 0) {
cerr << get_line() << ": internal error: "
@@ -579,7 +495,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
}
NetEConst*tmp;
NetExpr*texpr = elab_and_eval(des, scope, msb_[idx], -1);
NetExpr*texpr = elab_and_eval(des, scope, msb_[idx]);
tmp = dynamic_cast<NetEConst*>(texpr);
if (tmp == 0) {
@@ -587,20 +503,20 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
"Unable to evaluate constant expression ``" <<
*msb_[idx] << "''." << endl;
des->errors += 1;
return 0;
return;
}
mnum[idx] = tmp->value().as_long();
delete texpr;
texpr = elab_and_eval(des, scope, lsb_[idx], -1);
texpr = elab_and_eval(des, scope, lsb_[idx]);
tmp = dynamic_cast<NetEConst*>(texpr);
if (tmp == 0) {
cerr << msb_[idx]->get_line() << ": error: "
"Unable to evaluate constant expression ``" <<
*lsb_[idx] << "''." << endl;
des->errors += 1;
return 0;
return;
}
lnum[idx] = tmp->value().as_long();
@@ -616,7 +532,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
<< "'' declared both as a vector and a scalar."
<< endl;
des->errors += 1;
return 0;
return;
}
@@ -629,7 +545,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
" vs. [" << mnum[0] << ":" << lnum[0] << "]"
" for signal ``" << hname_ << "''" << endl;
des->errors += 1;
return 0;
return;
}
}
@@ -647,10 +563,6 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
attrib_list_t*attrib_list = evaluate_attributes(attributes, nattrib,
des, scope);
long array_s0 = 0;
long array_e0 = 0;
unsigned array_dimensions = 0;
/* If the ident has idx expressions, then this is a
memory. It can only have the idx registers after the msb
and lsb expressions are filled. And, if it has one index,
@@ -658,15 +570,15 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
if (lidx_ || ridx_) {
assert(lidx_ && ridx_);
NetExpr*lexp = elab_and_eval(des, scope, lidx_, -1);
NetExpr*rexp = elab_and_eval(des, scope, ridx_, -1);
NetExpr*lexp = elab_and_eval(des, scope, lidx_);
NetExpr*rexp = elab_and_eval(des, scope, ridx_);
if ((lexp == 0) || (rexp == 0)) {
cerr << get_line() << ": internal error: There is "
<< "a problem evaluating indices for ``"
<< hname_ << "''." << endl;
<< hname_.peek_tail_name() << "''." << endl;
des->errors += 1;
return 0;
return;
}
NetEConst*lcon = dynamic_cast<NetEConst*> (lexp);
@@ -674,10 +586,10 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
if ((lcon == 0) || (rcon == 0)) {
cerr << get_line() << ": internal error: The indices "
<< "are not constant for array ``"
<< hname_ << "''." << endl;
<< "are not constant for memory ``"
<< hname_.peek_tail_name() << "''." << endl;
des->errors += 1;
return 0;
return;
}
verinum lval = lcon->value();
@@ -686,141 +598,31 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
delete lexp;
delete rexp;
array_dimensions = 1;
array_s0 = lval.as_long();
array_e0 = rval.as_long();
perm_string name = lex_strings.make(hname_.peek_tail_name());
long lnum = lval.as_long();
long rnum = rval.as_long();
new NetMemory(scope, name, wid, lnum, rnum);
// The constructor automatically adds the memory object
// to the scope. Do I need to set line number information?
} else {
perm_string name = lex_strings.make(hname_.peek_tail_name());
NetNet*sig = new NetNet(scope, name, wtype, msb, lsb);
sig->set_line(*this);
sig->port_type(port_type_);
sig->set_signed(get_signed());
sig->set_isint(get_isint());
for (unsigned idx = 0 ; idx < nattrib ; idx += 1)
sig->attribute(attrib_list[idx].key, attrib_list[idx].val);
}
/* If the net type is supply0 or supply1, replace it
with a simple wire with a pulldown/pullup with supply
strength. In other words, transform:
supply0 foo;
to:
wire foo;
pulldown #(supply0) (foo);
This reduces the backend burden, and behaves exactly
the same. */
NetLogic*pull = 0;
if (wtype == NetNet::SUPPLY0 || wtype == NetNet::SUPPLY1) {
NetLogic::TYPE pull_type = (wtype==NetNet::SUPPLY1)
? NetLogic::PULLUP
: NetLogic::PULLDOWN;
pull = new NetLogic(scope, scope->local_symbol(),
1, pull_type, wid);
pull->set_line(*this);
pull->pin(0).drive0(Link::SUPPLY);
pull->pin(0).drive1(Link::SUPPLY);
des->add_node(pull);
wtype = NetNet::WIRE;
if (debug_elaborate) {
cerr << get_line() << ": debug: "
<< "Generate a SUPPLY pulldown for the "
<< "supply0 net." << endl;
}
}
perm_string name = peek_tail_name(hname_);
if (debug_elaborate) {
cerr << get_line() << ": debug: Create signal "
<< wtype << " ["<<msb<<":"<<lsb<<"] " << name
<< " in scope " << scope_path(scope) << endl;
}
NetNet*sig = array_dimensions > 0
? new NetNet(scope, name, wtype, msb, lsb, array_s0, array_e0)
: new NetNet(scope, name, wtype, msb, lsb);
ivl_variable_type_t use_data_type = data_type_;
if (use_data_type == IVL_VT_NO_TYPE) {
use_data_type = IVL_VT_LOGIC;
if (debug_elaborate) {
cerr << get_line() << ": debug: "
<< "Signal " << name
<< " in scope " << scope_path(scope)
<< " defaults to data type " << use_data_type << endl;
}
}
sig->data_type(use_data_type);
sig->set_line(*this);
sig->port_type(port_type_);
sig->set_signed(get_signed());
sig->set_isint(get_isint());
if (pull)
connect(sig->pin(0), pull->pin(0));
for (unsigned idx = 0 ; idx < nattrib ; idx += 1)
sig->attribute(attrib_list[idx].key, attrib_list[idx].val);
return sig;
}
/*
* $Log: elab_sig.cc,v $
* Revision 1.52 2007/06/02 03:42:12 steve
* Properly evaluate scope path expressions.
*
* Revision 1.51 2007/05/24 04:07:11 steve
* Rework the heirarchical identifier parse syntax and pform
* to handle more general combinations of heirarch and bit selects.
*
* Revision 1.50 2007/04/26 03:06:22 steve
* Rework hname_t to use perm_strings.
*
* Revision 1.49 2007/04/02 01:12:34 steve
* Seperate arrayness from word count
*
* Revision 1.48 2007/03/08 06:11:35 steve
* Elaborate scopes of modules instantated in generate loops.
*
* Revision 1.47 2007/03/07 04:24:59 steve
* Make integer width controllable.
*
* Revision 1.46 2007/03/06 05:22:49 steve
* Support signed function return values.
*
* Revision 1.45 2007/02/01 05:24:08 steve
* Include type in signal create message.
*
* Revision 1.44 2007/01/29 02:07:34 steve
* Types of task/function arguments set in multiple steps.
*
* Revision 1.43 2007/01/16 05:44:15 steve
* Major rework of array handling. Memories are replaced with the
* more general concept of arrays. The NetMemory and NetEMemory
* classes are removed from the ivl core program, and the IVL_LPM_RAM
* lpm type is removed from the ivl_target API.
*
* Revision 1.42 2006/06/02 04:48:50 steve
* Make elaborate_expr methods aware of the width that the context
* requires of it. In the process, fix sizing of the width of unary
* minus is context determined sizes.
*
* Revision 1.41 2006/04/10 00:37:42 steve
* Add support for generate loops w/ wires and gates.
*
* Revision 1.40 2005/07/11 16:56:50 steve
* Remove NetVariable and ivl_variable_t structures.
*
* Revision 1.39 2005/07/07 16:22:49 steve
* Generalize signals to carry types.
*
* Revision 1.38 2005/02/13 01:15:07 steve
* Replace supply nets with wires connected to pullup/down supply devices.
*
* Revision 1.37 2004/12/11 02:31:25 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.36 2004/09/27 22:34:10 steve
* Cleanup and factoring of autoconf.
*
+475 -1199
View File
File diff suppressed because it is too large Load Diff
+191 -113
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2005 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-2000 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: emit.cc,v 1.89 2007/01/16 05:44:15 steve Exp $"
#ident "$Id: emit.cc,v 1.77.2.2 2006/03/26 23:09:21 steve Exp $"
#endif
# include "config.h"
@@ -57,17 +57,18 @@ bool NetAddSub::emit_node(struct target_t*tgt) const
return true;
}
bool NetArrayDq::emit_node(struct target_t*tgt) const
{
return tgt->lpm_array_dq(this);
}
bool NetCaseCmp::emit_node(struct target_t*tgt) const
{
tgt->net_case_cmp(this);
return true;
}
bool NetCAssign::emit_node(struct target_t*tgt) const
{
tgt->net_cassign(this);
return true;
}
bool NetCLShift::emit_node(struct target_t*tgt) const
{
tgt->lpm_clshift(this);
@@ -80,16 +81,21 @@ bool NetCompare::emit_node(struct target_t*tgt) const
return true;
}
bool NetConcat::emit_node(struct target_t*tgt) const
{
return tgt->concat(this);
}
bool NetConst::emit_node(struct target_t*tgt) const
{
return tgt->net_const(this);
}
bool NetDecode::emit_node(struct target_t*tgt) const
{
return tgt->lpm_decode(this);
}
bool NetDemux::emit_node(struct target_t*tgt) const
{
return tgt->lpm_demux(this);
}
bool NetDivide::emit_node(struct target_t*tgt) const
{
tgt->lpm_divide(this);
@@ -102,9 +108,10 @@ bool NetFF::emit_node(struct target_t*tgt) const
return true;
}
bool NetLiteral::emit_node(struct target_t*tgt) const
bool NetForce::emit_node(struct target_t*tgt) const
{
return tgt->net_literal(this);
tgt->net_force(this);
return true;
}
bool NetModulo::emit_node(struct target_t*tgt) const
@@ -125,29 +132,10 @@ bool NetMux::emit_node(struct target_t*tgt) const
return true;
}
bool NetPartSelect::emit_node(struct target_t*tgt) const
bool NetRamDq::emit_node(struct target_t*tgt) const
{
return tgt->part_select(this);
}
bool NetReplicate::emit_node(struct target_t*tgt) const
{
return tgt->replicate(this);
}
bool NetSignExtend::emit_node(struct target_t*tgt) const
{
return tgt->sign_extend(this);
}
bool NetUReduce::emit_node(struct target_t*tgt) const
{
return tgt->ureduce(this);
}
bool NetSysFunc::emit_node(struct target_t*tgt) const
{
return tgt->net_sysfunction(this);
tgt->lpm_ram_dq(this);
return true;
}
bool NetUserFunc::emit_node(struct target_t*tgt) const
@@ -334,6 +322,9 @@ void NetScope::emit_scope(struct target_t*tgt) const
for (NetEvent*cur = events_ ; cur ; cur = cur->snext_)
tgt->event(cur);
for (NetVariable*cur = vars_ ; cur ; cur = cur->snext_)
tgt->variable(cur);
for (NetScope*cur = sub_ ; cur ; cur = cur->sib_)
cur->emit_scope(tgt);
@@ -343,19 +334,15 @@ void NetScope::emit_scope(struct target_t*tgt) const
tgt->signal(cur);
cur = cur->sig_next_;
} while (cur != signals_->sig_next_);
/* Run the signals again, but this time to connect the
delay paths. This is done as a second pass because
the paths reference other signals that may be later
in the list. We can do it here becase delay paths are
always connected within the scope. */
cur = signals_->sig_next_;
do {
tgt->signal_paths(cur);
cur = cur->sig_next_;
} while (cur != signals_->sig_next_);
}
if (memories_) {
NetMemory*cur = memories_->snext_;
do {
tgt->memory(cur);
cur = cur->snext_;
} while (cur != memories_->snext_);
}
}
bool NetScope::emit_defs(struct target_t*tgt) const
@@ -386,12 +373,13 @@ void NetWhile::emit_proc_recurse(struct target_t*tgt) const
proc_->emit_proc(tgt);
}
int Design::emit(struct target_t*tgt) const
bool Design::emit(struct target_t*tgt) const
{
int rc = 0;
bool rc = true;
if (tgt->start_design(this) == false)
return -2;
rc = rc && tgt->start_design(this);
if (rc == false)
return false;
// enumerate the scopes
for (list<NetScope*>::const_iterator scope = root_scopes_.begin();
@@ -400,36 +388,27 @@ int Design::emit(struct target_t*tgt) const
// emit nodes
bool nodes_rc = true;
if (nodes_) {
NetNode*cur = nodes_->node_next_;
do {
nodes_rc = nodes_rc && cur->emit_node(tgt);
rc = rc && cur->emit_node(tgt);
cur = cur->node_next_;
} while (cur != nodes_->node_next_);
}
// emit task and function definitions
bool tasks_rc = true;
for (list<NetScope*>::const_iterator scope = root_scopes_.begin();
scope != root_scopes_.end(); scope++)
tasks_rc &= (*scope)->emit_defs(tgt);
rc &= (*scope)->emit_defs(tgt);
// emit the processes
bool proc_rc = true;
for (const NetProcTop*idx = procs_ ; idx ; idx = idx->next_)
proc_rc &= idx->emit(tgt);
rc = rc && idx->emit(tgt);
rc = tgt->end_design(this);
if (nodes_rc == false)
return -1;
if (tasks_rc == false)
return -2;
if (proc_rc == false)
return -3;
if (tgt->end_design(this) != 0)
rc = false;
return rc;
}
@@ -464,6 +443,11 @@ void NetECRealParam::expr_scan(struct expr_scan_t*tgt) const
tgt->expr_rparam(this);
}
void NetEMemory::expr_scan(struct expr_scan_t*tgt) const
{
tgt->expr_memory(this);
}
void NetEParam::expr_scan(struct expr_scan_t*tgt) const
{
cerr << get_line() << ":internal error: unexpected NetEParam."
@@ -500,6 +484,11 @@ void NetESignal::expr_scan(struct expr_scan_t*tgt) const
tgt->expr_signal(this);
}
void NetEBitSel::expr_scan(struct expr_scan_t*tgt) const
{
tgt->expr_subsignal(this);
}
void NetETernary::expr_scan(struct expr_scan_t*tgt) const
{
tgt->expr_ternary(this);
@@ -510,7 +499,12 @@ void NetEUnary::expr_scan(struct expr_scan_t*tgt) const
tgt->expr_unary(this);
}
int emit(const Design*des, const char*type)
void NetEVariable::expr_scan(struct expr_scan_t*tgt) const
{
tgt->expr_variable(this);
}
bool emit(const Design*des, const char*type)
{
for (unsigned idx = 0 ; target_table[idx] ; idx += 1) {
const struct target*tgt = target_table[idx];
@@ -521,59 +515,17 @@ int emit(const Design*des, const char*type)
cerr << "error: Code generator type " << type
<< " not found." << endl;
return -1;
return false;
}
/*
* $Log: emit.cc,v $
* Revision 1.89 2007/01/16 05:44:15 steve
* Major rework of array handling. Memories are replaced with the
* more general concept of arrays. The NetMemory and NetEMemory
* classes are removed from the ivl core program, and the IVL_LPM_RAM
* lpm type is removed from the ivl_target API.
* Revision 1.77.2.2 2006/03/26 23:09:21 steve
* Handle asynchronous demux/bit replacements.
*
* Revision 1.88 2006/11/10 05:44:44 steve
* Process delay paths in second path over signals.
*
* Revision 1.87 2006/06/18 04:15:50 steve
* Add support for system functions in continuous assignments.
*
* Revision 1.86 2005/07/11 16:56:50 steve
* Remove NetVariable and ivl_variable_t structures.
*
* Revision 1.85 2005/07/07 16:22:49 steve
* Generalize signals to carry types.
*
* Revision 1.84 2005/05/24 01:44:27 steve
* Do sign extension of structuran nets.
*
* Revision 1.83 2005/02/08 00:12:36 steve
* Add the NetRepeat node, and code generator support.
*
* Revision 1.82 2005/02/03 04:56:20 steve
* laborate reduction gates into LPM_RED_ nodes.
*
* Revision 1.81 2005/01/24 05:28:30 steve
* Remove the NetEBitSel and combine all bit/part select
* behavior into the NetESelect node and IVL_EX_SELECT
* ivl_target expression type.
*
* Revision 1.80 2005/01/22 01:06:55 steve
* Change case compare from logic to an LPM node.
*
* Revision 1.79 2004/12/29 23:55:43 steve
* Unify elaboration of l-values for all proceedural assignments,
* including assing, cassign and force.
*
* Generate NetConcat devices for gate outputs that feed into a
* vector results. Use this to hande gate arrays. Also let gate
* arrays handle vectors of gates when the outputs allow for it.
*
* Revision 1.78 2004/12/11 02:31:26 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
* Revision 1.77.2.1 2006/02/19 00:11:31 steve
* Handle synthesis of FF vectors with l-value decoder.
*
* Revision 1.77 2004/10/04 01:10:53 steve
* Clean up spurious trailing white space.
@@ -600,5 +552,131 @@ int emit(const Design*des, const char*type)
* Revision 1.71 2003/01/26 21:15:58 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
* Revision 1.70 2002/11/03 20:36:10 steve
* Error message for mising code generator type.
*
* 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)
*
* Revision 1.62 2001/08/25 23:50:02 steve
* Change the NetAssign_ class to refer to the signal
* instead of link into the netlist. This is faster
* and uses less space. Make the NetAssignNB carry
* the delays instead of the NetAssign_ lval objects.
*
* Change the vvp code generator to support multiple
* l-values, i.e. concatenations of part selects.
*
* Revision 1.61 2001/07/27 04:51:44 steve
* Handle part select expressions as variants of
* NetESignal/IVL_EX_SIGNAL objects, instead of
* creating new and useless temporary signals.
*
* Revision 1.60 2001/07/25 03:10:49 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.59 2001/04/22 23:09:46 steve
* More UDP consolidation from Stephan Boettcher.
*
* Revision 1.58 2001/04/06 02:28:02 steve
* Generate vvp code for functions with ports.
*
* Revision 1.57 2001/04/02 02:28:12 steve
* Generate code for task calls.
*
* Revision 1.56 2001/03/27 03:31:06 steve
* Support error code from target_t::end_design method.
*
* Revision 1.55 2000/11/04 01:54:01 steve
* Modifications in support of gcc 2.96
*
* Revision 1.54 2000/09/26 01:35:42 steve
* Remove the obsolete NetEIdent class.
*
* Revision 1.53 2000/09/17 21:26:15 steve
* Add support for modulus (Eric Aardoom)
*
* Revision 1.52 2000/09/02 20:54:20 steve
* Rearrange NetAssign to make NetAssign_ separate.
*
* Revision 1.51 2000/08/14 04:39:56 steve
* add th t-dll functions for net_const, net_bufz and processes.
*
* Revision 1.50 2000/08/09 03:43:45 steve
* Move all file manipulation out of target class.
*
* Revision 1.49 2000/08/08 01:50:42 steve
* target methods need not take a file stream.
*
* Revision 1.48 2000/07/30 18:25:43 steve
* Rearrange task and function elaboration so that the
* NetTaskDef and NetFuncDef functions are created during
* signal enaboration, and carry these objects in the
* NetScope class instead of the extra, useless map in
* the Design class.
*
* Revision 1.47 2000/07/29 16:21:08 steve
* Report code generation errors through proc_delay.
*
* Revision 1.46 2000/07/27 05:13:44 steve
* Support elaboration of disable statements.
*
* Revision 1.45 2000/05/11 23:37:27 steve
* Add support for procedural continuous assignment.
*
* Revision 1.44 2000/05/04 03:37:58 steve
* Add infrastructure for system functions, move
* $time to that structure and add $random.
*
* Revision 1.43 2000/05/02 03:13:31 steve
* Move memories to the NetScope object.
*
* Revision 1.42 2000/05/02 00:58:12 steve
* Move signal tables to the NetScope class.
*
* Revision 1.41 2000/04/23 03:45:24 steve
* Add support for the procedural release statement.
*
* Revision 1.40 2000/04/22 04:20:19 steve
* Add support for force assignment.
*
* Revision 1.39 2000/04/12 04:23:58 steve
* Named events really should be expressed with PEIdent
* objects in the pform,
*
* Handle named events within the mix of net events
* and edges. As a unified lot they get caught together.
* wait statements are broken into more complex statements
* that include a conditional.
*
* Do not generate NetPEvent or NetNEvent objects in
* elaboration. NetEvent, NetEvWait and NetEvProbe
* take over those functions in the netlist.
*/
+25 -65
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: eval.cc,v 1.47 2007/06/04 19:14:06 steve Exp $"
#ident "$Id: eval.cc,v 1.36.2.3 2006/09/20 20:27:02 steve Exp $"
#endif
# include "config.h"
@@ -26,15 +26,14 @@
# include "PExpr.h"
# include "netlist.h"
# include "netmisc.h"
# include "compiler.h"
verinum* PExpr::eval_const(Design*, NetScope*) const
verinum* PExpr::eval_const(const Design*, const NetScope*) const
{
return 0;
}
verinum* PEBinary::eval_const(Design*des, NetScope*scope) const
verinum* PEBinary::eval_const(const Design*des, const NetScope*scope) const
{
verinum*l = left_->eval_const(des, scope);
if (l == 0) return 0;
@@ -113,7 +112,10 @@ verinum* PEBinary::eval_const(Design*des, NetScope*scope) const
case 'l': { // left shift (<<)
assert(r->is_defined());
unsigned long rv = r->as_ulong();
res = new verinum(verinum::V0, l->len());
unsigned use_wid = l->len();
if (! l->has_len())
use_wid += rv;
res = new verinum(verinum::V0, use_wid);
if (rv < res->len()) {
unsigned cnt = res->len() - rv;
for (unsigned idx = 0 ; idx < cnt ; idx += 1)
@@ -143,15 +145,16 @@ verinum* PEBinary::eval_const(Design*des, NetScope*scope) const
delete r;
return res;
}
verinum* PEConcat::eval_const(Design*des, NetScope*scope) const
verinum* PEConcat::eval_const(const Design*des, const NetScope*scope) const
{
verinum*accum = parms_[0]->eval_const(des, scope);
if (accum == 0)
return 0;
for (unsigned idx = 1 ; idx < parms_.count() ; idx += 1) {
verinum*tmp = parms_[idx]->eval_const(des, scope);
/* Oops, found an argument that is not constant. Give up. */
if (tmp == 0) {
delete accum;
return 0;
@@ -165,29 +168,14 @@ verinum* PEConcat::eval_const(Design*des, NetScope*scope) const
return accum;
}
/*
* Evaluate an identifier as a constant expression. This is only
* possible if the identifier is that of a parameter.
*/
verinum* PEIdent::eval_const(Design*des, NetScope*scope) const
verinum* PEIdent::eval_const(const Design*des, const NetScope*scope) const
{
assert(scope);
NetNet*net;
NetEvent*eve;
const NetExpr*expr;
const name_component_t&name_tail = path_.back();
// Handle the special case that this ident is a genvar
// variable name. In that case, the genvar meaning preempts
// everything and we just return that value immediately.
if (scope->genvar_tmp
&& strcmp(name_tail.name,scope->genvar_tmp) == 0) {
return new verinum(scope->genvar_tmp_val);
}
symbol_search(des, scope, path_, net, expr, eve);
const NetExpr*expr = des->find_parameter(scope, path_);
if (expr == 0)
return 0;
@@ -202,30 +190,30 @@ verinum* PEIdent::eval_const(Design*des, NetScope*scope) const
assert(eval);
if (!name_tail.index.empty())
if (msb_ || lsb_)
return 0;
return new verinum(eval->value());
}
verinum* PEFNumber::eval_const(Design*, NetScope*) const
verinum* PEFNumber::eval_const(const Design*, const NetScope*) const
{
long val = value_->as_long();
return new verinum(val);
}
verinum* PENumber::eval_const(Design*, NetScope*) const
verinum* PENumber::eval_const(const Design*, const NetScope*) const
{
return new verinum(value());
}
verinum* PEString::eval_const(Design*, NetScope*) const
verinum* PEString::eval_const(const Design*, const NetScope*) const
{
return new verinum(string(text_));
}
verinum* PETernary::eval_const(Design*des, NetScope*scope) const
verinum* PETernary::eval_const(const Design*des, const NetScope*scope) const
{
verinum*test = expr_->eval_const(des, scope);
if (test == 0)
@@ -245,7 +233,7 @@ verinum* PETernary::eval_const(Design*des, NetScope*scope) const
}
}
verinum* PEUnary::eval_const(Design*des, NetScope*scope) const
verinum* PEUnary::eval_const(const Design*des, const NetScope*scope) const
{
verinum*val = expr_->eval_const(des, scope);
if (val == 0)
@@ -259,7 +247,7 @@ verinum* PEUnary::eval_const(Design*des, NetScope*scope) const
/* We need to expand the value a bit if we are
taking the 2's complement so that we are
guaranteed to not overflow. */
verinum tmp ((uint64_t)0, val->len()+1);
verinum tmp (0UL, val->len()+1);
for (unsigned idx = 0 ; idx < val->len() ; idx += 1)
tmp.set(idx, val->get(idx));
@@ -276,42 +264,14 @@ verinum* PEUnary::eval_const(Design*des, NetScope*scope) const
/*
* $Log: eval.cc,v $
* Revision 1.47 2007/06/04 19:14:06 steve
* Build errors in picky GCC compilers.
* Revision 1.36.2.3 2006/09/20 20:27:02 steve
* Fix left shift of small unsized constants.
*
* Revision 1.46 2007/05/24 04:07:12 steve
* Rework the heirarchical identifier parse syntax and pform
* to handle more general combinations of heirarch and bit selects.
* Revision 1.36.2.2 2005/12/18 21:06:01 steve
* Properly fail when concat is not actually constant.
*
* Revision 1.45 2007/03/07 00:38:15 steve
* Lint fixes.
*
* Revision 1.44 2007/01/16 05:44:15 steve
* Major rework of array handling. Memories are replaced with the
* more general concept of arrays. The NetMemory and NetEMemory
* classes are removed from the ivl core program, and the IVL_LPM_RAM
* lpm type is removed from the ivl_target API.
*
* Revision 1.43 2006/08/08 05:11:37 steve
* Handle 64bit delay constants.
*
* Revision 1.42 2006/05/19 04:07:24 steve
* eval_const is not strict.
*
* Revision 1.41 2006/05/17 16:49:30 steve
* Error message if concat expression cannot evaluate.
*
* Revision 1.40 2006/04/10 00:37:42 steve
* Add support for generate loops w/ wires and gates.
*
* Revision 1.39 2005/12/07 04:04:23 steve
* Allow constant concat expressions.
*
* Revision 1.38 2005/11/27 17:01:57 steve
* Fix for stubborn compiler.
*
* Revision 1.37 2005/11/27 05:56:20 steve
* Handle bit select of parameter with ranges.
* Revision 1.36.2.1 2005/12/07 03:28:44 steve
* Support constant concatenation of constants.
*
* Revision 1.36 2003/06/21 01:21:43 steve
* Harmless fixup of warnings.
+3 -8
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: eval_attrib.cc,v 1.9 2007/06/04 19:14:06 steve Exp $"
#ident "$Id: eval_attrib.cc,v 1.7 2004/02/20 18:53:35 steve Exp $"
#endif
# include "config.h"
@@ -35,7 +35,8 @@
attrib_list_t* evaluate_attributes(const map<perm_string,PExpr*>&att,
unsigned&natt,
Design*des, NetScope*scope)
const Design*des,
const NetScope*scope)
{
natt = att.size();
if (natt == 0)
@@ -73,12 +74,6 @@ attrib_list_t* evaluate_attributes(const map<perm_string,PExpr*>&att,
/*
* $Log: eval_attrib.cc,v $
* Revision 1.9 2007/06/04 19:14:06 steve
* Build errors in picky GCC compilers.
*
* Revision 1.8 2005/11/27 17:01:57 steve
* Fix for stubborn compiler.
*
* Revision 1.7 2004/02/20 18:53:35 steve
* Addtrbute keys are perm_strings.
*
+252 -391
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: eval_tree.cc,v 1.77 2007/06/02 03:42:12 steve Exp $"
#ident "$Id: eval_tree.cc,v 1.62.2.5 2007/03/23 23:02:31 steve Exp $"
#endif
# include "config.h"
@@ -26,9 +26,8 @@
# include <iostream>
# include "netlist.h"
# include "ivl_assert.h"
NetExpr* NetExpr::eval_tree(int prune_to_width)
NetExpr* NetExpr::eval_tree()
{
return 0;
}
@@ -52,148 +51,33 @@ void NetEBinary::eval_sub_tree_()
}
}
bool NetEBinary::get_real_arguments_(verireal&lval, verireal&rval)
{
switch (left_->expr_type()) {
case IVL_VT_REAL: {
NetECReal*lc = dynamic_cast<NetECReal*> (left_);
if (lc == 0) return false;
lval = lc->value();
break;
}
case IVL_VT_BOOL:
case IVL_VT_LOGIC: {
NetEConst*lc = dynamic_cast<NetEConst*>(left_);
if (lc == 0) return false;
verinum tmp = lc->value();
lval = verireal(tmp.as_long());
break;
}
default:
assert(0);
}
switch (right_->expr_type()) {
case IVL_VT_REAL: {
NetECReal*rc = dynamic_cast<NetECReal*> (right_);
if (rc == 0) return 0;
rval = rc->value();
break;
}
case IVL_VT_BOOL:
case IVL_VT_LOGIC: {
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
if (rc == 0) return 0;
verinum tmp = rc->value();
rval = verireal(tmp.as_long());
break;
}
default:
assert(0);
}
return true;
}
NetExpr* NetEBAdd::eval_tree(int prune_to_width)
NetEConst* NetEBAdd::eval_tree()
{
eval_sub_tree_();
if (left_->expr_type() == IVL_VT_REAL || right_->expr_type()==IVL_VT_REAL)
return eval_tree_real_();
NetEConst*lc = dynamic_cast<NetEConst*>(left_);
if (lc == 0) return 0;
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
if (rc == 0) return 0;
/* If both operands are constant, then replace the entire
expression with a constant value. */
if (lc != 0 && rc != 0) {
verinum lval = lc->value();
verinum rval = rc->value();
verinum lval = lc->value();
verinum rval = rc->value();
verinum val;
switch (op_) {
case '+':
val = lval + rval;
break;
case '-':
val = lval - rval;
break;
default:
return 0;
}
return new NetEConst(val);
}
/* Try to combine a right constant value with the right
constant value of a sub-expression add. For example, the
expression (a + 2) - 1 can be rewritten as a + 1. */
NetEBAdd*se = dynamic_cast<NetEBAdd*>(left_);
lc = se? dynamic_cast<NetEConst*>(se->right_) : 0;
if (lc != 0 && rc != 0) {
assert(se != 0);
verinum lval = lc->value();
verinum rval = rc->value();
verinum val;
if (op_ == se->op_) {
/* (a + lval) + rval --> a + (rval+lval) */
/* (a - lval) - rval --> a - (rval+lval) */
val = rval + lval;
} else {
/* (a - lval) + rval --> a + (rval-lval) */
/* (a + lval) - rval --> a - (rval-lval) */
val = rval - lval;
}
NetEConst*tmp = new NetEConst(val);
left_ = se->left_->dup_expr();
delete se;
delete right_;
right_ = tmp;
/* We've changed the subexpression, but the result is
still not constant, so return nil here anyhow. */
verinum val;
switch (op_) {
case '+':
val = lval + rval;
break;
case '-':
val = lval - rval;
break;
default:
return 0;
}
/* Nothing more to be done, the value is not constant. */
return 0;
return new NetEConst(val);
}
NetECReal* NetEBAdd::eval_tree_real_()
{
verireal lval;
verireal rval;
bool flag = get_real_arguments_(lval, rval);
if (!flag) return 0;
verireal res_val;
switch (op()) {
case '+':
res_val = lval + rval;
break;
case '-':
res_val = lval - rval;
break;
default:
ivl_assert(*this, 0);
}
NetECReal*res = new NetECReal( res_val );
res->set_line(*this);
return res;
}
NetEConst* NetEBBits::eval_tree(int prune_to_width)
NetEConst* NetEBBits::eval_tree()
{
eval_sub_tree_();
@@ -291,9 +175,51 @@ NetEConst* NetEBBits::eval_tree(int prune_to_width)
return new NetEConst(res);
}
NetEConst* NetEBComp::eval_eqeq_()
{
NetEConst*l = dynamic_cast<NetEConst*>(left_);
if (l == 0) return 0;
NetEConst*r = dynamic_cast<NetEConst*>(right_);
if (r == 0) return 0;
const verinum&lv = l->value();
const verinum&rv = r->value();
unsigned s_len = lv.len();
if (rv.len() < s_len) s_len = rv.len();
verinum result(verinum::V1, 1);
for (unsigned idx = 0 ; idx < s_len; idx += 1) {
if (lv[idx] != rv[idx])
result = verinum::V0;
}
// If one operand was wider than the other, check that the
// remaining bits are all zero
if (lv.len() > s_len) {
for (unsigned idx = s_len; idx < lv.len(); idx += 1) {
if (lv[idx] != 0)
result = verinum::V0;
}
}
if (rv.len() > s_len) {
for (unsigned idx = s_len; idx < rv.len(); idx += 1) {
if (rv[idx] != 0)
result = verinum::V0;
}
}
return new NetEConst(result);
}
NetEConst* NetEBComp::eval_less_()
{
if (right_->expr_type() == ET_REAL)
return eval_leeq_real_(false, false);
if (left_->expr_type() == ET_REAL)
return eval_leeq_real_(false, false);
NetEConst*r = dynamic_cast<NetEConst*>(right_);
if (r == 0) return 0;
@@ -303,27 +229,32 @@ NetEConst* NetEBComp::eval_less_()
return new NetEConst(result);
}
if (left_->expr_width() == 0) {
cerr << get_line() << ": internal error: "
<< "Having trouble evaluating left expression of < op."
<< endl;
cerr << get_line() << ": : "
<< "Expression is: "
<< *this << endl;
return 0;
}
/* Detect the case where the right side is greater than or
/* Detect the case where the right side is greater that or
equal to the largest value the left side can possibly
have. Use the width of the left expression as all 1's to
calculate the maximum possible width for the left_
expression. This test only works of the compare is
unsigned. */
if (! (rv.has_sign() || left_->has_sign())) {
assert(left_->expr_width() > 0);
verinum lv (verinum::V1, left_->expr_width());
if (lv < rv) {
verinum result(verinum::V1, 1);
return new NetEConst(result);
}
have. */
assert(left_->expr_width() > 0);
verinum lv (verinum::V1, left_->expr_width() + 1);
lv.set(left_->expr_width(), verinum::V0);
lv.has_sign( left_->has_sign() );
if ((lv < rv) == verinum::V1) {
verinum result(verinum::V1, 1);
return new NetEConst(result);
}
/* Now go on to the normal test of the values. */
NetEConst*l = dynamic_cast<NetEConst*>(left_);
if (l == 0) return 0;
verinum lv = l->value();
lv = l->value();
if (! lv.is_defined()) {
verinum result(verinum::Vx, 1);
return new NetEConst(result);
@@ -345,14 +276,14 @@ NetEConst* NetEBComp::eval_less_()
return new NetEConst(result);
}
NetEConst* NetEBComp::eval_leeq_real_()
NetEConst* NetEBComp::eval_leeq_real_(bool gt_flag, bool include_eq_flag)
{
NetEConst*vtmp;
NetECReal*rtmp;
double lv, rv;
switch (left_->expr_type()) {
case IVL_VT_REAL:
case ET_REAL:
rtmp = dynamic_cast<NetECReal*> (left_);
if (rtmp == 0)
return 0;
@@ -360,7 +291,7 @@ NetEConst* NetEBComp::eval_leeq_real_()
lv = rtmp->value().as_double();
break;
case IVL_VT_LOGIC:
case ET_VECTOR:
vtmp = dynamic_cast<NetEConst*> (left_);
if (vtmp == 0)
return 0;
@@ -374,7 +305,7 @@ NetEConst* NetEBComp::eval_leeq_real_()
switch (right_->expr_type()) {
case IVL_VT_REAL:
case ET_REAL:
rtmp = dynamic_cast<NetECReal*> (right_);
if (rtmp == 0)
return 0;
@@ -382,7 +313,7 @@ NetEConst* NetEBComp::eval_leeq_real_()
rv = rtmp->value().as_double();
break;
case IVL_VT_LOGIC:
case ET_VECTOR:
vtmp = dynamic_cast<NetEConst*> (right_);
if (vtmp == 0)
return 0;
@@ -394,7 +325,16 @@ NetEConst* NetEBComp::eval_leeq_real_()
assert(0);
}
verinum result((lv <= rv)? verinum::V1 : verinum::V0, 1);
/* This function supports < and <=. If the eq_flag is true,
then include <=. Otherwise, include only <. */
bool flag;
if (gt_flag)
flag = include_eq_flag? (lv >= rv) : (lv > rv);
else
flag = include_eq_flag? (lv <= rv) : (lv < rv);
verinum result(flag? verinum::V1 : verinum::V0, 1);
vtmp = new NetEConst(result);
vtmp->set_line(*this);
@@ -403,10 +343,10 @@ NetEConst* NetEBComp::eval_leeq_real_()
NetEConst* NetEBComp::eval_leeq_()
{
if (right_->expr_type() == IVL_VT_REAL)
return eval_leeq_real_();
if (left_->expr_type() == IVL_VT_REAL)
return eval_leeq_real_();
if (right_->expr_type() == ET_REAL)
return eval_leeq_real_(false, true);
if (left_->expr_type() == ET_REAL)
return eval_leeq_real_(false, true);
NetEConst*r = dynamic_cast<NetEConst*>(right_);
if (r == 0) return 0;
@@ -427,7 +367,9 @@ NetEConst* NetEBComp::eval_leeq_()
equal to the largest value the left side can possibly
have. */
assert(left_->expr_width() > 0);
verinum lv (verinum::V1, left_->expr_width());
verinum lv (verinum::V1, left_->expr_width() + 1);
lv.set(left_->expr_width(), verinum::V0);
lv.has_sign( left_->has_sign() );
if (lv <= rv) {
verinum result(verinum::V1, 1);
return new NetEConst(result);
@@ -460,23 +402,10 @@ NetEConst* NetEBComp::eval_leeq_()
NetEConst* NetEBComp::eval_gt_()
{
if ((left_->expr_type() == IVL_VT_REAL)
&& (right_->expr_type() == IVL_VT_REAL)) {
NetECReal*tmpl = dynamic_cast<NetECReal*>(left_);
if (tmpl == 0)
return 0;
NetECReal*tmpr = dynamic_cast<NetECReal*>(right_);
if (tmpr == 0)
return 0;
double ll = tmpl->value().as_double();
double rr = tmpr->value().as_double();
verinum result ((ll > rr)? verinum::V1 : verinum::V0, 1, true);
return new NetEConst(result);
}
if (right_->expr_type() == ET_REAL)
return eval_leeq_real_(true, false);
if (left_->expr_type() == ET_REAL)
return eval_leeq_real_(true, false);
NetEConst*l = dynamic_cast<NetEConst*>(left_);
if (l == 0) return 0;
@@ -499,7 +428,7 @@ NetEConst* NetEBComp::eval_gt_()
}
/* Compare with a real value. Do it as double precision. */
if (right_->expr_type() == IVL_VT_REAL) {
if (right_->expr_type() == NetExpr::ET_REAL) {
NetECReal*tmp = dynamic_cast<NetECReal*>(right_);
if (tmp == 0)
return 0;
@@ -536,23 +465,10 @@ NetEConst* NetEBComp::eval_gt_()
NetEConst* NetEBComp::eval_gteq_()
{
if ((left_->expr_type() == IVL_VT_REAL)
&& (right_->expr_type() == IVL_VT_REAL)) {
NetECReal*tmpl = dynamic_cast<NetECReal*>(left_);
if (tmpl == 0)
return 0;
NetECReal*tmpr = dynamic_cast<NetECReal*>(right_);
if (tmpr == 0)
return 0;
double ll = tmpl->value().as_double();
double rr = tmpr->value().as_double();
verinum result ((ll >= rr)? verinum::V1 : verinum::V0, 1, true);
return new NetEConst(result);
}
if (right_->expr_type() == ET_REAL)
return eval_leeq_real_(true, true);
if (left_->expr_type() == ET_REAL)
return eval_leeq_real_(true, true);
NetEConst*l = dynamic_cast<NetEConst*>(left_);
if (l == 0) return 0;
@@ -565,7 +481,7 @@ NetEConst* NetEBComp::eval_gteq_()
/* Detect the case where the left side is greater than the
largest value the right side can possibly have. */
if (right_->expr_type() == IVL_VT_LOGIC) {
if (right_->expr_type() == NetExpr::ET_VECTOR) {
assert(right_->expr_width() > 0);
verinum rv (verinum::V1, right_->expr_width());
if (lv >= rv) {
@@ -575,7 +491,7 @@ NetEConst* NetEBComp::eval_gteq_()
}
/* Compare with a real value. Do it as double precision. */
if (right_->expr_type() == IVL_VT_REAL) {
if (right_->expr_type() == NetExpr::ET_REAL) {
NetECReal*tmp = dynamic_cast<NetECReal*>(right_);
if (tmp == 0)
return 0;
@@ -596,25 +512,21 @@ NetEConst* NetEBComp::eval_gteq_()
return new NetEConst(result);
}
if (lv.has_sign() && rv.has_sign()) {
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_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);
}
if (lv.as_ulong() >= rv.as_ulong()) {
verinum result(verinum::V1, 1);
return new NetEConst(result);
}
verinum result(verinum::V0, 1);
return new NetEConst(result);
}
NetEConst* NetEBComp::eval_eqeq_(bool ne_flag)
NetEConst* NetEBComp::eval_neeq_()
{
NetEConst*l = dynamic_cast<NetEConst*>(left_);
if (l == 0) return 0;
@@ -624,10 +536,7 @@ NetEConst* NetEBComp::eval_eqeq_(bool ne_flag)
const verinum&lv = l->value();
const verinum&rv = r->value();
const verinum::V eq_res = ne_flag? verinum::V0 : verinum::V1;
const verinum::V ne_res = ne_flag? verinum::V1 : verinum::V0;
verinum::V res = eq_res;
verinum::V res = verinum::V0;
unsigned top = lv.len();
if (rv.len() < top)
top = rv.len();
@@ -660,18 +569,10 @@ NetEConst* NetEBComp::eval_eqeq_(bool ne_flag)
break;
if (rv.get(idx) != lv.get(idx))
res = ne_res;
res = verinum::V1;
}
if (res != verinum::Vx) {
verinum::V lpad = verinum::V0;
verinum::V rpad = verinum::V0;
if (lv.has_sign() && lv.get(lv.len()-1) == verinum::V1)
lpad = verinum::V1;
if (rv.has_sign() && rv.get(rv.len()-1) == verinum::V1)
rpad = verinum::V1;
for (unsigned idx = top ; idx < lv.len() ; idx += 1)
switch (lv.get(idx)) {
@@ -680,14 +581,9 @@ NetEConst* NetEBComp::eval_eqeq_(bool ne_flag)
res = verinum::Vx;
break;
case verinum::V0:
if (res != verinum::Vx && rpad != verinum::V0)
res = ne_res;
break;
case verinum::V1:
if (res != verinum::Vx && rpad != verinum::V1)
res = ne_res;
if (res != verinum::Vx)
res = verinum::V1;
break;
default:
@@ -702,14 +598,9 @@ NetEConst* NetEBComp::eval_eqeq_(bool ne_flag)
res = verinum::Vx;
break;
case verinum::V0:
if (res != verinum::Vx && lpad != verinum::V0)
res = ne_res;
break;
case verinum::V1:
if (res != verinum::Vx && lpad != verinum::V1)
res = ne_res;
if (res != verinum::Vx)
res = verinum::V1;
break;
default:
@@ -768,7 +659,7 @@ NetEConst* NetEBComp::eval_neeqeq_()
return res;
}
NetEConst* NetEBComp::eval_tree(int prune_to_width)
NetEConst* NetEBComp::eval_tree()
{
eval_sub_tree_();
@@ -777,7 +668,7 @@ NetEConst* NetEBComp::eval_tree(int prune_to_width)
return eval_eqeqeq_();
case 'e': // Equality (==)
return eval_eqeq_(false);
return eval_eqeq_();
case 'G': // >=
return eval_gteq_();
@@ -789,7 +680,7 @@ NetEConst* NetEBComp::eval_tree(int prune_to_width)
return eval_neeqeq_();
case 'n': // not-equal (!=)
return eval_eqeq_(true);
return eval_neeq_();
case '<': // Less than
return eval_less_();
@@ -806,11 +697,11 @@ NetEConst* NetEBComp::eval_tree(int prune_to_width)
* The NetEBDiv operator includes the / and % operators. First evaluate
* the sub-expressions, then perform the required operation.
*/
NetExpr* NetEBDiv::eval_tree(int prune_to_width)
NetExpr* NetEBDiv::eval_tree()
{
eval_sub_tree_();
if (expr_type() == IVL_VT_REAL) {
if (expr_type() == NetExpr::ET_REAL) {
NetECReal*lc = dynamic_cast<NetECReal*>(left_);
if (lc == 0) return 0;
@@ -855,7 +746,7 @@ NetExpr* NetEBDiv::eval_tree(int prune_to_width)
} else {
assert(expr_type() == IVL_VT_LOGIC);
assert(expr_type() == NetExpr::ET_VECTOR);
NetEConst*lc = dynamic_cast<NetEConst*>(left_);
if (lc == 0) return 0;
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
@@ -876,7 +767,7 @@ NetExpr* NetEBDiv::eval_tree(int prune_to_width)
return 0;
}
NetEConst* NetEBLogic::eval_tree(int prune_to_width)
NetEConst* NetEBLogic::eval_tree()
{
eval_sub_tree_();
NetEConst*lc = dynamic_cast<NetEConst*>(left_);
@@ -942,14 +833,50 @@ NetEConst* NetEBLogic::eval_tree(int prune_to_width)
return new NetEConst(verinum(res, 1));
}
NetExpr* NetEBMult::eval_tree_real_()
{
verireal lval;
verireal rval;
bool flag = get_real_arguments_(lval, rval);
if (! flag) return 0;
switch (left_->expr_type()) {
case ET_REAL: {
NetECReal*lc = dynamic_cast<NetECReal*> (left_);
if (lc == 0) return 0;
lval = lc->value();
break;
}
case ET_VECTOR: {
NetEConst*lc = dynamic_cast<NetEConst*>(left_);
if (lc == 0) return 0;
verinum tmp = lc->value();
lval = verireal(tmp.as_long());
break;
}
default:
assert(0);
}
switch (right_->expr_type()) {
case ET_REAL: {
NetECReal*rc = dynamic_cast<NetECReal*> (right_);
if (rc == 0) return 0;
rval = rc->value();
break;
}
case ET_VECTOR: {
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
if (rc == 0) return 0;
verinum tmp = rc->value();
rval = verireal(tmp.as_long());
break;
}
default:
assert(0);
}
NetECReal*res = new NetECReal(lval * rval);
@@ -957,14 +884,14 @@ NetExpr* NetEBMult::eval_tree_real_()
return res;
}
NetExpr* NetEBMult::eval_tree(int prune_to_width)
NetExpr* NetEBMult::eval_tree()
{
eval_sub_tree_();
if (expr_type() == IVL_VT_REAL)
if (expr_type() == ET_REAL)
return eval_tree_real_();
assert(expr_type() == IVL_VT_LOGIC);
assert(expr_type() == ET_VECTOR);
NetEConst*lc = dynamic_cast<NetEConst*>(left_);
if (lc == 0) return 0;
@@ -977,45 +904,11 @@ NetExpr* NetEBMult::eval_tree(int prune_to_width)
return new NetEConst(lval * rval);
}
NetExpr* NetEBPow::eval_tree_real_()
{
verireal lval;
verireal rval;
bool flag = get_real_arguments_(lval, rval);
if (! flag) return 0;
NetECReal*res = new NetECReal( pow(lval,rval) );
res->set_line(*this);
return res;
}
NetExpr* NetEBPow::eval_tree(int prune_to_width)
{
eval_sub_tree_();
if (expr_type() == IVL_VT_REAL)
return eval_tree_real_();
assert(expr_type() == IVL_VT_LOGIC);
NetEConst*lc = dynamic_cast<NetEConst*>(left_);
if (lc == 0) return 0;
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
if (rc == 0) return 0;
verinum lval = lc->value();
verinum rval = rc->value();
return new NetEConst( pow(lval,rval) );
}
/*
* Evaluate the shift operator if possible. For this to work, both
* operands must be constant.
*/
NetEConst* NetEBShift::eval_tree(int prune_to_width)
NetEConst* NetEBShift::eval_tree()
{
eval_sub_tree_();
NetEConst*re = dynamic_cast<NetEConst*>(right_);
@@ -1038,13 +931,6 @@ NetEConst* NetEBShift::eval_tree(int prune_to_width)
unsigned shift = rv.as_ulong();
if (debug_eval_tree) {
cerr << get_line() << ": debug: "
<< "Evaluate " << lv << "<<" << op() << ">> "
<< rv << ", wid=" << wid << ", shift=" << shift
<< ", lv.has_len()=" << lv.has_len() << endl;
}
if ((wid == 0) || ! lv.has_len()) {
/* If the caller doesn't care what the width is,
then calcuate a width from the trimmed left
@@ -1056,9 +942,6 @@ NetEConst* NetEBShift::eval_tree(int prune_to_width)
wid = lv.len() + shift;
}
if (prune_to_width > 0 && wid > (unsigned)prune_to_width)
wid = prune_to_width;
assert(wid);
verinum nv (verinum::V0, wid, lv.has_len());
@@ -1099,7 +982,7 @@ NetEConst* NetEBShift::eval_tree(int prune_to_width)
return res;
}
NetEConst* NetEConcat::eval_tree(int prune_to_width)
NetEConst* NetEConcat::eval_tree()
{
unsigned repeat_val = repeat();
unsigned local_errors = 0;
@@ -1193,26 +1076,61 @@ NetEConst* NetEConcat::eval_tree(int prune_to_width)
return res;
}
NetExpr* NetEParam::eval_tree(int prune_to_width)
/*
* 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()
{
if (des_ == 0) {
assert(scope_ == 0);
return 0;
/* 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;
}
}
if (debug_elaborate) {
cerr << get_line() << ": debug: evaluating expression: "
<< *this << endl;
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)
return 0;
assert(scope_);
const NetExpr*expr_msb;
const NetExpr*expr_lsb;
const NetExpr*expr = scope_->get_parameter(name_, expr_msb, expr_lsb);
const NetExpr*expr = scope_->get_parameter(name_);
if (expr == 0) {
cerr << get_line() << ": internal error: Unable to match "
<< "parameter " << name_ << " in scope "
<< scope_path(scope_) << endl;
<< scope_->name() << endl;
return 0;
}
@@ -1259,8 +1177,7 @@ NetExpr* NetEParam::eval_tree(int prune_to_width)
switch (res->expr_type()) {
case IVL_VT_BOOL:
case IVL_VT_LOGIC:
case NetExpr::ET_VECTOR:
{ NetEConst*tmp = dynamic_cast<NetEConst*>(res);
if (tmp == 0) {
cerr << get_line() << ": internal error: parameter "
@@ -1277,7 +1194,7 @@ NetExpr* NetEParam::eval_tree(int prune_to_width)
return ptmp;
}
case IVL_VT_REAL:
case NetExpr::ET_REAL:
{ NetECReal*tmp = dynamic_cast<NetECReal*>(res);
if (tmp == 0) {
cerr << get_line() << ": internal error: parameter "
@@ -1300,7 +1217,7 @@ NetExpr* NetEParam::eval_tree(int prune_to_width)
}
}
NetEConst* NetESelect::eval_tree(int prune_to_width)
NetEConst* NetESelect::eval_tree()
{
NetEConst*expr = dynamic_cast<NetEConst*>(expr_);
if (expr == 0) {
@@ -1313,50 +1230,31 @@ NetEConst* NetESelect::eval_tree(int prune_to_width)
expr = dynamic_cast<NetEConst*>(expr_);
}
long bval = 0;
if (base_) {
NetEConst*base = dynamic_cast<NetEConst*>(base_);
if (base == 0) {
NetExpr*tmp = base_->eval_tree();
if (tmp != 0) {
delete base_;
base_ = tmp;
}
base = dynamic_cast<NetEConst*>(base_);
NetEConst*base = dynamic_cast<NetEConst*>(base_);
if (base == 0) {
NetExpr*tmp = base_->eval_tree();
if (tmp != 0) {
delete base_;
base_ = tmp;
}
if (base == 0)
return 0;
bval = base->value().as_long();
base = dynamic_cast<NetEConst*>(base_);
}
if (expr == 0)
return 0;
if (base == 0)
return 0;
verinum eval = expr->value();
verinum oval (verinum::V0, expr_width(), true);
verinum::V pad_bit = verinum::Vx;
if (base_ == 0) {
/* If the base is NULL (different from 0) the this
select is here for sign extension. So calculate a
proper pad bit. Extend x or z or 0, and sign extend 1
if this is signed. */
unsigned top = expr->expr_width()-1;
pad_bit = eval.get(top);
if (pad_bit==verinum::V1 && !has_sign())
pad_bit = verinum::V0;
}
long bval = base->value().as_long();
for (unsigned long idx = 0 ; idx < expr_width() ; idx += 1) {
if ((bval >= 0) && ((unsigned long) bval < eval.len()))
oval.set(idx, eval.get(bval));
else
oval.set(idx, pad_bit);
oval.set(idx, verinum::Vx);
bval += 1;
}
@@ -1373,7 +1271,7 @@ NetEConst* NetESelect::eval_tree(int prune_to_width)
* evaluates to x or z, then merge the constant bits of the true and
* false expressions.
*/
NetExpr* NetETernary::eval_tree(int prune_to_width)
NetExpr* NetETernary::eval_tree()
{
NetExpr*tmp;
@@ -1510,7 +1408,7 @@ void NetEUnary::eval_expr_()
expr_ = oper;
}
NetEConst* NetEUnary::eval_tree(int prune_to_width)
NetEConst* NetEUnary::eval_tree()
{
eval_expr_();
NetEConst*rval = dynamic_cast<NetEConst*>(expr_);
@@ -1567,12 +1465,12 @@ NetEConst* NetEUnary::eval_tree(int prune_to_width)
}
NetEConst* NetEUBits::eval_tree(int prune_to_width)
NetEConst* NetEUBits::eval_tree()
{
return NetEUnary::eval_tree(prune_to_width);
return NetEUnary::eval_tree();
}
NetEConst* NetEUReduce::eval_tree(int prune_to_width)
NetEConst* NetEUReduce::eval_tree()
{
eval_expr_();
NetEConst*rval = dynamic_cast<NetEConst*>(expr_);
@@ -1655,57 +1553,20 @@ NetEConst* NetEUReduce::eval_tree(int prune_to_width)
/*
* $Log: eval_tree.cc,v $
* Revision 1.77 2007/06/02 03:42:12 steve
* Properly evaluate scope path expressions.
* Revision 1.62.2.5 2007/03/23 23:02:31 steve
* Fix compile time eval of <= comparison.
*
* Revision 1.76 2007/05/31 18:36:06 steve
* Fix warning (ldolittle)
* Revision 1.62.2.4 2007/03/23 20:59:25 steve
* Fix compile time evaluation of < operator.
*
* Revision 1.75 2007/04/07 04:46:18 steve
* Handle evaluate of addition of real valued constants.
* Revision 1.62.2.3 2005/09/09 02:17:08 steve
* Evaluate magnitude compare with real operands.
*
* Revision 1.74 2007/03/08 05:30:02 steve
* Limit the calculated widths of constants.
* Revision 1.62.2.2 2005/09/04 15:41:54 steve
* More explicit internal error message.
*
* Revision 1.73 2007/01/16 05:44:15 steve
* Major rework of array handling. Memories are replaced with the
* more general concept of arrays. The NetMemory and NetEMemory
* classes are removed from the ivl core program, and the IVL_LPM_RAM
* lpm type is removed from the ivl_target API.
*
* Revision 1.72 2006/11/04 06:16:27 steve
* Fix padding of constant eval of NetESelect.
*
* Revision 1.71 2006/10/30 05:44:49 steve
* Expression widths with unsized literals are pseudo-infinite width.
*
* Revision 1.70 2006/09/19 23:00:15 steve
* Use elab_and_eval for bit select expressions.
*
* Revision 1.69 2006/07/31 03:50:17 steve
* Add support for power in constant expressions.
*
* Revision 1.68 2006/03/18 22:52:27 steve
* Properly handle signedness in compare.
*
* Revision 1.67 2005/11/27 05:56:20 steve
* Handle bit select of parameter with ranges.
*
* Revision 1.66 2005/11/10 13:28:12 steve
* Reorganize signal part select handling, and add support for
* indexed part selects.
*
* Expand expression constant propagation to eliminate extra
* sums in certain cases.
*
* Revision 1.65 2005/09/14 02:53:14 steve
* Support bool expressions and compares handle them optimally.
*
* Revision 1.64 2005/07/11 16:56:50 steve
* Remove NetVariable and ivl_variable_t structures.
*
* Revision 1.63 2005/06/17 05:05:53 steve
* Watch out for signed constants in magnitude compare.
* Revision 1.62.2.1 2005/09/04 15:39:19 steve
* More explicit internal error message.
*
* Revision 1.62 2004/10/04 01:10:53 steve
* Clean up spurious trailing white space.
+2 -8
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: hello_vpi.c,v 1.5 2007/01/17 05:35:48 steve Exp $"
#ident "$Id: hello_vpi.c,v 1.3 2002/08/12 01:35:01 steve Exp $"
#endif
/*
@@ -33,7 +33,7 @@
# include <vpi_user.h>
static PLI_INT32 my_hello_calltf(char *xx)
static int my_hello_calltf(char *xx)
{
vpi_printf("Hello World, from VPI.\n");
return 0;
@@ -62,12 +62,6 @@ void (*vlog_startup_routines[])() = {
};
/*
* $Log: hello_vpi.c,v $
* Revision 1.5 2007/01/17 05:35:48 steve
* Fix typo is hello_vpi.c example.
*
* Revision 1.4 2006/10/30 22:46:25 steve
* Updates for Cygwin portability (pr1585922)
*
* Revision 1.3 2002/08/12 01:35:01 steve
* conditional ident string using autoconfig.
*
+3 -3
View File
@@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
* $Id: sqrt-virtex.v,v 1.5 2007/03/22 16:08:18 steve Exp $"
* $Id: sqrt-virtex.v,v 1.4.2.2 2005/02/23 18:37:52 steve Exp $"
*/
/*
@@ -130,7 +130,7 @@
* contains Verilog code that simulates the mapped design. This output
* Verilog has the single root module "chip_root", which came from the
* name of the root module when we were making the EDIF file in the
* first place. The module has ports named just line the ports of the
* first place. The module has ports named just like the ports of the
* chip_root module below.
*
* The generated Verilog uses the library in the directory
@@ -183,7 +183,7 @@
* where sqrt(y) is the exact square root of y and floor(N) is the
* largest integer <= N.
*
* For 32 bit numbers, this will never run more than 16 iterations,
* For 32bit numbers, this will never run more then 16 iterations,
* which amounts to 16 clocks.
*/
+2 -2
View File
@@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
* $Id: sqrt.vl,v 1.5 2007/03/22 16:08:18 steve Exp $"
* $Id: sqrt.vl,v 1.4 2004/10/04 01:10:56 steve Exp $"
*/
/*
@@ -50,7 +50,7 @@
* where sqrt(y) is the exact square root of y and floor(N) is the
* largest integer <= N.
*
* For 32 bit numbers, this will never run more than 16 iterations,
* For 32bit numbers, this will never run more then 16 iterations,
* which amounts to 16 clocks.
*/
+542 -451
View File
File diff suppressed because it is too large Load Diff
-84
View File
@@ -1,84 +0,0 @@
Icarus Verilog Extensions
Icarus Verilog supports certain extensions to the baseline IEEE1364
standard. Some of these are picked from extended variants of the
language, such as SystemVerilog, and some are expressions of internal
behavior of Icarus Verilog, made available as a tool debugging aid.
* Builtin System Functions
** Extended Verilog Data Types
This feature is turned off if the generation flag "-g" is set to other
then the default "2x". For example, "iverilog -g2x" enables extended
data types, and "iverilog -g2" disables them.
Icarus Verilog adds support for extended data types. This extended
type syntax is based on a proposal by Cadence Design Systems,
originally as an update to the IEEE1364. That original proposal has
apparently been absorbed by the IEEE1800 SystemVerilog
standard. Icarus Verilog currently only takes the new primitive types
from the proposal.
Extended data types separates the concept of net/variable from the
data type. Both nets and variables can declared with any data
type. The primitive types available are:
logic - The familiar 0, 1, x and z, optionally with strength.
bool - Limited to only 0 and 1
real - 64bit real values
Nets with logic type may have multiple drivers with strength, and the
value is resolved the usual way. Only logic values may be driven to
logic nets, so bool values driven onto logic nets are implicitly
converted to logic.
Nets with any other type may not have multiple drivers. The compiler
should detect the multiple drivers and report an error.
- Declarations
The declaration of a net is extended to include the type of the wire,
with the syntax:
wire <type> <wire-assignment-list>... ;
The <type>, if omitted, is taken to be logic. The "wire" can be any of
the net keywords. Wires can be logic, bool, real, or vectors of logic
or bool. Some valid examples:
wire real foo = 1.0;
tri logic bus[31:0];
wire bool addr[23:0];
... and so on.
The declarations of variables is similar. The "reg" keyword is used to
specify that this is a variable. Variables can have the same data
types as nets.
- Ports
Module and task ports in standard verilog are restricted to logic
types. This extension removes that restriction, allowing any type to
pass through the port consistent with the continuous assignment
connectivity that is implied by the type.
- Expressions
Expressions in the face of real values is covered by the baseline
Verilog standard.
The bool type supports the same operators as the logic type, with the
obvious differences imposed by the limited domain.
Comparison operators (not case compare) return logic if either of
their operands is logic. If both are bool or real (including mix of
bool and real) then the result is bool. This is because comparison of
bools and reals always return exactly true or false.
Case comparison returns bool. This differs from baseline Verilog,
which strictly speaking returns a logic, but only 0 or 1 values.
All the arithmetic operators return bool if both of their operands are
bool or real. Otherwise, they return logic.
+7 -32
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2005 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
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: functor.cc,v 1.35 2005/07/07 16:22:49 steve Exp $"
#ident "$Id: functor.cc,v 1.32.2.1 2006/04/23 04:26:14 steve Exp $"
#endif
# include "config.h"
@@ -59,10 +59,6 @@ void functor_t::lpm_divide(class Design*, class NetDivide*)
{
}
void functor_t::lpm_literal(class Design*, class NetLiteral*)
{
}
void functor_t::lpm_modulo(class Design*, class NetModulo*)
{
}
@@ -83,15 +79,10 @@ void functor_t::lpm_mux(class Design*, class NetMux*)
{
}
void functor_t::sign_extend(class Design*, class NetSignExtend*)
void functor_t::lpm_ram_dq(class Design*, class NetRamDq*)
{
}
void functor_t::lpm_ureduce(class Design*, class NetUReduce*)
{
}
void NetScope::run_functor(Design*des, functor_t*fun)
{
for (NetScope*cur = sub_ ; cur ; cur = cur->sib_) {
@@ -198,11 +189,6 @@ void NetFF::functor_node(Design*des, functor_t*fun)
fun->lpm_ff(des, this);
}
void NetLiteral::functor_node(Design*des, functor_t*fun)
{
fun->lpm_literal(des, this);
}
void NetLogic::functor_node(Design*des, functor_t*fun)
{
fun->lpm_logic(des, this);
@@ -223,14 +209,9 @@ void NetMux::functor_node(Design*des, functor_t*fun)
fun->lpm_mux(des, this);
}
void NetSignExtend::functor_node(Design*des, functor_t*fun)
void NetRamDq::functor_node(Design*des, functor_t*fun)
{
fun->sign_extend(des, this);
}
void NetUReduce::functor_node(Design*des, functor_t*fun)
{
fun->lpm_ureduce(des, this);
fun->lpm_ram_dq(des, this);
}
proc_match_t::~proc_match_t()
@@ -294,14 +275,8 @@ int proc_match_t::event_wait(NetEvWait*)
/*
* $Log: functor.cc,v $
* Revision 1.35 2005/07/07 16:22:49 steve
* Generalize signals to carry types.
*
* Revision 1.34 2005/05/24 01:44:27 steve
* Do sign extension of structuran nets.
*
* Revision 1.33 2005/02/03 04:56:20 steve
* laborate reduction gates into LPM_RED_ nodes.
* Revision 1.32.2.1 2006/04/23 04:26:14 steve
* Constant propagate addresses through NetRamDq read ports.
*
* Revision 1.32 2004/10/04 01:10:53 steve
* Clean up spurious trailing white space.
+6 -17
View File
@@ -1,7 +1,7 @@
#ifndef __functor_H
#define __functor_H
/*
* Copyright (c) 1999-2005 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2000 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: functor.h,v 1.23 2005/07/07 16:22:49 steve Exp $"
#ident "$Id: functor.h,v 1.20.2.1 2006/04/23 04:26:14 steve Exp $"
#endif
/*
@@ -63,9 +63,6 @@ struct functor_t {
/* This method is called for each structural constant. */
virtual void lpm_divide(class Design*des, class NetDivide*);
/* Constant literals. */
virtual void lpm_literal(class Design*des, class NetLiteral*);
/* This method is called for each structural constant. */
virtual void lpm_modulo(class Design*des, class NetModulo*);
@@ -81,10 +78,8 @@ struct functor_t {
/* This method is called for each MUX. */
virtual void lpm_mux(class Design*des, class NetMux*);
/* This method is called for each unary reduction gate. */
virtual void lpm_ureduce(class Design*des, class NetUReduce*);
virtual void sign_extend(class Design*des, class NetSignExtend*);
/* This is called for eacm RamDq device. */
virtual void lpm_ram_dq(class Design*des, class NetRamDq*);
};
struct proc_match_t {
@@ -100,14 +95,8 @@ struct proc_match_t {
/*
* $Log: functor.h,v $
* Revision 1.23 2005/07/07 16:22:49 steve
* Generalize signals to carry types.
*
* Revision 1.22 2005/05/24 01:44:27 steve
* Do sign extension of structuran nets.
*
* Revision 1.21 2005/02/03 04:56:20 steve
* laborate reduction gates into LPM_RED_ nodes.
* Revision 1.20.2.1 2006/04/23 04:26:14 steve
* Constant propagate addresses through NetRamDq read ports.
*
* Revision 1.20 2002/08/12 01:34:59 steve
* conditional ident string using autoconfig.
+2 -11
View File
@@ -1,7 +1,4 @@
NOTE: THE CONTENTS OF THIS FILE ARE BEING MOVED TO THE DOCUMENTATION
WIKI AT http://iverilog.wikia.com. PLEASE ADD NEW ENTRIES THERE.
Icarus Verilog vs. IEEE1364
Copyright 2000 Stephen Williams
@@ -252,7 +249,7 @@ exactly the same so far as the compiler is concerned.
Unfortunately, Cadence seems to feel otherwise. In particular, it has
been reported that although {1'b0, 16} causes an error, {1'b0, 15+1}
is accepted. Further testing shows that any expression other than a
is accepted. Further testing shows that any expression other then a
simple unsized constant is accepted there, even if all the operands of
all the operators that make up the expression are unsized integers.
@@ -501,14 +498,8 @@ of 4-value behavior in the dead zone, and appears more user friendly
when viewed by reasonable viewers.
$Id: ieee1364-notes.txt,v 1.19 2007/04/18 02:36:13 steve Exp $
$Id: ieee1364-notes.txt,v 1.17 2003/07/15 03:49:22 steve Exp $
$Log: ieee1364-notes.txt,v $
Revision 1.19 2007/04/18 02:36:13 steve
Put to iverilog wiki for further notes.
Revision 1.18 2007/03/22 16:08:16 steve
Spelling fixes from Larry
Revision 1.17 2003/07/15 03:49:22 steve
Spelling fixes.
+4 -12
View File
@@ -17,12 +17,12 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: iverilog-vpi.sh,v 1.17 2007/02/06 05:07:31 steve Exp $"
#ident "$Id: iverilog-vpi.sh,v 1.14 2004/05/20 00:40:34 steve Exp $"
# These are the variables used for compiling files
CC=@IVCC@
CXX=@IVCXX@
CFLAGS="@PIC@ @IVCFLAGS@ -I@INCLUDEDIR@"
CC=gcc
CXX=gcc
CFLAGS="@PIC@ -O -I@INCLUDEDIR@"
# These are used for linking...
LD=gcc
@@ -63,19 +63,11 @@ do
;;
*.cc) CXSRC="$CXSRC $parm"
LD=$CXX
if [ x$OUT = x ]; then
OUT=`basename $parm .cc`
fi
;;
*.cpp) CXSRC="$CXSRC $parm"
LD=$CXX
if [ x$OUT = x ]; then
OUT=`basename $parm .cpp`
fi
;;
*.o) OBJ="$OBJ $parm"
if [ x$OUT = x ]; then
OUT=`basename $parm .o`
+37 -33
View File
@@ -9,10 +9,9 @@ ivl_design_roots
ivl_design_time_precision
ivl_const_bits
ivl_const_real
ivl_const_pin
ivl_const_pins
ivl_const_signed
ivl_const_type
ivl_const_width
ivl_event_any
ivl_event_basename
@@ -22,13 +21,14 @@ ivl_event_neg
ivl_event_nneg
ivl_event_npos
ivl_event_pos
ivl_event_scope
ivl_expr_type
ivl_expr_bits
ivl_expr_def
ivl_expr_dvalue
ivl_expr_event
ivl_expr_lsi
ivl_expr_memory
ivl_expr_name
ivl_expr_opcode
ivl_expr_oper1
@@ -44,34 +44,36 @@ ivl_expr_signed
ivl_expr_string
ivl_expr_uvalue
ivl_expr_value
ivl_expr_variable
ivl_expr_width
ivl_logic_attr
ivl_logic_attr_cnt
ivl_logic_attr_val
ivl_logic_basename
ivl_logic_delay
ivl_logic_drive0
ivl_logic_drive1
ivl_logic_name
ivl_logic_pin
ivl_logic_pins
ivl_logic_basename
ivl_logic_scope
ivl_logic_type
ivl_logic_pin
ivl_logic_pins
ivl_logic_udp
ivl_logic_width
ivl_lpm_array
ivl_lpm_aset_value
ivl_lpm_async_clr
ivl_lpm_async_set
ivl_lpm_base
ivl_lpm_attr_cnt
ivl_lpm_attr_val
ivl_lpm_basename
ivl_lpm_clk
ivl_lpm_data
ivl_lpm_datab
ivl_lpm_data2
ivl_lpm_data2_width
ivl_lpm_decode
ivl_lpm_define
ivl_lpm_enable
ivl_lpm_memory
ivl_lpm_name
ivl_lpm_q
ivl_lpm_scope
@@ -80,17 +82,25 @@ ivl_lpm_selects
ivl_lpm_signed
ivl_lpm_size
ivl_lpm_sset_value
ivl_lpm_string
ivl_lpm_sync_clr
ivl_lpm_sync_set
ivl_lpm_type
ivl_lpm_width
ivl_lval_idx
ivl_lval_mem
ivl_lval_mux
ivl_lval_part_off
ivl_lval_pin
ivl_lval_pins
ivl_lval_sig
ivl_lval_width
ivl_lval_var
ivl_memory_basename
ivl_memory_root
ivl_memory_scope
ivl_memory_size
ivl_memory_width
ivl_nexus_get_private
ivl_nexus_name
@@ -109,12 +119,6 @@ ivl_nexus_ptr_sig
ivl_parameter_basename
ivl_parameter_expr
ivl_path_condit
ivl_path_delay
ivl_path_source
ivl_path_source_negedge
ivl_path_source_posedge
ivl_scope_attr_cnt
ivl_scope_attr_val
ivl_scope_basename
@@ -126,6 +130,8 @@ ivl_scope_logs
ivl_scope_log
ivl_scope_lpms
ivl_scope_lpm
ivl_scope_mem
ivl_scope_mems
ivl_scope_name
ivl_scope_param
ivl_scope_params
@@ -137,30 +143,23 @@ ivl_scope_sig
ivl_scope_time_units
ivl_scope_type
ivl_scope_tname
ivl_scope_var
ivl_scope_vars
ivl_signal_array_base
ivl_signal_array_count
ivl_signal_attr
ivl_signal_attr_cnt
ivl_signal_attr_val
ivl_signal_basename
ivl_signal_data_type
ivl_signal_dimensions
ivl_signal_integer
ivl_signal_local
ivl_signal_lsb
ivl_signal_msb
ivl_signal_name
ivl_signal_nex
ivl_signal_npath
ivl_signal_path
ivl_signal_pin
ivl_signal_pins
ivl_signal_port
ivl_signal_signed
ivl_signal_type
ivl_signal_width
ivl_path_delay
ivl_path_source
ivl_signal_name
ivl_signal_basename
ivl_process_attr_cnt
ivl_process_attr_val
@@ -188,6 +187,8 @@ ivl_stmt_lvals
ivl_stmt_lwidth
ivl_stmt_name
ivl_stmt_nevent
ivl_stmt_nexus
ivl_stmt_nexus_count
ivl_stmt_parm
ivl_stmt_parm_count
ivl_stmt_rval
@@ -199,3 +200,6 @@ ivl_udp_nin
ivl_udp_row
ivl_udp_rows
ivl_udp_sequ
ivl_variable_name
ivl_variable_type
-43
View File
@@ -1,43 +0,0 @@
/*
* Copyright (c) 2007 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: ivl_assert.h,v 1.1 2007/01/31 04:21:10 steve Exp $"
#endif
#ifndef __ivl_assert_h
#define __ivl_assert_h
# include <assert.h>
#define ivl_assert(tok, expression) \
do { \
if (! (expression)) \
__ivl_assert(#expression, tok, __FILE__, __LINE__); \
} while(0)
#define __ivl_assert(expression, tok, file, line) \
do { \
cerr << (tok).get_line() << ": assert: " \
<< file << ":" << line \
<< ": failed assertion " << (expression) << endl; \
abort(); \
} while(0)
#endif
+272 -734
View File
File diff suppressed because it is too large Load Diff
+9 -9
View File
@@ -18,7 +18,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.18 2006/10/30 22:45:37 steve Exp $"
#ident "$Id: Makefile.in,v 1.17 2004/10/04 01:10:56 steve Exp $"
#
#
SHELL = /bin/sh
@@ -44,18 +44,18 @@ CPPFLAGS = @ident_support@ -I. -I.. -I$(srcdir)/.. -I$(srcdir) @CPPFLAGS@ @DEFS@
CFLAGS = -Wall @CFLAGS@
LDFLAGS = @LDFLAGS@
all: ivlpp@EXEEXT@
all: ivlpp
clean:
rm -f *.o lexor.c parse.c parse.h parse.output ivlpp@EXEEXT@
rm -f *.o lexor.c parse.c parse.h parse.output ivlpp
distclean: clean
rm -f Makefile
O = main.o lexor.o parse.o
ivlpp@EXEEXT@: $O
$(CC) $(LDFLAGS) $O -o ivlpp@EXEEXT@ @EXTRALIBS@
ivlpp: $O
$(CC) $(LDFLAGS) $O -o ivlpp @EXTRALIBS@
lexor.c: lexor.lex
flex -s -olexor.c $(srcdir)/lexor.lex
@@ -63,16 +63,16 @@ lexor.c: lexor.lex
parse.h parse.c: parse.y
bison --verbose -t -d -o parse.c $(srcdir)/parse.y
install: all installdirs $(libdir)/ivl/ivlpp@EXEEXT@
install: all installdirs $(libdir)/ivl/ivlpp
$(libdir)/ivl/ivlpp@EXEEXT@: ivlpp@EXEEXT@
$(INSTALL_PROGRAM) ./ivlpp@EXEEXT@ $(libdir)/ivl/ivlpp@EXEEXT@
$(libdir)/ivl/ivlpp: ivlpp
$(INSTALL_PROGRAM) ./ivlpp $(libdir)/ivl/ivlpp
installdirs: ../mkinstalldirs
$(srcdir)/../mkinstalldirs $(libdir)/ivl
uninstall:
rm -f $(libdir)/ivl/ivlpp@EXEEXT@
rm -f $(libdir)/ivl/ivlpp
lexor.o: lexor.c parse.h globals.h
main.o: main.c globals.h
+6 -71
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: lexor.lex,v 1.48 2007/05/30 23:21:20 steve Exp $"
#ident "$Id: lexor.lex,v 1.46.2.1 2007/05/25 18:35:45 steve Exp $"
#endif
# include "config.h"
@@ -70,14 +70,7 @@ struct include_stack_t {
static void emit_pathline(struct include_stack_t *isp);
/*
* The file_queue is a singly-linked list of the files that were
* listed on the command line/file list.
*/
static struct include_stack_t*file_queue = 0;
/*
* The istack is the inclusion stack.
*/
static struct include_stack_t*istack = 0;
static struct include_stack_t*standby = 0;
@@ -118,11 +111,11 @@ static void ifdef_leave(void)
if (strcmp(istack->path,cur->path) != 0) {
fprintf(stderr, "%s:%u: warning: "
"This `endif matches an ifdef in another file.\n",
istack->path, istack->lineno+1);
istack->path, istack->lineno);
fprintf(stderr, "%s:%u: : "
"This is the odd matched `ifdef.\n",
cur->path, cur->lineno+1);
cur->path, cur->lineno);
}
free(cur->path);
@@ -316,24 +309,7 @@ W [ \t\b\f]+
yy_push_state(IFDEF_SUPR);
}
<IFDEF_TRUE>`elsif{W}[a-zA-Z_][a-zA-Z0-9_$]* {
BEGIN(IFDEF_SUPR);
}
<IFDEF_FALSE>`elsif{W}[a-zA-Z_][a-zA-Z0-9_$]* {
char*name = strchr(yytext, '`');
assert(name);
name += 6;
name += strspn(name, " \t\b\f");
if (is_defined(name)) {
BEGIN(IFDEF_TRUE);
} else {
BEGIN(IFDEF_FALSE);
}
}
<IFDEF_SUPR>`elsif{W}[a-zA-Z_][a-zA-Z0-9_$]* { }
<IFDEF_TRUE>`else { BEGIN(IFDEF_SUPR); }
<IFDEF_TRUE>`else { BEGIN(IFDEF_FALSE); }
<IFDEF_FALSE>`else { BEGIN(IFDEF_TRUE); }
<IFDEF_SUPR>`else { }
@@ -346,42 +322,6 @@ W [ \t\b\f]+
<IFDEF_FALSE,IFDEF_TRUE,IFDEF_SUPR>`endif { ifdef_leave(); yy_pop_state(); }
`ifdef {
fprintf(stderr, "%s:%u: `ifdef without a macro name - ignored.\n",
istack->path, istack->lineno+1);
error_count += 1;
}
`ifndef {
fprintf(stderr, "%s:%u: `ifndef without a macro name - ignored.\n",
istack->path, istack->lineno+1);
error_count += 1;
}
`elsif {
fprintf(stderr, "%s:%u: `elsif without a macro name - ignored.\n",
istack->path, istack->lineno+1);
error_count += 1;
}
`elsif{W}[a-zA-Z_][a-zA-Z0-9_$]* {
fprintf(stderr, "%s:%u: `elsif without a matching `ifdef - ignored.\n",
istack->path, istack->lineno+1);
error_count += 1;
}
`else {
fprintf(stderr, "%s:%u: `else without a matching `ifdef - ignored.\n",
istack->path, istack->lineno+1);
error_count += 1;
}
`endif {
fprintf(stderr, "%s:%u: `endif without a matching `ifdef - ignored.\n",
istack->path, istack->lineno+1);
error_count += 1;
}
/* This pattern notices macros and arranges for them to be replaced. */
`[a-zA-Z][a-zA-Z0-9_$]* { def_match(); }
@@ -819,7 +759,7 @@ static void lexor_done()
ifdef_stack = cur->next;
fprintf(stderr, "%s:%u: error: This `ifdef lacks an `endif.\n",
cur->path, cur->lineno+1);
cur->path, cur->lineno);
free(cur->path);
free(cur);
@@ -837,14 +777,11 @@ static int yywrap()
int line_mask_flag = 0;
struct include_stack_t*isp = istack;
istack = isp->next;
FILE *delayed_close = (FILE *) 0;
/* Delete the current input buffers, and free the cell. */
yy_delete_buffer(YY_CURRENT_BUFFER);
if (isp->file) {
/* Delay the close of this file, because the yyrestart
below seems to have some memory of this file. */
delayed_close = isp->file;
fclose(isp->file);
free(isp->path);
} else {
/* If I am printing line directives and I just finished
@@ -888,7 +825,6 @@ static int yywrap()
}
yyrestart(istack->file);
if (delayed_close) fclose(delayed_close);
return 0;
}
@@ -897,7 +833,6 @@ static int yywrap()
top. If I need to print a line directive, do so. */
yy_switch_to_buffer(istack->yybs);
if (delayed_close) fclose(delayed_close);
if (line_direct_flag && istack->path && !line_mask_flag)
fprintf(yyout, "\n`line %u \"%s\" 2\n",
+37 -88
View File
@@ -17,7 +17,7 @@ const char COPYRIGHT[] =
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: main.c,v 1.23 2006/10/02 18:16:18 steve Exp $"
#ident "$Id: main.c,v 1.20.2.1 2006/06/27 01:37:14 steve Exp $"
#endif
# include "config.h"
@@ -58,8 +58,6 @@ extern int getopt(int argc, char*argv[], const char*fmt);
extern int optind;
extern const char*optarg;
#endif
/* Path to the dependency file, if there is one. */
char *dep_path = NULL;
/*
* Keep in source_list an array of pointers to file names. The array
@@ -91,76 +89,6 @@ int line_direct_flag = 0;
unsigned error_count = 0;
FILE *depend_file = NULL;
static int flist_read_flags(const char*path)
{
char line_buf[2048];
FILE*fd = fopen(path, "r");
if (fd == 0) {
fprintf(stderr, "%s: unable to open for reading.\n", path);
return -1;
}
while (fgets(line_buf, sizeof line_buf, fd) != 0) {
/* Skip leading white space. */
char*cp = line_buf + strspn(line_buf, " \t\r\b\f");
/* Remove trailing white space. */
char*tail = cp + strlen(cp);
while (tail > cp) {
if (! isspace(tail[-1]))
break;
tail -= 1;
tail[0] = 0;
}
/* Skip empty lines */
if (*cp == 0)
continue;
/* Skip comment lines */
if (cp[0] == '#')
continue;
/* The arg points to the argument to the keyword. */
char*arg = strchr(cp, ':');
if (arg) *arg++ = 0;
if (strcmp(cp,"D") == 0) {
char*val = strchr(arg, '=');
if (val)
*val++ = 0;
else
val = "1";
define_macro(arg, val, 0);
} else if (strcmp(cp,"I") == 0) {
include_dir = realloc(include_dir,
(include_cnt+1)*sizeof(char*));
include_dir[include_cnt] = strdup(arg);
include_cnt += 1;
} else if (strcmp(cp,"keyword") == 0) {
char*buf = malloc(strlen(arg) + 2);
buf[0] = '`';
strcpy(buf+1, optarg);
define_macro(optarg, buf, 1);
free(buf);
} else if (strcmp(cp,"M") == 0) {
if (dep_path) {
fprintf(stderr, "duplicate -M flag.\n");
} else {
dep_path = strdup(arg);
}
} else {
fprintf(stderr, "%s: Invalid keyword %s\n", path, cp);
}
}
fclose(fd);
return 0;
}
/*
* This function reads from a file a list of file names. Each name
* starts with the first non-space character, and ends with the last
@@ -198,7 +126,8 @@ int main(int argc, char*argv[])
int opt, idx;
const char*flist_path = 0;
unsigned flag_errors = 0;
char*out_path = 0;
const char*out_path = 0;
const char*dep_path = NULL;
FILE*out;
/* Define preprocessor keywords that I plan to just pass. */
@@ -224,11 +153,20 @@ int main(int argc, char*argv[])
include_dir[0] = strdup(".");
include_cnt = 1;
while ((opt=getopt(argc, argv, "F:f:K:Lo:v")) != EOF) switch (opt) {
while ((opt = getopt(argc, argv, "D:f:I:K:LM:o:v")) != EOF) switch (opt) {
case 'F':
flist_read_flags(optarg);
break;
case 'D': {
char*tmp = strdup(optarg);
char*val = strchr(tmp, '=');
if (val)
*val++ = 0;
else
val = "1";
define_macro(tmp, val, 0);
free(tmp);
break;
}
case 'f':
if (flist_path) {
@@ -238,6 +176,13 @@ int main(int argc, char*argv[])
flist_path = optarg;
break;
case 'I':
include_dir = realloc(include_dir,
(include_cnt+1)*sizeof(char*));
include_dir[include_cnt] = strdup(optarg);
include_cnt += 1;
break;
case 'K': {
char*buf = malloc(strlen(optarg) + 2);
buf[0] = '`';
@@ -251,6 +196,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");
@@ -272,11 +225,13 @@ int main(int argc, char*argv[])
}
if (flag_errors) {
fprintf(stderr, "\nUsage: %s [-v][-L][-F<fil>][-f<fil>] <file>...\n"
" -F<fil> - Get defines and includes from file\n"
fprintf(stderr, "\nUsage: %s [-v][-L][-I<dir>][-D<def>] <file>...\n"
" -D<def> - Predefine a value.\n"
" -f<fil> - Read the sources listed in the file\n"
" -I<dir> - Add an include file search directory\n"
" -K<def> - Define a keyword macro that I just pass\n"
" -L - Emit line number directives\n"
" -M<fil> - Write dependencies to <fil>\n"
" -o<fil> - Send the output to <fil>\n"
" -v - Print version information\n",
argv[0]);
@@ -335,14 +290,8 @@ int main(int argc, char*argv[])
/*
* $Log: main.c,v $
* Revision 1.23 2006/10/02 18:16:18 steve
* Save dep_path because arg space is overrun.
*
* Revision 1.22 2006/07/26 00:11:40 steve
* Pass depfiles through temp defines file.
*
* Revision 1.21 2006/07/26 00:02:48 steve
* Pass defines and includes through temp file.
* Revision 1.20.2.1 2006/06/27 01:37:14 steve
* Fix const/non-const warnings.
*
* Revision 1.20 2004/09/10 00:15:45 steve
* Remove bad casts.
+10 -50
View File
@@ -21,7 +21,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: lexor.lex,v 1.96 2007/06/14 03:50:00 steve Exp $"
#ident "$Id: lexor.lex,v 1.86.2.4 2007/02/09 05:29:24 steve Exp $"
#endif
# include "config.h"
@@ -53,7 +53,6 @@ extern YYLTYPE yylloc;
struct file_name_cell {
const char*text;
struct file_name_cell*next;
bool library_flag;
};
static struct file_name_cell*file_names = 0;
@@ -73,13 +72,6 @@ static const char* set_file_name(char*text)
cur = new struct file_name_cell;
cur->text = text;
cur->next = file_names;
/* Check this file name with the list of library file
names. If there is a match, then turn on the
pform_library_flag. This is how the parser knows that
modules declared in this file are library modules. */
cur->library_flag = library_file_map[cur->text];
pform_library_flag = cur->library_flag;
return text;
}
@@ -109,7 +101,6 @@ static int comment_enter;
%s UDPTABLE
%x PPTIMESCALE
%x PPDEFAULT_NETTYPE
%s EDGES
W [ \t\b\f\r]+
@@ -143,7 +134,6 @@ W [ \t\b\f\r]+
"<<<" { return K_LS; /* Note: Functionally, <<< is the same as <<. */}
">>" { return K_RS; }
">>>" { return K_RSS; }
"**" { return K_POW; }
"<=" { return K_LE; }
">=" { return K_GE; }
"=>" { return K_EG; }
@@ -166,9 +156,9 @@ W [ \t\b\f\r]+
/* Watch out for the tricky case of (*). Cannot parse this as "(*"
and ")", but since I know that this is really ( * ), replace it
with "*" and return that. */
"("{W}*"*"{W}*")" { return '*'; }
"(*"{W}*")" { return '*'; }
<EDGES>"]" { BEGIN(0); return yytext[0]; }
[}{;:\[\],()#=.@&!?<>%|^~+*/-] { return yytext[0]; }
\" { BEGIN(CSTRING); }
@@ -211,44 +201,14 @@ W [ \t\b\f\r]+
<UDPTABLE>[pP] { return 'p'; }
<UDPTABLE>[01\?\*\-] { return yytext[0]; }
<EDGES>"01" { return K_edge_descriptor; }
<EDGES>"0x" { return K_edge_descriptor; }
<EDGES>"0z" { return K_edge_descriptor; }
<EDGES>"10" { return K_edge_descriptor; }
<EDGES>"1x" { return K_edge_descriptor; }
<EDGES>"1z" { return K_edge_descriptor; }
<EDGES>"x0" { return K_edge_descriptor; }
<EDGES>"x1" { return K_edge_descriptor; }
<EDGES>"z0" { return K_edge_descriptor; }
<EDGES>"z1" { return K_edge_descriptor; }
[a-zA-Z_][a-zA-Z0-9$_]* {
int rc = lexor_keyword_code(yytext, yyleng);
switch (rc) {
case IDENTIFIER:
if (rc == IDENTIFIER) {
yylval.text = strdup(yytext);
if (strncmp(yylval.text,"PATHPULSE$", 10) == 0)
rc = PATHPULSE_IDENTIFIER;
break;
case K_bool:
case K_logic:
case K_wone:
if (! gn_cadence_types_enabled()) {
yylval.text = strdup(yytext);
rc = IDENTIFIER;
} else {
yylval.text = 0;
}
break;
case K_edge:
BEGIN(EDGES);
break;
default:
} else {
yylval.text = 0;
break;
}
return rc;
@@ -321,10 +281,10 @@ W [ \t\b\f\r]+
^{W}?`disable_portfaults{W}?.* { }
^{W}?`enable_portfaults{W}?.* { }
^{W}?`endcelldefine{W}?.* { }
`endprotect { }
^{W}?`endprotect{W}?.* { }
^{W}?`nosuppress_faults{W}?.* { }
^{W}?`nounconnected_drive{W}?.* { }
`protect { }
^{W}?`protect{W}?.* { }
^{W}?`resetall{W}?.* { }
^{W}?`suppress_faults{W}?.* { }
^{W}?`unconnected_drive{W}?.* { }
@@ -485,7 +445,7 @@ static verinum*make_unsized_binary(const char*txt)
ptr += 1;
}
verinum*out = new verinum(bits, size, false);
verinum*out = new verinum(bits, size);
out->has_sign(sign_flag);
delete[]bits;
return out;
@@ -545,7 +505,7 @@ static verinum*make_unsized_octal(const char*txt)
ptr += 1;
}
verinum*out = new verinum(bits, size, false);
verinum*out = new verinum(bits, size);
out->has_sign(sign_flag);
delete[]bits;
return out;
@@ -615,7 +575,7 @@ static verinum*make_unsized_hex(const char*txt)
ptr += 1;
}
verinum*out = new verinum(bits, size, false);
verinum*out = new verinum(bits, size);
out->has_sign(sign_flag);
delete[]bits;
return out;
-7
View File
@@ -14,7 +14,6 @@ always, K_always
and, K_and
assign, K_assign
begin, K_begin
bool, K_bool
buf, K_buf
bufif0, K_bufif0
bufif1, K_bufif1
@@ -31,7 +30,6 @@ else, K_else
end, K_end
endcase, K_endcase
endfunction, K_endfunction
endgenerate, K_endgenerate
endmodule, K_endmodule
endprimitive, K_endprimitive
endspecify, K_endspecify
@@ -43,12 +41,9 @@ force, K_force
forever, K_forever
fork, K_fork
function, K_function
generate, K_generate
genvar, K_genvar
highz0, K_highz0
highz1, K_highz1
if, K_if
ifnone, K_ifnone
initial, K_initial
inout, K_inout
input, K_input
@@ -56,7 +51,6 @@ integer, K_integer
join, K_join
large, K_large
localparam, K_localparam
logic, K_logic
macromodule, K_macromodule
medium, K_medium
module, K_module
@@ -116,7 +110,6 @@ weak0, K_weak0
weak1, K_weak1
while, K_while
wire, K_wire
wone, K_wone
wor, K_wor
xnor, K_xnor
xor, K_xor
+4 -2
View File
@@ -16,7 +16,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.36 2007/02/06 05:07:32 steve Exp $"
#ident "$Id: Makefile.in,v 1.34.2.1 2005/02/23 18:40:24 steve Exp $"
#
#
SHELL = /bin/sh
@@ -41,6 +41,7 @@ INSTALL_DATA = @INSTALL_DATA@
CPPFLAGS = @ident_support@ -I. -I.. -I$(srcdir) -I$(srcdir)/.. @CPPFLAGS@ @DEFS@ @PICFLAG@
CFLAGS = -Wall @CFLAGS@
LDFLAGS = @LDFLAGS@
STRIP = @STRIP@
RANLIB = @RANLIB@
A = a_close.o a_compare_handles.o a_configure.o a_fetch_argc.o \
@@ -91,7 +92,8 @@ clean:
rm -rf *.o dep libveriuser.a libveriuser.o bin32
distclean: clean
rm -f Makefile config.status config.log config.cache config.h
rm -f Makefile config.status config.log config.cache
rm -rf autom4te.cache
install:: all installdirs $(libdir64)/libveriuser.a $(INSTALL32)
+2 -5
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: a_next.c,v 1.4 2006/10/30 22:45:37 steve Exp $"
#ident "$Id: a_next.c,v 1.3 2003/06/17 16:55:07 steve Exp $"
#endif
#include <stdio.h>
@@ -34,7 +34,7 @@ handle acc_next(PLI_INT32 *type, handle scope, handle prev)
/* trace */
if (pli_trace) {
PLI_INT32 *ip;
int *ip;
fprintf(pli_trace, "acc_next(%p <", type);
for (ip = type; *ip; ip++) {
fprintf(pli_trace, "%s%d", ip != type ? "," : "", *ip);
@@ -94,9 +94,6 @@ handle acc_next_scope(handle scope, handle prev)
/*
* $Log: a_next.c,v $
* Revision 1.4 2006/10/30 22:45:37 steve
* Updates for Cygwin portability (pr1585922)
*
* Revision 1.3 2003/06/17 16:55:07 steve
* 1) setlinebuf() for vpi_trace
* 2) Addes error checks for trace file opens
+2 -5
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: getinstance.c,v 1.5 2005/09/20 18:34:01 steve Exp $"
#ident "$Id: getinstance.c,v 1.4 2003/05/18 00:16:35 steve Exp $"
#endif
#include <veriuser.h>
@@ -28,14 +28,11 @@
*/
PLI_BYTE8* tf_getinstance(void)
{
return (PLI_BYTE8 *)vpi_handle(vpiSysTfCall, 0 /* NULL */);
return (char *)vpi_handle(vpiSysTfCall, 0 /* NULL */);
}
/*
* $Log: getinstance.c,v $
* Revision 1.5 2005/09/20 18:34:01 steve
* Clean up compiler warnings.
*
* Revision 1.4 2003/05/18 00:16:35 steve
* Add PLI_TRACE tracing of PLI1 modules.
*
+10 -16
View File
@@ -18,7 +18,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: veriusertfs.c,v 1.17 2007/05/08 22:01:26 steve Exp $"
#ident "$Id: veriusertfs.c,v 1.15 2004/09/10 23:13:05 steve Exp $"
#endif
/*
@@ -44,9 +44,9 @@ typedef struct t_pli_data {
int paramvc; /* parameter number for misctf */
} s_pli_data, *p_pli_data;
static PLI_INT32 compiletf(char *);
static PLI_INT32 calltf(char *);
static PLI_INT32 callback(p_cb_data);
static int compiletf(char *);
static int calltf(char *);
static int callback(p_cb_data);
/*
* Register veriusertfs routines/wrappers. Iterate over the tfcell
@@ -58,7 +58,7 @@ void veriusertfs_register_table(p_tfcell vtable)
p_tfcell tf;
s_vpi_systf_data tf_data;
p_pli_data data;
static char trace_buf[1024];
char trace_buf[1024];
if (!pli_trace && (path = getenv("PLI_TRACE"))) {
if (strcmp(path,"-") == 0)
@@ -69,8 +69,8 @@ void veriusertfs_register_table(p_tfcell vtable)
perror(path);
exit(1);
}
setvbuf(pli_trace, trace_buf, _IOLBF, sizeof(trace_buf));
}
setvbuf(pli_trace, trace_buf, _IOLBF, sizeof(trace_buf));
}
for (tf = vtable; tf; tf++) {
@@ -139,7 +139,7 @@ void veriusertfs_register_table(p_tfcell vtable)
* This function calls the veriusertfs checktf and sets up all the
* callbacks misctf requires.
*/
static PLI_INT32 compiletf(char *data)
static int compiletf(char *data)
{
p_pli_data pli;
p_tfcell tf;
@@ -221,7 +221,7 @@ static PLI_INT32 compiletf(char *data)
/*
* This function is the wrapper for the veriusertfs calltf routine.
*/
static PLI_INT32 calltf(char *data)
static int calltf(char *data)
{
int rc = 0;
p_pli_data pli;
@@ -249,13 +249,13 @@ static PLI_INT32 calltf(char *data)
*/
extern int async_misctf_enable;
static PLI_INT32 callback(p_cb_data data)
static int callback(p_cb_data data)
{
p_pli_data pli;
p_tfcell tf;
int reason;
int paramvc = 0;
PLI_INT32 rc;
int rc;
/* not enabled */
if (data->reason == cbValueChange && !async_misctf_enable)
@@ -389,12 +389,6 @@ PLI_INT32 tf_setrealdelay(double dly)
}
/*
* $Log: veriusertfs.c,v $
* Revision 1.17 2007/05/08 22:01:26 steve
* Trace file line buffer must be static.
*
* Revision 1.16 2006/10/30 22:45:37 steve
* Updates for Cygwin portability (pr1585922)
*
* Revision 1.15 2004/09/10 23:13:05 steve
* Compile cleanup of C code.
*
+1 -16
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: link_const.cc,v 1.18 2007/04/14 03:10:51 steve Exp $"
#ident "$Id: link_const.cc,v 1.17 2004/10/04 01:10:53 steve Exp $"
#endif
# include "config.h"
@@ -132,8 +132,6 @@ verinum::V Nexus::driven_value() const
} else if ((sig = dynamic_cast<const NetNet*>(cur->get_obj()))) {
// If we find an attached SUPPLY0/1, the we know
// from that what the driven value is. Stop now.
if (sig->type() == NetNet::SUPPLY0) {
driven_ = V0;
return verinum::V0;
@@ -142,16 +140,6 @@ verinum::V Nexus::driven_value() const
driven_ = V1;
return verinum::V1;
}
// If we find an attached TRI0/1, then this is a
// good guess for the driven value, but keep
// looking for something better.
if (sig->type() == NetNet::TRI0) {
val = verinum::V0;
}
if (sig->type() == NetNet::TRI1) {
val = verinum::V1;
}
}
}
@@ -176,9 +164,6 @@ verinum::V Nexus::driven_value() const
/*
* $Log: link_const.cc,v $
* Revision 1.18 2007/04/14 03:10:51 steve
* Properly account for tri0 connected to otherwise open mux input.
*
* Revision 1.17 2004/10/04 01:10:53 steve
* Clean up spurious trailing white space.
*
+2 -2
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: load_module.cc,v 1.13 2005/03/22 15:53:48 steve Exp $"
#ident "$Id: load_module.cc,v 1.12.2.1 2005/03/22 15:53:12 steve Exp $"
#endif
# include "config.h"
@@ -193,7 +193,7 @@ int build_library_index(const char*path, bool key_case_sensitive)
/*
* $Log: load_module.cc,v $
* Revision 1.13 2005/03/22 15:53:48 steve
* Revision 1.12.2.1 2005/03/22 15:53:12 steve
* popen must be matched by pclose.
*
* Revision 1.12 2003/06/05 04:31:09 steve
+7
View File
@@ -1,4 +1,11 @@
Icarus Verilog for Mac OS X
NOTE: Icarus Verilog version 0.8 is known to compile "out of the
box" on MacOSX 10.3. OSX 10.3 users need only the developer tools
included with new systems or available for free download from
Apple. Install Xcode and skip directly to step #3.
This file describes the procedure to build and install Icarus Verilog
on Mac OS X. I assume that you have experience with Unix and
Terminal.app and a basic knowledge of how to download, compile and
+38 -116
View File
@@ -1,6 +1,6 @@
const char COPYRIGHT[] =
"Copyright (c) 1998-2005 Stephen Williams ([email protected])";
"Copyright (c) 1998-2004 Stephen Williams ([email protected])";
/*
* This source code is free software; you can redistribute it
@@ -19,7 +19,7 @@ const char COPYRIGHT[] =
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: main.cc,v 1.95 2007/04/19 02:52:53 steve Exp $"
#ident "$Id: main.cc,v 1.86.2.3 2006/06/12 00:16:53 steve Exp $"
#endif
# include "config.h"
@@ -81,20 +81,12 @@ const char*basedir = ".";
const char*target = "null";
/*
* These are the language support control flags. These support which
* language features (the generation) to support. The generation_flag
* is a major moce, and the gn_* flags control specifc sub-features.
*/
generation_t generation_flag = GN_DEFAULT;
bool gn_cadence_types_flag = true;
bool gn_specify_blocks_flag = true;
map<string,const char*> flags;
char*vpi_module_list = 0;
map<perm_string,unsigned> missing_modules;
map<string,bool> library_file_map;
list<const char*> library_suff;
@@ -111,6 +103,7 @@ FILE *depend_file = NULL;
bool warn_implicit = false;
bool warn_timescale = false;
bool warn_portbinding = false;
bool warn_unused = false;
bool error_implicit = false;
@@ -120,14 +113,14 @@ bool error_implicit = false;
bool debug_scopes = false;
bool debug_eval_tree = false;
bool debug_elaborate = false;
bool debug_synth2 = false;
bool debug_synth = false;
bool debug_cprop = false;
/*
* Verbose messages enabled.
*/
bool verbose_flag = false;
unsigned integer_width = 32;
/*
* Keep a heap of identifier strings that I encounter. This is a more
* efficient way to allocate those strings.
@@ -148,9 +141,7 @@ extern void synth(Design*des);
extern void synth2(Design*des);
extern void syn_rules(Design*des);
extern void nodangle(Design*des);
#ifdef WITH_T_XNF
extern void xnfio(Design*des);
#endif
typedef void (*net_func)(Design*);
static struct net_func_map {
@@ -162,9 +153,7 @@ static struct net_func_map {
{ "synth", &synth },
{ "synth2", &synth2 },
{ "syn-rules", &syn_rules },
#ifdef WITH_T_XNF
{ "xnfio", &xnfio },
#endif
{ 0, 0 }
};
@@ -190,29 +179,17 @@ const char *net_func_to_name(const net_func func)
static void process_generation_flag(const char*gen)
{
if (strcmp(gen,"1") == 0) {
if (strcmp(gen,"1") == 0)
generation_flag = GN_VER1995;
} else if (strcmp(gen,"2") == 0) {
else if (strcmp(gen,"2") == 0)
generation_flag = GN_VER2001;
} else if (strcmp(gen,"2x") == 0) {
generation_flag = GN_VER2001X;
else if (strcmp(gen,"3.0") == 0)
generation_flag = GN_SYSVER30;
} else if (strcmp(gen,"xtypes") == 0) {
gn_cadence_types_flag = true;
} else if (strcmp(gen,"no-xtypes") == 0) {
gn_cadence_types_flag = false;
} else if (strcmp(gen,"specify") == 0) {
gn_specify_blocks_flag = true;
} else if (strcmp(gen,"no-specify") == 0) {
gn_specify_blocks_flag = false;
} else {
}
else
generation_flag = GN_DEFAULT;
}
static void parm_to_flagmap(const string&flag)
@@ -273,22 +250,13 @@ static void parm_to_flagmap(const string&flag)
* functor:<name>
* Append a named functor to the processing path.
*
* generation:<1|2|2x|xtypes|no-xtypes|specify|no-specify>
* generation:<1|2|3.0>
* This is the generation flag
*
* ivlpp:<preprocessor command>
* This specifies the ivlpp command line used to process
* library modules as I read them in.
*
* iwidth:<bits>
* This specifies the width of integer variables. (that is,
* variables declared using the "integer" keyword.)
*
* library_file:<path>
* This marks that a source file with the given path is a
* library. Any modules in that file are marked as library
* modules.
*
* module:<name>
* Load a VPI module.
*
@@ -350,9 +318,12 @@ static void read_iconfig_file(const char*ipath)
} else if (strcmp(cp,"elaborate") == 0) {
debug_elaborate = true;
cerr << "debug: Enable elaborate debug" << endl;
} else if (strcmp(cp,"synth2") == 0) {
debug_synth2 = true;
cerr << "debug: Enable synth2 debug" << endl;
} else if (strcmp(cp,"synth") == 0) {
debug_synth = true;
cerr << "debug: Enable synthesis debug" << endl;
} else if (strcmp(cp,"cprop") == 0) {
debug_cprop = true;
cerr << "debug: Enable cprop debug" << endl;
} else {
}
@@ -379,13 +350,6 @@ static void read_iconfig_file(const char*ipath)
} else if (strcmp(buf, "ivlpp") == 0) {
ivlpp_string = strdup(cp);
} else if (strcmp(buf, "iwidth") == 0) {
integer_width = strtoul(cp,0,10);
} else if (strcmp(buf, "library_file") == 0) {
const char* path = strdup(cp);
library_file_map[path] = true;
} else if (strcmp(buf,"module") == 0) {
if (vpi_module_list == 0) {
vpi_module_list = strdup(cp);
@@ -422,6 +386,9 @@ static void read_iconfig_file(const char*ipath)
case 't':
warn_timescale = true;
break;
case 'u':
warn_unused = true;
break;
default:
break;
}
@@ -586,21 +553,11 @@ int main(int argc, char*argv[])
case GN_VER2001:
cout << "IEEE1364-2001";
break;
case GN_VER2001X:
cout << "IEEE1364-2001+Extensions";
case GN_SYSVER30:
cout << "SystemVerilog 3.0";
break;
}
if (gn_specify_blocks_flag)
cout << ",specify";
else
cout << ",no-specify";
if (gn_cadence_types_flag)
cout << ",xtypes";
else
cout << ",no-xtypes";
cout << endl << "PARSING INPUT" << endl;
}
@@ -653,20 +610,11 @@ int main(int argc, char*argv[])
for (mod = pform_modules.begin()
; mod != pform_modules.end()
; mod++) {
/* Don't choose library modules. */
if ((*mod).second->library_flag)
continue;
/* Don't choose modules instantiated in other
modules. */
if (mentioned_p[(*mod).second->mod_name()])
continue;
/* What's left might as well be chosen as a root. */
if (verbose_flag)
cout << " " << (*mod).second->mod_name();
roots.push_back((*mod).second->mod_name());
if (mentioned_p[(*mod).second->mod_name()] == false) {
if (verbose_flag)
cout << " " << (*mod).second->mod_name();
roots.push_back((*mod).second->mod_name());
}
}
if (verbose_flag)
cout << endl;
@@ -762,18 +710,12 @@ int main(int argc, char*argv[])
cout << "CODE GENERATION -t "<<target<< endl;
}
int emit_rc;
bool emit_rc;
emit_rc = emit(des, target);
if (emit_rc > 0) {
cerr << "error: Code generation had "
<< emit_rc << " errors."
<< endl;
if (!emit_rc) {
cerr << "error: Code generation had errors." << endl;
return 1;
}
if (emit_rc < 0) {
cerr << "error: Code generator failure: " << emit_rc << endl;
return -1;
}
if (verbose_flag) {
if (times_flag) {
@@ -815,34 +757,14 @@ int main(int argc, char*argv[])
/*
* $Log: main.cc,v $
* Revision 1.95 2007/04/19 02:52:53 steve
* Add support for -v flag in command file.
* Revision 1.86.2.3 2006/06/12 00:16:53 steve
* Add support for -Wunused warnings.
*
* Revision 1.94 2007/03/07 04:24:59 steve
* Make integer width controllable.
* Revision 1.86.2.2 2006/04/23 04:25:45 steve
* Add cprop debugging.
*
* Revision 1.93 2006/09/28 04:35:18 steve
* Support selective control of specify and xtypes features.
*
* Revision 1.92 2005/07/14 23:38:43 steve
* Display as version 0.9.devel
*
* Revision 1.91 2005/07/07 16:22:49 steve
* Generalize signals to carry types.
*
* Revision 1.90 2005/06/28 04:25:55 steve
* Remove reference to SystemVerilog.
*
* Revision 1.89 2005/04/24 23:44:02 steve
* Update DFF support to new data flow.
*
* Revision 1.88 2005/01/22 01:06:55 steve
* Change case compare from logic to an LPM node.
*
* Revision 1.87 2004/12/11 02:31:26 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
* Revision 1.86.2.1 2006/04/01 01:37:24 steve
* Add synth debug flag
*
* Revision 1.86 2004/10/04 01:10:53 steve
* Clean up spurious trailing white space.
+1 -1
View File
@@ -71,7 +71,7 @@ The msys package is available from the mingw download site. This is
not the compiler but a collection of *nix tools ported to Windows and
wrapped in a convenient installer. The msys package is all the various
basic tools (shells, file utils, etc) and the msysDTK is extra
developer tools other than the compiler.
developer tools other then the compiler.
Download the msys-1.x.x.exe and msysdtc-1.x.x.exe binaries. These are
self-installing packages. Install msys first, and then msysDTC. Most
+121 -71
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: net_assign.cc,v 1.22 2007/01/16 05:44:15 steve Exp $"
#ident "$Id: net_assign.cc,v 1.18.2.3 2006/05/02 02:00:15 steve Exp $"
#endif
# include "config.h"
@@ -39,11 +39,31 @@ unsigned count_lval_width(const NetAssign_*idx)
}
NetAssign_::NetAssign_(NetNet*s)
: sig_(s), word_(0), base_(0)
: sig_(s), mem_(0), var_(0), bmux_(0)
{
lwid_ = sig_->vector_width();
loff_ = 0;
lwid_ = sig_->pin_count();
sig_->incr_lref();
more = 0;
mem_lref_ = false;
}
NetAssign_::NetAssign_(NetMemory*s)
: sig_(0), mem_(s), var_(0), bmux_(0)
{
loff_ = 0;
lwid_ = mem_->width();
more = 0;
mem_lref_ = false;
}
NetAssign_::NetAssign_(NetVariable*s)
: sig_(0), mem_(0), var_(s), bmux_(0)
{
loff_ = 0;
lwid_ = 0;
more = 0;
mem_lref_ = false;
}
NetAssign_::~NetAssign_()
@@ -54,40 +74,47 @@ NetAssign_::~NetAssign_()
sig_->type(NetNet::WIRE);
}
if (mem_) {
NetNet*exp = mem_->reg_from_explode();
if (exp && mem_lref_) {
exp->decr_lref();
if (turn_sig_to_wire_on_release_ && exp->peek_lref() == 0)
exp->type(NetNet::WIRE);
}
}
assert( more == 0 );
if (word_) delete word_;
if (bmux_) delete bmux_;
}
void NetAssign_::set_word(NetExpr*r)
void NetAssign_::set_bmux(NetExpr*r)
{
assert(word_ == 0);
word_ = r;
assert(bmux_ == 0);
bmux_ = r;
}
NetExpr* NetAssign_::word()
NetExpr* NetAssign_::bmux()
{
return word_;
return bmux_;
}
const NetExpr* NetAssign_::word() const
const NetExpr* NetAssign_::bmux() const
{
return word_;
}
const NetExpr* NetAssign_::get_base() const
{
return base_;
return bmux_;
}
unsigned NetAssign_::lwidth() const
{
return lwid_;
if (mem_) return lwid_;
else if (bmux_) return 1;
else return lwid_;
}
perm_string NetAssign_::name() const
{
if (sig_) {
return sig_->name();
} else if (mem_) {
return mem_->name();
} else {
return perm_string::literal("");
}
@@ -95,13 +122,48 @@ perm_string NetAssign_::name() const
NetNet* NetAssign_::sig() const
{
return sig_;
if (mem_)
return 0;
else
return sig_;
}
void NetAssign_::set_part(NetExpr*base, unsigned wid)
NetMemory* NetAssign_::mem() const
{
base_ = base;
lwid_ = wid;
return mem_;
}
NetVariable* NetAssign_::var() const
{
return var_;
}
void NetAssign_::incr_mem_lref()
{
if (! mem_lref_) {
assert(mem_);
NetNet*exp = mem_->reg_from_explode();
assert(exp);
exp->incr_lref();
mem_lref_ = true;
}
}
void NetAssign_::set_part(unsigned lo, unsigned lw)
{
loff_ = lo;
lwid_ = lw;
if (sig_) {
assert(sig_->pin_count() >= (lo + lw));
} else {
assert(mem_);
assert(lwid_ == mem_->width());
}
}
unsigned NetAssign_::get_loff() const
{
return loff_;
}
/*
@@ -221,60 +283,16 @@ NetAssignNB::~NetAssignNB()
{
}
NetCAssign::NetCAssign(NetAssign_*lv, NetExpr*rv)
: NetAssignBase(lv, rv)
{
}
NetCAssign::~NetCAssign()
{
}
NetDeassign::NetDeassign(NetAssign_*l)
: NetAssignBase(l, 0)
{
}
NetDeassign::~NetDeassign()
{
}
NetForce::NetForce(NetAssign_*lv, NetExpr*rv)
: NetAssignBase(lv, rv)
{
}
NetForce::~NetForce()
{
}
NetRelease::NetRelease(NetAssign_*l)
: NetAssignBase(l, 0)
{
}
NetRelease::~NetRelease()
{
}
/*
* $Log: net_assign.cc,v $
* Revision 1.22 2007/01/16 05:44:15 steve
* Major rework of array handling. Memories are replaced with the
* more general concept of arrays. The NetMemory and NetEMemory
* classes are removed from the ivl core program, and the IVL_LPM_RAM
* lpm type is removed from the ivl_target API.
* Revision 1.18.2.3 2006/05/02 02:00:15 steve
* Fix uninitialized mem_lref_ member.
*
* Revision 1.21 2006/02/02 02:43:58 steve
* Allow part selects of memory words in l-values.
* Revision 1.18.2.2 2006/04/16 19:26:38 steve
* Fix handling of exploded memories with partial or missing resets.
*
* Revision 1.20 2005/07/11 16:56:50 steve
* Remove NetVariable and ivl_variable_t structures.
*
* Revision 1.19 2004/12/11 02:31:26 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
* Revision 1.18.2.1 2006/03/12 07:34:17 steve
* Fix the memsynth1 case.
*
* Revision 1.18 2004/08/28 15:08:31 steve
* Do not change reg to wire in NetAssign_ unless synthesizing.
@@ -285,5 +303,37 @@ NetRelease::~NetRelease()
* Revision 1.16 2003/01/26 21:15:58 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
* Revision 1.15 2002/08/12 01:34:59 steve
* conditional ident string using autoconfig.
*
* Revision 1.14 2002/08/04 18:28:15 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.13 2002/07/02 03:02:57 steve
* Change the signal to a net when assignments go away.
*
* Revision 1.12 2002/06/08 23:42:46 steve
* Add NetRamDq synthsesis from memory l-values.
*
* Revision 1.11 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.10 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.9 2002/04/21 22:31:02 steve
* Redo handling of assignment internal delays.
* Leave it possible for them to be calculated
* at run time.
*/
+141 -103
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: net_design.cc,v 1.54 2007/06/05 04:18:09 steve Exp $"
#ident "$Id: net_design.cc,v 1.45.2.1 2006/10/04 00:34:45 steve Exp $"
#endif
# include "config.h"
@@ -32,7 +32,6 @@
# include "netlist.h"
# include "util.h"
# include "compiler.h"
# include "netmisc.h"
# include <sstream>
Design:: Design()
@@ -68,8 +67,8 @@ int Design::get_precision() const
return des_precision_;
}
uint64_t Design::scale_to_precision(uint64_t val,
const NetScope*scope) const
unsigned long Design::scale_to_precision(unsigned long val,
const NetScope*scope) const
{
int units = scope->time_unit();
assert( units >= des_precision_ );
@@ -85,7 +84,7 @@ uint64_t Design::scale_to_precision(uint64_t val,
NetScope* Design::make_root_scope(perm_string root)
{
NetScope *root_scope_;
root_scope_ = new NetScope(0, hname_t(root), NetScope::MODULE);
root_scope_ = new NetScope(0, root, NetScope::MODULE);
/* This relies on the fact that the basename return value is
permallocated. */
root_scope_->set_module_name(root_scope_->basename());
@@ -115,27 +114,26 @@ const list<NetScope*> Design::find_root_scopes() const
* more step down the tree until the name runs out or the search
* fails.
*/
NetScope* Design::find_scope(const std::list<hname_t>&path) const
NetScope* Design::find_scope(const hname_t&path) const
{
if (path.empty())
if (path.peek_name(0) == 0)
return 0;
for (list<NetScope*>::const_iterator scope = root_scopes_.begin()
; scope != root_scopes_.end(); scope++) {
NetScope*cur = *scope;
if (path.front() != cur->fullname())
if (strcmp(path.peek_name(0), cur->basename()) != 0)
continue;
std::list<hname_t> tmp = path;
tmp.pop_front();
unsigned hidx = 1;
while (cur) {
if (tmp.empty()) return cur;
const char*name = path.peek_name(hidx);
if (name == 0)
return cur;
cur = cur->child( tmp.front() );
tmp.pop_front();
cur = cur->child(name);
hidx += 1;
}
}
@@ -145,34 +143,28 @@ NetScope* Design::find_scope(const std::list<hname_t>&path) const
/*
* This is a relative lookup of a scope by name. The starting point is
* the scope parameter within which I start looking for the scope. If
* I do not find the scope within the passed scope, start looking in
* parent scopes until I find it, or I run out of parent scopes.
* the scope parameter is the place within which I start looking for
* the scope. If I do not find the scope within the passed scope,
* start looking in parent scopes until I find it, or I run out of
* parent scopes.
*/
NetScope* Design::find_scope(NetScope*scope, const std::list<hname_t>&path) const
NetScope* Design::find_scope(NetScope*scope, const hname_t&path) const
{
assert(scope);
if (path.empty())
if (path.peek_name(0) == 0)
return scope;
for ( ; scope ; scope = scope->parent()) {
std::list<hname_t> tmp = path;
unsigned hidx = 0;
const char*key = path.peek_name(hidx);
NetScope*cur = scope;
do {
hname_t key = tmp.front();
if (cur->type() == NetScope::MODULE
&& cur->module_name()==key.peek_name()) {
/* Up references may match module name */
} else {
cur = cur->child( key );
if (cur == 0) break;
}
tmp.pop_front();
} while (!tmp.empty());
cur = cur->child(key);
if (cur == 0) break;
hidx += 1;
key = path.peek_name(hidx);
} while (key);
if (cur) return cur;
}
@@ -181,6 +173,71 @@ NetScope* Design::find_scope(NetScope*scope, const std::list<hname_t>&path) cons
return find_scope(path);
}
/*
* Find a parameter from within a specified context. If the name is
* not here, keep looking up until I run out of up to look at. The
* method works by scanning scopes, starting with the passed scope and
* working up towards the root, looking for the named parameter. The
* name in this case can be hierarchical, so there is an inner loop to
* follow the scopes of the name down to to key.
*
* The expression value of the parameter is returned as the result,
* and the scope that contains the parameter is returned in the out
* argument found_in.
*/
const NetExpr* Design::find_parameter(NetScope*scope,
const hname_t&path,
NetScope*&found_in) const
{
for ( ; scope ; scope = scope->parent()) {
unsigned hidx = 0;
NetScope*cur = scope;
while (path.peek_name(hidx+1)) {
cur = cur->child(path.peek_name(hidx));
if (cur == 0)
break;
hidx += 1;
}
if (cur == 0)
continue;
if (const NetExpr*res = cur->get_parameter(path.peek_name(hidx))) {
found_in = cur;
return res;
}
}
return 0;
}
const NetExpr* Design::find_parameter(const NetScope*scope,
const hname_t&path) const
{
for ( ; scope ; scope = scope->parent()) {
unsigned hidx = 0;
const NetScope*cur = scope;
while (path.peek_name(hidx+1)) {
cur = cur->child(path.peek_name(hidx));
if (cur == 0)
break;
hidx += 1;
}
if (cur == 0)
continue;
if (const NetExpr*res = cur->get_parameter(path.peek_name(hidx)))
return res;
}
return 0;
}
/*
* This method runs through the scope, noticing the defparam
* statements that were collected during the elaborate_scope pass and
@@ -204,30 +261,29 @@ void NetScope::run_defparams(Design*des)
}
}
map<pform_name_t,NetExpr*>::const_iterator pp;
map<hname_t,NetExpr*>::const_iterator pp;
for (pp = defparams.begin() ; pp != defparams.end() ; pp ++ ) {
NetExpr*val = (*pp).second;
pform_name_t path = (*pp).first;
hname_t path = (*pp).first;
perm_string perm_name = peek_tail_name(path);
path.pop_back();
list<hname_t> eval_path = eval_scope_path(des, this, path);
char*tmp = path.remove_tail_name();
perm_string perm_name = lex_strings.make(tmp);
delete[]tmp;
/* If there is no path on the name, then the targ_scope
is the current scope. */
NetScope*targ_scope = des->find_scope(this, eval_path);
NetScope*targ_scope = des->find_scope(this, path);
if (targ_scope == 0) {
cerr << val->get_line() << ": warning: scope of " <<
path << "." << perm_name << " not found." << endl;
continue;
}
bool flag = targ_scope->replace_parameter(perm_name, val);
bool flag = targ_scope->replace_parameter(perm_name, val->dup_expr());
if (! flag) {
cerr << val->get_line() << ": warning: parameter "
<< perm_name << " not found in "
<< scope_path(targ_scope) << "." << endl;
<< targ_scope->name() << "." << endl;
}
}
@@ -334,27 +390,18 @@ void NetScope::evaluate_parameters(Design*des)
assert(expr);
switch (expr->expr_type()) {
case IVL_VT_REAL:
case NetExpr::ET_REAL:
if (! dynamic_cast<const NetECReal*>(expr)) {
NetExpr*nexpr = expr->eval_tree();
if (nexpr == 0) {
cerr << (*cur).second.expr->get_line()
<< ": internal error: "
<< "unable to evaluate real parameter value: "
<< *expr << endl;
des->errors += 1;
continue;
}
assert(nexpr);
delete expr;
(*cur).second.expr = nexpr;
cerr << (*cur).second.expr->get_line()
<< ": internal error: "
"unable to evaluate real parameter values: " <<
*expr << endl;
des->errors += 1;
continue;
}
break;
case IVL_VT_LOGIC:
case IVL_VT_BOOL:
case NetExpr::ET_VECTOR:
if (! dynamic_cast<const NetEConst*>(expr)) {
// Try to evaluate the expression.
@@ -434,52 +481,68 @@ const char* Design::get_flag(const string&key) const
* It is the job of this function to properly implement Verilog scope
* rules as signals are concerned.
*/
NetNet* Design::find_signal(NetScope*scope, pform_name_t path)
NetNet* Design::find_signal(NetScope*scope, hname_t path)
{
assert(scope);
perm_string key = peek_tail_name(path);
path.pop_back();
if (! path.empty()) {
list<hname_t> eval_path = eval_scope_path(this, scope, path);
scope = find_scope(scope, eval_path);
}
char*key = path.remove_tail_name();
if (path.peek_name(0))
scope = find_scope(scope, path);
while (scope) {
if (NetNet*net = scope->find_signal(key))
if (NetNet*net = scope->find_signal(key)) {
delete key;
return net;
}
if (scope->type() == NetScope::MODULE)
break;
scope = scope->parent();
}
delete key;
return 0;
}
NetFuncDef* Design::find_function(NetScope*scope, const pform_name_t&name)
NetFuncDef* Design::find_function(NetScope*scope, const hname_t&name)
{
assert(scope);
std::list<hname_t> eval_path = eval_scope_path(this, scope, name);
NetScope*func = find_scope(scope, eval_path);
NetScope*func = find_scope(scope, name);
if (func && (func->type() == NetScope::FUNC))
return func->func_def();
return 0;
}
NetScope* Design::find_task(NetScope*scope, const pform_name_t&name)
NetFuncDef* Design::find_function(const hname_t&key)
{
std::list<hname_t> eval_path = eval_scope_path(this, scope, name);
NetScope*task = find_scope(scope, eval_path);
NetScope*func = find_scope(key);
if (func && (func->type() == NetScope::FUNC))
return func->func_def();
return 0;
}
NetScope* Design::find_task(NetScope*scope, const hname_t&name)
{
NetScope*task = find_scope(scope, name);
if (task && (task->type() == NetScope::TASK))
return task;
return 0;
}
NetScope* Design::find_task(const hname_t&key)
{
NetScope*task = find_scope(key);
if (task && (task->type() == NetScope::TASK))
return task;
return 0;
}
void Design::add_node(NetNode*net)
{
assert(net->design_ == 0);
@@ -555,33 +618,8 @@ void Design::delete_process(NetProcTop*top)
/*
* $Log: net_design.cc,v $
* Revision 1.54 2007/06/05 04:18:09 steve
* Upward names may reference modules by module_name.
*
* Revision 1.53 2007/06/02 03:42:13 steve
* Properly evaluate scope path expressions.
*
* Revision 1.52 2007/05/24 04:07:12 steve
* Rework the heirarchical identifier parse syntax and pform
* to handle more general combinations of heirarch and bit selects.
*
* Revision 1.51 2007/04/26 03:06:22 steve
* Rework hname_t to use perm_strings.
*
* Revision 1.50 2006/08/08 05:11:37 steve
* Handle 64bit delay constants.
*
* Revision 1.49 2006/07/31 03:50:17 steve
* Add support for power in constant expressions.
*
* Revision 1.48 2005/11/27 05:56:20 steve
* Handle bit select of parameter with ranges.
*
* Revision 1.47 2005/09/14 02:53:14 steve
* Support bool expressions and compares handle them optimally.
*
* Revision 1.46 2005/07/11 16:56:50 steve
* Remove NetVariable and ivl_variable_t structures.
* Revision 1.45.2.1 2006/10/04 00:34:45 steve
* Fix a dangling reference to NetEParam objects in defparams.
*
* Revision 1.45 2004/10/04 01:10:54 steve
* Clean up spurious trailing white space.
+3 -6
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: net_event.cc,v 1.27 2007/06/02 03:42:13 steve Exp $"
#ident "$Id: net_event.cc,v 1.26 2004/10/04 01:10:54 steve Exp $"
#endif
# include "config.h"
@@ -56,10 +56,10 @@ perm_string NetEvent::name() const
return name_;
}
NetScope* NetEvent::scope()
string NetEvent::full_name() const
{
assert(scope_);
return scope_;
return scope_->name() + "." + string(name_);
}
const NetScope* NetEvent::scope() const
@@ -449,9 +449,6 @@ NetProc* NetEvWait::statement()
/*
* $Log: net_event.cc,v $
* Revision 1.27 2007/06/02 03:42:13 steve
* Properly evaluate scope path expressions.
*
* Revision 1.26 2004/10/04 01:10:54 steve
* Clean up spurious trailing white space.
*
+33 -89
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: net_expr.cc,v 1.27 2006/07/31 03:50:17 steve Exp $"
#ident "$Id: net_expr.cc,v 1.23 2004/10/04 01:10:54 steve Exp $"
#endif
# include "config.h"
@@ -25,12 +25,9 @@
# include "compiler.h"
# include <iostream>
/*
* the grand default data type is a logic vector.
*/
ivl_variable_type_t NetExpr::expr_type() const
NetExpr::TYPE NetExpr::expr_type() const
{
return IVL_VT_LOGIC;
return ET_VECTOR;
}
/*
@@ -99,15 +96,15 @@ NetEBAdd* NetEBAdd::dup_expr() const
return result;
}
ivl_variable_type_t NetEBAdd::expr_type() const
NetExpr::TYPE NetEBAdd::expr_type() const
{
if (left_->expr_type() == IVL_VT_REAL)
return IVL_VT_REAL;
if (left_->expr_type() == ET_REAL)
return ET_REAL;
if (right_->expr_type() == IVL_VT_REAL)
return IVL_VT_REAL;
if (right_->expr_type() == ET_REAL)
return ET_REAL;
return IVL_VT_LOGIC;
return ET_VECTOR;
}
/*
@@ -164,21 +161,6 @@ bool NetEBComp::has_width() const
return true;
}
ivl_variable_type_t NetEBComp::expr_type() const
{
// Case compare always returns BOOL
if (op() == 'E' || op() == 'N')
return IVL_VT_BOOL;
if (left()->expr_type() == IVL_VT_LOGIC)
return IVL_VT_LOGIC;
if (right()->expr_type() == IVL_VT_LOGIC)
return IVL_VT_LOGIC;
return IVL_VT_BOOL;
}
NetEBDiv::NetEBDiv(char op, NetExpr*l, NetExpr*r)
: NetEBinary(op, l, r)
{
@@ -201,15 +183,15 @@ NetEBDiv* NetEBDiv::dup_expr() const
return result;
}
ivl_variable_type_t NetEBDiv::expr_type() const
NetExpr::TYPE NetEBDiv::expr_type() const
{
if (left_->expr_type() == IVL_VT_REAL)
return IVL_VT_REAL;
if (left_->expr_type() == ET_REAL)
return ET_REAL;
if (right_->expr_type() == IVL_VT_REAL)
return IVL_VT_REAL;
if (right_->expr_type() == ET_REAL)
return ET_REAL;
return IVL_VT_LOGIC;
return ET_VECTOR;
}
NetEBMult::NetEBMult(char op, NetExpr*l, NetExpr*r)
@@ -237,49 +219,15 @@ NetEBMult* NetEBMult::dup_expr() const
return result;
}
ivl_variable_type_t NetEBMult::expr_type() const
NetExpr::TYPE NetEBMult::expr_type() const
{
if (left_->expr_type() == IVL_VT_REAL)
return IVL_VT_REAL;
if (left_->expr_type() == ET_REAL)
return ET_REAL;
if (right_->expr_type() == IVL_VT_REAL)
return IVL_VT_REAL;
if (right_->expr_type() == ET_REAL)
return ET_REAL;
return IVL_VT_LOGIC;
}
NetEBPow::NetEBPow(char op, NetExpr*l, NetExpr*r)
: NetEBinary(op, l, r)
{
assert(op == 'p');
expr_width(l->expr_width());
cast_signed(l->has_sign() || r->has_sign());
}
NetEBPow::~NetEBPow()
{
}
NetEBPow* NetEBPow::dup_expr() const
{
NetEBPow*result = new NetEBPow(op_, left_->dup_expr(),
right_->dup_expr());
result->set_line(*this);
return result;
}
ivl_variable_type_t NetEBPow::expr_type() const
{
if (right_->expr_type() == IVL_VT_REAL)
return IVL_VT_REAL;
if (left_->expr_type() == IVL_VT_REAL)
return IVL_VT_REAL;
if (left_->has_sign())
return IVL_VT_REAL;
if (right_->has_sign())
return IVL_VT_REAL;
return IVL_VT_LOGIC;
return ET_VECTOR;
}
NetEBShift::NetEBShift(char op, NetExpr*l, NetExpr*r)
@@ -424,9 +372,9 @@ NetECReal* NetECReal::dup_expr() const
return tmp;
}
ivl_variable_type_t NetECReal::expr_type() const
NetExpr::TYPE NetECReal::expr_type() const
{
return IVL_VT_REAL;
return ET_REAL;
}
NetECRealParam::NetECRealParam(NetScope*s, perm_string n, const verireal&v)
@@ -502,7 +450,15 @@ bool NetESelect::has_width() const
return true;
}
NetESFunc::NetESFunc(const char*n, ivl_variable_type_t t,
bool NetESelect::set_width(unsigned w)
{
if (expr_width() == 1)
return true;
else
return false;
}
NetESFunc::NetESFunc(const char*n, NetExpr::TYPE t,
unsigned width, unsigned np)
: name_(0), type_(t)
{
@@ -553,25 +509,13 @@ NetExpr* NetESFunc::parm(unsigned idx)
return parms_[idx];
}
ivl_variable_type_t NetESFunc::expr_type() const
NetExpr::TYPE NetESFunc::expr_type() const
{
return type_;
}
/*
* $Log: net_expr.cc,v $
* Revision 1.27 2006/07/31 03:50:17 steve
* Add support for power in constant expressions.
*
* Revision 1.26 2005/11/26 00:35:43 steve
* More precise about r-value width of constants.
*
* Revision 1.25 2005/09/14 02:53:14 steve
* Support bool expressions and compares handle them optimally.
*
* Revision 1.24 2005/07/11 16:56:50 steve
* Remove NetVariable and ivl_variable_t structures.
*
* Revision 1.23 2004/10/04 01:10:54 steve
* Clean up spurious trailing white space.
*
+102 -6
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: net_force.cc,v 1.13 2004/12/11 02:31:26 steve Exp $"
#ident "$Id: net_force.cc,v 1.12 2004/02/18 17:11:56 steve Exp $"
#endif
# include "config.h"
@@ -33,14 +33,110 @@
# include "netlist.h"
# include <assert.h>
/*
* Construct the procedural continuous assignment statement. This is a
* bit different from a normal assignment because the the lval is only
* intermittently connected. The deassign in particular disconnects
* the signals when they are not being assigned anymore. Because of
* this, there is no other reference to the lval to make it stay put
* so we increment the eref.
*
* XXXX I'm not sure this is the right way. Perhaps I should create
* output pins to connect to the netlist? But that would cause the
* link ring to grow, and that is not quite correct either. Hmm...
*/
NetCAssign::NetCAssign(NetScope*s, perm_string n, NetNet*l)
: NetNode(s, n, l->pin_count()), lval_(l)
{
lval_->incr_eref();
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
pin(idx).set_dir(Link::INPUT);
pin(idx).set_name(perm_string::literal("I"), idx);
}
}
NetCAssign::~NetCAssign()
{
lval_->decr_eref();
}
const NetNet* NetCAssign::lval() const
{
return lval_;
}
const Link& NetCAssign::lval_pin(unsigned idx) const
{
assert(idx < lval_->pin_count());
return lval_->pin(idx);
}
NetDeassign::NetDeassign(NetNet*l)
: lval_(l)
{
lval_->incr_eref();
}
NetDeassign::~NetDeassign()
{
lval_->decr_eref();
}
const NetNet*NetDeassign::lval() const
{
return lval_;
}
NetForce::NetForce(NetScope*s, perm_string n, NetNet*l)
: NetNode(s, n, l->pin_count()), lval_(l)
{
lval_->incr_eref();
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
pin(idx).set_dir(Link::INPUT);
pin(idx).set_name(perm_string::literal("I"), idx);
}
}
NetForce::~NetForce()
{
lval_->decr_eref();
}
const Link& NetForce::lval_pin(unsigned idx) const
{
assert(idx < lval_->pin_count());
return lval_->pin(idx);
}
const NetNet* NetForce::lval() const
{
return lval_;
}
NetRelease::NetRelease(NetNet*l)
: lval_(l)
{
/* Put myself into a release list that the net is
keeping. This is so that the NetNet can detach itself if
and when it is deleted by the optimizer. */
release_next_ = lval_->release_list_;
lval_->release_list_ = this;
}
NetRelease::~NetRelease()
{
assert(lval_ == 0);
}
const NetNet*NetRelease::lval() const
{
return lval_;
}
/*
* $Log: net_force.cc,v $
* Revision 1.13 2004/12/11 02:31:26 steve
* Rework of internals to carry vectors through nexus instead
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
* down this path.
*
* Revision 1.12 2004/02/18 17:11:56 steve
* Use perm_strings for named langiage items.
*
+70 -67
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: net_func.cc,v 1.10 2007/06/02 03:42:13 steve Exp $"
#ident "$Id: net_func.cc,v 1.6 2004/05/31 23:34:37 steve Exp $"
#endif
# include "config.h"
@@ -26,25 +26,42 @@
# include "PExpr.h"
# include <iostream>
/*
* To make a NetUserFunc device, make as many pins as there are ports
* in the function. Get the port count from the function definition,
* which accounts for all the inputs, plus one for the phantom output
* that is the result.
*/
static unsigned count_def_pins(const NetFuncDef*def)
{
assert(def->return_sig());
unsigned sum = def->return_sig()->pin_count();
for (unsigned idx = 0 ; idx < def->port_count() ; idx += 1)
sum += def->port(idx)->pin_count();
return sum;
}
NetUserFunc::NetUserFunc(NetScope*s, perm_string n, NetScope*d)
: NetNode(s, n, d->func_def()->port_count()+1),
: NetNode(s, n, count_def_pins(d->func_def())),
def_(d)
{
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(def_->basename(), 0);
NetFuncDef*def = def_->func_def();
for (unsigned idx = 1 ; idx < pin_count() ; idx += 1) {
unsigned port_wid = port_width(0);
for (unsigned idx = 0 ; idx < port_wid ; idx += 1) {
pin(idx).set_dir(Link::OUTPUT);
pin(idx).set_name(def_->basename(), idx);
}
pin(idx).set_dir(Link::INPUT);
pin(idx).set_name(perm_string::literal("D"), idx-1);
pin(idx).drive0(Link::HIGHZ);
pin(idx).drive1(Link::HIGHZ);
unsigned pin_base = port_wid;
for (unsigned idx = 1 ; idx < port_count() ; idx += 1) {
const NetNet*port_sig = def->port(idx-1);
unsigned bits = port_width(idx);
for (unsigned bit = 0; bit < bits; bit += 1) {
pin(pin_base+bit).set_dir(Link::INPUT);
pin(pin_base+bit).set_name(port_sig->name(), bit);
pin(pin_base+bit).drive0(Link::HIGHZ);
pin(pin_base+bit).drive1(Link::HIGHZ);
}
pin_base += bits;
}
}
@@ -52,6 +69,11 @@ NetUserFunc::~NetUserFunc()
{
}
unsigned NetUserFunc::port_count() const
{
return def_->func_def()->port_count() + 1;
}
unsigned NetUserFunc::port_width(unsigned port) const
{
NetFuncDef*def = def_->func_def();
@@ -60,16 +82,44 @@ unsigned NetUserFunc::port_width(unsigned port) const
if (port == 0) {
const NetNet*sig = def->return_sig();
assert(sig);
return sig->vector_width();
return sig->pin_count();
}
port -= 1;
assert(port < def->port_count());
const NetNet*port_sig = def->port(port);
return port_sig->vector_width();
return port_sig->pin_count();
}
Link& NetUserFunc::port_pin(unsigned port, unsigned idx)
{
NetFuncDef*def = def_->func_def();
unsigned pin_base = 0;
const NetNet*port_sig;
if (port == 0)
return pin(idx);
port_sig = def->return_sig();
pin_base += port_sig->pin_count();
port -= 1;
assert(port < def->port_count());
for (unsigned port_idx = 0 ; port_idx < port ; port_idx += 1) {
port_sig = def->port(port_idx);
pin_base += port_sig->pin_count();
}
port_sig = def->port(port);
assert(idx < port_sig->pin_count());
assert((pin_base+idx) < pin_count());
return pin(pin_base+idx);
}
const NetScope* NetUserFunc::def() const
{
return def_;
@@ -95,14 +145,14 @@ bool PECallFunction::check_call_matches_definition_(Design*des, NetScope*dscope)
if (dscope->type() != NetScope::FUNC) {
cerr << get_line() << ": error: Attempt to call scope "
<< scope_path(dscope) << " as a function." << endl;
<< dscope->name() << " as a function." << endl;
des->errors += 1;
return false;
}
if (parms_count != dscope->func_def()->port_count()) {
cerr << get_line() << ": error: Function " << scope_path(dscope)
<< " expects " << (dscope->func_def()->port_count())
cerr << get_line() << ": error: Function " << dscope->name()
<< " expects " << (dscope->func_def()->port_count()-1)
<< " arguments, you passed " << parms_count << "."
<< endl;
des->errors += 1;
@@ -112,55 +162,8 @@ bool PECallFunction::check_call_matches_definition_(Design*des, NetScope*dscope)
return true;
}
NetSysFunc::NetSysFunc(NetScope*s, perm_string n,
const struct sfunc_return_type*def,
unsigned ports)
: NetNode(s, n, ports)
{
def_ = def;
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(perm_string::literal("Q"), 0);
for (unsigned idx = 1 ; idx < pin_count() ; idx += 1) {
pin(idx).set_dir(Link::INPUT);
pin(idx).set_name(perm_string::literal("D"), idx-1);
pin(idx).drive0(Link::HIGHZ);
pin(idx).drive1(Link::HIGHZ);
}
}
NetSysFunc::~NetSysFunc()
{
}
const char*NetSysFunc::func_name() const
{
return def_->name;
}
unsigned NetSysFunc::vector_width() const
{
return def_->wid;
}
/*
* $Log: net_func.cc,v $
* Revision 1.10 2007/06/02 03:42:13 steve
* Properly evaluate scope path expressions.
*
* Revision 1.9 2007/04/17 04:17:47 steve
* Fix argument count in function error message.
*
* Revision 1.8 2006/06/18 04:15:50 steve
* Add support for system functions in continuous assignments.
*
* Revision 1.7 2005/03/18 02:56:03 steve
* Add support for LPM_UFUNC user defined functions.
*
* Revision 1.6 2004/05/31 23:34:37 steve
* Rewire/generalize parsing an elaboration of
* function return values to allow for better
+127 -99
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: net_link.cc,v 1.21 2007/06/02 03:42:13 steve Exp $"
#ident "$Id: net_link.cc,v 1.14.2.6 2006/08/23 04:09:14 steve Exp $"
#endif
# include "config.h"
@@ -40,18 +40,16 @@ void connect(Nexus*l, Link&r)
if (l == r.nexus_)
return;
Nexus*tmp = r.nexus_;
while (Link*cur = tmp->list_) {
tmp->list_ = cur->next_;
cur->nexus_ = 0;
cur->next_ = 0;
cur->prev_ = 0;
l->relink(cur);
}
l->driven_ = Nexus::NO_GUESS;
assert(tmp->list_ == 0);
delete tmp;
}
@@ -60,13 +58,15 @@ void connect(Link&l, Link&r)
assert(&l != &r);
if (r.is_linked() && !l.is_linked())
connect(r.nexus_, l);
else if (r.nexus_->list_len_ > l.nexus_->list_len_)
connect(r.nexus_, l);
else
connect(l.nexus_, r);
}
Link::Link()
: dir_(PASSIVE), drive0_(STRONG), drive1_(STRONG), init_(verinum::Vx),
inst_(0), next_(0), nexus_(0)
inst_(0), next_(0), prev_(0), nexus_(0)
{
(new Nexus()) -> relink(this);
}
@@ -218,6 +218,7 @@ Nexus::Nexus()
{
name_ = 0;
list_ = 0;
list_len_ = 0;
driven_ = NO_GUESS;
t_cookie_ = 0;
}
@@ -244,6 +245,18 @@ verinum::V Nexus::get_init() const
return verinum::Vz;
}
int Nexus::is_driven() const
{
int count = 0;
for (Link*cur = list_ ; cur ; cur = cur->next_) {
if (cur->get_dir() == Link::OUTPUT)
count += 1;
}
return count;
}
void Nexus::unlink(Link*that)
{
if (name_) {
@@ -257,22 +270,32 @@ void Nexus::unlink(Link*that)
driven_ = NO_GUESS;
assert(that);
assert(that->nexus_ == this);
if (list_ == that) {
assert(that->prev_ == 0);
// Move the second item the front of the list.
list_ = that->next_;
if (list_)
list_->prev_ = 0;
list_len_ -= 1;
// Clear the pointers for the link.
that->next_ = 0;
that->prev_ = 0;
that->nexus_ = 0;
return;
}
Link*cur = list_;
while (cur->next_ != that) {
assert(cur->next_);
cur = cur->next_;
}
Link*cur = that->prev_;
assert(cur->nexus_ == this);
cur->next_ = that->next_;
if (cur->next_)
cur->next_->prev_ = cur;
that->nexus_ = 0;
that->next_ = 0;
that->prev_ = 0;
list_len_ -= 1;
}
void Nexus::relink(Link*that)
@@ -290,8 +313,13 @@ void Nexus::relink(Link*that)
assert(that->nexus_ == 0);
assert(that->next_ == 0);
that->next_ = list_;
that->prev_ = 0;
if (that->next_)
that->next_->prev_ = that;
that->nexus_ = this;
list_ = that;
list_len_ += 1;
}
Link* Nexus::first_nlink()
@@ -304,42 +332,18 @@ const Link* Nexus::first_nlink() const
return list_;
}
ivl_nexus_t Nexus::t_cookie() const
void* Nexus::t_cookie() const
{
return t_cookie_;
}
ivl_nexus_t Nexus::t_cookie(ivl_nexus_t val)const
void* Nexus::t_cookie(void*val)const
{
ivl_nexus_t tmp = t_cookie_;
void*tmp = t_cookie_;
t_cookie_ = val;
return tmp;
}
unsigned Nexus::vector_width() const
{
for (const Link*cur = first_nlink() ; cur ; cur = cur->next_nlink()) {
const NetNet*sig = dynamic_cast<const NetNet*>(cur->get_obj());
if (sig == 0)
continue;
return sig->vector_width();
}
return 0;
}
NetNet* Nexus::pick_any_net()
{
for (Link*cur = first_nlink() ; cur ; cur = cur->next_nlink()) {
NetNet*sig = dynamic_cast<NetNet*>(cur->get_obj());
if (sig != 0)
return sig;
}
return 0;
}
const char* Nexus::name() const
{
if (name_)
@@ -387,11 +391,12 @@ const char* Nexus::name() const
obj->name() << " pin " << pin << "(" <<
lnk->get_name() << "<" << lnk->get_inst() << ">)"
" type=" << typeid(*obj).name() << "?" << endl;
return 0;
}
assert(sig);
ostringstream tmp;
tmp << scope_path(sig->scope()) << "." << sig->name();
tmp << sig->name();
if (sig->pin_count() > 1)
tmp << "<" << pin << ">";
@@ -405,6 +410,7 @@ const char* Nexus::name() const
NexusSet::NexusSet()
{
items_ = 0;
index_ = 0;
nitems_ = 0;
}
@@ -413,8 +419,11 @@ NexusSet::~NexusSet()
if (nitems_ > 0) {
assert(items_ != 0);
delete[] items_;
assert(index_ != 0);
delete[] index_;
} else {
assert(items_ == 0);
assert(index_ == 0);
}
}
@@ -423,26 +432,44 @@ unsigned NexusSet::count() const
return nitems_;
}
/*
* Add the Nexus to the nexus set at the *end* of the array. This
* preserves order, which is used in a few cases by the
* synthesizer. But for efficiency, also create a sorted index.
*/
void NexusSet::add(Nexus*that)
{
/* Handle the special case that the set is empty. */
if (nitems_ == 0) {
assert(items_ == 0);
assert(index_ == 0);
items_ = (Nexus**)malloc(sizeof(Nexus*));
items_[0] = that;
index_ = (unsigned*)malloc(sizeof(unsigned));
index_[0] = 0;
nitems_ = 1;
return;
}
unsigned ptr = bsearch_(that);
if (ptr < nitems_) {
assert(items_[ptr] == that);
if (ptr < nitems_ && items_[index_[ptr]] == that) {
assert(items_[index_[ptr]] == that);
return;
}
assert(ptr == nitems_);
items_ = (Nexus**) realloc(items_, (nitems_+1) * sizeof(Nexus*));
index_ = (unsigned*)realloc(index_, (nitems_+1) * sizeof(unsigned));
items_[nitems_] = that;
unsigned dest = nitems_;
for (unsigned idx = ptr ; idx < nitems_ ; idx += 1) {
unsigned tmp = index_[idx];
index_[idx] = dest;
dest = tmp;
}
index_[nitems_] = dest;
items_ = (Nexus**)realloc(items_, (nitems_+1) * sizeof(Nexus*));
items_[ptr] = that;
nitems_ += 1;
}
@@ -458,20 +485,31 @@ void NexusSet::rem(Nexus*that)
return;
unsigned ptr = bsearch_(that);
if (ptr >= nitems_)
if (ptr >= nitems_ || items_[index_[ptr]] != that)
return;
if (nitems_ == 1) {
free(items_);
free(index_);
items_ = 0;
index_ = 0;
nitems_ = 0;
return;
}
for (unsigned idx = ptr ; idx < (nitems_-1) ; idx += 1)
unsigned index_ptr = index_[ptr];
for (unsigned idx = index_ptr ; idx < (nitems_-1) ; idx += 1)
items_[idx] = items_[idx+1];
items_ = (Nexus**)realloc(items_, (nitems_-1) * sizeof(Nexus*));
for (unsigned idx = ptr ; idx < (nitems_-1) ; idx += 1)
index_[idx] = index_[idx+1];
for (unsigned idx = 0 ; idx < (nitems_-1) ; idx += 1)
if (index_[idx] > index_ptr)
index_[idx] -= 1;
items_ = (Nexus**) realloc(items_, (nitems_-1) * sizeof(Nexus*));
index_ = (unsigned*)realloc(index_, (nitems_-1) * sizeof(unsigned));
nitems_ -= 1;
}
@@ -487,14 +525,37 @@ Nexus* NexusSet::operator[] (unsigned idx) const
return items_[idx];
}
/*
* This method uses binary search to locate the item in the list of
* nexus pointers. If the item is in the set, then this method returns
* the index where it exists in the *index* array. If the item is not
* in the set, the index points to where in the array the item should go.
*/
unsigned NexusSet::bsearch_(Nexus*that) const
{
for (unsigned idx = 0 ; idx < nitems_ ; idx += 1) {
if (items_[idx] == that)
return idx;
unsigned low = 0, hig = nitems_;
while (low < hig) {
unsigned mid = (low + hig) / 2;
if (mid == hig) mid -= 1;
assert(mid >= low);
assert(mid < hig);
if (items_[index_[mid]] == that) {
return mid;
} else if (items_[index_[mid]] > that) {
hig = mid;
} else {
low = mid+1;
}
}
return nitems_;
assert(low == hig);
assert(low == nitems_ || items_[index_[low]] >= that);
return low;
}
bool NexusSet::contains(const NexusSet&that) const
@@ -503,7 +564,7 @@ bool NexusSet::contains(const NexusSet&that) const
unsigned where = bsearch_(that[idx]);
if (where == nitems_)
return false;
if (items_[where] != that[idx])
if (items_[index_[where]] != that[idx])
return false;
}
@@ -516,7 +577,7 @@ bool NexusSet::intersect(const NexusSet&that) const
unsigned where = bsearch_(that[idx]);
if (where == nitems_)
continue;
if (items_[where] == that[idx])
if (items_[index_[where]] == that[idx])
return true;
}
@@ -525,26 +586,23 @@ bool NexusSet::intersect(const NexusSet&that) const
/*
* $Log: net_link.cc,v $
* Revision 1.21 2007/06/02 03:42:13 steve
* Properly evaluate scope path expressions.
* Revision 1.14.2.6 2006/08/23 04:09:14 steve
* missing sig diagnostics.
*
* Revision 1.20 2007/03/26 18:17:50 steve
* Remove pretense of general use for t_cookie.
* Revision 1.14.2.5 2006/08/15 03:41:24 steve
* Improve performance of unlink of heavily connected nexa.
*
* Revision 1.19 2006/02/02 02:43:58 steve
* Allow part selects of memory words in l-values.
* Revision 1.14.2.4 2006/08/08 02:17:48 steve
* Improved nexus management performance.
*
* Revision 1.18 2005/09/25 23:40:11 steve
* Simplify NexusSet set handling.
* Revision 1.14.2.3 2006/07/23 19:42:33 steve
* Handle statement output override better in blocks.
*
* Revision 1.17 2005/06/13 23:22:37 steve
* Fix compile errors.
* Revision 1.14.2.2 2006/01/27 02:05:46 steve
* Speed up processing of connect when one side is empty.
*
* Revision 1.16 2005/04/24 23:44:02 steve
* Update DFF support to new data flow.
*
* Revision 1.15 2005/01/09 20:16:01 steve
* Use PartSelect/PV and VP to handle part selects through ports.
* Revision 1.14.2.1 2005/09/25 23:30:31 steve
* More predictable ordering of items in NexusSet.
*
* Revision 1.14 2004/02/18 17:11:56 steve
* Use perm_strings for named langiage items.
@@ -570,35 +628,5 @@ bool NexusSet::intersect(const NexusSet&that) const
* Revision 1.7 2002/06/24 01:49:39 steve
* Make link_drive_constant cache its results in
* the Nexus, to improve cprop performance.
*
* Revision 1.6 2002/04/21 04:59:08 steve
* Add support for conbinational events by finding
* the inputs to expressions and some statements.
* Get case and assignment statements working.
*
* Revision 1.5 2001/07/25 03:10:49 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.4 2000/10/06 23:46:50 steve
* ivl_target updates, including more complete
* handling of ivl_nexus_t objects. Much reduced
* dependencies on pointers to netlist objects.
*
* Revision 1.3 2000/08/26 00:54:03 steve
* Get at gate information for ivl_target interface.
*
* Revision 1.2 2000/07/14 06:12:57 steve
* Move inital value handling from NetNet to Nexus
* objects. This allows better propogation of inital
* values.
*
* Clean up constant propagation a bit to account
* for regs that are not really values.
*
* Revision 1.1 2000/06/25 19:59:42 steve
* Redesign Links to include the Nexus class that
* carries properties of the connected set of links.
*
*/
+35 -32
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2005 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2004 Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: net_modulo.cc,v 1.9 2005/09/15 22:54:47 steve Exp $"
#ident "$Id: net_modulo.cc,v 1.7 2004/02/18 17:11:56 steve Exp $"
#endif
# include "config.h"
@@ -30,22 +30,25 @@
# include "netlist.h"
# include "compiler.h"
/*
* 0 -- Result
* 1 -- DataA
* 2 -- DataB
*/
NetModulo::NetModulo(NetScope*s, perm_string n, unsigned wr,
unsigned wa, unsigned wb)
: NetNode(s, n, 3),
: NetNode(s, n, wr+wa+wb),
width_r_(wr), width_a_(wa), width_b_(wb)
{
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(perm_string::literal("Result"), 0);
pin(1).set_dir(Link::INPUT);
pin(1).set_name(perm_string::literal("DataA"), 0);
pin(2).set_dir(Link::INPUT);
pin(2).set_name(perm_string::literal("DataB"), 0);
unsigned p = 0;
for (unsigned idx = 0 ; idx < width_r_ ; idx += 1, p += 1) {
pin(p).set_dir(Link::OUTPUT);
pin(p).set_name(perm_string::literal("Result"), idx);
}
for (unsigned idx = 0 ; idx < width_a_ ; idx += 1, p += 1) {
pin(p).set_dir(Link::INPUT);
pin(p).set_name(perm_string::literal("DataA"), idx);
}
for (unsigned idx = 0 ; idx < width_b_ ; idx += 1, p += 1) {
pin(p).set_dir(Link::INPUT);
pin(p).set_name(perm_string::literal("DataB"), idx);
}
}
NetModulo::~NetModulo()
@@ -67,44 +70,44 @@ unsigned NetModulo::width_b() const
return width_b_;
}
Link& NetModulo::pin_Result()
Link& NetModulo::pin_Result(unsigned idx)
{
return pin(0);
assert(idx < width_r_);
return pin(idx);
}
const Link& NetModulo::pin_Result() const
const Link& NetModulo::pin_Result(unsigned idx) const
{
return pin(0);
assert(idx < width_r_);
return pin(idx);
}
Link& NetModulo::pin_DataA()
Link& NetModulo::pin_DataA(unsigned idx)
{
return pin(1);
assert(idx < width_a_);
return pin(idx+width_r_);
}
const Link& NetModulo::pin_DataA() const
const Link& NetModulo::pin_DataA(unsigned idx) const
{
return pin(1);
assert(idx < width_a_);
return pin(idx+width_r_);
}
Link& NetModulo::pin_DataB()
Link& NetModulo::pin_DataB(unsigned idx)
{
return pin(2);
assert(idx < width_b_);
return pin(idx+width_r_+width_a_);
}
const Link& NetModulo::pin_DataB() const
const Link& NetModulo::pin_DataB(unsigned idx) const
{
return pin(2);
assert(idx < width_b_);
return pin(idx+width_r_+width_a_);
}
/*
* $Log: net_modulo.cc,v $
* Revision 1.9 2005/09/15 22:54:47 steve
* Fix bug configuring NetModulo pins.
*
* Revision 1.8 2005/03/12 06:43:35 steve
* Update support for LPM_MOD.
*
* Revision 1.7 2004/02/18 17:11:56 steve
* Use perm_strings for named langiage items.
*
+29 -31
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: net_nex_input.cc,v 1.16 2007/01/16 05:44:15 steve Exp $"
#ident "$Id: net_nex_input.cc,v 1.12.2.1 2006/05/21 21:58:47 steve Exp $"
#endif
# include "config.h"
@@ -54,6 +54,15 @@ NexusSet* NetEBinary::nex_input()
return result;
}
NexusSet* NetEBitSel::nex_input()
{
NexusSet*result = sig_->nex_input();
NexusSet*tmp = idx_->nex_input();
result->add(*tmp);
delete tmp;
return result;
}
NexusSet* NetEConcat::nex_input()
{
NexusSet*result = parms_[0]->nex_input();
@@ -78,6 +87,12 @@ NexusSet* NetECReal::nex_input()
return new NexusSet;
}
NexusSet* NetEMemory::nex_input()
{
NexusSet*result = idx_->nex_input();
return result;
}
/*
* A parameter by definition has no inputs. It represents a constant
* value, even if that value is a constant expression.
@@ -123,7 +138,8 @@ NexusSet* NetESFunc::nex_input()
NexusSet* NetESignal::nex_input()
{
NexusSet*result = new NexusSet;
for (unsigned idx = 0 ; idx < net_->pin_count() ; idx += 1)
assert(msi_ <= net_->pin_count());
for (unsigned idx = lsi_ ; idx <= msi_ ; idx += 1)
result->add(net_->pin(idx).nexus());
return result;
@@ -162,21 +178,17 @@ NexusSet* NetEUnary::nex_input()
return expr_->nex_input();
}
NexusSet* NetEVariable::nex_input()
{
return new NexusSet;
}
NexusSet* NetAssign_::nex_input()
{
NexusSet*result = new NexusSet;
if (word_) {
NexusSet*tmp = word_->nex_input();
result->add(*tmp);
delete tmp;
}
if (base_) {
NexusSet*tmp = base_->nex_input();
result->add(*tmp);
delete tmp;
}
return result;
if (bmux_ == 0)
return new NexusSet;
else
return bmux_->nex_input();
}
NexusSet* NetAssignBase::nex_input()
@@ -387,22 +399,8 @@ NexusSet* NetWhile::nex_input()
/*
* $Log: net_nex_input.cc,v $
* Revision 1.16 2007/01/16 05:44:15 steve
* Major rework of array handling. Memories are replaced with the
* more general concept of arrays. The NetMemory and NetEMemory
* classes are removed from the ivl core program, and the IVL_LPM_RAM
* lpm type is removed from the ivl_target API.
*
* Revision 1.15 2006/04/16 00:15:43 steve
* Fix part selects in l-values.
*
* Revision 1.14 2005/07/11 16:56:50 steve
* Remove NetVariable and ivl_variable_t structures.
*
* Revision 1.13 2005/01/24 05:28:30 steve
* Remove the NetEBitSel and combine all bit/part select
* behavior into the NetESelect node and IVL_EX_SELECT
* ivl_target expression type.
* Revision 1.12.2.1 2006/05/21 21:58:47 steve
* NetESignal input is only selected bits.
*
* Revision 1.12 2004/09/04 04:24:15 steve
* PR1026: assignment statements can have sensitivities in the l-values.
+74 -24
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: net_nex_output.cc,v 1.14 2007/04/17 04:34:23 steve Exp $"
#ident "$Id: net_nex_output.cc,v 1.11.2.8 2006/08/08 02:17:48 steve Exp $"
#endif
# include "config.h"
@@ -47,7 +47,55 @@ void NetAssignBase::nex_output(NexusSet&out)
{
for (NetAssign_*cur = lval_ ; cur ; cur = cur->more) {
if (NetNet*lsig = cur->sig()) {
out.add(lsig->pin(0).nexus());
if (cur->bmux()) {
for (unsigned idx = 0; idx < lsig->pin_count(); idx += 1) {
out.add(lsig->pin(idx).nexus());
}
continue;
}
/* Handle l-value signals. We don't need to worry
here about whether there is a bmux, because the
synthesizer will detect that mux and create a
decoder between the expression and the signal. */
for (unsigned idx = 0 ; idx < cur->lwidth() ; idx += 1) {
unsigned off = cur->get_loff() + idx;
out.add(lsig->pin(off).nexus());
}
} else if (NetMemory*lmem = cur->mem()) {
/* Memories here are treated as a bunch of reg
devices. Use the explode_to_reg method to get
access to the FF version of the memory and use
that in our l-value management. */
NetNet*tmp = lmem->explode_to_reg();
if (NetEConst*ae = dynamic_cast<NetEConst*>(cur->bmux())) {
/* The address is constant, so simply
connect to the right pins and we are
done. */
long adr_s = ae->value().as_long();
unsigned adr = lmem->index_to_address(adr_s) * lmem->width();
if (adr >= lmem->count()*lmem->width()) {
/* Skip assignments with constant
addresses that are outside the
range of memories. */
} else {
for (unsigned idx=0; idx<cur->lwidth(); idx += 1)
out.add(tmp->pin(adr+idx).nexus());
}
} else {
/* Put all the bits of the memory into the
set. The synthesis will generate a
decoder to handle this. */
for (unsigned idx = 0; idx < tmp->pin_count(); idx+=1)
out.add(tmp->pin(idx).nexus());
}
} else {
/* Quoting from netlist.h comments for class NetMemory:
* "This is not a node because memory objects can only be
@@ -66,21 +114,17 @@ void NetBlock::nex_output(NexusSet&out)
if (last_ == 0)
return;
NetProc*cur = last_;
NetProc*cur = last_->next_;
do {
cur = cur->next_;
cur->nex_output(out);
} while (cur != last_);
cur = cur->next_;
} while (cur != last_->next_);
}
void NetCase::nex_output(NexusSet&out)
{
for (unsigned idx = 0 ; idx < nitems_ ; idx += 1) {
// Empty statements clearly have no output.
if (items_[idx].statement == 0)
continue;
assert(items_[idx].statement);
items_[idx].statement->nex_output(out);
}
@@ -115,15 +159,6 @@ void NetSTask::nex_output(NexusSet&out)
{
}
/*
* Consider a task call to not have any outputs. This is not quite
* right, we should be listing as outputs all the output ports, but for
* the purposes that this method is used, this will do for now.
*/
void NetUTask::nex_output(NexusSet&out)
{
}
void NetWhile::nex_output(NexusSet&out)
{
if (proc_ != 0)
@@ -132,14 +167,29 @@ void NetWhile::nex_output(NexusSet&out)
/*
* $Log: net_nex_output.cc,v $
* Revision 1.14 2007/04/17 04:34:23 steve
* Fix handling calls to tasks in combinational always block
* Revision 1.11.2.8 2006/08/08 02:17:48 steve
* Improved nexus management performance.
*
* Revision 1.13 2007/04/05 01:53:52 steve
* Probe of case statement inputs can skip nul statements.
* Revision 1.11.2.7 2006/06/02 23:42:48 steve
* Compilation warnings.
*
* Revision 1.12 2005/02/14 04:58:50 steve
* l-value input may be a vector.
* Revision 1.11.2.6 2006/06/01 03:01:48 steve
* Handle condit clauses with unassigned outputs.
*
* Revision 1.11.2.5 2006/05/18 01:47:12 steve
* Fix synthesis of l-value bit select in block.
*
* Revision 1.11.2.4 2006/05/05 01:56:36 steve
* Handle memory assignments out of range during synthesis
*
* Revision 1.11.2.3 2006/04/16 19:26:38 steve
* Fix handling of exploded memories with partial or missing resets.
*
* Revision 1.11.2.2 2006/03/12 07:34:17 steve
* Fix the memsynth1 case.
*
* Revision 1.11.2.1 2006/01/18 01:23:23 steve
* Rework l-value handling to allow for more l-value type flexibility.
*
* Revision 1.11 2004/09/16 03:17:33 steve
* net_output handles l-value concatenations.
+3 -6
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: net_proc.cc,v 1.7 2006/08/08 05:11:37 steve Exp $"
#ident "$Id: net_proc.cc,v 1.6 2002/08/12 01:34:59 steve Exp $"
#endif
# include "config.h"
@@ -131,7 +131,7 @@ NetForever::~NetForever()
delete statement_;
}
NetPDelay::NetPDelay(uint64_t d, NetProc*st)
NetPDelay::NetPDelay(unsigned long d, NetProc*st)
: delay_(d), expr_(0), statement_(st)
{
}
@@ -146,7 +146,7 @@ NetPDelay::~NetPDelay()
if (expr_) delete expr_;
}
uint64_t NetPDelay::delay() const
unsigned long NetPDelay::delay() const
{
assert(expr_ == 0);
return delay_;
@@ -177,9 +177,6 @@ const NetExpr* NetRepeat::expr() const
/*
* $Log: net_proc.cc,v $
* Revision 1.7 2006/08/08 05:11:37 steve
* Handle 64bit delay constants.
*
* Revision 1.6 2002/08/12 01:34:59 steve
* conditional ident string using autoconfig.
*

Some files were not shown because too many files have changed in this diff Show More