Compare commits

...
178 Commits
Author SHA1 Message Date
steve 87e813766a Detect and ignore specify edge expressions 2007-06-14 03:50:00 +00:00
steve e24e77660f Detect and use the nan function. 2007-06-13 01:03:57 +00:00
steve 8ec6d9983d Put instantiated modules in the proper generated scope. 2007-06-12 04:05:45 +00:00
steve ae82eccdc4 handle constant inf values. 2007-06-12 02:36:58 +00:00
steve fa18d9bc01 Do not propogate until initialized. 2007-06-12 02:25:00 +00:00
steve 16ec4cb685 displan pmos gates. 2007-06-12 02:23:40 +00:00
steve 6f08f92ffc Prepare for snapshot 20070608 2007-06-09 01:06:51 +00:00
steve 0a38499941 Properly handle signed conversion to real 2007-06-07 03:20:15 +00:00
steve 55f8e5d364 int vs long expressions on 64bit arch (ldoolitt) 2007-06-05 21:52:22 +00:00
steve b631268f56 Error resiliency (ldoolitt) 2007-06-05 21:35:51 +00:00
steve 1a8ffe2a9c More standard PLI_BYTE8. 2007-06-05 21:32:30 +00:00
steve e4bcc87dc1 Upward names may reference modules by module_name. 2007-06-05 04:18:09 +00:00
steve 34111a25cb Bring in .SFT file automatically if -m used. 2007-06-05 01:56:12 +00:00
steve 8fd42fbf61 Build errors in picky GCC compilers. 2007-06-04 19:14:06 +00:00
steve 129a064e1a Handle bit/part select of array words in nets. 2007-06-04 02:19:07 +00:00
steve c7d97f4146 Properly evaluate scope path expressions. 2007-06-02 03:42:12 +00:00
steve 1f9a246c6d Fix warning (ldolittle) 2007-05-31 18:36:06 +00:00
steve 17fd3bae15 Missing return value to perm_string dump 2007-05-31 18:35:50 +00:00
steve 29aa68302e Add elsif support (Martin Whitaker) 2007-05-30 23:21:20 +00:00
steve 8dcd09797f Fix uninitialized lineno variable. 2007-05-25 18:21:39 +00:00
steve ddd36ecb6c Rework the heirarchical identifier parse syntax and pform
to handle more general combinations of heirarch and bit selects.
2007-05-24 04:07:11 +00:00
steve 67b1eee7ce Better configuration messages (Alan Feldstein) 2007-05-16 23:59:12 +00:00
steve 629c6e9a40 Fix hname_t use of space for 1 perm_string. 2007-05-16 19:12:33 +00:00
steve 6ea1337be0 Trace file line buffer must be static. 2007-05-08 22:01:26 +00:00
steve b981c81d37 Rework hname_t to use perm_strings. 2007-04-26 03:06:21 +00:00
steve 210e28e571 Prepare for 20070421 snapshot. 2007-04-22 00:32:07 +00:00
steve f6ad90f8d3 Rename assign_list to cont_assign_list. 2007-04-21 04:45:36 +00:00
steve 890f592eec Fix detect of signal that is an array. 2007-04-21 03:20:47 +00:00
steve f9c1c02f8d Add support for -v flag in command file. 2007-04-19 02:52:53 +00:00
steve 26f47c26f0 Handle arrayed strength-aware net devices. 2007-04-19 01:19:06 +00:00
steve c0496ea648 Add support for multiple command files. (Cary R.) 2007-04-18 03:23:38 +00:00
steve 498d8fe6ad Add support for Gg and Ee formats. 2007-04-18 02:40:20 +00:00
steve dafc653935 Put to iverilog wiki for further notes. 2007-04-18 02:36:13 +00:00
steve 401faef5b8 Fix vpi_get_value vpiRealVal of signed constants. 2007-04-18 01:57:07 +00:00
steve 22efa9f066 Fix elaboration of multiply of two constants. 2007-04-18 01:40:49 +00:00
steve 583abb7f49 Fix handling calls to tasks in combinational always block 2007-04-17 04:34:23 +00:00
steve fe65ae8db0 Support part select of array words in net contexts. 2007-04-17 04:18:10 +00:00
steve cc48a6c8d7 Fix argument count in function error message. 2007-04-17 04:17:47 +00:00
steve 36471e9f96 Properly ignore unsupported ifnone. 2007-04-16 01:10:07 +00:00
steve 427d5664ef Fix missing zero if time value is exactly 0. 2007-04-16 00:47:12 +00:00
steve 253fdc6232 Fix scanf to abort on failed matches. 2007-04-16 00:09:58 +00:00
steve 79fdb2b243 Attach line number information to task calls. 2007-04-15 20:45:40 +00:00
steve 089bdefad1 Fix div/mod calculation that caused a hang for some divisions. 2007-04-15 02:07:24 +00:00
steve 8ed1a010f7 Allow bit/part select of vectors in continuous assignments. 2007-04-15 01:37:29 +00:00
steve 9931e4c013 Finish up part select of array words. 2007-04-14 04:43:01 +00:00
steve acdb278b97 Handle system functions with no arguments. 2007-04-14 03:27:51 +00:00
steve d3a54547aa Properly account for tri0 connected to otherwise open mux input. 2007-04-14 03:10:51 +00:00
steve f621448ced Parse edge sensitive paths without edge specifier. 2007-04-13 02:34:35 +00:00
steve 2229825783 fix handling of unary reduction logic in certain nets. 2007-04-12 05:21:54 +00:00
steve fb7ce1d330 Support for vpi_get_value of scaler values. (ravi@bluespec) 2007-04-12 04:45:52 +00:00
steve ff7625cd9c nexus vectors of VT_BOOL objects. (ravi@bluespec) 2007-04-12 04:40:37 +00:00
steve 8f9738719b Add support for vpiSize on system task handle. ([email protected]) 2007-04-12 04:33:39 +00:00
steve 31914c7fcd vpip_make_binary_const cannot free the string passed in to it. 2007-04-12 04:25:58 +00:00
steve abaeb1e702 Add printtimescale (caryr) 2007-04-12 02:50:51 +00:00
steve 513fa72d99 Cleanup timeformat argument checking. 2007-04-10 04:56:26 +00:00
steve 65baeaed8f vpi_free_object doesnot free callback out from under runtime. 2007-04-10 04:32:05 +00:00
steve fbc731d19e Allow nexus aliases to array words. 2007-04-10 03:40:04 +00:00
steve 5047a3add3 variable arrays generated without writing a record for each word. 2007-04-10 01:26:15 +00:00
steve d3588b4e23 More strict use of PLI_BYTE8 type. 2007-04-09 22:49:33 +00:00
steve 33e5f22cf1 Handle evaluate of addition of real valued constants. 2007-04-07 04:46:18 +00:00
steve af913e7eb1 Allow implicit wires in assign l-value. 2007-04-05 03:09:50 +00:00
steve dd995b3409 Probe of case statement inputs can skip nul statements. 2007-04-05 01:53:52 +00:00
steve a863b2390c Remove useless assert 2007-04-04 02:31:57 +00:00
steve c5524b4acf t-dll should not canonicalize word addresses, elaboration already does it. 2007-04-04 01:50:38 +00:00
steve d883979fd8 Seperate arrayness from word count 2007-04-02 01:12:34 +00:00
steve 37111eb4a8 Tighter parsing of statement lists and expression lists. 2007-04-01 23:02:03 +00:00
steve bd1b00ca29 Improve port mismatch error message. 2007-04-01 23:01:10 +00:00
steve 0168502bbb Get offsets into indexed part selects correct. 2007-04-01 05:28:26 +00:00
steve ea74940be4 Fix that save expression lookaside always clears cached variable values. 2007-04-01 05:26:17 +00:00
steve 8856c07d88 More efficient allocate of ivl_nexus_t objects. 2007-03-26 20:32:47 +00:00
steve 9e21880cdc Handle part select of array words. 2007-03-26 19:23:13 +00:00
steve fe8da0bf14 Remove pretense of general use for t_cookie. 2007-03-26 18:17:50 +00:00
steve fe02214fcc do not calculate nexus name unless needed. 2007-03-26 16:51:48 +00:00
steve 611d2c81b3 Spelling fixes from Larry 2007-03-22 16:08:14 +00:00
steve 96443f1338 Clear lookaside even if source bit is a constant. 2007-03-20 04:26:56 +00:00
steve 32fb919b00 Replace some asserts with ivl_asserts. 2007-03-14 05:06:49 +00:00
steve 72ec3a2c09 VPI tasks take PLI_BYTE* by the standard. 2007-03-14 04:05:51 +00:00
steve a50ec29ad9 Elaborate scopes of modules instantated in generate loops. 2007-03-08 06:11:35 +00:00
steve d9efe3312e Limit the calculated widths of constants. 2007-03-08 05:30:02 +00:00
steve 29b4d5a46e document the +integer-width plus-arg. 2007-03-08 03:06:47 +00:00
steve f23a5bfa96 Make integer width controllable. 2007-03-07 04:24:59 +00:00
steve 74ac5dbf58 Cast to remove ambiguities calling pow function. 2007-03-07 03:55:42 +00:00
steve ae88f5cc68 Lint fixes. 2007-03-07 00:38:15 +00:00
steve 760f2182ba Support signed function return values. 2007-03-06 05:22:49 +00:00
steve e6fa72c318 Handle processes within generate loops. 2007-03-05 05:59:10 +00:00
steve 8c434ca6fa Update spec file to be more suse compliant. 2007-03-04 20:49:49 +00:00
steve 6f810e0dba Assert that modpath finds a delay. 2007-03-04 06:26:58 +00:00
steve b68f17483e UDP schedules its output instead of pushing it. 2007-03-04 06:26:33 +00:00
steve 606751dbfd Check that path source/destination are ports. 2007-03-03 05:56:55 +00:00
steve fc9a90c9e0 Add support for edge sensitive spec paths. 2007-03-02 06:13:22 +00:00
steve b21390b228 Better error message when operating on array. 2007-03-02 01:55:36 +00:00
steve 1352eada12 Improved buildrequires and clean (Günter Dannoritzer) 2007-03-02 01:30:47 +00:00
steve 243cf94165 Add support for conditional specify delay paths. 2007-03-01 06:19:38 +00:00
steve e789b3a5cf Snapshot 20070227 2007-02-28 01:34:42 +00:00
steve bb02da0319 Better error message around repeat concatenation syntax. 2007-02-27 06:10:16 +00:00
steve 0946f40c7b Detect and warn about lval array index out fo bounds. 2007-02-27 05:14:38 +00:00
steve 80a2b05733 Do not assign to words constant-indexed out of range. 2007-02-27 05:13:34 +00:00
steve 6804732b9e Spelling fixes (larry doolittle) 2007-02-26 19:49:48 +00:00
steve d6969b719a Prevent lost of width while calculation address. 2007-02-26 01:51:40 +00:00
steve d2ba78559a Process Verilog escape sequences much earlier. 2007-02-25 23:08:24 +00:00
steve 1f54f128c1 Handle unary minus of real valued expressions. 2007-02-20 05:58:36 +00:00
steve 2c32a81d91 Improved version of pr1639064 patch handles huge values. (larry doolittle) 2007-02-19 01:45:56 +00:00
steve cd5b1b111c Fix print of integers as real. <larry Doolittle> 2007-02-18 06:01:25 +00:00
steve 9d4fc92df5 Get page size from sysconf. 2007-02-16 23:30:14 +00:00
steve 45307f6144 Handle type of ternary expressions properly. 2007-02-14 05:59:46 +00:00
steve 92c36f152d Treat BOOL and LOGIC the same according to VPI functions. 2007-02-14 05:59:24 +00:00
steve 4f74d9df98 Add the mov/wr opcode. 2007-02-14 05:58:14 +00:00
steve 0137832003 Include types for ternary and string in dump. 2007-02-14 05:57:51 +00:00
steve 189532c5bf Hande specparam with min/myp/max values. 2007-02-13 04:39:25 +00:00
steve 7d2d87f7c6 NAND output is inverted once AFTER AND is calculated. 2007-02-12 05:08:27 +00:00
steve 521f66f040 Get padding right when loading array word into big vector. 2007-02-12 04:37:58 +00:00
steve c1c2381261 Parse all specify paths to pform. 2007-02-12 01:52:21 +00:00
steve 97234cb7ca Lexor handle escaped slash in strings. 2007-02-09 05:19:04 +00:00
steve 3fd80b09f0 Administrative/Makefile fixes, mostly for windows. (Cary R.) 2007-02-06 05:07:31 +00:00
steve 2b3acfb344 Expression lookaside cannot hold complex expressions 2007-02-06 04:43:53 +00:00
steve 326329d497 Set some missing local flags. 2007-02-05 01:42:31 +00:00
steve d958a4a5af Handle relink of continuous assignment. 2007-02-05 01:08:10 +00:00
steve 7d42c50253 Lookaside is invalid when working a new scope. 2007-02-02 04:48:49 +00:00
steve 6d91be5b19 Use inttypes.h instead of stdint.h for portability. 2007-02-02 04:33:00 +00:00
steve d52f41535f Ternary output node is local. 2007-02-01 19:06:06 +00:00
steve a623502ece More generous handling of errors in blocks. 2007-02-01 05:52:24 +00:00
steve d22e9713f7 Error message better reflects more general reality. 2007-02-01 05:25:26 +00:00
steve 5869d7d879 Include type in signal create message. 2007-02-01 05:24:08 +00:00
steve 074a6a44e3 Detect and report arrays without index in net contexts. 2007-02-01 03:14:33 +00:00
steve 85ceea7358 Fix missing check for thread bits width in ADDI 2007-01-31 22:28:55 +00:00
steve b2e1db6adb Add method to bind assertions to verilog source lines. 2007-01-31 04:21:10 +00:00
steve 05efaa6427 Treat VPI argument array with constant index specially. 2007-01-30 05:28:23 +00:00
steve cfe2198e5e Types of task/function arguments set in multiple steps. 2007-01-29 02:07:34 +00:00
steve d175eb17f1 Clarify the use of ivl_scope_def for not-functions. 2007-01-29 01:52:51 +00:00
steve 2de8bafb5c Fix padding of x when literal is sized and unsigned. 2007-01-27 05:36:11 +00:00
steve 8e1c7e2891 More literal implementation of inertial delay model. 2007-01-26 05:15:41 +00:00
steve 8ae6240947 Snapshot 20070123 2007-01-24 01:24:47 +00:00
steve f77d803aeb Clean up elaboration of for-loop increment expression. 2007-01-21 04:26:36 +00:00
steve 4b829bf04f Get argument widths right for shift results. 2007-01-20 02:10:45 +00:00
steve 17a508047b Better size error details. 2007-01-20 02:09:54 +00:00
steve b350b14f93 DLL API changes for windows. 2007-01-19 23:49:33 +00:00
steve ca9da51a79 Precalculate constant power expressions, and constant function arguments. 2007-01-19 05:42:40 +00:00
steve 98417cb03a Fix calculation of verinum pow operation. 2007-01-19 05:42:04 +00:00
steve f07257067a Handle real constants in vector expressions. 2007-01-19 05:24:53 +00:00
steve e4d7eda02a Fix missing data_type mark for array words. 2007-01-19 04:26:24 +00:00
steve 4d8164945e Fix missing passive setting for array word pins. 2007-01-19 04:25:37 +00:00
steve c0954349e4 Fix bad lookaside references in vvp thread code generator. 2007-01-19 02:30:19 +00:00
steve e89b9fc25e Do not match array words in expression lookaside. 2007-01-18 00:59:48 +00:00
steve 11a83c352d Add missing array source files to CVS. 2007-01-18 00:24:10 +00:00
steve d8d7673d27 Fix typo is hello_vpi.c example. 2007-01-17 05:35:48 +00:00
steve 6f3ddce7c4 Dead code for memories in scopes. 2007-01-17 05:00:12 +00:00
steve f5a7ee0736 Remove dead code related to memories. 2007-01-17 04:39:18 +00:00
steve 91d84e7dc7 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.
2007-01-16 05:44:14 +00:00
steve 5c3b2f4193 Snapshot 20061210 2006-12-10 17:18:56 +00:00
steve 0ae45e5644 Fix build error overloading pow function. 2006-12-10 17:15:48 +00:00
steve 296c2a575a Snapshot 20061209 2006-12-09 20:07:58 +00:00
steve 316422d93b Handle vpiRealVal reads of signals, and real anyedge events. 2006-12-09 19:06:53 +00:00
steve 2c7d2effd1 Fix an uninitialized variable warning. 2006-12-09 01:59:35 +00:00
steve 4fb5556d1c Handle very wide signed divide. 2006-12-08 19:56:09 +00:00
steve 2eeea7003e @* without inputs is an error. 2006-12-08 04:09:41 +00:00
steve d7de70bdeb Prevent name clash when processing parameter in net. 2006-12-08 03:43:26 +00:00
steve 078019ddec Parse the case of module arrays with port binding by name. 2006-12-06 05:32:36 +00:00
steve b4c3e8208f Parse bit selects in $setuphold notifiers. 2006-12-03 04:46:51 +00:00
steve 2f9a3e90ae Handle comments in file names. 2006-11-30 06:00:28 +00:00
steve 4f8a7ea84a Use new vvp_fun_XXX in place of old functor table for NAND/NOR/XNOR/EEQ. 2006-11-28 05:57:20 +00:00
steve a3da90aa4a Dump nand logic. 2006-11-28 05:56:41 +00:00
steve 48029ed8e5 Fix crash handling constant true conditional. 2006-11-27 02:01:07 +00:00
steve 94f07d16e3 Fix compile time eval of condition expresion to do reduction OR of vectors. 2006-11-26 07:10:30 +00:00
steve 041091cfac Fix nexus widths for direct link assign and ternary nets. 2006-11-26 06:29:16 +00:00
steve 0af4ea7cbe Better document the .scope record. 2006-11-23 23:02:36 +00:00
steve d6f98599f8 Do not intertangle modpaths due to references to input nets. 2006-11-23 22:42:48 +00:00
steve 2ac30824ac Fix spurious event from net8 that is forced. 2006-11-22 06:10:05 +00:00
steve 64b4e2fa01 Get the .event input from the signal instead of the signal input. 2006-11-22 06:09:08 +00:00
steve f5a204720d Support part writes into part select nodes. 2006-11-16 01:11:26 +00:00
steve 21522c90bc Process delay paths in second path over signals. 2006-11-10 05:44:44 +00:00
steve 34b5a31ff4 Add test_width methods for PETernary and PEString. 2006-11-10 04:54:26 +00:00
steve c339dc4bbc 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.
2006-11-04 06:19:24 +00:00
steve ed5d3188b3 Fix padding of constant eval of NetESelect. 2006-11-04 06:16:27 +00:00
steve 8e379bd634 Handle dup of pad as well as normal select. 2006-11-04 06:10:13 +00:00
steve 841378426f Updates for Cygwin portability (pr1585922) 2006-10-30 22:45:36 +00:00
steve 2302693201 Expression widths with unsized literals are pseudo-infinite width. 2006-10-30 05:44:49 +00:00
steve 2a8b960b06 More detailed internal error message. 2006-10-15 03:25:57 +00:00
steve 0e102a94b2 Fix rendering of signed numbers in real expressions. 2006-10-10 23:54:28 +00:00
189 changed files with 9921 additions and 5095 deletions
+1
View File
@@ -17,6 +17,7 @@ configure
Makefile
check
check.cc
check.vvp
config.status
config.log
config.cache
+5 -2
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 then what is included?" And
invoke the error without any Verilog other than 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,8 +160,11 @@ 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.4 2003/02/19 04:36:31 steve Exp $
$Id: BUGS.txt,v 1.5 2007/03/22 16:08:14 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.
+58 -186
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.5 2002/11/02 03:27:52 steve Exp $"
#ident "$Id: HName.cc,v 1.8 2007/06/02 03:42:12 steve Exp $"
#endif
# include "config.h"
@@ -29,235 +29,107 @@
# include <malloc.h>
#endif
hname_t::hname_t()
{
item_ = 0;
count_ = 0;
number_ = INT_MIN;
}
hname_t::hname_t(const char*text)
hname_t::hname_t(perm_string text)
{
item_ = strdup(text);
count_ = 1;
name_ = text;
number_ = INT_MIN;
}
hname_t::hname_t(perm_string text, int num)
{
name_ = text;
number_ = num;
}
hname_t::hname_t(const hname_t&that)
{
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;
}
name_ = that.name_;
number_ = that.number_;
}
hname_t& hname_t::operator = (const hname_t&that)
{
name_ = that.name_;
number_ = that.number_;
return *this;
}
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;
}
}
unsigned hname_t::component_count() const
perm_string hname_t::peek_name(void) const
{
return count_;
return name_;
}
void hname_t::append(const char*text)
bool hname_t::has_number() const
{
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;
}
return number_ != INT_MIN;
}
void hname_t::prepend(const char*text)
int hname_t::peek_number() const
{
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];
}
return number_;
}
bool operator < (const hname_t&l, const hname_t&r)
{
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)
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
return false;
if (rc && !lc)
return true;
// Must be ==
return false;
}
bool operator == (const hname_t&l, const hname_t&r)
{
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);
if (l.peek_name() == r.peek_name()) {
if (l.has_number() && r.has_number())
return l.peek_number() == r.peek_number();
else
return true;
}
if (lc || rc)
return false;
// Must be ==
return true;
return false;
}
bool operator != (const hname_t&l, const hname_t&r)
{ return ! (l==r); }
ostream& operator<< (ostream&out, const hname_t&that)
{
switch (that.count_) {
case 0:
if (that.peek_name() == 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.
+31 -33
View File
@@ -1,7 +1,7 @@
#ifndef __HName_H
#define __HName_H
/*
* Copyright (c) 2001 Stephen Williams ([email protected])
* Copyright (c) 2001-2007 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,10 +19,11 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: HName.h,v 1.4 2002/11/02 03:27:51 steve Exp $"
#ident "$Id: HName.h,v 1.7 2007/06/02 03:42:12 steve Exp $"
#endif
# include <iostream>
# include "StringHeap.h"
#ifdef __GNUC__
#if __GNUC__ > 2
using namespace std;
@@ -30,59 +31,56 @@ using namespace std;
#endif
/*
* This class represents a Verilog hierarchical name. A hierarchical
* name is an ordered list of simple names.
* 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.
*/
class hname_t {
public:
hname_t ();
explicit hname_t (const char*text);
explicit hname_t (perm_string text);
explicit hname_t (perm_string text, int num);
hname_t (const hname_t&that);
~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);
hname_t& operator= (const hname_t&);
// 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);
// Return the string part of the hname_t.
perm_string peek_name(void) 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&);
bool has_number() const;
int peek_number() const;
private:
union {
char**array_;
char* item_;
};
unsigned count_;
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_;
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.
+16 -14
View File
@@ -16,7 +16,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.178 2006/09/23 04:57:19 steve Exp $"
#ident "$Id: Makefile.in,v 1.181 2007/05/24 04:07:11 steve Exp $"
#
#
SHELL = /bin/sh
@@ -43,7 +43,6 @@ mandir = @mandir@
libdir64 = @libdir64@
dllib=@DLLIB@
strip_dynamic=@strip_dynamic@
CC = @CC@
CXX = @CXX@
@@ -51,7 +50,6 @@ INSTALL = @INSTALL@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
STRIP = @STRIP@
LEX = @LEX@
YACC = @YACC@
@@ -68,7 +66,7 @@ all: dep ivl@EXEEXT@
# In the windows world, the installer will need a dosify program to
# dosify text files.
ifeq (@WIN32@,yes)
ifeq (@MING32@,yes)
all: dep dosify.exe
dosify.exe: dosify.c
$(CC) -o dosify.exe dosify.c
@@ -84,17 +82,20 @@ check: all
clean:
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) $@); done
for dir in vpi ivlpp tgt-verilog driver; \
for dir in vpi ivlpp tgt-verilog tgt-pal driver driver-vpi; \
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 ivl@EXEEXT@
rm -rf dep
distclean: clean
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) $@); done
for dir in vpi ivlpp tgt-verilog driver; \
for dir in vpi ivlpp tgt-verilog tgt-pal driver driver-vpi; \
do (cd $$dir ; $(MAKE) $@); done
rm -f Makefile config.status config.log config.cache config.h
rm -f _pli_types.h
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
@@ -107,7 +108,7 @@ load_module.o netlist.o netmisc.o net_assign.o \
net_design.o net_event.o net_expr.o net_force.o net_func.o \
net_link.o net_modulo.o net_nex_input.o net_nex_output.o \
net_proc.o net_scope.o net_udp.o pad_to_width.o \
parse.o parse_misc.o pform.o pform_dump.o \
parse.o parse_misc.o pform.o pform_dump.o pform_types.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 \
@@ -128,11 +129,10 @@ 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) -o ivl@EXEEXT@ ivl.exp $O $(dllib) @EXTRALIBS@
$(CXX) $(LDFLAGS) -o ivl@EXEEXT@ ivl.exp $O $(dllib) @EXTRALIBS@
else
ivl@EXEEXT@: $O
$(CXX) $(LDFLAGS) -o ivl@EXEEXT@ $O $(dllib)
endif
ifeq (@MINGW32@,yes)
@@ -142,6 +142,9 @@ 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@;' \
@@ -182,7 +185,7 @@ iverilog-vpi.ps: $(srcdir)/iverilog-vpi.man
iverilog-vpi.pdf: iverilog-vpi.ps
ps2pdf iverilog-vpi.ps iverilog-vpi.pdf
ifeq (@WIN32@,yes)
ifeq (@MING32@,yes)
INSTALL_DOC = $(prefix)/iverilog-vpi.pdf $(mandir)/man1/iverilog-vpi.1
INSTALL_DOCDIR = $(mandir)/man1
all: dep iverilog-vpi.pdf
@@ -209,7 +212,6 @@ $(bindir)/iverilog-vpi: ./iverilog-vpi
$(libdir)/ivl/ivl@EXEEXT@: ./ivl@EXEEXT@
$(INSTALL_PROGRAM) ./ivl@EXEEXT@ $(libdir)/ivl/ivl@EXEEXT@
$(STRIP) $(strip_dynamic) $(libdir)/ivl/ivl@EXEEXT@
$(libdir)/ivl/xnf-s.conf: $(srcdir)/xnf-s.conf
$(INSTALL_DATA) $(srcdir)/xnf-s.conf $(libdir)/ivl/xnf-s.conf
@@ -266,14 +268,14 @@ uninstall:
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) $@); done
for dir in vpi ivlpp driver; \
do (cd $$dir ; $(MAKE) $@); done
for f in xnf.conf xnf-s.conf ivl; \
for f in xnf.conf xnf-s.conf ivl@EXEEXT@; \
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
rm -f $(mandir)/man1/iverilog-vpi.1 $(prefix)/iverilog-vpi.pdf
-include $(patsubst %.o, dep/%.d, $O)
+11 -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: Module.cc,v 1.25 2004/10/04 01:10:51 steve Exp $"
#ident "$Id: Module.cc,v 1.27 2007/05/24 04:07:11 steve Exp $"
#endif
# include "config.h"
@@ -31,6 +31,7 @@
Module::Module(perm_string n)
: name_(n)
{
library_flag = false;
default_nettype = NetNet::NONE;
}
@@ -110,9 +111,9 @@ unsigned Module::find_port(const char*name) const
}
PWire* Module::get_wire(const hname_t&name) const
PWire* Module::get_wire(const pform_name_t&name) const
{
map<hname_t,PWire*>::const_iterator obj = wires_.find(name);
map<pform_name_t,PWire*>::const_iterator obj = wires_.find(name);
if (obj == wires_.end())
return 0;
else
@@ -132,11 +133,6 @@ 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_;
@@ -150,6 +146,13 @@ 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.
*
+18 -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: Module.h,v 1.41 2006/09/23 04:57:19 steve Exp $"
#ident "$Id: Module.h,v 1.43 2007/05/24 04:07:11 steve Exp $"
#endif
# include <list>
@@ -30,6 +30,7 @@
# include "named.h"
# include "LineInfo.h"
# include "netlist.h"
# include "pform_types.h"
class PEvent;
class PExpr;
class PEIdent;
@@ -68,6 +69,12 @@ 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
@@ -92,7 +99,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<hname_t,PExpr*>defparms;
map<pform_name_t,PExpr*>defparms;
/* Parameters may be overridden at instantiation time;
the overrides do not contain explicit parameter names,
@@ -144,10 +151,9 @@ class Module : public LineInfo {
// Find a wire by name. This is used for connecting gates to
// existing wires, etc.
PWire* get_wire(const hname_t&name) const;
PWire* get_wire(const pform_name_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;
@@ -162,7 +168,7 @@ class Module : public LineInfo {
private:
perm_string name_;
map<hname_t,PWire*> wires_;
map<pform_name_t,PWire*> wires_;
list<PGate*> gates_;
list<PProcess*> behaviors_;
map<perm_string,PTask*> tasks_;
@@ -176,6 +182,13 @@ 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.42 2007/04/19 02:52:53 steve
* Add support for -v flag in command file.
*
* Revision 1.41 2006/09/23 04:57:19 steve
* Basic support for specify timing.
*
+53 -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: PExpr.cc,v 1.37 2005/10/04 04:09:25 steve Exp $"
#ident "$Id: PExpr.cc,v 1.39 2007/05/24 04:07:11 steve Exp $"
#endif
# include "config.h"
@@ -75,13 +75,44 @@ bool PEBinary::is_constant(Module*mod) const
return left_->is_constant(mod) && right_->is_constant(mod);
}
PECallFunction::PECallFunction(const hname_t&n, const svector<PExpr *> &parms)
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)
: path_(n), parms_(parms)
{
}
PECallFunction::PECallFunction(const hname_t&n)
: path_(n)
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))
{
}
@@ -147,33 +178,32 @@ bool PEFNumber::is_constant(Module*) const
return true;
}
PEIdent::PEIdent(const hname_t&s)
: path_(s), msb_(0), lsb_(0), sel_(SEL_NONE), idx_(0)
PEIdent::PEIdent(const pform_name_t&that)
: path_(that)
{
}
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;
/* 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));
/* */
perm_string tmp = path_.back().name;
{ map<perm_string,Module::param_expr_t>::const_iterator cur;
cur = mod->parameters.find(tmp);
@@ -270,6 +300,13 @@ 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.
*
+163 -46
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: PExpr.h,v 1.83 2006/06/18 04:15:50 steve Exp $"
#ident "$Id: PExpr.h,v 1.90 2007/06/04 19:14:06 steve Exp $"
#endif
# include <string>
@@ -27,6 +27,7 @@
# include "netlist.h"
# include "verinum.h"
# include "LineInfo.h"
# include "pform_types.h"
class Design;
class Module;
@@ -51,6 +52,31 @@ 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
@@ -99,7 +125,7 @@ class PExpr : public LineInfo {
// This attempts to evaluate a constant expression, and return
// a verinum as a result. If the expression cannot be
// evaluated, return 0.
virtual verinum* eval_const(const Design*des, NetScope*sc) const;
virtual verinum* eval_const(Design*des, NetScope*sc) const;
// This method returns true if that expression is the same as
// this expression. This method is used for comparing
@@ -125,7 +151,7 @@ class PEConcat : public PExpr {
PEConcat(const svector<PExpr*>&p, PExpr*r =0);
~PEConcat();
virtual verinum* eval_const(const Design*des, NetScope*sc) const;
virtual verinum* eval_const(Design*des, NetScope*sc) const;
virtual void dump(ostream&) const;
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope,
@@ -196,7 +222,7 @@ 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(const Design*des, NetScope*sc) const;
virtual verinum* eval_const(Design*des, NetScope*sc) const;
/* A PEFNumber is a constant, so this returns true. */
virtual bool is_constant(Module*) const;
@@ -222,10 +248,18 @@ class PEFNumber : public PExpr {
class PEIdent : public PExpr {
public:
explicit PEIdent(const hname_t&s);
explicit PEIdent(perm_string);
explicit PEIdent(const pform_name_t&);
~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;
// Identifiers are allowed (with restrictions) is assign l-values.
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope,
@@ -256,14 +290,23 @@ class PEIdent : public PExpr {
NetNet* elaborate_port(Design*des, NetScope*sc) const;
virtual bool is_constant(Module*) const;
verinum* eval_const(const Design*des, NetScope*sc) const;
verinum* eval_const(Design*des, NetScope*sc) const;
const hname_t& path() const;
const pform_name_t& path() const { return path_; }
private:
NetAssign_*elaborate_lval_net_part_(Design*, NetScope*, NetNet*) const;
NetAssign_*elaborate_lval_net_idx_up_(Design*, NetScope*, NetNet*) const;
NetAssign_*elaborate_lval_net_idx_do_(Design*, NetScope*, NetNet*) const;
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,
@@ -273,44 +316,41 @@ class PEIdent : public PExpr {
const NetExpr*par_msb,
const NetExpr*par_lsb) const;
NetExpr*elaborate_expr_net(Design*des,
NetScope*scope,
NetNet*net,
NetScope*found) const;
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,
NetNet*net,
NetESignal*net,
NetScope*found) const;
NetExpr*elaborate_expr_net_idx_up_(Design*des,
NetScope*scope,
NetNet*net,
NetESignal*net,
NetScope*found) const;
NetExpr*elaborate_expr_net_idx_do_(Design*des,
NetScope*scope,
NetNet*net,
NetESignal*net,
NetScope*found) const;
NetExpr*elaborate_expr_net_bit_(Design*des,
NetScope*scope,
NetNet*net,
NetESignal*net,
NetScope*found) const;
hname_t path_;
public:
// Use these to support part-select operators.
PExpr*msb_;
PExpr*lsb_;
enum { SEL_NONE, SEL_PART, SEL_IDX_UP, SEL_IDX_DO } sel_;
// If this is a reference to a memory/array, this is the index
// expression. If this is a reference to a vector, this is a
// bit select.
std::vector<PExpr*> idx_;
NetNet* elaborate_net_ram_(Design*des, NetScope*scope,
NetMemory*mem, unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay) const;
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;
NetNet* elaborate_net_bitmux_(Design*des, NetScope*scope,
NetNet*sig,
@@ -321,9 +361,6 @@ class PEIdent : public PExpr {
Link::strength_t drive1) const;
private:
NetAssign_* elaborate_mem_lval_(Design*des, NetScope*scope,
NetMemory*mem) const;
NetNet* elaborate_lnet_common_(Design*des, NetScope*scope,
bool implicit_net_ok,
bool bidirectional_flag) const;
@@ -332,6 +369,7 @@ class PEIdent : public PExpr {
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;
};
@@ -344,6 +382,10 @@ 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,
@@ -358,7 +400,7 @@ class PENumber : public PExpr {
NetScope*scope,
bool is_force) const;
virtual verinum* eval_const(const Design*des, NetScope*sc) const;
virtual verinum* eval_const(Design*des, NetScope*sc) const;
virtual bool is_the_same(const PExpr*that) const;
virtual bool is_constant(Module*) const;
@@ -382,6 +424,11 @@ 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,
@@ -392,7 +439,7 @@ class PEString : public PExpr {
virtual NetEConst*elaborate_expr(Design*des, NetScope*,
int expr_width, bool) const;
virtual NetEConst*elaborate_pexpr(Design*des, NetScope*sc) const;
verinum* eval_const(const Design*, NetScope*) const;
verinum* eval_const(Design*, NetScope*) const;
virtual bool is_constant(Module*) const;
@@ -407,6 +454,7 @@ class PEUnary : public PExpr {
~PEUnary();
virtual void dump(ostream&out) const;
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned width,
const NetExpr* rise,
@@ -417,7 +465,7 @@ class PEUnary : public PExpr {
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
int expr_width, bool sys_task_arg) const;
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
virtual verinum* eval_const(const Design*des, NetScope*sc) const;
virtual verinum* eval_const(Design*des, NetScope*sc) const;
virtual bool is_constant(Module*) const;
@@ -435,6 +483,11 @@ 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,
@@ -445,15 +498,17 @@ class PEBinary : public PExpr {
virtual NetEBinary*elaborate_expr(Design*des, NetScope*,
int expr_width, bool sys_task_arg) const;
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
virtual verinum* eval_const(const Design*des, NetScope*sc) const;
virtual verinum* eval_const(Design*des, NetScope*sc) const;
private:
protected:
char op_;
PExpr*left_;
PExpr*right_;
NetEBinary*elaborate_expr_base_(Design*, NetExpr*lp, NetExpr*rp) const;
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;
private:
NetNet* elaborate_net_add_(Design*des, NetScope*scope,
unsigned lwidth,
const NetExpr* rise,
@@ -496,6 +551,34 @@ class PEBinary : public PExpr {
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;
};
/*
* This class supports the ternary (?:) operator. The operator takes
* three expressions, the test, the true result and the false result.
@@ -509,6 +592,10 @@ 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,
@@ -519,7 +606,7 @@ class PETernary : public PExpr {
virtual NetETernary*elaborate_expr(Design*des, NetScope*,
int expr_width, bool sys_task_arg) const;
virtual NetETernary*elaborate_pexpr(Design*des, NetScope*sc) const;
virtual verinum* eval_const(const Design*des, NetScope*sc) const;
virtual verinum* eval_const(Design*des, NetScope*sc) const;
private:
PExpr*expr_;
@@ -534,11 +621,14 @@ class PETernary : public PExpr {
*/
class PECallFunction : public PExpr {
public:
explicit PECallFunction(const hname_t&n, const svector<PExpr *> &parms);
explicit PECallFunction(const hname_t&n);
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);
~PECallFunction();
virtual void dump(ostream &) const;
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned width,
const NetExpr* rise,
@@ -550,7 +640,7 @@ class PECallFunction : public PExpr {
int expr_wid, bool sys_task_arg) const;
private:
hname_t path_;
pform_name_t path_;
svector<PExpr *> parms_;
bool check_call_matches_definition_(Design*des, NetScope*dscope) const;
@@ -567,6 +657,33 @@ class PECallFunction : public PExpr {
/*
* $Log: PExpr.h,v $
* Revision 1.90 2007/06/04 19:14:06 steve
* Build errors in picky GCC 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.
*
+9 -3
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: PGenerate.cc,v 1.1 2006/04/10 02:40:18 steve Exp $"
#ident "$Id: PGenerate.cc,v 1.4 2007/06/02 03:42:12 steve Exp $"
#endif
# include "PGenerate.h"
@@ -26,6 +26,7 @@
PGenerate::PGenerate(unsigned id)
: id_number(id)
{
parent = 0;
}
PGenerate::~PGenerate()
@@ -42,9 +43,9 @@ PWire* PGenerate::add_wire(PWire*wire)
return wire;
}
PWire* PGenerate::get_wire(const hname_t&name) const
PWire* PGenerate::get_wire(const pform_name_t&name) const
{
map<hname_t,PWire*>::const_iterator obj = wires.find(name);
map<pform_name_t,PWire*>::const_iterator obj = wires.find(name);
if (obj == wires.end())
return 0;
else
@@ -55,3 +56,8 @@ void PGenerate::add_gate(PGate*gate)
{
gates.push_back(gate);
}
void PGenerate::add_behavior(PProcess*proc)
{
behaviors.push_back(proc);
}
+12 -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: PGenerate.h,v 1.1 2006/04/10 02:40:18 steve Exp $"
#ident "$Id: PGenerate.h,v 1.4 2007/06/02 03:42:12 steve Exp $"
#endif
# include "LineInfo.h"
@@ -27,10 +27,12 @@
# include "HName.h"
# include <list>
# include <map>
# include "pform_types.h"
class Design;
class NetScope;
class PExpr;
class PProcess;
class PGate;
class PWire;
@@ -58,13 +60,19 @@ class PGenerate : public LineInfo {
PExpr*loop_test;
PExpr*loop_step;
map<hname_t,PWire*>wires;
map<pform_name_t,PWire*>wires;
PWire* add_wire(PWire*);
PWire* get_wire(const hname_t&name) const;
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.
@@ -73,7 +81,7 @@ class PGenerate : public LineInfo {
bool elaborate_sig(Design*des) const;
bool elaborate(Design*des) const;
void dump(ostream&out) const;
void dump(ostream&out, unsigned indent) const;
private:
bool generate_scope_loop_(Design*des, NetScope*container);
+4 -2
View File
@@ -17,13 +17,15 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: PSpec.cc,v 1.1 2006/09/26 19:48:40 steve Exp $"
#ident "$Id: PSpec.cc,v 1.2 2007/02/12 01:52:21 steve Exp $"
#endif
# include "PSpec.h"
PSpecPath::PSpecPath(unsigned src_cnt, unsigned dst_cnt)
: src(src_cnt), dst(dst_cnt)
: conditional(false), condition(0), edge(0),
src(src_cnt), dst(dst_cnt),
data_source_expression(0)
{
}
+32 -1
View File
@@ -19,13 +19,37 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: PSpec.h,v 1.1 2006/09/23 04:57:19 steve Exp $"
#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:
@@ -37,10 +61,17 @@ class PSpecPath : public LineInfo {
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;
};
+5 -1
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.13 2004/05/31 23:34:36 steve Exp $"
#ident "$Id: PTask.h,v 1.14 2007/03/06 05:22:49 steve Exp $"
#endif
# include "LineInfo.h"
@@ -35,6 +35,7 @@ class PExpr;
enum PTaskFuncEnum {
PTF_NONE,
PTF_REG,
PTF_REG_S,
PTF_INTEGER,
PTF_REAL,
PTF_REALTIME,
@@ -117,6 +118,9 @@ 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 2004/05/31 23:34:36 steve
* Rewire/generalize parsing an elaboration of
* function return values to allow for better
+17 -20
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2005 Stephen Williams ([email protected])
* Copyright (c) 1999-2007 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,29 +17,14 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: PWire.cc,v 1.11 2005/07/07 16:22:49 steve Exp $"
#ident "$Id: PWire.cc,v 1.14 2007/05/24 04:07:11 steve Exp $"
#endif
# include "config.h"
# include "PWire.h"
# include <assert.h>
PWire::PWire(const hname_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),
lidx_(0), ridx_(0)
{
if (t == NetNet::INTEGER) {
type_ = NetNet::REG;
signed_ = true;
isint_ = true;
}
}
PWire::PWire(char*n,
PWire::PWire(const pform_name_t&n,
NetNet::Type t,
NetNet::PortType pt,
ivl_variable_type_t dt)
@@ -59,7 +44,7 @@ NetNet::Type PWire::get_wire_type() const
return type_;
}
const hname_t& PWire::path() const
const pform_name_t& PWire::path() const
{
return hname_;
}
@@ -154,13 +139,25 @@ 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.
*
+18 -48
View File
@@ -1,7 +1,7 @@
#ifndef __PWire_H
#define __PWire_H
/*
* Copyright (c) 1998-2000 Stephen Williams ([email protected])
* Copyright (c) 1998-2007 Stephen Williams ([email protected])
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@@ -19,13 +19,14 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: PWire.h,v 1.19 2006/04/10 00:37:42 steve Exp $"
#ident "$Id: PWire.h,v 1.21 2007/05/24 04:07:11 steve Exp $"
#endif
# include "netlist.h"
# include "LineInfo.h"
# include <map>
# include "svector.h"
# include "StringHeap.h"
#ifdef HAVE_IOSFWD
# include <iosfwd>
@@ -42,24 +43,21 @@ class Design;
* identifies a port by keeping it in its port list.
*
* The hname parameter to the constructor is a hierarchical name. It
* 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.
* 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.
*/
class PWire : public LineInfo {
public:
PWire(const hname_t&hname,
NetNet::Type t,
NetNet::PortType pt,
ivl_variable_type_t dt);
PWire(char*name,
PWire(const pform_name_t&hname,
NetNet::Type t,
NetNet::PortType pt,
ivl_variable_type_t dt);
// Return a hierarchical name.
const hname_t&path() const;
const pform_name_t&path() const;
NetNet::Type get_wire_type() const;
bool set_wire_type(NetNet::Type);
@@ -83,10 +81,10 @@ class PWire : public LineInfo {
// Write myself to the specified stream.
void dump(ostream&out, unsigned ind=4) const;
void elaborate_sig(Design*, NetScope*scope) const;
NetNet* elaborate_sig(Design*, NetScope*scope) const;
private:
hname_t hname_;
pform_name_t hname_;
NetNet::Type type_;
NetNet::PortType port_type_;
ivl_variable_type_t data_type_;
@@ -110,6 +108,13 @@ 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.
*
@@ -146,40 +151,5 @@ 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
+15 -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: Statement.cc,v 1.29 2004/02/18 17:11:54 steve Exp $"
#ident "$Id: Statement.cc,v 1.30 2007/05/24 04:07:11 steve Exp $"
#endif
# include "config.h"
@@ -107,16 +107,22 @@ PBlock::~PBlock()
delete list_[idx];
}
PCallTask::PCallTask(const hname_t&n, const svector<PExpr*>&p)
PCallTask::PCallTask(const pform_name_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 hname_t& PCallTask::path() const
const pform_name_t& PCallTask::path() const
{
return path_;
}
@@ -178,7 +184,7 @@ PDelayStatement::~PDelayStatement()
{
}
PDisable::PDisable(const hname_t&sc)
PDisable::PDisable(const pform_name_t&sc)
: scope_(sc)
{
}
@@ -273,7 +279,7 @@ PRepeat::~PRepeat()
delete statement_;
}
PTrigger::PTrigger(const hname_t&e)
PTrigger::PTrigger(const pform_name_t&e)
: event_(e)
{
}
@@ -295,6 +301,10 @@ 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.
*
+18 -8
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.42 2005/12/05 21:21:18 steve Exp $"
#ident "$Id: Statement.h,v 1.44 2007/05/24 04:07:11 steve Exp $"
#endif
# include <string>
@@ -55,6 +55,8 @@ class PProcess : public LineInfo {
virtual ~PProcess();
bool elaborate(Design*des, NetScope*scope) const;
Type type() const { return type_; }
Statement*statement() { return statement_; }
@@ -171,10 +173,11 @@ class PBlock : public Statement {
class PCallTask : public Statement {
public:
explicit PCallTask(const hname_t&n, const svector<PExpr*>&parms);
explicit PCallTask(const pform_name_t&n, const svector<PExpr*>&parms);
explicit PCallTask(perm_string n, const svector<PExpr*>&parms);
~PCallTask();
const hname_t& path() const;
const pform_name_t& path() const;
unsigned nparms() const { return parms_.count(); }
@@ -195,7 +198,7 @@ class PCallTask : public Statement {
NetProc* elaborate_sys(Design*des, NetScope*scope) const;
NetProc* elaborate_usr(Design*des, NetScope*scope) const;
hname_t path_;
pform_name_t path_;
svector<PExpr*> parms_;
};
@@ -294,14 +297,14 @@ class PDelayStatement : public Statement {
class PDisable : public Statement {
public:
explicit PDisable(const hname_t&sc);
explicit PDisable(const pform_name_t&sc);
~PDisable();
virtual void dump(ostream&out, unsigned ind) const;
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
private:
hname_t scope_;
pform_name_t scope_;
};
/*
@@ -431,14 +434,14 @@ class PRelease : public Statement {
class PTrigger : public Statement {
public:
explicit PTrigger(const hname_t&ev);
explicit PTrigger(const pform_name_t&ev);
~PTrigger();
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void dump(ostream&out, unsigned ind) const;
private:
hname_t event_;
pform_name_t event_;
};
class PWhile : public Statement {
@@ -458,6 +461,13 @@ 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.
*
+6 -3
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.7 2003/11/12 02:38:44 steve Exp $"
#ident "$Id: _pli_types.h.in,v 1.8 2007/06/05 21:32:30 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 signed char PLI_BYTE8;
typedef char PLI_BYTE8;
typedef unsigned char PLI_UBYTE8;
# define PLI_UINT64_FMT PRIu64
@@ -84,12 +84,15 @@ typedef signed int PLI_INT32;
typedef unsigned int PLI_UINT32;
typedef signed short PLI_INT16;
typedef unsigned short PLI_UINT16;
typedef signed char PLI_BYTE8;
typedef 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
+3 -3
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.6 2004/10/04 01:10:52 steve Exp $"
#ident "$Id: aclocal.m4,v 1.7 2007/05/16 23:59:12 steve Exp $"
],[while (0) {}],
[AS_VAR_SET(ax_cv_cpp_ident, yes)],
[AS_VAR_SET(ax_cv_cpp_ident, no)])])
@@ -48,7 +48,7 @@ AC_DEFUN([AX_C_UNDERSCORES_LEADING],
[AS_VAR_SET(ax_cv_c_underscores_leading, yes)],
[AS_VAR_SET(ax_cv_c_underscores_leading, no)])])
if test $ax_cv_c_underscores_leading = yes -a "$CYGWIN" != "yes" -a "$MINGW32" != "yes"; then
AC_DEFINE(NEED_LU)
AC_DEFINE([NEED_LU], [1], [Symbol names in object files produced by C compiler have leading underscores.])
fi
])# AX_C_UNDERSCORES_LEADING
@@ -63,7 +63,7 @@ AC_DEFUN([AX_C_UNDERSCORES_TRAILING],
[AS_VAR_SET(ax_cv_c_underscores_trailing, yes)],
[AS_VAR_SET(ax_cv_c_underscores_trailing, no)])])
if test $ax_cv_c_underscores_trailing = yes; then
AC_DEFINE(NEED_TU)
AC_DEFINE([NEED_TU], [1], [Symbol names in object files produced by C compiler have trailing underscores.])
fi
])# AX_C_UNDERSCORES_TRAILING
+2 -5
View File
@@ -16,7 +16,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.12 2006/02/15 18:42:42 steve Exp $"
#ident "$Id: Makefile.in,v 1.13 2007/02/06 05:07:31 steve Exp $"
#
#
SHELL = /bin/sh
@@ -35,8 +35,6 @@ includedir = $(prefix)/include
vpidir = @libdir@/ivl/@vpidir1@
strip_dynamic=@strip_dynamic@
CC = @CC@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
@@ -45,7 +43,6 @@ INSTALL_DATA = @INSTALL_DATA@
CPPFLAGS = @ident_support@ -I$(srcdir) -I$(srcdir)/.. -I.. @CPPFLAGS@ @DEFS@ @PICFLAG@
CFLAGS = -Wall @CFLAGS@
LDFLAGS = @LDFLAGS@
STRIP = @STRIP@
SHARED = @shared@
@@ -74,7 +71,7 @@ dep:
O = cadpli.o
SYSTEM_VPI_LDFLAGS = -L../vvp -lvpi
ifeq (@WIN32@,yes)
ifeq (@MING32@,yes)
SYSTEM_VPI_LDFLAGS += @EXTRALIBS@
endif
+1 -1
View File
@@ -37,7 +37,7 @@ AC_SUBST(DLLIB)
AX_CPP_PRECOMP
# Compiler option for position independent code, needed whan making shared objects.
# Compiler option for position independent code, needed when making shared objects.
AX_C_PICFLAG
# Linker option used when compiling the target
+17 -7
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.31 2006/09/28 04:35:18 steve Exp $"
#ident "$Id: compiler.h,v 1.33 2007/04/19 02:52:53 steve Exp $"
#endif
# include <list>
@@ -32,11 +32,8 @@
*/
/* 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 integer_width is the width of integer variables. */
extern unsigned integer_width;
/* The TIME_WIDTH is the width of time variables. */
#ifndef TIME_WIDTH
@@ -120,13 +117,20 @@ 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.
@@ -148,6 +152,12 @@ 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.32 2007/03/07 04:24:59 steve
* Make integer width controllable.
*
* Revision 1.31 2006/09/28 04:35:18 steve
* Support selective control of specify and xtypes features.
*
+9 -1
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.11 2004/10/04 01:10:52 steve Exp $"
#ident "$Id: config.h.in,v 1.12 2007/02/02 04:33:00 steve Exp $"
#endif
#if defined(__cplusplus)
@@ -37,6 +37,7 @@
# 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
@@ -48,8 +49,15 @@
# 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.
*
+2 -2
View File
@@ -66,7 +66,7 @@ AC_TRY_LINK(
#include <sys/times.h>
,{clock_t a = times(0)/sysconf(_SC_CLK_TCK);},
do_times=yes
AC_DEFINE(HAVE_TIMES,1),
AC_DEFINE([HAVE_TIMES], [1], [The times system call is available in the host operating system.]),
do_times=no
)
AC_MSG_RESULT($do_times)
@@ -93,7 +93,7 @@ AC_C_BIGENDIAN
AX_LD_EXTRALIBS
# Compiler option for position independent code, needed whan making shared objects.
# Compiler option for position independent code, needed when making shared objects.
# CFLAGS inherited by cadpli/Makefile?
AX_C_PICFLAG
+6 -1
View File
@@ -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.55 2006/05/24 04:32:57 steve Exp $"
#ident "$Id: cprop.cc,v 1.56 2007/03/07 00:38:15 steve Exp $"
#endif
# include "config.h"
@@ -215,7 +215,9 @@ void cprop_functor::lpm_ff(Design*des, NetFF*obj)
void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
{
#if 0
NetScope*scope = obj->scope();
#endif
switch (obj->type()) {
#if 0
@@ -948,6 +950,9 @@ void cprop(Design*des)
/*
* $Log: cprop.cc,v $
* Revision 1.56 2007/03/07 00:38:15 steve
* Lint fixes.
*
* Revision 1.55 2006/05/24 04:32:57 steve
* Fix handling of ternary-to-bufif0 constant propagation.
*
+94 -76
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.170 2006/10/03 05:06:00 steve Exp $"
#ident "$Id: design_dump.cc,v 1.176 2007/06/02 03:42:12 steve Exp $"
#endif
# include "config.h"
@@ -30,6 +30,7 @@
# include <iomanip>
# include "netlist.h"
# include "compiler.h"
# include "ivl_assert.h"
static ostream& operator<< (ostream&o, NetBlock::Type t)
{
@@ -90,9 +91,31 @@ ostream& operator << (ostream&o, ivl_variable_type_t val)
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 src "
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]
@@ -112,8 +135,8 @@ void NetDelaySrc::dump(ostream&o, unsigned ind) const
/* Dump a net. This can be a wire or register. */
void NetNet::dump_net(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << type() << ": " << name() << "[" <<
pin_count() << "]";
o << setw(ind) << "" << type() << ": " << name()
<< "[" << s0_ << ":" << e0_ << " count=" << pin_count() << "]";
if (local_flag_)
o << " (local)";
o << " " << data_type_;
@@ -137,7 +160,7 @@ void NetNet::dump_net(ostream&o, unsigned ind) const
}
o << " (eref=" << peek_eref() << ", lref=" << peek_lref() << ")";
if (scope())
o << " scope=" << scope()->name();
o << " scope=" << scope_path(scope());
o << " #(" << rise_time() << "," << fall_time() << ","
<< decay_time() << ") vector_width=" << vector_width()
<< " pin_count=" << pin_count()
@@ -167,13 +190,6 @@ void NetNet::dump_net(ostream&o, unsigned ind) const
dump_obj_attr(o, ind+4);
}
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. */
@@ -239,6 +255,15 @@ void NetAddSub::dump_node(ostream&o, unsigned ind) const
dump_obj_attr(o, ind+4);
}
void NetArrayDq::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "NetArrayDq: " << name()
<< " array=" << mem_->name()
<< endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
void NetCLShift::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "Combinatorial shift (NetCLShift): " <<
@@ -258,7 +283,7 @@ void NetConcat::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "NetConcat: "
<< name()
<< " scope=" << (scope()? scope()->name() : "")
<< " scope=" << scope_path(scope())
<< " width=" << width_ << endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
@@ -282,7 +307,7 @@ void NetMux::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "Multiplexer (NetMux): " << name()
<< " width=" << width_ << " swidth=" << swidth_ << " size=" << size_
<< " scope=" << scope()->name() << endl;
<< " scope=" << scope_path(scope()) << endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
@@ -290,7 +315,7 @@ 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()? scope()->name() : "")
<< " scope=" << scope_path(scope())
<< " delay=(" << rise_time() << "," << fall_time() << "," <<
decay_time() << ") width=" << width() << endl;
dump_node_pins(o, ind+4);
@@ -318,7 +343,7 @@ void NetConst::dump_node(ostream&o, unsigned ind) const
void NetFF::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "LPM_FF: " << name()
<< " scope=" << (scope()? scope()->name() : "")
<< " scope=" << scope_path(scope())
<< " aset_value=" << aset_value_ << endl;
dump_node_pins(o, ind+4);
@@ -393,7 +418,7 @@ void NetLogic::dump_node(ostream&o, unsigned ind) const
}
o << " #(" << rise_time()
<< "," << fall_time() << "," << decay_time() << ") " << name()
<< " scope=" << (scope()? scope()->name() : "")
<< " scope=" << scope_path(scope())
<< endl;
dump_node_pins(o, ind+4);
@@ -427,14 +452,6 @@ void NetPartSelect::dump_node(ostream&o, unsigned ind) const
dump_obj_attr(o, ind+4);
}
void NetRamDq::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "LPM_RAM_DQ (" << mem_->name() << "): "
<< name() << endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
void NetReplicate::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "NetReplicate: "
@@ -480,7 +497,7 @@ void NetUReduce::dump_node(ostream&o, unsigned ind) const
}
o << " #(" << rise_time()
<< "," << fall_time() << "," << decay_time() << ") " << name()
<< " scope=" << (scope()? scope()->name() : "")
<< " scope=" << scope_path(scope())
<< endl;
dump_node_pins(o, ind+4);
@@ -496,7 +513,7 @@ void NetSysFunc::dump_node(ostream&o, unsigned ind) const
void NetUserFunc::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << def_->name() << "(";
o << setw(ind) << "" << scope_path(def_) << "(";
o << ")" << endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
@@ -504,7 +521,7 @@ void NetUserFunc::dump_node(ostream&o, unsigned ind) const
void NetTaskDef::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "task " << name_ << ";" << endl;
o << setw(ind) << "" << "task " << scope_path(scope_) << ";" << endl;
for (unsigned idx = 0 ; idx < ports_.count() ; idx += 1) {
o << setw(ind+4) << "";
@@ -546,11 +563,11 @@ void NetProcTop::dump(ostream&o, unsigned ind) const
switch (type_) {
case NetProcTop::KINITIAL:
o << "initial /* " << get_line() << " in "
<< scope_->name() << " */" << endl;
<< scope_path(scope_) << " */" << endl;
break;
case NetProcTop::KALWAYS:
o << "always /* " << get_line() << " in "
<< scope_->name() << " */" << endl;
<< scope_path(scope_) << " */" << endl;
break;
}
@@ -566,21 +583,9 @@ void NetAssign_::dump_lval(ostream&o) const
{
if (sig_) {
o << sig_->name();
if (bmux_) {
o << "[" << *bmux_ << "]";
} else if (base_) {
o << "[" << *base_ << " +: " << lwid_ << "]";
if (word_) {
o << "[word=" << *word_ << "]";
}
} 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 << "]";
if (base_) {
o << "[" << *base_ << " +: " << lwid_ << "]";
}
@@ -644,7 +649,7 @@ void NetBlock::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << type_;
if (subscope_)
o << " : " << subscope_->name();
o << " : " << scope_path(subscope_);
o << endl;
if (last_) {
@@ -721,7 +726,7 @@ void NetDeassign::dump(ostream&o, unsigned ind) const
void NetDisable::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "disable " << target_->name() << "; "
o << setw(ind) << "" << "disable " << scope_path(target_) << "; "
<< "/* " << get_line() << " */" << endl;
}
@@ -740,7 +745,7 @@ void NetEvProbe::dump_node(ostream&o, unsigned ind) const
o << "negedge ";
break;
}
o << setw(ind) << "" << "-> " << event_->full_name() << "; " << endl;
o << setw(ind) << "" << "-> " << event_->name() << "; " << endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
@@ -753,11 +758,13 @@ void NetEvTrig::dump(ostream&o, unsigned ind) const
void NetEvWait::dump(ostream&o, unsigned ind) const
{
assert(nevents() > 0);
o << setw(ind) <<"" << "@(" << event(0)->full_name();
o << setw(ind) <<"" << "@(";
if (nevents() > 0)
o << event(0)->name();
for (unsigned idx = 1 ; idx < nevents() ; idx += 1)
o << " or " << event(idx)->full_name();
o << " or " << event(idx)->name();
o << ") // " << get_line() << endl;
@@ -782,7 +789,7 @@ void NetForever::dump(ostream&o, unsigned ind) const
void NetFuncDef::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "function " << scope_->name() << endl;
o << setw(ind) << "" << "function " << scope_path(scope_) << endl;
if (result_sig_)
o << setw(ind+2) << "" << "Return signal: "
<< result_sig_->name() << endl;
@@ -825,7 +832,7 @@ void NetRepeat::dump(ostream&o, unsigned ind) const
void NetScope::dump(ostream&o) const
{
/* This is a constructed hierarchical name. */
o << name();
o << scope_path(this);
switch (type_) {
case BEGIN_END:
@@ -883,7 +890,7 @@ void NetScope::dump(ostream&o) const
/* Dump the saved defparam assignments here. */
{
map<hname_t,NetExpr*>::const_iterator pp;
map<pform_name_t,NetExpr*>::const_iterator pp;
for (pp = defparams.begin()
; pp != defparams.end() ; pp ++ ) {
o << " defparam " << (*pp).first << " = " <<
@@ -894,7 +901,8 @@ void NetScope::dump(ostream&o) const
/* Dump the events in this scope. */
for (NetEvent*cur = events_ ; cur ; cur = cur->snext_) {
o << " event " << cur->name() << "; nprobe="
<< cur->nprobe() << " // " << cur->get_line() << endl;
<< cur->nprobe() << " scope=" << scope_path(cur->scope())
<< " // " << cur->get_line() << endl;
}
// Dump the signals,
@@ -906,15 +914,6 @@ void NetScope::dump(ostream&o) const
} while (cur != signals_->sig_next_);
}
// Dump the memories,
if (memories_) {
NetMemory*cur = memories_->snext_;
do {
cur->dump(o, 4);
cur = cur->snext_;
} while (cur != memories_->snext_);
}
// Dump specparams
typedef map<perm_string,spec_val_t>::const_iterator specparam_it_t;
for (specparam_it_t cur = specparams.begin()
@@ -977,7 +976,7 @@ void NetSTask::dump(ostream&o, unsigned ind) const
void NetUTask::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << task_->name() << ";" << endl;
o << setw(ind) << "" << scope_path(task_) << ";" << endl;
}
void NetWhile::dump(ostream&o, unsigned ind) const
@@ -1112,7 +1111,7 @@ void NetEEvent::dump(ostream&o) const
void NetEScope::dump(ostream&o) const
{
o << "<scope=" << scope_->name() << ">";
o << "<scope=" << scope_path(scope_) << ">";
}
void NetESelect::dump(ostream&o) const
@@ -1148,22 +1147,19 @@ void NetESignal::dump(ostream&o) const
{
if (has_sign())
o << "+";
o << name() << "[" << msi()<<":"<<lsi() << "]";
}
void NetEMemory::dump(ostream&o) const
{
o << mem_->name() << "[";
if (idx_) idx_->dump(o);
o << "]";
o << name();
if (word_) o << "[word=" << *word_ << "]";
o << "[" << msi()<<":"<<lsi() << "]";
}
void NetEParam::dump(ostream&o) const
{
if (scope_ != 0)
o << "<" << scope_->name() << "." << name_ << ">";
else
o << "<" << scope_path(scope_) << "." << name_ << ">";
else if (name_)
o << "<" << name_ << ">";
else
o << "<" "???" ">";
}
void NetETernary::dump(ostream&o) const
@@ -1174,7 +1170,7 @@ void NetETernary::dump(ostream&o) const
void NetEUFunc::dump(ostream&o) const
{
o << name() << "(";
o << func_->basename() << "(";
if (parms_.count() > 0) {
parms_[0]->dump(o);
for (unsigned idx = 1 ; idx < parms_.count() ; idx += 1) {
@@ -1229,6 +1225,28 @@ 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.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.174 2007/03/02 06:13:22 steve
* Add support for edge sensitive spec paths.
*
* Revision 1.173 2007/02/01 03:14:33 steve
* Detect and report arrays without index in net contexts.
*
* 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.171 2006/10/30 05:44:49 steve
* Expression widths with unsized literals are pseudo-infinite width.
*
* Revision 1.170 2006/10/03 05:06:00 steve
* Support real valued specify delays, properly scaled.
*
+4 -4
View File
@@ -16,7 +16,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.24 2004/10/13 22:01:34 steve Exp $"
#ident "$Id: Makefile.in,v 1.26 2007/02/06 05:07:31 steve Exp $"
#
#
SHELL = /bin/sh
@@ -50,7 +50,7 @@ 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@
rm -f iverilog@EXEEXT@ iverilog.pdf iverilog.ps
distclean: clean
rm -f Makefile
@@ -80,7 +80,7 @@ iverilog.ps: $(srcdir)/iverilog.man
iverilog.pdf: iverilog.ps
ps2pdf iverilog.ps iverilog.pdf
ifeq (@WIN32@,yes)
ifeq (@MING32@,yes)
INSTALL_DOC = $(prefix)/iverilog.pdf $(mandir)/man1/iverilog.1
INSTALL_DOCDIR = $(mandir)/man1
all: iverilog.pdf
@@ -105,4 +105,4 @@ installdirs: ../mkinstalldirs
uninstall:
rm -f $(bindir)/iverilog@EXEEXT@
rm -f $(mandir)/man1/iverilog.1
rm -f $(mandir)/man1/iverilog.1 $(prefix)/iverilog.pdf
+42 -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: cflexor.lex,v 1.8 2004/10/04 01:10:56 steve Exp $"
#ident "$Id: cflexor.lex,v 1.11 2007/03/22 16:08:18 steve Exp $"
#endif
# include "cfparse.h"
@@ -37,12 +37,14 @@
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
%%
@@ -76,6 +78,7 @@ 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+]* {
@@ -112,17 +115,50 @@ 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. */
"/"[^\*\/].* { cflval.text = strdup(yytext);
return TOK_STRING; }
[^/\n \t\b\r+-].* { cflval.text = strdup(yytext);
return TOK_STRING; }
"/"[\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); }
<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;
+13 -5
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.10 2003/09/26 21:25:58 steve Exp $"
#ident "$Id: cfparse.y,v 1.12 2007/04/19 02:52:53 steve Exp $"
#endif
@@ -62,6 +62,7 @@ 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
%%
@@ -83,7 +84,7 @@ item
: TOK_STRING
{ char*tmp = substitutions($1);
translate_file_name(tmp);
process_file_name(tmp);
process_file_name(tmp, 0);
free($1);
free(tmp);
}
@@ -98,9 +99,7 @@ item
| TOK_Dv TOK_STRING
{ char*tmp = substitutions($2);
translate_file_name(tmp);
process_file_name(tmp);
fprintf(stderr, "%s:%u: Ignoring -v in front of %s\n",
@1.text, @1.first_line, $2);
process_file_name(tmp, 1);
free($2);
free(tmp);
}
@@ -145,6 +144,15 @@ 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. */
+11 -2
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.19 2003/11/18 06:31:46 steve Exp $"
#ident "$Id: globals.h,v 1.21 2007/04/19 02:52:53 steve Exp $"
#endif
# include <stddef.h>
@@ -49,11 +49,14 @@ 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);
extern void process_file_name(const char*name, int lib_flag);
/* Add the name to the list of library directories. */
extern void process_library_switch(const char*name);
@@ -77,6 +80,12 @@ 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.
*
+14 -6
View File
@@ -1,4 +1,4 @@
.TH iverilog 1 "$Date: 2006/09/28 04:35:18 $" Version "$Date: 2006/09/28 04:35:18 $"
.TH iverilog 1 "$Date: 2007/06/05 01:56:12 $" Version "$Date: 2007/06/05 01:56:12 $"
.SH NAME
iverilog - Icarus Verilog compiler
@@ -62,13 +62,13 @@ 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 acuracy of
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
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
@@ -89,6 +89,8 @@ 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
@@ -199,7 +201,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 then \fBall\fP) can also be
switch. All the warning types (other than \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.
@@ -264,7 +266,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 substitued in file names.
character. Variables are substituted in file names.
.TP 8
.B -y\ \fIlibdir\fP
@@ -319,13 +321,19 @@ 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
substitued in contexts that explicitly support them, including file
substituted in contexts that explicitly support them, including file
and directory strings.
Variable values come from the operating system environment, and not
+81 -7
View File
@@ -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.72 2006/10/02 18:15:47 steve Exp $"
#ident "$Id: main.c,v 1.76 2007/06/05 01:56:12 steve Exp $"
#endif
# include "config.h"
@@ -113,6 +113,8 @@ const char*gen_xtypes = "xtypes";
char warning_flags[16] = "";
unsigned integer_width = 32;
char*mod_list = 0;
char*command_filename = 0;
@@ -134,7 +136,6 @@ char*iconfig_common_path = iconfig_common_path_buf;
int synth_flag = 0;
int verbose_flag = 0;
int command_file = 0;
FILE *fp;
@@ -143,6 +144,48 @@ 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>
@@ -360,7 +403,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)
void process_file_name(const char*name, int lib_flag)
{
if (strlen(name) > 4 && strcasecmp(".sft", name+strlen(name)-4) == 0) {
fprintf(iconfig_file,"sys_func:%s\n", name);
@@ -368,6 +411,8 @@ void process_file_name(const char*name)
} else {
fprintf(source_file, "%s\n", name);
source_count += 1;
if (lib_flag)
fprintf(iconfig_file,"library_file:%s\n", name);
}
}
@@ -410,6 +455,20 @@ int process_generation(const char*name)
return 0;
}
/*
* If it exists add the SFT file for the given module.
*/
void add_sft_file(const char *module)
{
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;
@@ -520,8 +579,7 @@ int main(int argc, char **argv)
}
break;
case 'c':
command_filename = malloc(strlen(optarg)+1);
strcpy(command_filename, optarg);
add_cmd_file(optarg);
break;
case 'D':
process_define(optarg);
@@ -554,6 +612,7 @@ int main(int argc, char **argv)
case 'm':
fprintf(iconfig_file, "module:%s\n", optarg);
add_sft_file(optarg);
break;
case 'N':
@@ -639,7 +698,7 @@ int main(int argc, char **argv)
fprintf(iconfig_file, "out:%s\n", opath);
if (depfile) fprintf(iconfig_file, "depfile:%s\n", depfile);
if (command_filename) {
while ( (command_filename = get_cmd_file()) ) {
int rc;
if (( fp = fopen(command_filename, "r")) == NULL ) {
@@ -655,6 +714,7 @@ int main(int argc, char **argv)
command_filename);
return 1;
}
free(command_filename);
}
if (depfile) {
@@ -664,7 +724,7 @@ int main(int argc, char **argv)
/* Finally, process all the remaining words on the command
line as file names. */
for (idx = optind ; idx < argc ; idx += 1)
process_file_name(argv[idx]);
process_file_name(argv[idx], 0);
fclose(source_file);
@@ -724,6 +784,8 @@ 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. */
@@ -740,6 +802,18 @@ 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.75 2007/04/19 02:52:53 steve
* Add support for -v flag in command file.
*
* Revision 1.74 2007/04/18 03:23:38 steve
* Add support for multiple command files. (Cary R.)
*
* Revision 1.73 2007/03/07 04:24:59 steve
* Make integer width controllable.
*
* Revision 1.72 2006/10/02 18:15:47 steve
* Fix handling of dep path in new argument passing method.
*
+6 -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: dup_expr.cc,v 1.20 2005/07/11 16:56:50 steve Exp $"
#ident "$Id: dup_expr.cc,v 1.21 2006/11/04 06:10:13 steve Exp $"
#endif
# include "config.h"
@@ -67,7 +67,8 @@ NetEScope* NetEScope::dup_expr() const
NetESelect* NetESelect::dup_expr() const
{
return new NetESelect(expr_->dup_expr(), base_->dup_expr(),
return new NetESelect(expr_->dup_expr(),
base_? base_->dup_expr() : 0,
expr_width());
}
@@ -133,6 +134,9 @@ NetEUReduce* NetEUReduce::dup_expr() const
/*
* $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.20 2005/07/11 16:56:50 steve
* Remove NetVariable and ivl_variable_t structures.
*
+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: elab_anet.cc,v 1.12 2006/05/01 20:47:58 steve Exp $"
#ident "$Id: elab_anet.cc,v 1.13 2007/03/22 16:08:14 steve Exp $"
#endif
# include "config.h"
@@ -84,7 +84,7 @@ 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 then 1 by repeating the
Allow for a repeat count other than 1 by repeating the
connect loop as many times as necessary. */
NetNet*osig = new NetNet(scope, scope->local_symbol(),
@@ -169,6 +169,9 @@ 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.
*
+597 -288
View File
File diff suppressed because it is too large Load Diff
+186 -200
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000 Stephen Williams ([email protected])
* Copyright (c) 2000-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: elab_lval.cc,v 1.36 2006/06/02 04:48:50 steve Exp $"
#ident "$Id: elab_lval.cc,v 1.44 2007/06/02 03:42:12 steve Exp $"
#endif
# include "config.h"
@@ -25,8 +25,9 @@
# 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
@@ -149,51 +150,63 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
bool is_force) const
{
NetNet* reg = 0;
NetMemory* mem = 0;
const NetExpr*par = 0;
NetEvent* eve = 0;
symbol_search(des, scope, path_, reg, mem, par, eve);
if (mem) {
if (is_force) {
cerr << get_line() << ": error: Memories "
<< "(" << path_ << " in this case)"
<< " are not allowed"
<< " as l-values to force statements." << endl;
des->errors += 1;
return 0;
}
return elaborate_mem_lval_(des, scope, mem);
}
symbol_search(des, scope, path_, reg, par, eve);
if (reg == 0) {
cerr << get_line() << ": error: Could not find variable ``"
<< path_ << "'' in ``" << scope->name() <<
<< path_ << "'' in ``" << scope_path(scope) <<
"''" << endl;
des->errors += 1;
return 0;
}
assert(reg);
ivl_assert(*this, reg);
if (sel_ == SEL_PART)
return elaborate_lval_net_part_(des, scope, reg);
const name_component_t&name_tail = path_.back();
if (sel_ == SEL_IDX_UP)
return elaborate_lval_net_idx_up_(des, scope, reg);
index_component_t::ctype_t use_sel = index_component_t::SEL_NONE;
if (!name_tail.index.empty())
use_sel = name_tail.index.back().sel;
if (sel_ == SEL_IDX_DO)
return elaborate_lval_net_idx_do_(des, scope, reg);
// 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;
}
/* 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) {
cerr << get_line() << ": error: " << path_ <<
" is not a reg/integer/time in " << scope->name() <<
" is not a valid l-value in " << scope_path(scope) <<
"." << endl;
cerr << reg->get_line() << ": : " << path_ <<
" is declared here as " << reg->type() << "." << endl;
@@ -201,32 +214,32 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
return 0;
}
assert(msb_ == 0);
assert(lsb_ == 0);
long msb, lsb;
NetExpr*mux;
if (! idx_.empty()) {
if (use_sel == index_component_t::SEL_BIT) {
const index_component_t&index_tail = name_tail.index.back();
ivl_assert(*this, index_tail.msb != 0);
ivl_assert(*this, index_tail.lsb == 0);
/* If there is only a single select expression, it is a
bit select. Evaluate the constant value and treat it
as a part select with a bit width of 1. If the
expression it not constant, then return the
expression as a mux. */
assert(idx_.size() == 1);
verinum*v = idx_[0]->eval_const(des, scope);
if (v == 0) {
NetExpr*m = idx_[0]->elaborate_expr(des, scope, -1, false);
assert(m);
msb = 0;
lsb = 0;
mux = m;
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 {
msb = v->as_long();
lsb = v->as_long();
mux = 0;
msb = 0;
lsb = 0;
mux = index_expr;
}
} else {
@@ -300,53 +313,85 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
return lv;
}
NetAssign_* PEIdent::elaborate_lval_net_part_(Design*des,
NetAssign_* PEIdent::elaborate_lval_net_word_(Design*des,
NetScope*scope,
NetNet*reg) const
{
assert(msb_ && lsb_);
const name_component_t&name_tail = path_.back();
ivl_assert(*this, !name_tail.index.empty());
/* 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. */
NetExpr*lsb_ex = elab_and_eval(des, scope, lsb_, -1);
NetEConst*lsb_c = dynamic_cast<NetEConst*>(lsb_ex);
if (lsb_c == 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;
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;
}
}
NetExpr*msb_ex = elab_and_eval(des, scope, msb_, -1);
NetEConst*msb_c = dynamic_cast<NetEConst*>(msb_ex);
if (msb_c == 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;
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;
}
}
long msb = msb_c->value().as_long();
long lsb = lsb_c->value().as_long();
/* An array word may also have part selects applied to them. */
delete msb_ex;
delete lsb_ex;
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;
NetAssign_*lv = 0;
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. */
lv = new NetAssign_(reg);
} else {
@@ -362,7 +407,7 @@ NetAssign_* PEIdent::elaborate_lval_net_part_(Design*des,
<< reg->name() << "[" << msb<<":"<<lsb<<"]"
<< " is reversed." << endl;
des->errors += 1;
return 0;
return false;
}
/* If the part select extends beyond the extreme of the
@@ -375,50 +420,43 @@ NetAssign_* PEIdent::elaborate_lval_net_part_(Design*des,
<< reg->name() << "[" << msb<<":"<<lsb<<"]"
<< " is out of range." << endl;
des->errors += 1;
return 0;
return false;
}
lv = new NetAssign_(reg);
lv->set_part(new NetEConst(verinum(loff)), wid);
}
return lv;
return true;
}
NetAssign_* PEIdent::elaborate_lval_net_idx_up_(Design*des,
NetScope*scope,
NetNet*reg) const
bool PEIdent::elaborate_lval_net_idx_up_(Design*des,
NetScope*scope,
NetAssign_*lv) const
{
assert(lsb_);
assert(msb_);
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->name() <<
" is not a reg/integer/time in " << scope_path(scope) <<
"." << endl;
cerr << reg->get_line() << ": : " << path_ <<
" is declared here as " << reg->type() << "." << endl;
des->errors += 1;
return 0;
return false;
}
/* Calculate the width expression (in the lsb_ position)
first. If the expression is not constant, error but guess 1
so we can keep going and find more errors. */
NetExpr*wid_ex = elab_and_eval(des, scope, lsb_, -1);
NetEConst*wid_c = dynamic_cast<NetEConst*>(wid_ex);
unsigned long wid;
calculate_up_do_width_(des, scope, wid);
if (wid_c == 0) {
cerr << get_line() << ": error: Indexed part width must be "
<< "constant. Expression in question is..." << endl;
cerr << get_line() << ": : " << *wid_ex << endl;
des->errors += 1;
}
unsigned wid = wid_c? wid_c->value().as_ulong() : 1;
delete wid_ex;
NetExpr*base = elab_and_eval(des, scope, msb_, -1);
NetExpr*base = elab_and_eval(des, scope, index_tail.msb, -1);
/* Correct the mux for the range of the vector. */
if (reg->msb() < reg->lsb())
@@ -426,112 +464,30 @@ NetAssign_* PEIdent::elaborate_lval_net_idx_up_(Design*des,
else if (reg->lsb() != 0)
base = make_add_expr(base, - reg->lsb());
NetAssign_*lv = new NetAssign_(reg);
if (debug_elaborate)
cerr << get_line() << ": debug: Set part select width="
<< wid << ", base=" << *base << endl;
lv->set_part(base, wid);
return lv;
return true;
}
NetAssign_* PEIdent::elaborate_lval_net_idx_do_(Design*des,
NetScope*scope,
NetNet*reg) const
bool PEIdent::elaborate_lval_net_idx_do_(Design*des,
NetScope*scope,
NetAssign_*lv) const
{
assert(lsb_);
assert(msb_);
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 0;
}
NetAssign_* PEIdent::elaborate_mem_lval_(Design*des, NetScope*scope,
NetMemory*mem) const
{
if (idx_.empty()) {
cerr << get_line() << ": error: Assign to memory \""
<< mem->name() << "\" requires a word select index."
<< endl;
des->errors += 1;
return 0;
}
if (idx_.size() != mem->dimensions()) {
cerr << get_line() << ": error: " << idx_.size()
<< " indices do not properly address a "
<< mem->dimensions() << "-dimension memory/array."
<< endl;
des->errors += 1;
return 0;
}
// XXXX For now, require exactly 1 index.
assert(idx_.size() == 1);
/* Elaborate the address expression. */
NetExpr*ix = elab_and_eval(des, scope, idx_[0], -1);
if (ix == 0)
return 0;
NetAssign_*lv = new NetAssign_(mem);
lv->set_bmux(ix);
/* If there is no extra part select, then we are done. */
if (msb_ == 0 && lsb_ == 0) {
lv->set_part(0, mem->width());
return lv;
}
assert(sel_ != SEL_NONE);
assert(msb_ && lsb_);
if (sel_ == SEL_PART) {
NetExpr*le = elab_and_eval(des, scope, lsb_, -1);
NetExpr*me = elab_and_eval(des, scope, msb_, -1);
NetEConst*lec = dynamic_cast<NetEConst*>(le);
NetEConst*mec = dynamic_cast<NetEConst*>(me);
if (lec == 0 || mec == 0) {
cerr << get_line() << ": error: Part select "
<< "expressions must be constant." << endl;
des->errors += 1;
delete le;
delete me;
return lv;
}
verinum wedv = mec->value() - lec->value();
unsigned wid = wedv.as_long() + 1;
lv->set_part(lec, wid);
return lv;
}
assert(sel_ == SEL_IDX_UP || sel_ == SEL_IDX_DO);
NetExpr*wid_ex = elab_and_eval(des, scope, lsb_, -1);
NetEConst*wid_ec = dynamic_cast<NetEConst*> (wid_ex);
if (wid_ec == 0) {
cerr << lsb_->get_line() << ": error: "
<< "Second expression of indexed part select "
<< "most be constant." << endl;
des->errors += 1;
return lv;
}
unsigned wid = wid_ec->value().as_ulong();
NetExpr*base_ex = elab_and_eval(des, scope, msb_, -1);
if (base_ex == 0) {
return 0;
}
if (sel_ == SEL_IDX_DO && wid > 1) {
base_ex = make_add_expr(base_ex, 1-(long)wid);
}
lv->set_part(base_ex, wid);
return lv;
return false;
}
NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*, bool) const
@@ -544,6 +500,36 @@ 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
+389 -153
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2005 Stephen Williams ([email protected])
* Copyright (c) 1999-2007 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: elab_net.cc,v 1.189 2006/08/08 05:11:37 steve Exp $"
#ident "$Id: elab_net.cc,v 1.207 2007/06/12 04:05:45 steve Exp $"
#endif
# include "config.h"
@@ -28,6 +28,7 @@
# include "compiler.h"
# include <iostream>
# include "ivl_assert.h"
/*
* This is a state flag that determines whether an elaborate_net must
@@ -760,7 +761,7 @@ NetNet* PEBinary::elaborate_net_div_(Design*des, NetScope*scope,
// Make an output signal that is the width of the l-value.
// Due to above calculation of rwidth, we know that the result
// will be no more then the l-value, so it is safe to connect
// will be no more than the l-value, so it is safe to connect
// all the result pins to the osig.
NetNet*osig = new NetNet(scope, scope->local_symbol(),
@@ -947,14 +948,17 @@ NetNet* PEBinary::elaborate_net_mul_(Design*des, NetScope*scope,
}
NetConst*odev = new NetConst(scope, scope->local_symbol(), res);
des->add_node(odev);
odev->set_line(*this);
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, lwidth);
for (unsigned idx = 0 ; idx < lwidth ; idx += 1)
connect(odev->pin(idx), osig->pin(idx));
des->add_node(odev);
osig->data_type(IVL_VT_LOGIC);
osig->set_line(*this);
osig->local_flag(true);
osig->data_type(IVL_VT_LOGIC);
connect(odev->pin(0), osig->pin(0));
return osig;
}
@@ -1096,6 +1100,8 @@ NetNet* PEBinary::elaborate_net_shift_(Design*des, NetScope*scope,
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, 1);
tmp->data_type( data_type );
tmp->local_flag(true);
tmp->set_line(*this);
connect(sign_bit->pin(0), tmp->pin(0));
connect(sign_bit->pin(0), sign_pad->pin(1));
@@ -1141,6 +1147,13 @@ NetNet* PEBinary::elaborate_net_shift_(Design*des, NetScope*scope,
des->add_node(part);
if (debug_elaborate) {
cerr << get_line() << ": debug: Elaborate shift "
<< "(" << op_ << ") as concatenation of "
<< pad_width << " zeros with " << part_width
<< " bits of expression." << endl;
}
/* Attach a signal to the part select output (NetConcat
input) */
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
@@ -1217,7 +1230,7 @@ NetNet* PECallFunction::elaborate_net(Design*des, NetScope*scope,
unsigned errors = 0;
unsigned func_pins = 0;
if (path_.peek_name(0)[0] == '$')
if (path_.front().name[0] == '$')
return elaborate_net_sfunc_(des, scope,
width, rise, fall, decay,
drive0, drive1);
@@ -1227,7 +1240,7 @@ NetNet* PECallFunction::elaborate_net(Design*des, NetScope*scope,
NetFuncDef*def = des->find_function(scope, path_);
if (def == 0) {
cerr << get_line() << ": error: No function " << path_ <<
" in this context (" << scope->name() << ")." << endl;
" in this context (" << scope_path(scope) << ")." << endl;
des->errors += 1;
return 0;
}
@@ -1307,11 +1320,13 @@ NetNet* PECallFunction::elaborate_net_sfunc_(Design*des, NetScope*scope,
Link::strength_t drive0,
Link::strength_t drive1) const
{
perm_string name = peek_tail_name(path_);
/* Handle the special case that the function call is to
$signed. This takes a single expression argument, and
forces it to be a signed result. Otherwise, it is as if the
$signed did not exist. */
if (strcmp(path_.peek_name(0), "$signed") == 0) {
if (strcmp(name, "$signed") == 0) {
if ((parms_.count() != 1) || (parms_[0] == 0)) {
cerr << get_line() << ": error: The $signed() function "
<< "takes exactly one(1) argument." << endl;
@@ -1327,7 +1342,7 @@ NetNet* PECallFunction::elaborate_net_sfunc_(Design*des, NetScope*scope,
}
/* handle $unsigned like $signed */
if (strcmp(path_.peek_name(0), "$unsigned") == 0) {
if (strcmp(name, "$unsigned") == 0) {
if ((parms_.count() != 1) || (parms_[0] == 0)) {
cerr << get_line() << ": error: The $unsigned() function "
<< "takes exactly one(1) argument." << endl;
@@ -1342,11 +1357,11 @@ NetNet* PECallFunction::elaborate_net_sfunc_(Design*des, NetScope*scope,
return sub;
}
const struct sfunc_return_type*def = lookup_sys_func(path_.peek_name(0));
const struct sfunc_return_type*def = lookup_sys_func(name);
if (def == 0) {
cerr << get_line() << ": error: System function "
<< path_.peek_name(0) << " not defined." << endl;
<< peek_tail_name(path_) << " not defined." << endl;
des->errors += 1;
return 0;
}
@@ -1407,7 +1422,7 @@ NetNet* PEConcat::elaborate_net(Design*des, NetScope*scope,
NetEConst*erep = dynamic_cast<NetEConst*>(etmp);
if (erep == 0) {
cerr << get_line() << ": internal error: Unable to "
cerr << get_line() << ": error: Unable to "
<< "evaluate constant repeat expression." << endl;
des->errors += 1;
return 0;
@@ -1497,7 +1512,7 @@ NetNet* PEConcat::elaborate_net(Design*des, NetScope*scope,
concat operator from least significant to most significant,
which is opposite from how they are given in the list.
Allow for a repeat count other then 1 by repeating the
Allow for a repeat count other than 1 by repeating the
connect loop as many times as necessary. */
NetNet*osig = new NetNet(scope, scope->local_symbol(),
@@ -1532,15 +1547,19 @@ NetNet* PEIdent::elaborate_net_bitmux_(Design*des, NetScope*scope,
Link::strength_t drive0,
Link::strength_t drive1) const
{
assert(msb_ == 0);
assert(lsb_ == 0);
assert(idx_.size() == 1);
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.sel == index_component_t::SEL_BIT);
ivl_assert(*this, index_tail.msb != 0);
ivl_assert(*this, index_tail.lsb == 0);
/* Elaborate the selector. */
NetNet*sel;
if (sig->msb() < sig->lsb()) {
NetExpr*sel_expr = idx_[0]->elaborate_expr(des, scope, -1, false);
NetExpr*sel_expr = index_tail.msb->elaborate_expr(des, scope, -1, false);
sel_expr = make_sub_expr(sig->lsb(), sel_expr);
if (NetExpr*tmp = sel_expr->eval_tree()) {
delete sel_expr;
@@ -1550,7 +1569,7 @@ NetNet* PEIdent::elaborate_net_bitmux_(Design*des, NetScope*scope,
sel = sel_expr->synthesize(des);
} else if (sig->lsb() != 0) {
NetExpr*sel_expr = idx_[0]->elaborate_expr(des, scope, -1,false);
NetExpr*sel_expr = index_tail.msb->elaborate_expr(des, scope, -1,false);
sel_expr = make_add_expr(sel_expr, - sig->lsb());
if (NetExpr*tmp = sel_expr->eval_tree()) {
delete sel_expr;
@@ -1560,7 +1579,7 @@ NetNet* PEIdent::elaborate_net_bitmux_(Design*des, NetScope*scope,
sel = sel_expr->synthesize(des);
} else {
sel = idx_[0]->elaborate_net(des, scope, 0, 0, 0, 0);
sel = index_tail.msb->elaborate_net(des, scope, 0, 0, 0, 0);
}
if (debug_elaborate) {
@@ -1591,21 +1610,15 @@ NetNet* PEIdent::elaborate_net(Design*des, NetScope*scope,
Link::strength_t drive0,
Link::strength_t drive1) const
{
assert(scope);
ivl_assert(*this, scope);
const name_component_t&name_tail = path_.back();
NetNet* sig = 0;
NetMemory* mem = 0;
const NetExpr*par = 0;
NetEvent* eve = 0;
symbol_search(des, scope, path_, sig, mem, par, eve);
/* If the identifier is a memory instead of a signal,
then handle it elsewhere. Create a RAM. */
if (mem != 0) {
return elaborate_net_ram_(des, scope, mem, lwidth,
rise, fall, decay);
}
symbol_search(des, scope, path_, sig, par, eve);
/* If this is a parameter name, then create a constant node
that connects to a signal with the correct name. */
@@ -1615,7 +1628,7 @@ NetNet* PEIdent::elaborate_net(Design*des, NetScope*scope,
assert(pc);
verinum pvalue = pc->value();
/* If the desired lwidth is more then the width of the
/* If the desired lwidth is more than the width of the
constant value, extend the value to fit the desired
output. */
if (lwidth > pvalue.len()) {
@@ -1626,7 +1639,7 @@ NetNet* PEIdent::elaborate_net(Design*des, NetScope*scope,
pvalue = tmp;
}
sig = new NetNet(scope, lex_strings.make(path_.peek_name(0)),
sig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, pvalue.len());
sig->set_line(*this);
sig->data_type(IVL_VT_LOGIC);
@@ -1641,15 +1654,16 @@ NetNet* PEIdent::elaborate_net(Design*des, NetScope*scope,
/* Check for the error case that the name is not found, and it
is hierarchical. We can't just create a name in another
scope, it's just not allowed. */
if (sig == 0 && path_.component_count() != 1) {
if (sig == 0 && path_.size() != 1) {
cerr << get_line() << ": error: The hierarchical name "
<< path_ << " is undefined in "
<< scope->name() << "." << endl;
<< scope_path(scope) << "." << endl;
hname_t tmp_path = path_;
delete[] tmp_path.remove_tail_name();
pform_name_t tmp_path = path_;
tmp_path.pop_back();
NetScope*tmp_scope = des->find_scope(scope, tmp_path);
list<hname_t> stmp_path = eval_scope_path(des, scope, tmp_path);
NetScope*tmp_scope = des->find_scope(scope, stmp_path);
if (tmp_scope == 0) {
cerr << get_line() << ": : I can't even find "
<< "the scope " << tmp_path << "." << endl;
@@ -1662,33 +1676,49 @@ NetNet* PEIdent::elaborate_net(Design*des, NetScope*scope,
/* Fallback, this may be an implicitly declared net. */
if (sig == 0) {
NetNet::Type nettype = scope->default_nettype();
sig = new NetNet(scope, lex_strings.make(path_.peek_name(0)),
sig = new NetNet(scope, name_tail.name,
nettype, 1);
sig->data_type(IVL_VT_LOGIC);
if (error_implicit || (nettype == NetNet::NONE)) {
cerr << get_line() << ": error: "
<< scope->name() << "." << path_.peek_name(0)
<< scope_path(scope) << "." << name_tail.name
<< " not defined in this scope." << endl;
des->errors += 1;
} else if (warn_implicit) {
cerr << get_line() << ": warning: implicit "
"definition of wire " << scope->name()
<< "." << path_.peek_name(0) << "." << endl;
"definition of wire " << scope_path(scope)
<< "." << name_tail.name << "." << endl;
}
}
assert(sig);
ivl_assert(*this, sig);
/* Handle the case that this is an array elsewhere. */
if (sig->array_dimensions() > 0) {
if (name_tail.index.size() == 0) {
cerr << get_line() << ": error: Array " << sig->name()
<< " cannot be used here without an index." << endl;
des->errors += 1;
return 0;
}
return elaborate_net_array_(des, scope, sig, lwidth,
rise, fall, decay,
drive0, drive1);
}
index_component_t::ctype_t use_sel = index_component_t::SEL_NONE;
if (!name_tail.index.empty())
use_sel = name_tail.index.back().sel;
/* Catch the case of a non-constant bit select. That should be
handled elsewhere. */
if (! idx_.empty()) {
assert(msb_ == 0);
assert(lsb_ == 0);
assert(idx_.size() == 1);
if (use_sel == index_component_t::SEL_BIT) {
const index_component_t&index_tail = name_tail.index.back();
verinum*mval = idx_[0]->eval_const(des, scope);
verinum*mval = index_tail.msb->eval_const(des, scope);
if (mval == 0) {
return elaborate_net_bitmux_(des, scope, sig, rise,
fall, decay, drive0, drive1);
@@ -1728,68 +1758,174 @@ NetNet* PEIdent::elaborate_net(Design*des, NetScope*scope,
return sig;
}
/*
* When I run into an identifier in an expression that refers to a
* memory, create a RAM port object.
*/
NetNet* PEIdent::elaborate_net_ram_(Design*des, NetScope*scope,
NetMemory*mem, unsigned lwidth,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay) const
NetNet* PEIdent::process_select_(Design*des, NetScope*scope,
NetNet*sig) const
{
assert(scope);
if (idx_.empty()) {
cerr << get_line() << ": error: memory reference without"
" the required index expression." << endl;
des->errors += 1;
return 0;
// If there are more index items then there are array
// dimensions, then treat them as word part selects. For
// example, if this is a memory array, then array dimensions
// is 1 and
unsigned midx, lidx;
if (! eval_part_select_(des, scope, sig, midx, lidx))
return sig;
unsigned part_count = midx-lidx+1;
// Maybe this is a full-width constant part select? If
// so, do nothing.
if (part_count == sig->vector_width())
return sig;
if (debug_elaborate) {
cerr << get_line() << ": debug: Elaborate part select"
<< " of word from " << sig->name() << "[base="<<lidx
<< " wid=" << part_count << "]" << endl;
}
assert(msb_ == 0);
assert(lsb_ == 0);
assert(idx_.size() == 1);
NetPartSelect*ps = new NetPartSelect(sig, lidx, part_count,
NetPartSelect::VP);
ps->set_line(*sig);
des->add_node(ps);
/* Even if this expression must be fully self determined, the
index expression does not, so make sure this flag is off
while elaborating the address expression. */
const bool must_be_self_determined_save = must_be_self_determined_flag;
must_be_self_determined_flag = false;
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, part_count-1, 0);
tmp->data_type( sig->data_type() );
tmp->local_flag(true);
connect(tmp->pin(0), ps->pin(0));
NetExpr*adr_expr = elab_and_eval(des, scope, idx_[0], -1);
return tmp;
}
/* If an offset is needed, subtract it from the address to get
an expression for the canonical address. */
if (mem->index_to_address(0) != 0) {
adr_expr = make_add_expr(adr_expr, mem->index_to_address(0));
if (NetExpr*tmp = adr_expr->eval_tree()) {
delete adr_expr;
adr_expr = tmp;
NetNet* PEIdent::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
{
const name_component_t&name_tail = path_.back();
ivl_assert(*this, name_tail.index.size() >= 1);
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);
if (debug_elaborate)
cerr << get_line() << ": debug: elaborate array "
<< name_tail.name << " with index " << index_head << endl;
NetExpr*index_ex = elab_and_eval(des, scope, index_head.msb, -1);
if (index_ex == 0)
return 0;
if (NetEConst*index_co = dynamic_cast<NetEConst*> (index_ex)) {
long index = index_co->value().as_long();
if (!sig->array_index_is_valid(index)) {
// Oops! The index is a constant known to be
// outside the array. Change the expression to a
// constant X vector.
verinum xxx (verinum::Vx, sig->vector_width());
NetConst*con_n = new NetConst(scope, scope->local_symbol(), xxx);
des->add_node(con_n);
con_n->set_line(*index_co);
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, sig->vector_width());
tmp->set_line(*this);
tmp->local_flag(true);
tmp->data_type(sig->data_type());
connect(tmp->pin(0), con_n->pin(0));
return tmp;
}
assert(sig->array_index_is_valid(index));
index = sig->array_index_to_address(index);
if (debug_elaborate) {
cerr << get_line() << ": debug: Elaborate word "
<< index << " of " << sig->name() << endl;
}
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, sig->vector_width());
tmp->set_line(*this);
tmp->local_flag(true);
tmp->data_type(sig->data_type());
connect(tmp->pin(0), sig->pin(index));
// If there are more indices then needed to get to the
// word, then there is a part/bit select for the word.
if (name_tail.index.size() > sig->array_dimensions())
tmp = process_select_(des, scope, tmp);
return tmp;
}
NetNet*adr = adr_expr->synthesize(des);
delete adr_expr;
must_be_self_determined_flag = must_be_self_determined_save;
unsigned selwid = index_ex->expr_width();
if (adr == 0)
return 0;
NetArrayDq*mux = new NetArrayDq(scope, scope->local_symbol(),
sig, selwid);
mux->set_line(*this);
des->add_node(mux);
NetRamDq*ram = new NetRamDq(scope, scope->local_symbol(),
mem, adr->vector_width());
des->add_node(ram);
// Adjust the expression to calculate the canonical offset?
if (long array_base = sig->array_first()) {
index_ex = make_add_expr(index_ex, 0-array_base);
}
connect(ram->pin_Address(), adr->pin(0));
NetNet*index_net = index_ex->synthesize(des);
connect(mux->pin_Address(), index_net->pin(0));
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, ram->width());
osig->data_type(IVL_VT_LOGIC);
osig->local_flag(true);
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, sig->vector_width());
tmp->set_line(*this);
tmp->local_flag(true);
tmp->data_type(sig->data_type());
connect(tmp->pin(0), mux->pin_Result());
#if 0
connect(ram->pin_Q(), osig->pin(0));
// If there are more index items then there are array
// dimensions, then treat them as word part selects. For
// example, if this is a memory array, then array dimensions
// is 1 and
unsigned midx, lidx;
if (eval_part_select_(des, scope, sig, midx, lidx)) do {
return osig;
unsigned part_count = midx-lidx+1;
// Maybe this is a full-width constant part select? If
// so, do nothing.
if (part_count == sig->vector_width())
break;
if (debug_elaborate) {
cerr << get_line() << ": debug: Elaborate part select"
<< " of word from " << sig->name() << "[base="<<lidx
<< " wid=" << part_count << "]" << endl;
}
NetPartSelect*ps = new NetPartSelect(sig, lidx, part_count,
NetPartSelect::VP);
ps->set_line(*sig);
des->add_node(ps);
NetNet*tmp2 = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, part_count-1, 0);
tmp2->data_type( tmp->data_type() );
tmp2->local_flag(true);
connect(tmp2->pin(0), ps->pin(0));
tmp = tmp2;
} while (0);
#else
if (name_tail.index.size() > sig->array_dimensions())
tmp = process_select_(des, scope, sig);
#endif
return tmp;
}
/*
@@ -1864,6 +2000,8 @@ NetNet* PEConcat::elaborate_lnet_common_(Design*des, NetScope*scope,
/* Assume that the data types of the nets are all the same, so
we can take the data type of any, the first will do. */
osig->data_type(nets[0]->data_type());
osig->local_flag(true);
osig->set_line(*this);
if (debug_elaborate) {
cerr << get_line() << ": debug: Generating part selects "
@@ -1942,15 +2080,15 @@ NetNet* PEIdent::make_implicit_net_(Design*des, NetScope*scope) const
NetNet*sig = 0;
if (!error_implicit && nettype!=NetNet::NONE) {
sig = new NetNet(scope, lex_strings.make(path_.peek_name(0)),
sig = new NetNet(scope, peek_tail_name(path_),
NetNet::IMPLICIT, 1);
/* Implicit nets are always scalar logic. */
sig->data_type(IVL_VT_LOGIC);
if (warn_implicit) {
cerr << get_line() << ": warning: implicit "
"definition of wire logic " << scope->name()
<< "." << path_.peek_name(0) << "." << endl;
"definition of wire logic " << scope_path(scope)
<< "." << peek_tail_name(path_) << "." << endl;
}
} else {
@@ -1973,20 +2111,30 @@ NetNet* PEIdent::make_implicit_net_(Design*des, NetScope*scope) const
bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
unsigned&midx, unsigned&lidx) const
{
switch (sel_) {
const name_component_t&name_tail = path_.back();
// Only treat as part/bit selects any index that is beyond the
// word selects for an array. This is not an array, then
// dimensions==0 and any index is treated as a select.
if (name_tail.index.size() <= sig->array_dimensions()) {
midx = sig->vector_width()-1;
lidx = 0;
return true;
}
ivl_assert(*this, !name_tail.index.empty());
const index_component_t&index_tail = name_tail.index.back();
switch (index_tail.sel) {
default:
cerr << get_line() << ": internal error: "
<< "Unexpected sel_ value = " << sel_ << endl;
assert(0);
<< "Unexpected sel_ value = " << index_tail.sel << endl;
ivl_assert(*this, 0);
break;
case PEIdent::SEL_IDX_DO:
case PEIdent::SEL_IDX_UP: {
assert(msb_);
assert(lsb_);
assert(idx_.empty());
NetExpr*tmp_ex = elab_and_eval(des, scope, msb_, -1);
case index_component_t::SEL_IDX_DO:
case index_component_t::SEL_IDX_UP: {
NetExpr*tmp_ex = elab_and_eval(des, scope, index_tail.msb, -1);
NetEConst*tmp = dynamic_cast<NetEConst*>(tmp_ex);
assert(tmp);
@@ -1994,14 +2142,14 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
midx = sig->sb_to_idx(midx_val);
delete tmp_ex;
tmp_ex = elab_and_eval(des, scope, lsb_, -1);
tmp_ex = elab_and_eval(des, scope, index_tail.lsb, -1);
tmp = dynamic_cast<NetEConst*>(tmp_ex);
assert(tmp);
long wid = tmp->value().as_long();
delete tmp_ex;
if (sel_ == PEIdent::SEL_IDX_UP)
if (index_tail.sel == index_component_t::SEL_IDX_UP)
lidx = sig->sb_to_idx(midx_val+wid-1);
else
lidx = sig->sb_to_idx(midx_val-wid+1);
@@ -2015,12 +2163,9 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
break;
}
case PEIdent::SEL_PART: {
assert(msb_);
assert(lsb_);
assert(idx_.empty());
case index_component_t::SEL_PART: {
NetExpr*tmp_ex = elab_and_eval(des, scope, msb_, -1);
NetExpr*tmp_ex = elab_and_eval(des, scope, index_tail.msb, -1);
NetEConst*tmp = dynamic_cast<NetEConst*>(tmp_ex);
assert(tmp);
@@ -2028,8 +2173,13 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
midx = sig->sb_to_idx(midx_val);
delete tmp_ex;
tmp_ex = elab_and_eval(des, scope, lsb_, -1);
tmp_ex = elab_and_eval(des, scope, index_tail.lsb, -1);
tmp = dynamic_cast<NetEConst*>(tmp_ex);
if (tmp == 0) {
cerr << get_line() << ": internal error: "
<< "lsb expression is not constant?: "
<< *tmp_ex << ", " << *index_tail.lsb << endl;
}
assert(tmp);
long lidx_val = tmp->value().as_long();
@@ -2062,18 +2212,17 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
break;
}
case PEIdent::SEL_NONE:
if (!idx_.empty()) {
assert(msb_ == 0);
assert(lsb_ == 0);
assert(idx_.size() == 1);
verinum*mval = idx_[0]->eval_const(des, scope);
case index_component_t::SEL_BIT:
if (name_tail.index.size() > sig->array_dimensions()) {
verinum*mval = index_tail.msb->eval_const(des, scope);
if (mval == 0) {
cerr << get_line() << ": error: Index of " << path_ <<
" needs to be constant in this context." <<
endl;
cerr << get_line() << ": : Index expression is: "
<< *(idx_[0]) << endl;
<< *index_tail.msb << endl;
cerr << get_line() << ": : Context scope is: "
<< scope_path(scope) << endl;
des->errors += 1;
return false;
}
@@ -2090,17 +2239,9 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
lidx = midx;
} else {
if (msb_ || lsb_) {
cerr << get_line() << ": internal error: "
<< "Unexpected msb_/lsb_ values?" << endl;
if (msb_)
cerr << get_line() << " : "
<< *msb_ << endl;
if (lsb_)
cerr << get_line() << " : "
<< *lsb_ << endl;
}
assert(msb_ == 0 && lsb_ == 0);
cerr << get_line() << ": internal error: "
<< "Bit select " << path_ << endl;
ivl_assert(*this, 0);
midx = sig->vector_width() - 1;
lidx = 0;
}
@@ -2122,19 +2263,10 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
assert(scope);
NetNet* sig = 0;
NetMemory* mem = 0;
const NetExpr*par = 0;
NetEvent* eve = 0;
symbol_search(des, scope, path_, sig, mem, par, eve);
if (mem != 0) {
cerr << get_line() << ": error: memories (" << path_
<< ") cannot be l-values in continuous "
<< "assignments." << endl;
des->errors += 1;
return 0;
}
symbol_search(des, scope, path_, sig, par, eve);
if (eve != 0) {
cerr << get_line() << ": error: named events (" << path_
@@ -2179,12 +2311,50 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
sig->port_type(NetNet::PINOUT);
}
unsigned midx, lidx;
if (! eval_part_select_(des, scope, sig, midx, lidx))
return 0;
// Default part select is the entire word.
unsigned midx = sig->vector_width()-1, lidx = 0;
// The default word select is the first.
unsigned widx = 0;
const name_component_t&name_tail = path_.back();
if (sig->array_dimensions() > 0) {
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);
NetExpr*tmp_ex = elab_and_eval(des, scope, index_head.msb, -1);
NetEConst*tmp = dynamic_cast<NetEConst*>(tmp_ex);
assert(tmp);
long widx_val = tmp->value().as_long();
widx = sig->array_index_to_address(widx_val);
delete tmp_ex;
if (debug_elaborate)
cerr << get_line() << ": debug: Use [" << widx << "]"
<< " to index l-value array." << endl;
} else if (!name_tail.index.empty()) {
if (! eval_part_select_(des, scope, sig, midx, lidx))
return 0;
}
unsigned subnet_wid = midx-lidx+1;
if (sig->pin_count() > 1) {
assert(widx < sig->pin_count());
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
sig->type(), sig->vector_width());
tmp->set_line(*this);
tmp->local_flag(true);
connect(sig->pin(widx), tmp->pin(0));
sig = tmp;
}
/* If the desired l-value vector is narrower then the
signal itself, then use a NetPartSelect node to
arrange for connection to the desired bits. All this
@@ -2213,6 +2383,8 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
sig->scope()->local_symbol(),
NetNet::WIRE, subnet_wid);
subsig->data_type( sig->data_type() );
subsig->local_flag(true);
subsig->set_line(*this);
NetPartSelect*sub = new NetPartSelect(sig, lidx, subnet_wid,
part_dir);
@@ -2253,7 +2425,7 @@ NetNet* PEIdent::elaborate_port(Design*des, NetScope*scope) const
NetNet*sig = des->find_signal(scope, path_);
if (sig == 0) {
cerr << get_line() << ": error: no wire/reg " << path_
<< " in module " << scope->name() << "." << endl;
<< " in module " << scope_path(scope) << "." << endl;
des->errors += 1;
return 0;
}
@@ -2272,7 +2444,7 @@ NetNet* PEIdent::elaborate_port(Design*des, NetScope*scope) const
case NetNet::NOT_A_PORT:
cerr << get_line() << ": error: signal " << path_ << " in"
<< " module " << scope->name() << " is not a port." << endl;
<< " module " << scope_path(scope) << " is not a port." << endl;
cerr << get_line() << ": : Are you missing an input/"
<< "output/inout declaration?" << endl;
des->errors += 1;
@@ -2284,7 +2456,7 @@ NetNet* PEIdent::elaborate_port(Design*des, NetScope*scope) const
case NetNet::PIMPLICIT:
cerr << get_line() << ": internal error: signal " << path_
<< " in module " << scope->name() << " is left as "
<< " in module " << scope_path(scope) << " is left as "
<< "port type PIMPLICIT." << endl;
des->errors += 1;
return 0;
@@ -2588,6 +2760,11 @@ NetNet* PETernary::elaborate_net(Design*des, NetScope*scope,
if (tru_sig->vector_width() < dwidth)
tru_sig = pad_to_width(des, tru_sig, dwidth);
if (dwidth < fal_sig->vector_width())
fal_sig = crop_to_width(des, fal_sig, dwidth);
if (dwidth < tru_sig->vector_width())
tru_sig = crop_to_width(des, tru_sig, dwidth);
/* Make the device and connect its outputs to the osig and
inputs to the tru and false case nets. Also connect the
@@ -2609,7 +2786,8 @@ NetNet* PETernary::elaborate_net(Design*des, NetScope*scope,
if (rise || fall || decay) {
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, dwidth);
sig->data_type(expr_type);
tmp->data_type(expr_type);
tmp->local_flag(true);
NetBUFZ*tmpz = new NetBUFZ(scope, scope->local_symbol(), dwidth);
tmpz->rise_time(rise);
@@ -2636,8 +2814,8 @@ NetNet* PETernary::elaborate_net(Design*des, NetScope*scope,
/* If the MUX device results is too narrow to fill out the
desired result, then pad it. It is OK to have a too-narrow
result here because the dwidth choise is >= the width of
both alternatives. Thus, padding here is equivilent to
result here because the dwidth choice is >= the width of
both alternatives. Thus, padding here is equivalent to
padding inside, and is cheaper. */
if (dwidth < width)
sig = pad_to_width(des, sig, width);
@@ -2840,6 +3018,64 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
/*
* $Log: elab_net.cc,v $
* Revision 1.207 2007/06/12 04:05:45 steve
* Put instantiated modules in the proper generated scope.
*
* Revision 1.206 2007/06/04 02:19:07 steve
* Handle bit/part select of array words in nets.
*
* Revision 1.205 2007/06/02 03:42:12 steve
* Properly evaluate scope path expressions.
*
* Revision 1.204 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.203 2007/04/18 01:40:49 steve
* Fix elaboration of multiply of two constants.
*
* Revision 1.202 2007/04/17 04:18:10 steve
* Support part select of array words in net contexts.
*
* Revision 1.201 2007/03/22 16:08:14 steve
* Spelling fixes from Larry
*
* Revision 1.200 2007/02/27 06:10:16 steve
* Better error message around repeat concatenation syntax.
*
* Revision 1.199 2007/02/26 19:49:48 steve
* Spelling fixes (larry doolittle)
*
* Revision 1.198 2007/02/05 01:42:31 steve
* Set some missing local flags.
*
* Revision 1.197 2007/02/01 19:06:06 steve
* Ternary output node is local.
*
* Revision 1.196 2007/02/01 03:14:33 steve
* Detect and report arrays without index in net contexts.
*
* Revision 1.195 2007/01/31 04:21:10 steve
* Add method to bind assertions to verilog source lines.
*
* Revision 1.194 2007/01/20 02:10:45 steve
* Get argument widths right for shift results.
*
* Revision 1.193 2007/01/19 04:26:24 steve
* Fix missing data_type mark for array words.
*
* Revision 1.192 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.191 2006/12/08 03:43:26 steve
* Prevent name clash when processing parameter in net.
*
* Revision 1.190 2006/11/26 06:29:16 steve
* Fix nexus widths for direct link assign and ternary nets.
*
* Revision 1.189 2006/08/08 05:11:37 steve
* Handle 64bit delay constants.
*
+42 -20
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.24 2006/06/02 04:48:50 steve Exp $"
#ident "$Id: elab_pexpr.cc,v 1.28 2007/06/02 03:42:12 steve Exp $"
#endif
# include "config.h"
@@ -25,6 +25,7 @@
# include "PExpr.h"
# include "compiler.h"
# include "util.h"
# include "netmisc.h"
# include <iostream>
@@ -53,7 +54,7 @@ NetExpr*PEBinary::elaborate_pexpr (Design*des, NetScope*scope) const
return 0;
}
NetEBinary*tmp = elaborate_expr_base_(des, lp, rp);
NetEBinary*tmp = elaborate_expr_base_(des, lp, rp, -1);
return tmp;
}
@@ -130,47 +131,53 @@ NetExpr*PEFNumber::elaborate_pexpr(Design*des, NetScope*scope) const
*/
NetExpr*PEIdent::elaborate_pexpr(Design*des, NetScope*scope) const
{
hname_t path = path_;
char*name = path.remove_tail_name();
pform_name_t path = path_;
name_component_t name_tail = path_.back();
path.pop_back();
NetScope*pscope = scope;
if (path.peek_name(0))
pscope = des->find_scope(scope, path);
perm_string perm_name = lex_strings.make(name);
delete name;
if (path_.size() > 0) {
list<hname_t> tmp = eval_scope_path(des, scope, path);
pscope = des->find_scope(scope, tmp);
}
const NetExpr*ex_msb;
const NetExpr*ex_lsb;
const NetExpr*ex = pscope->get_parameter(perm_name, ex_msb, ex_lsb);
const NetExpr*ex = pscope->get_parameter(name_tail.name, ex_msb, ex_lsb);
if (ex == 0) {
cerr << get_line() << ": error: identifier ``" << path_ <<
"'' is not a parameter in " << scope->name() << "." << endl;
cerr << get_line() << ": error: identifier ``" << name_tail.name <<
"'' is not a parameter in "<< scope_path(scope)<< "." << endl;
des->errors += 1;
return 0;
}
NetExpr*res = new NetEParam(des, pscope, perm_name);
NetExpr*res = new NetEParam(des, pscope, name_tail.name);
res->set_line(*this);
assert(res);
if (msb_ && lsb_) {
assert(idx_.empty());
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:
cerr << get_line() << ": sorry: Cannot part select "
"bits of parameters." << endl;
des->errors += 1;
break;
} else if (!idx_.empty()) {
assert(msb_==0);
assert(lsb_==0);
assert(idx_.size() == 1);
case index_component_t::SEL_BIT:
/* We have here a bit select. Insert a NetESelect node
to handle it. */
NetExpr*tmp = idx_[0]->elaborate_pexpr(des, scope);
NetExpr*tmp = name_tail.index.back().msb->elaborate_pexpr(des, scope);
if (tmp != 0) {
res = new NetESelect(res, tmp, 1);
}
break;
}
return res;
@@ -236,6 +243,21 @@ 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
+47 -23
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_scope.cc,v 1.41 2006/06/02 04:48:50 steve Exp $"
#ident "$Id: elab_scope.cc,v 1.46 2007/06/02 03:42:12 steve Exp $"
#endif
# include "config.h"
@@ -51,7 +51,7 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
{
if (debug_scopes) {
cerr << get_line() << ": debug: Elaborate scope "
<< scope->name() << "." << endl;
<< scope_path(scope) << "." << endl;
}
// Generate all the parameters that this instance of this
@@ -66,7 +66,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<hname_t,PExpr*>::const_iterator hparm_it_t;
typedef map<pform_name_t,PExpr*>::const_iterator pform_parm_it_t;
// This loop scans the parameters in the module, and creates
@@ -156,7 +156,7 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
if (! flag) {
cerr << val->get_line() << ": warning: parameter "
<< (*cur).first << " not found in "
<< scope->name() << "." << endl;
<< scope_path(scope) << "." << endl;
}
}
@@ -200,7 +200,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 (hparm_it_t cur = defparms.begin()
for (pform_parm_it_t cur = defparms.begin()
; cur != defparms.end() ; cur ++ ) {
PExpr*ex = (*cur).second;
@@ -243,7 +243,8 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
for (tasks_it_t cur = tasks_.begin()
; cur != tasks_.end() ; cur ++ ) {
NetScope*task_scope = new NetScope(scope, (*cur).first,
hname_t use_name( (*cur).first );
NetScope*task_scope = new NetScope(scope, use_name,
NetScope::TASK);
(*cur).second->elaborate_scope(des, task_scope);
}
@@ -258,7 +259,8 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
for (funcs_it_t cur = funcs_.begin()
; cur != funcs_.end() ; cur ++ ) {
NetScope*func_scope = new NetScope(scope, (*cur).first,
hname_t use_name( (*cur).first );
NetScope*func_scope = new NetScope(scope, use_name,
NetScope::FUNC);
(*cur).second->elaborate_scope(des, func_scope);
}
@@ -288,7 +290,7 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
}
// Scan through all the named events in this scope. We do not
// need anything more then the current scope to do this
// need anything more than the current scope to do this
// elaboration, so do it now. This allows for normal
// elaboration to reference these events.
@@ -351,11 +353,7 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
// that each instance has a unique name in the
// container. The format of using [] is part of the
// Verilog standard.
char name_buf[128];
snprintf(name_buf, sizeof name_buf,
"%s[%d]", scope_name.str(), genvar);
perm_string use_name = lex_strings.make(name_buf);
hname_t use_name (scope_name, genvar);
if (debug_elaborate)
cerr << get_line() << ": debug: "
<< "Create generated scope " << use_name << endl;
@@ -374,6 +372,19 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
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);
@@ -418,7 +429,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(get_name())) {
if (sc->child(hname_t(get_name()))) {
cerr << get_line() << ": error: Instance/Scope name " <<
get_name() << " already used in this context." <<
endl;
@@ -441,8 +452,8 @@ 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 "
<< sc->name() << "." << get_name() << " within "
<< scn->name() << "." << endl;
<< scope_path(sc) << "." << get_name() << " within "
<< scope_path(scn) << "." << endl;
des->errors += 1;
return;
@@ -485,24 +496,21 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
// instantiation line.
for (int idx = 0 ; idx < instance_count ; idx += 1) {
perm_string use_name = get_name();
hname_t 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;
snprintf(name_buf, sizeof name_buf,
"%s[%d]", get_name().str(), instance_idx);
use_name = lex_strings.make(name_buf);
use_name = hname_t(get_name(), instance_idx);
}
if (debug_scopes) {
cerr << get_line() << ": debug: Module instance " << use_name
<< " becomes child of " << sc->name()
<< " becomes child of " << scope_path(sc)
<< "." << endl;
}
@@ -639,7 +647,7 @@ void PBlock::elaborate_scope(Design*des, NetScope*scope) const
NetScope*my_scope = scope;
if (name_ != 0) {
my_scope = new NetScope(scope, name_, bl_type_==BL_PAR
my_scope = new NetScope(scope, hname_t(name_), bl_type_==BL_PAR
? NetScope::FORK_JOIN
: NetScope::BEGIN_END);
}
@@ -748,6 +756,22 @@ 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
+205 -126
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.42 2006/06/02 04:48:50 steve Exp $"
#ident "$Id: elab_sig.cc,v 1.52 2007/06/02 03:42:12 steve Exp $"
#endif
# include "config.h"
@@ -34,6 +34,7 @@
# 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
@@ -41,8 +42,10 @@
* within the port_t that have a matching name.
*/
static bool signal_is_in_port(const svector<Module::port_t*>&ports,
const hname_t&name)
NetNet*sig)
{
perm_string name = sig->name();
for (unsigned idx = 0 ; idx < ports.count() ; idx += 1) {
Module::port_t*pp = ports[idx];
@@ -53,9 +56,15 @@ 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 (pp->expr[cc]->path() == name)
if (pname == name)
return true;
}
}
@@ -63,14 +72,28 @@ 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) {
@@ -78,12 +101,12 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
if (pp == 0)
continue;
map<hname_t,PWire*>::const_iterator wt;
map<pform_name_t,PWire*>::const_iterator wt;
for (unsigned cc = 0 ; cc < pp->expr.count() ; cc += 1) {
hname_t port_path (pp->expr[cc]->path());
wt = wl.find(port_path);
pform_name_t port_path (pp->expr[cc]->path());
wt = wires_.find(port_path);
if (wt == wl.end()) {
if (wt == wires_.end()) {
cerr << get_line() << ": error: "
<< "Port " << pp->expr[cc]->path() << " ("
<< (idx+1) << ") of module " << name_
@@ -103,14 +126,11 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
}
}
for (map<hname_t,PWire*>::const_iterator wt = wl.begin()
; wt != wl.end()
; wt ++ ) {
for (map<pform_name_t,PWire*>::const_iterator wt = wires_.begin()
; wt != wires_.end() ; wt ++ ) {
PWire*cur = (*wt).second;
cur->elaborate_sig(des, scope);
NetNet*sig = scope->find_signal_in_child(cur->path());
NetNet*sig = cur->elaborate_sig(des, scope);
// If this wire is a signal of the module (as opposed to
// a port of a function) and is a port, then check that
@@ -122,12 +142,10 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
if (sig && (sig->scope() == scope)
&& (cur->get_port_type() != NetNet::NOT_A_PORT)) {
hname_t name = (*wt).first;
if (! signal_is_in_port(ports, name)) {
if (! signal_is_in_port(ports, sig)) {
cerr << cur->get_line() << ": error: Signal "
<< name << " has a declared direction "
<< sig->name() << " has a declared direction "
<< "but is not a port." << endl;
des->errors += 1;
}
@@ -190,11 +208,13 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
for (mfunc_it_t cur = funcs_.begin()
; cur != funcs_.end() ; cur ++) {
NetScope*fscope = scope->child((*cur).first);
hname_t use_name ( (*cur).first );
NetScope*fscope = scope->child(use_name);
if (scope == 0) {
cerr << (*cur).second->get_line() << ": internal error: "
<< "Child scope for function " << (*cur).first
<< " missing in " << scope->name() << "." << endl;
<< " missing in " << scope_path(scope) << "." << endl;
des->errors += 1;
continue;
}
@@ -211,7 +231,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((*cur).first);
NetScope*tscope = scope->child( hname_t((*cur).first) );
assert(tscope);
(*cur).second->elaborate_sig(des, tscope);
}
@@ -234,9 +254,9 @@ bool PGModule::elaborate_sig_mod_(Design*des, NetScope*scope,
if (my_scope->parent() != scope) {
cerr << get_line() << ": internal error: "
<< "Instance " << my_scope->name()
<< " is in parent " << my_scope->parent()->name()
<< " instead of " << scope->name()
<< "Instance " << scope_path(my_scope)
<< " is in parent " << scope_path(my_scope->parent())
<< " instead of " << scope_path(scope)
<< endl;
}
assert(my_scope->parent() == scope);
@@ -259,7 +279,7 @@ bool PGenerate::elaborate_sig(Design*des) const
if (debug_elaborate)
cerr << get_line() << ": debug: Elaborate nets in "
<< "scope " << (*cur)->name() << endl;
<< "scope " << scope_path(*cur) << endl;
flag = elaborate_sig_(des, *cur) & flag;
}
@@ -270,7 +290,7 @@ bool PGenerate::elaborate_sig_(Design*des, NetScope*scope) const
{
// Scan the declared PWires to elaborate the obvious signals
// in the current scope.
typedef map<hname_t,PWire*>::const_iterator wires_it_t;
typedef map<pform_name_t,PWire*>::const_iterator wires_it_t;
for (wires_it_t wt = wires.begin()
; wt != wires.end() ; wt ++ ) {
@@ -278,11 +298,17 @@ bool PGenerate::elaborate_sig_(Design*des, NetScope*scope) const
if (debug_elaborate)
cerr << get_line() << ": debug: Elaborate PWire "
<< cur->path() << " in scope " << scope->name() << endl;
<< 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;
}
@@ -316,6 +342,7 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
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);
@@ -349,12 +376,13 @@ 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);
@@ -396,22 +424,24 @@ 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>. */
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));
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);
if (ppath != scope->basename()) {
cerr << get_line() << ": internal error: function "
<< "port " << (*ports_)[idx]->path()
<< " has wrong name for function "
<< scope->name() << "." << endl;
<< scope_path(scope) << "." << endl;
des->errors += 1;
}
NetNet*tmp = scope->find_signal(pname);
if (tmp == 0) {
cerr << get_line() << ": internal error: function "
<< scope->name() << " is missing port "
<< scope_path(scope) << " is missing port "
<< pname << "." << endl;
scope->dump(cerr);
cerr << get_line() << ": Continuing..." << endl;
@@ -449,36 +479,34 @@ 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>. */
hname_t path = (*ports_)[idx]->path();
assert(path.peek_name(0) && path.peek_name(1));
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);
/* check that the current scope really does have the
name of the first component of the task port name. Do
this by looking up the task scope in the parent of
the current scope. */
if (scope->parent()->child(path.peek_name(0)) != scope) {
cerr << "internal error: task scope " << path
<< " not the same as scope " << scope->name()
<< "?!" << endl;
return;
}
ivl_assert(*this, scope->basename() == scope_name);
/* 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(path.peek_name(1));
NetNet*tmp = scope->find_signal(port_name);
if (tmp == 0) {
cerr << get_line() << ": internal error: "
<< "Could not find port " << path.peek_name(1)
<< " in scope " << scope->name() << endl;
<< "Could not find port " << port_name
<< " in scope " << scope_path(scope) << endl;
scope->dump(cerr);
}
ports[idx] = tmp;
}
NetTaskDef*def = new NetTaskDef(scope->name(), ports);
NetTaskDef*def = new NetTaskDef(scope, ports);
scope->set_task_def(def);
}
@@ -494,16 +522,19 @@ bool PGate::elaborate_sig(Design*des, NetScope*scope) const
* elaboration this creates an object in the design that represent the
* defined item.
*/
void PWire::elaborate_sig(Design*des, NetScope*scope) const
NetNet* 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. */
{ 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));
{ 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) );
if (scope == 0) {
cerr << get_line() << ": internal error: "
@@ -556,7 +587,7 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
"Unable to evaluate constant expression ``" <<
*msb_[idx] << "''." << endl;
des->errors += 1;
return;
return 0;
}
mnum[idx] = tmp->value().as_long();
@@ -569,7 +600,7 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
"Unable to evaluate constant expression ``" <<
*lsb_[idx] << "''." << endl;
des->errors += 1;
return;
return 0;
}
lnum[idx] = tmp->value().as_long();
@@ -585,7 +616,7 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
<< "'' declared both as a vector and a scalar."
<< endl;
des->errors += 1;
return;
return 0;
}
@@ -598,7 +629,7 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
" vs. [" << mnum[0] << ":" << lnum[0] << "]"
" for signal ``" << hname_ << "''" << endl;
des->errors += 1;
return;
return 0;
}
}
@@ -616,6 +647,10 @@ void 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,
@@ -629,9 +664,9 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
if ((lexp == 0) || (rexp == 0)) {
cerr << get_line() << ": internal error: There is "
<< "a problem evaluating indices for ``"
<< hname_.peek_tail_name() << "''." << endl;
<< hname_ << "''." << endl;
des->errors += 1;
return;
return 0;
}
NetEConst*lcon = dynamic_cast<NetEConst*> (lexp);
@@ -639,10 +674,10 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
if ((lcon == 0) || (rcon == 0)) {
cerr << get_line() << ": internal error: The indices "
<< "are not constant for memory ``"
<< hname_.peek_tail_name() << "''." << endl;
<< "are not constant for array ``"
<< hname_ << "''." << endl;
des->errors += 1;
return;
return 0;
}
verinum lval = lcon->value();
@@ -651,75 +686,119 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
delete lexp;
delete rexp;
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 {
/* 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 = lex_strings.make(hname_.peek_tail_name());
if (debug_elaborate) {
cerr << get_line() << ": debug: Create signal "
<< name << "["<<msb<<":"<<lsb<<"]"
<< " in scope " << scope->name() << endl;
}
NetNet*sig = new NetNet(scope, name, wtype, msb, lsb);
sig->data_type(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);
array_dimensions = 1;
array_s0 = lval.as_long();
array_e0 = rval.as_long();
}
/* 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
+335 -131
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: elaborate.cc,v 1.347 2006/10/03 15:33:49 steve Exp $"
#ident "$Id: elaborate.cc,v 1.374 2007/06/05 21:35:51 steve Exp $"
#endif
# include "config.h"
@@ -41,6 +41,7 @@
# include "util.h"
# include "parse_api.h"
# include "compiler.h"
# include "ivl_assert.h"
static Link::strength_t drive_type(PGate::strength_t drv)
@@ -86,10 +87,17 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
assert(pin(0));
assert(pin(1));
/* Normally, l-values to continuous assignments are NOT allowed
to implicitly declare nets. However, so many tools do allow
it that Icarus Verilog will allow it, at least if extensions
are enabled. */
bool implicit_lval_ok = false;
if (generation_flag == GN_VER2001X)
implicit_lval_ok = true;
/* Elaborate the l-value. */
NetNet*lval = pin(0)->elaborate_lnet(des, scope);
NetNet*lval = pin(0)->elaborate_lnet(des, scope, implicit_lval_ok);
if (lval == 0) {
des->errors += 1;
return;
}
@@ -115,8 +123,14 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
return;
}
assert(rid);
assert(rid->pin_count() == 1);
ivl_assert(*this, rid);
if (rid->pin_count() != 1) {
cerr << get_line() << ": internal error: "
<< "Invalid elaborate_net results here:" << endl;
rid->dump_net(cerr, 4);
des->errors += 1;
}
ivl_assert(*this, rid->pin_count() == 1);
/* If the right hand net is the same type as the left
side net (i.e., WIRE/WIRE) then it is enough to just
@@ -181,6 +195,17 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
lval->vector_width());
rid = tmp;
}
} else if (cnt < rid->vector_width()) {
if (debug_elaborate)
cerr << get_line() << ": debug: PGAssign "
<< "Truncate r-value from "
<< cnt << " bits to "
<< lval->vector_width() << " bits." << endl;
NetNet*tmp = crop_to_width(des, rid, lval->vector_width());
rid = tmp;
}
if (! need_driver_flag) {
@@ -306,7 +331,7 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
name = scope->local_symbol();
/* If the Verilog source has a range specification for the
gates, then I am expected to make more then one
gates, then I am expected to make more than one
gate. Figure out how many are desired. */
if (msb_) {
NetExpr*msb_exp = elab_and_eval(des, scope, msb_, -1);
@@ -632,7 +657,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
if (debug_elaborate) {
cerr << get_line() << ": debug: Instantiate module "
<< rmod->mod_name() << " with instance name "
<< get_name() << " in scope " << scope->name() << endl;
<< get_name() << " in scope " << scope_path(scope) << endl;
}
// This is the array of pin expressions, shuffled to match the
@@ -751,8 +776,9 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
if (mport.count() == 0)
continue;
NetNet*tmp = des->find_signal(instance[0],
mport[0]->path());
perm_string pname = peek_tail_name(mport[0]->path());
NetNet*tmp = instance[0]->find_signal(pname);
assert(tmp);
if (tmp->port_type() == NetNet::PINPUT) {
@@ -925,7 +951,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
if (debug_elaborate) {
cerr << get_line() << ": debug: " << get_name()
<< ": Port " << idx << " has vector width of "
<< ": Port " << (idx+1) << " has vector width of "
<< prts_vector_width << "." << endl;
}
@@ -934,8 +960,10 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
// based, but users count parameter positions from 1.
if ((instance.count() == 1)
&& (prts_vector_width != sig->vector_width())) {
const char *tmp3 = rmod->ports[idx]->name.str();
if (tmp3 == 0) tmp3 = "???";
cerr << get_line() << ": warning: Port " << (idx+1)
<< " (" << rmod->ports[idx]->name << ") of "
<< " (" << tmp3 << ") of "
<< type_ << " expects " << prts_vector_width <<
" bits, got " << sig->vector_width() << "." << endl;
@@ -1419,10 +1447,20 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
delay = elaborate_delay_expr(delay_, des, scope);
assert(rval());
/* Elaborate the r-value expression, then try to evaluate it. */
assert(rval());
NetExpr*rv = elab_and_eval(des, scope, rval(), lv->lwidth());
/* Find out what the r-value width is going to be. We guess it
will be the l-value width, but it may turn out to be
something else based on self-determined widths inside. */
unsigned use_width = lv->lwidth();
bool unsized_flag = false;
use_width = rval()->test_width(des, scope, use_width, use_width, unsized_flag);
/* Now elaborate to the expected width. Pass the lwidth to
prune any constant result to fit with the lvalue at hand. */
NetExpr*rv = elab_and_eval(des, scope, rval(), use_width, lv->lwidth());
if (rv == 0) return 0;
assert(rv);
@@ -1465,7 +1503,6 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
NetESignal*sig = new NetESignal(tmp);
/* Generate an assignment of the l-value to the temporary... */
string n = scope->local_hsymbol();
NetAssign_*lvt = new NetAssign_(tmp);
NetAssign*a1 = new NetAssign(lvt, rv);
@@ -1588,10 +1625,10 @@ NetProc* PBlock::elaborate(Design*des, NetScope*scope) const
NetScope*nscope = 0;
if (name_.str() != 0) {
nscope = scope->child(name_);
nscope = scope->child(hname_t(name_));
if (nscope == 0) {
cerr << get_line() << ": internal error: "
"unable to find block scope " << scope->name()
"unable to find block scope " << scope_path(scope)
<< "<" << name_ << ">" << endl;
des->errors += 1;
return 0;
@@ -1602,7 +1639,6 @@ NetProc* PBlock::elaborate(Design*des, NetScope*scope) const
}
NetBlock*cur = new NetBlock(type, nscope);
bool fail_flag = false;
if (nscope == 0)
nscope = scope;
@@ -1620,8 +1656,12 @@ NetProc* PBlock::elaborate(Design*des, NetScope*scope) const
for (unsigned idx = 0 ; idx < list_.count() ; idx += 1) {
assert(list_[idx]);
NetProc*tmp = list_[idx]->elaborate(des, nscope);
// If the statement fails to elaborate, then simply
// ignore it. Presumably, the elaborate for the
// statement already generated an error message and
// marked the error count in the design so no need to
// do any of that here.
if (tmp == 0) {
fail_flag = true;
continue;
}
@@ -1635,11 +1675,6 @@ NetProc* PBlock::elaborate(Design*des, NetScope*scope) const
cur->append(tmp);
}
if (fail_flag) {
delete cur;
cur = 0;
}
return cur;
}
@@ -1739,16 +1774,26 @@ NetProc* PCondit::elaborate(Design*des, NetScope*scope) const
<< "is a constant " << val << "." << endl;
}
verinum::V reduced = verinum::V0;
for (unsigned idx = 0 ; idx < val.len() ; idx += 1)
reduced = reduced | val[idx];
delete expr;
if (val[0] == verinum::V1)
return if_->elaborate(des, scope);
if (reduced == verinum::V1)
if (if_) {
return if_->elaborate(des, scope);
} else {
NetBlock*tmp = new NetBlock(NetBlock::SEQU, 0);
tmp->set_line(*this);
return tmp;
}
else if (else_)
return else_->elaborate(des, scope);
else
return new NetBlock(NetBlock::SEQU, 0);
}
// If the condition expression is more then 1 bits, then
// If the condition expression is more than 1 bits, then
// generate a comparison operator to get the result down to
// one bit. Turn <e> into <e> != 0;
@@ -1796,7 +1841,7 @@ NetProc* PCondit::elaborate(Design*des, NetScope*scope) const
NetProc* PCallTask::elaborate(Design*des, NetScope*scope) const
{
if (path_.peek_name(0)[0] == '$')
if (peek_tail_name(path_)[0] == '$')
return elaborate_sys(des, scope);
else
return elaborate_usr(des, scope);
@@ -1832,16 +1877,15 @@ NetProc* PCallTask::elaborate_sys(Design*des, NetScope*scope) const
/* Attempt to pre-evaluate the parameters. It may be
possible to at least partially reduce the
expression. */
if (eparms[idx] && !dynamic_cast<NetEConst*>(eparms[idx])) {
NetExpr*tmp = eparms[idx]->eval_tree();
if (tmp != 0) {
if (eparms[idx]) {
if (NetExpr*tmp = eparms[idx]->eval_tree()) {
delete eparms[idx];
eparms[idx] = tmp;
}
}
}
NetSTask*cur = new NetSTask(path_.peek_name(0), eparms);
NetSTask*cur = new NetSTask(peek_tail_name(path_), eparms);
return cur;
}
@@ -1890,7 +1934,7 @@ NetProc* PCallTask::elaborate_usr(Design*des, NetScope*scope) const
NetTaskDef*def = task->task_def();
if (def == 0) {
cerr << get_line() << ": internal error: task " << path_
<< " doesn't have a definition in " << scope->name()
<< " doesn't have a definition in " << scope_path(scope)
<< "." << endl;
des->errors += 1;
return 0;
@@ -1899,7 +1943,8 @@ NetProc* PCallTask::elaborate_usr(Design*des, NetScope*scope) const
if (nparms() != def->port_count()) {
cerr << get_line() << ": error: Port count mismatch in call to ``"
<< path_ << "''." << endl;
<< path_ << "''. Got " << nparms()
<< " ports, expecting " << def->port_count() << " ports." << endl;
des->errors += 1;
return 0;
}
@@ -1910,6 +1955,7 @@ NetProc* PCallTask::elaborate_usr(Design*des, NetScope*scope) const
to make a sequential block to hold the generated code. */
if (nparms() == 0) {
cur = new NetUTask(task);
cur->set_line(*this);
return cur;
}
@@ -1950,6 +1996,7 @@ NetProc* PCallTask::elaborate_usr(Design*des, NetScope*scope) const
/* Generate the task call proper... */
cur = new NetUTask(task);
cur->set_line(*this);
block->append(cur);
@@ -2098,10 +2145,12 @@ NetProc* PDisable::elaborate(Design*des, NetScope*scope) const
{
assert(scope);
NetScope*target = des->find_scope(scope, scope_);
list<hname_t> spath = eval_scope_path(des, scope, scope_);
NetScope*target = des->find_scope(scope, spath);
if (target == 0) {
cerr << get_line() << ": error: Cannot find scope "
<< scope_ << " in " << scope->name() << endl;
<< scope_ << " in " << scope_path(scope) << endl;
des->errors += 1;
return 0;
}
@@ -2238,8 +2287,9 @@ NetProc* PEventStatement::elaborate_st(Design*des, NetScope*scope,
}
if (nset->count() == 0) {
cerr << get_line() << ": warning: No inputs to statement."
<< " Ignoring @*." << endl;
cerr << get_line() << ": error: No inputs to statement."
<< " The @* cannot execute." << endl;
des->errors += 1;
return enet;
}
@@ -2264,12 +2314,11 @@ NetProc* PEventStatement::elaborate_st(Design*des, NetScope*scope,
if (PEIdent*id = dynamic_cast<PEIdent*>(expr_[idx]->expr())) {
NetNet* sig = 0;
NetMemory* mem = 0;
const NetExpr*par = 0;
NetEvent* eve = 0;
NetScope*found_in = symbol_search(des, scope, id->path(),
sig, mem, par, eve);
sig, par, eve);
if (found_in && eve) {
wa->add_event(eve);
@@ -2377,7 +2426,7 @@ NetProc* PEventStatement::elaborate_wait(Design*des, NetScope*scope,
return 0;
}
// If the condition expression is more then 1 bits, then
// If the condition expression is more than 1 bits, then
// generate a reduction operator to get the result down to
// one bit. In other words, Turn <e> into |<e>;
@@ -2610,11 +2659,17 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const
assert(sig);
NetAssign_*lv = new NetAssign_(sig);
/* Calculate the width of the initialization as if this were
any other assignment statement. */
unsigned use_width = lv->lwidth();
bool unsized_flag = false;
use_width = expr1_->test_width(des, scope, use_width, use_width, unsized_flag);
/* Make the r-value of the initial assignment, and size it
properly. Then use it to build the assignment statement. */
etmp = elab_and_eval(des, scope, expr1_, lv->lwidth());
etmp->set_width(lv->lwidth());
etmp = pad_to_width(etmp, lv->lwidth());
etmp = elab_and_eval(des, scope, expr1_, use_width);
etmp->set_width(use_width);
etmp = pad_to_width(etmp, use_width);
if (debug_elaborate) {
cerr << get_line() << ": debug: FOR initial assign: "
@@ -2655,8 +2710,7 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const
/* Make the rvalue of the increment expression, and size it
for the lvalue. */
etmp = expr2_->elaborate_expr(des, scope, lv->lwidth(), false);
etmp->set_width(lv->lwidth());
etmp = elab_and_eval(des, scope, expr2_, lv->lwidth());
NetAssign*step = new NetAssign(lv, etmp);
step->set_line(*this);
@@ -2713,7 +2767,7 @@ void PFunction::elaborate(Design*des, NetScope*scope) const
if (def == 0) {
cerr << get_line() << ": internal error: "
<< "No function definition for function "
<< scope->name() << endl;
<< scope_path(scope) << endl;
return;
}
@@ -2722,7 +2776,7 @@ void PFunction::elaborate(Design*des, NetScope*scope) const
NetProc*st = statement_->elaborate(des, scope);
if (st == 0) {
cerr << statement_->get_line() << ": error: Unable to elaborate "
"statement in function " << def->name() << "." << endl;
"statement in function " << scope->basename() << "." << endl;
des->errors += 1;
return;
}
@@ -2823,7 +2877,7 @@ void PTask::elaborate(Design*des, NetScope*task) const
st = statement_->elaborate(des, task);
if (st == 0) {
cerr << statement_->get_line() << ": Unable to elaborate "
"statement in task " << task->name()
"statement in task " << scope_path(task)
<< " at " << get_line() << "." << endl;
return;
}
@@ -2837,12 +2891,11 @@ NetProc* PTrigger::elaborate(Design*des, NetScope*scope) const
assert(scope);
NetNet* sig = 0;
NetMemory* mem = 0;
const NetExpr*par = 0;
NetEvent* eve = 0;
NetScope*found_in = symbol_search(des, scope, event_,
sig, mem, par, eve);
sig, par, eve);
if (found_in == 0) {
cerr << get_line() << ": error: event <" << event_ << ">"
@@ -2873,6 +2926,79 @@ NetProc* PWhile::elaborate(Design*des, NetScope*scope) const
return loop;
}
bool PProcess::elaborate(Design*des, NetScope*scope) const
{
NetProc*cur = statement_->elaborate(des, scope);
if (cur == 0) {
return false;
}
NetProcTop*top=0;
switch (type()) {
case PProcess::PR_INITIAL:
top = new NetProcTop(scope, NetProcTop::KINITIAL, cur);
break;
case PProcess::PR_ALWAYS:
top = new NetProcTop(scope, NetProcTop::KALWAYS, cur);
break;
}
ivl_assert(*this, top);
// Evaluate the attributes for this process, if there
// are any. These attributes are to be attached to the
// NetProcTop object.
struct attrib_list_t*attrib_list = 0;
unsigned attrib_list_n = 0;
attrib_list = evaluate_attributes(attributes, attrib_list_n, des, scope);
for (unsigned adx = 0 ; adx < attrib_list_n ; adx += 1)
top->attribute(attrib_list[adx].key,
attrib_list[adx].val);
delete[]attrib_list;
top->set_line(*this);
des->add_process(top);
/* Detect the special case that this is a combinational
always block. We want to attach an _ivl_schedule_push
attribute to this process so that it starts up and
gets into its wait statement before non-combinational
code is executed. */
do {
if (top->type() != NetProcTop::KALWAYS)
break;
NetEvWait*st = dynamic_cast<NetEvWait*>(top->statement());
if (st == 0)
break;
if (st->nevents() != 1)
break;
NetEvent*ev = st->event(0);
if (ev->nprobe() == 0)
break;
bool anyedge_test = true;
for (unsigned idx = 0 ; anyedge_test && (idx<ev->nprobe())
; idx += 1) {
const NetEvProbe*pr = ev->probe(idx);
if (pr->edge() != NetEvProbe::ANYEDGE)
anyedge_test = false;
}
if (! anyedge_test)
break;
top->attribute(perm_string::literal("_ivl_schedule_push"),
verinum(1));
} while (0);
return true;
}
void PSpecPath::elaborate(Design*des, NetScope*scope) const
{
uint64_t delay_value[12];
@@ -2883,6 +3009,18 @@ void PSpecPath::elaborate(Design*des, NetScope*scope) const
if (!gn_specify_blocks_flag)
return;
/* Check for various path types that are not supported. */
if (conditional && !condition) {
cerr << get_line() << ": sorry: ifnone specify paths"
<< " are not supported." << endl;
cerr << get_line() << ": : Use -g no-specify to ignore"
<< " specify blocks." << endl;
des->errors += 1;
return;
}
ivl_assert(*this, conditional || (condition==0));
ndelays = delays.size();
if (ndelays > 12)
ndelays = 12;
@@ -2927,13 +3065,30 @@ void PSpecPath::elaborate(Design*des, NetScope*scope) const
break;
}
NetNet*condit_sig = 0;
if (conditional) {
ivl_assert(*this, condition);
NetExpr*tmp = elab_and_eval(des, scope, condition, -1);
ivl_assert(*condition, tmp);
// FIXME: Look for constant expressions here?
// Get a net form.
condit_sig = tmp->synthesize(des);
ivl_assert(*condition, condit_sig);
}
/* Create all the various paths from the path specifier. */
typedef std::vector<perm_string>::const_iterator str_vector_iter;
for (str_vector_iter cur = dst.begin()
; cur != dst.end() ; cur ++) {
if (debug_elaborate) {
cerr << get_line() << ": debug: Path to " << (*cur) << endl;
cerr << get_line() << ": debug: Path to " << (*cur);
if (condit_sig)
cerr << " if " << condit_sig->name();
cerr << endl;
}
NetNet*dst_sig = scope->find_signal(*cur);
@@ -2944,10 +3099,26 @@ void PSpecPath::elaborate(Design*des, NetScope*scope) const
continue;
}
if (dst_sig->port_type() != NetNet::POUTPUT
&& dst_sig->port_type() != NetNet::PINOUT) {
cerr << get_line() << ": error: Path destination "
<< *cur << " must be an output or inout port." << endl;
des->errors += 1;
}
NetDelaySrc*path = new NetDelaySrc(scope, scope->local_symbol(),
src.size());
src.size(), condit_sig);
path->set_line(*this);
// The presence of the data_source_expression indicates
// that this is an edge sensitive path. If so, then set
// the edges. Note that edge==0 is BOTH edges.
if (data_source_expression) {
if (edge >= 0) path->set_posedge();
if (edge <= 0) path->set_negedge();
}
switch (ndelays) {
case 12:
path->set_delays(delay_value[0], delay_value[1],
@@ -2980,10 +3151,22 @@ void PSpecPath::elaborate(Design*des, NetScope*scope) const
NetNet*src_sig = scope->find_signal(*cur_src);
assert(src_sig);
if (src_sig->port_type() != NetNet::PINPUT
& src_sig->port_type() != NetNet::PINOUT) {
cerr << get_line() << ": error: Path source "
<< *cur_src << " must be an input or inout port."
<< endl;
des->errors += 1;
}
connect(src_sig->pin(0), path->pin(idx));
idx += 1;
}
if (condit_sig)
connect(condit_sig->pin(0), path->pin(idx));
dst_sig->add_delay_path(path);
}
@@ -3027,6 +3210,7 @@ bool Module::elaborate(Design*des, NetScope*scope) const
<< " value=" << value.integer << endl;
} else {
value.type = IVL_VT_NO_TYPE;
cerr << (*cur).second->get_line() << ": error: "
<< "specparam " << (*cur).first << " value"
<< " is not constant: " << *val << endl;
@@ -3051,7 +3235,8 @@ bool Module::elaborate(Design*des, NetScope*scope) const
for (mfunc_it_t cur = funcs_.begin()
; cur != funcs_.end() ; cur ++) {
NetScope*fscope = scope->child((*cur).first);
hname_t use_name ( (*cur).first );
NetScope*fscope = scope->child(use_name);
assert(fscope);
(*cur).second->elaborate(des, fscope);
}
@@ -3063,7 +3248,8 @@ bool Module::elaborate(Design*des, NetScope*scope) const
for (mtask_it_t cur = tasks_.begin()
; cur != tasks_.end() ; cur ++) {
NetScope*tscope = scope->child((*cur).first);
hname_t use_name ( (*cur).first );
NetScope*tscope = scope->child(use_name);
assert(tscope);
(*cur).second->elaborate(des, tscope);
}
@@ -3086,80 +3272,9 @@ bool Module::elaborate(Design*des, NetScope*scope) const
const list<PProcess*>&sl = get_behaviors();
for (list<PProcess*>::const_iterator st = sl.begin()
; st != sl.end()
; st ++ ) {
NetProc*cur = (*st)->statement()->elaborate(des, scope);
if (cur == 0) {
result_flag = false;
continue;
}
NetProcTop*top=NULL;
switch ((*st)->type()) {
case PProcess::PR_INITIAL:
top = new NetProcTop(scope, NetProcTop::KINITIAL, cur);
break;
case PProcess::PR_ALWAYS:
top = new NetProcTop(scope, NetProcTop::KALWAYS, cur);
break;
}
assert(top);
// Evaluate the attributes for this process, if there
// are any. These attributes are to be attached to the
// NetProcTop object.
struct attrib_list_t*attrib_list = 0;
unsigned attrib_list_n = 0;
attrib_list = evaluate_attributes((*st)->attributes,
attrib_list_n,
des, scope);
for (unsigned adx = 0 ; adx < attrib_list_n ; adx += 1)
top->attribute(attrib_list[adx].key,
attrib_list[adx].val);
delete[]attrib_list;
top->set_line(*(*st));
des->add_process(top);
/* Detect the special case that this is a combinational
always block. We want to attach an _ivl_schedule_push
attribute to this process so that it starts up and
gets into its wait statement before non-combinational
code is executed. */
do {
if (top->type() != NetProcTop::KALWAYS)
break;
NetEvWait*st = dynamic_cast<NetEvWait*>(top->statement());
if (st == 0)
break;
if (st->nevents() != 1)
break;
NetEvent*ev = st->event(0);
if (ev->nprobe() == 0)
break;
bool anyedge_test = true;
for (unsigned idx = 0 ; anyedge_test && (idx<ev->nprobe())
; idx += 1) {
const NetEvProbe*pr = ev->probe(idx);
if (pr->edge() != NetEvProbe::ANYEDGE)
anyedge_test = false;
}
if (! anyedge_test)
break;
top->attribute(perm_string::literal("_ivl_schedule_push"),
verinum(1));
} while (0);
; st != sl.end() ; st ++ ) {
result_flag &= (*st)->elaborate(des, scope);
}
// Elaborate the specify paths of the module.
@@ -3183,7 +3298,7 @@ bool PGenerate::elaborate(Design*des) const
if (debug_elaborate)
cerr << get_line() << ": debug: Elaborate in "
<< "scope " << (*cur)->name() << endl;
<< "scope " << scope_path(*cur) << endl;
flag = elaborate_(des, *cur) & flag;
}
@@ -3194,10 +3309,12 @@ bool PGenerate::elaborate(Design*des) const
bool PGenerate::elaborate_(Design*des, NetScope*scope) const
{
typedef list<PGate*>::const_iterator gates_it_t;
for (gates_it_t cur = gates.begin() ; cur != gates.end() ; cur ++ ) {
for (gates_it_t cur = gates.begin() ; cur != gates.end() ; cur ++ )
(*cur)->elaborate(des, scope);
typedef list<PProcess*>::const_iterator proc_it_t;
for (proc_it_t cur = behaviors.begin(); cur != behaviors.end(); cur++)
(*cur)->elaborate(des, scope);
}
return true;
}
@@ -3311,6 +3428,93 @@ Design* elaborate(list<perm_string>roots)
/*
* $Log: elaborate.cc,v $
* Revision 1.374 2007/06/05 21:35:51 steve
* Error resiliency (ldoolitt)
*
* Revision 1.373 2007/06/04 02:19:07 steve
* Handle bit/part select of array words in nets.
*
* Revision 1.372 2007/06/02 03:42:12 steve
* Properly evaluate scope path expressions.
*
* Revision 1.371 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.370 2007/04/16 01:10:07 steve
* Properly ignore unsupported ifnone.
*
* Revision 1.369 2007/04/15 20:45:40 steve
* Attach line number information to task calls.
*
* Revision 1.368 2007/04/13 02:34:35 steve
* Parse edge sensitive paths without edge specifier.
*
* Revision 1.367 2007/04/05 03:09:50 steve
* Allow implicit wires in assign l-value.
*
* Revision 1.366 2007/04/01 23:01:10 steve
* Improve port mismatch error message.
*
* Revision 1.365 2007/03/22 16:08:15 steve
* Spelling fixes from Larry
*
* Revision 1.364 2007/03/08 05:30:02 steve
* Limit the calculated widths of constants.
*
* Revision 1.363 2007/03/05 05:59:10 steve
* Handle processes within generate loops.
*
* Revision 1.362 2007/03/03 05:56:55 steve
* Check that path source/destination are ports.
*
* Revision 1.361 2007/03/02 06:13:22 steve
* Add support for edge sensitive spec paths.
*
* Revision 1.360 2007/03/01 06:19:38 steve
* Add support for conditional specify delay paths.
*
* Revision 1.359 2007/02/12 01:52:21 steve
* Parse all specify paths to pform.
*
* Revision 1.358 2007/02/01 05:52:24 steve
* More generous handling of errors in blocks.
*
* Revision 1.357 2007/01/21 04:26:36 steve
* Clean up elaboration of for-loop increment expression.
*
* Revision 1.356 2007/01/19 05:42:40 steve
* Precalculate constant power expressions, and constant function arguments.
*
* Revision 1.355 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.354 2006/12/09 01:59:35 steve
* Fix an uninitialized variable warning.
*
* Revision 1.353 2006/12/08 04:09:41 steve
* @* without inputs is an error.
*
* Revision 1.352 2006/11/27 02:01:07 steve
* Fix crash handling constant true conditional.
*
* Revision 1.351 2006/11/26 07:10:30 steve
* Fix compile time eval of condition expresion to do reduction OR of vectors.
*
* Revision 1.350 2006/11/26 06:29:16 steve
* Fix nexus widths for direct link assign and ternary nets.
*
* Revision 1.349 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.348 2006/10/30 05:44:49 steve
* Expression widths with unsized literals are pseudo-infinite width.
*
* Revision 1.347 2006/10/03 15:33:49 steve
* no-specify turns of specparam elaboration.
*
+26 -19
View File
@@ -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.87 2006/06/18 04:15:50 steve Exp $"
#ident "$Id: emit.cc,v 1.89 2007/01/16 05:44:15 steve Exp $"
#endif
# include "config.h"
@@ -57,6 +57,11 @@ 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);
@@ -125,12 +130,6 @@ bool NetPartSelect::emit_node(struct target_t*tgt) const
return tgt->part_select(this);
}
bool NetRamDq::emit_node(struct target_t*tgt) const
{
tgt->lpm_ram_dq(this);
return true;
}
bool NetReplicate::emit_node(struct target_t*tgt) const
{
return tgt->replicate(this);
@@ -344,15 +343,19 @@ 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
@@ -461,11 +464,6 @@ 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."
@@ -529,6 +527,15 @@ int emit(const Design*des, const char*type)
/*
* $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.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.
*
+31 -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: eval.cc,v 1.43 2006/08/08 05:11:37 steve Exp $"
#ident "$Id: eval.cc,v 1.47 2007/06/04 19:14:06 steve Exp $"
#endif
# include "config.h"
@@ -29,12 +29,12 @@
# include "netmisc.h"
# include "compiler.h"
verinum* PExpr::eval_const(const Design*, NetScope*) const
verinum* PExpr::eval_const(Design*, NetScope*) const
{
return 0;
}
verinum* PEBinary::eval_const(const Design*des, NetScope*scope) const
verinum* PEBinary::eval_const(Design*des, NetScope*scope) const
{
verinum*l = left_->eval_const(des, scope);
if (l == 0) return 0;
@@ -143,7 +143,7 @@ verinum* PEBinary::eval_const(const Design*des, NetScope*scope) const
delete r;
return res;
}
verinum* PEConcat::eval_const(const Design*des, NetScope*scope) const
verinum* PEConcat::eval_const(Design*des, NetScope*scope) const
{
verinum*accum = parms_[0]->eval_const(des, scope);
if (accum == 0)
@@ -170,24 +170,24 @@ verinum* PEConcat::eval_const(const Design*des, NetScope*scope) const
* Evaluate an identifier as a constant expression. This is only
* possible if the identifier is that of a parameter.
*/
verinum* PEIdent::eval_const(const Design*des, NetScope*scope) const
verinum* PEIdent::eval_const(Design*des, NetScope*scope) const
{
assert(scope);
NetNet*net;
NetMemory*mem;
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(path_.peek_tail_name(),scope->genvar_tmp) == 0) {
&& strcmp(name_tail.name,scope->genvar_tmp) == 0) {
return new verinum(scope->genvar_tmp_val);
}
NetScope*found_in = symbol_search(des, scope, path_,
net, mem, expr, eve);
symbol_search(des, scope, path_, net, expr, eve);
if (expr == 0)
return 0;
@@ -202,30 +202,30 @@ verinum* PEIdent::eval_const(const Design*des, NetScope*scope) const
assert(eval);
if (msb_ || lsb_)
if (!name_tail.index.empty())
return 0;
return new verinum(eval->value());
}
verinum* PEFNumber::eval_const(const Design*, NetScope*) const
verinum* PEFNumber::eval_const(Design*, NetScope*) const
{
long val = value_->as_long();
return new verinum(val);
}
verinum* PENumber::eval_const(const Design*, NetScope*) const
verinum* PENumber::eval_const(Design*, NetScope*) const
{
return new verinum(value());
}
verinum* PEString::eval_const(const Design*, NetScope*) const
verinum* PEString::eval_const(Design*, NetScope*) const
{
return new verinum(string(text_));
}
verinum* PETernary::eval_const(const Design*des, NetScope*scope) const
verinum* PETernary::eval_const(Design*des, NetScope*scope) const
{
verinum*test = expr_->eval_const(des, scope);
if (test == 0)
@@ -245,7 +245,7 @@ verinum* PETernary::eval_const(const Design*des, NetScope*scope) const
}
}
verinum* PEUnary::eval_const(const Design*des, NetScope*scope) const
verinum* PEUnary::eval_const(Design*des, NetScope*scope) const
{
verinum*val = expr_->eval_const(des, scope);
if (val == 0)
@@ -276,6 +276,22 @@ verinum* PEUnary::eval_const(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.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.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.
*
+5 -3
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.8 2005/11/27 17:01:57 steve Exp $"
#ident "$Id: eval_attrib.cc,v 1.9 2007/06/04 19:14:06 steve Exp $"
#endif
# include "config.h"
@@ -35,8 +35,7 @@
attrib_list_t* evaluate_attributes(const map<perm_string,PExpr*>&att,
unsigned&natt,
const Design*des,
NetScope*scope)
Design*des, NetScope*scope)
{
natt = att.size();
if (natt == 0)
@@ -74,6 +73,9 @@ 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.
*
+165 -156
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.70 2006/09/19 23:00:15 steve Exp $"
#ident "$Id: eval_tree.cc,v 1.77 2007/06/02 03:42:12 steve Exp $"
#endif
# include "config.h"
@@ -26,8 +26,9 @@
# include <iostream>
# include "netlist.h"
# include "ivl_assert.h"
NetExpr* NetExpr::eval_tree()
NetExpr* NetExpr::eval_tree(int prune_to_width)
{
return 0;
}
@@ -51,9 +52,61 @@ void NetEBinary::eval_sub_tree_()
}
}
NetEConst* NetEBAdd::eval_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)
{
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_);
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
@@ -115,7 +168,32 @@ NetEConst* NetEBAdd::eval_tree()
return 0;
}
NetEConst* NetEBBits::eval_tree()
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)
{
eval_sub_tree_();
@@ -690,7 +768,7 @@ NetEConst* NetEBComp::eval_neeqeq_()
return res;
}
NetEConst* NetEBComp::eval_tree()
NetEConst* NetEBComp::eval_tree(int prune_to_width)
{
eval_sub_tree_();
@@ -728,7 +806,7 @@ NetEConst* NetEBComp::eval_tree()
* The NetEBDiv operator includes the / and % operators. First evaluate
* the sub-expressions, then perform the required operation.
*/
NetExpr* NetEBDiv::eval_tree()
NetExpr* NetEBDiv::eval_tree(int prune_to_width)
{
eval_sub_tree_();
@@ -798,7 +876,7 @@ NetExpr* NetEBDiv::eval_tree()
return 0;
}
NetEConst* NetEBLogic::eval_tree()
NetEConst* NetEBLogic::eval_tree(int prune_to_width)
{
eval_sub_tree_();
NetEConst*lc = dynamic_cast<NetEConst*>(left_);
@@ -864,52 +942,14 @@ NetEConst* NetEBLogic::eval_tree()
return new NetEConst(verinum(res, 1));
}
NetExpr* NetEBMult::eval_tree_real_()
{
verireal lval;
verireal rval;
switch (left_->expr_type()) {
case IVL_VT_REAL: {
NetECReal*lc = dynamic_cast<NetECReal*> (left_);
if (lc == 0) return 0;
lval = lc->value();
break;
}
case IVL_VT_BOOL:
case IVL_VT_LOGIC: {
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 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);
}
bool flag = get_real_arguments_(lval, rval);
if (! flag) return 0;
NetECReal*res = new NetECReal(lval * rval);
@@ -917,7 +957,7 @@ NetExpr* NetEBMult::eval_tree_real_()
return res;
}
NetExpr* NetEBMult::eval_tree()
NetExpr* NetEBMult::eval_tree(int prune_to_width)
{
eval_sub_tree_();
@@ -942,55 +982,15 @@ NetExpr* NetEBPow::eval_tree_real_()
verireal lval;
verireal rval;
switch (left_->expr_type()) {
case IVL_VT_REAL: {
NetECReal*lc = dynamic_cast<NetECReal*> (left_);
if (lc == 0) return 0;
lval = lc->value();
break;
}
case IVL_VT_BOOL:
case IVL_VT_LOGIC: {
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 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);
}
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()
NetExpr* NetEBPow::eval_tree(int prune_to_width)
{
eval_sub_tree_();
@@ -1015,7 +1015,7 @@ NetExpr* NetEBPow::eval_tree()
* Evaluate the shift operator if possible. For this to work, both
* operands must be constant.
*/
NetEConst* NetEBShift::eval_tree()
NetEConst* NetEBShift::eval_tree(int prune_to_width)
{
eval_sub_tree_();
NetEConst*re = dynamic_cast<NetEConst*>(right_);
@@ -1042,7 +1042,7 @@ NetEConst* NetEBShift::eval_tree()
cerr << get_line() << ": debug: "
<< "Evaluate " << lv << "<<" << op() << ">> "
<< rv << ", wid=" << wid << ", shift=" << shift
<< ", lv.las_len()=" << lv.has_len() << endl;
<< ", lv.has_len()=" << lv.has_len() << endl;
}
if ((wid == 0) || ! lv.has_len()) {
@@ -1056,6 +1056,9 @@ NetEConst* NetEBShift::eval_tree()
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());
@@ -1096,7 +1099,7 @@ NetEConst* NetEBShift::eval_tree()
return res;
}
NetEConst* NetEConcat::eval_tree()
NetEConst* NetEConcat::eval_tree(int prune_to_width)
{
unsigned repeat_val = repeat();
unsigned local_errors = 0;
@@ -1190,55 +1193,18 @@ NetEConst* NetEConcat::eval_tree()
return res;
}
/*
* There are limits to our ability to evaluate a memory reference
* expression, because the content of a memory is never
* constant. However, the index expression may be precalculated, and
* there are certain index values that do give us constant results.
*/
NetExpr* NetEMemory::eval_tree()
NetExpr* NetEParam::eval_tree(int prune_to_width)
{
/* Attempt to evaluate the index expression to a constant, if
it is not already. */
if (idx_ && !dynamic_cast<NetEConst*>(idx_)) {
NetExpr* tmp = idx_->eval_tree();
if (tmp) {
delete idx_;
idx_ = tmp;
}
}
NetEConst*itmp = dynamic_cast<NetEConst*>(idx_);
if (itmp == 0)
if (des_ == 0) {
assert(scope_ == 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;
if (debug_elaborate) {
cerr << get_line() << ": debug: evaluating expression: "
<< *this << endl;
}
return 0;
}
NetExpr* NetEParam::eval_tree()
{
if (des_ == 0)
return 0;
assert(scope_);
const NetExpr*expr_msb;
const NetExpr*expr_lsb;
@@ -1246,7 +1212,7 @@ NetExpr* NetEParam::eval_tree()
if (expr == 0) {
cerr << get_line() << ": internal error: Unable to match "
<< "parameter " << name_ << " in scope "
<< scope_->name() << endl;
<< scope_path(scope_) << endl;
return 0;
}
@@ -1334,7 +1300,7 @@ NetExpr* NetEParam::eval_tree()
}
}
NetEConst* NetESelect::eval_tree()
NetEConst* NetESelect::eval_tree(int prune_to_width)
{
NetEConst*expr = dynamic_cast<NetEConst*>(expr_);
if (expr == 0) {
@@ -1347,31 +1313,50 @@ NetEConst* NetESelect::eval_tree()
expr = dynamic_cast<NetEConst*>(expr_);
}
NetEConst*base = dynamic_cast<NetEConst*>(base_);
if (base == 0) {
NetExpr*tmp = base_->eval_tree();
if (tmp != 0) {
delete base_;
base_ = tmp;
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_);
}
base = dynamic_cast<NetEConst*>(base_);
if (base == 0)
return 0;
bval = base->value().as_long();
}
if (expr == 0)
return 0;
if (base == 0)
return 0;
verinum eval = expr->value();
verinum oval (verinum::V0, expr_width(), true);
long bval = base->value().as_long();
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;
}
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, verinum::Vx);
oval.set(idx, pad_bit);
bval += 1;
}
@@ -1388,7 +1373,7 @@ NetEConst* NetESelect::eval_tree()
* evaluates to x or z, then merge the constant bits of the true and
* false expressions.
*/
NetExpr* NetETernary::eval_tree()
NetExpr* NetETernary::eval_tree(int prune_to_width)
{
NetExpr*tmp;
@@ -1525,7 +1510,7 @@ void NetEUnary::eval_expr_()
expr_ = oper;
}
NetEConst* NetEUnary::eval_tree()
NetEConst* NetEUnary::eval_tree(int prune_to_width)
{
eval_expr_();
NetEConst*rval = dynamic_cast<NetEConst*>(expr_);
@@ -1582,12 +1567,12 @@ NetEConst* NetEUnary::eval_tree()
}
NetEConst* NetEUBits::eval_tree()
NetEConst* NetEUBits::eval_tree(int prune_to_width)
{
return NetEUnary::eval_tree();
return NetEUnary::eval_tree(prune_to_width);
}
NetEConst* NetEUReduce::eval_tree()
NetEConst* NetEUReduce::eval_tree(int prune_to_width)
{
eval_expr_();
NetEConst*rval = dynamic_cast<NetEConst*>(expr_);
@@ -1670,6 +1655,30 @@ NetEConst* NetEUReduce::eval_tree()
/*
* $Log: eval_tree.cc,v $
* Revision 1.77 2007/06/02 03:42:12 steve
* Properly evaluate scope path expressions.
*
* Revision 1.76 2007/05/31 18:36:06 steve
* Fix warning (ldolittle)
*
* Revision 1.75 2007/04/07 04:46:18 steve
* Handle evaluate of addition of real valued constants.
*
* Revision 1.74 2007/03/08 05:30:02 steve
* Limit the calculated widths of constants.
*
* 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.
*
+8 -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: hello_vpi.c,v 1.3 2002/08/12 01:35:01 steve Exp $"
#ident "$Id: hello_vpi.c,v 1.5 2007/01/17 05:35:48 steve Exp $"
#endif
/*
@@ -33,7 +33,7 @@
# include <vpi_user.h>
static int my_hello_calltf(char *xx)
static PLI_INT32 my_hello_calltf(char *xx)
{
vpi_printf("Hello World, from VPI.\n");
return 0;
@@ -62,6 +62,12 @@ 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.
*
+4 -4
View File
@@ -16,13 +16,13 @@
* 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.4 2003/11/25 18:35:31 steve Exp $"
* $Id: sqrt-virtex.v,v 1.5 2007/03/22 16:08:18 steve Exp $"
*/
/*
* This module is a synthesizeable square-root function. It is also a
* detailed example of how to target Xilinx Virtex parts using
* Icarus Verilog. In fact, for no particular reason other then to
* Icarus Verilog. In fact, for no particular reason other than to
* be excessively specific, I will step through the process of
* generating a design for a Spartan-II XC2S15-VQ100, and also how to
* generate a generic library part for larger Virtex designs.
@@ -129,7 +129,7 @@
* This command creates from the chip.ngd the file "chip_root.v" that
* 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 hte EDIF file in 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
* chip_root module below.
*
@@ -183,7 +183,7 @@
* where sqrt(y) is the exact square root of y and floor(N) is the
* largest integer <= N.
*
* For 32bit numbers, this will never run more then 16 iterations,
* For 32 bit numbers, this will never run more than 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.4 2004/10/04 01:10:56 steve Exp $"
* $Id: sqrt.vl,v 1.5 2007/03/22 16:08:18 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 32bit numbers, this will never run more then 16 iterations,
* For 32 bit numbers, this will never run more than 16 iterations,
* which amounts to 16 clocks.
*/
+79 -75
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: expr_synth.cc,v 1.80 2006/08/08 05:11:37 steve Exp $"
#ident "$Id: expr_synth.cc,v 1.87 2007/06/02 03:42:12 steve Exp $"
#endif
# include "config.h"
@@ -26,6 +26,7 @@
# include "netlist.h"
# include "netmisc.h"
# include "ivl_assert.h"
NetNet* NetExpr::synthesize(Design*des)
{
@@ -91,7 +92,6 @@ NetNet* NetEBBits::synthesize(Design*des)
NetScope*scope = lsig->scope();
assert(scope);
string path = des->local_symbol(scope->name());
if (lsig->vector_width() != rsig->vector_width()) {
cerr << get_line() << ": internal error: bitwise (" << op_
@@ -449,10 +449,14 @@ NetNet* NetEBShift::synthesize(Design*des)
osig->data_type(expr_type());
osig->local_flag(true);
// ushift is the amount of pad created by the shift.
unsigned long ushift = shift>=0? shift : -shift;
if (ushift > osig->vector_width())
ushift = osig->vector_width();
// part_width is the bits of the vector that survive the shift.
unsigned long part_width = osig->vector_width() - ushift;
verinum znum (verinum::V0, ushift, true);
NetConst*zcon = new NetConst(scope, scope->local_symbol(),
znum);
@@ -469,8 +473,24 @@ NetNet* NetEBShift::synthesize(Design*des)
NetNet*zsig = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, znum.len());
zsig->data_type(osig->data_type());
zsig->local_flag(true);
zsig->set_line(*this);
connect(zcon->pin(0), zsig->pin(0));
/* Create a part select to reduce the width of the lsig
to the amount left by the shift. */
NetPartSelect*psel = new NetPartSelect(lsig, shift<0? ushift : 0,
part_width,
NetPartSelect::VP);
des->add_node(psel);
NetNet*psig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, part_width);
psig->data_type(expr_type());
psig->local_flag(true);
psig->set_line(*this);
connect(psig->pin(0), psel->pin(0));
NetConcat*ccat = new NetConcat(scope, scope->local_symbol(),
osig->vector_width(), 2);
ccat->set_line(*this);
@@ -478,10 +498,12 @@ NetNet* NetEBShift::synthesize(Design*des)
connect(ccat->pin(0), osig->pin(0));
if (shift > 0) {
// Left shift.
connect(ccat->pin(1), zsig->pin(0));
connect(ccat->pin(2), lsig->pin(0));
connect(ccat->pin(2), psig->pin(0));
} else {
connect(ccat->pin(1), lsig->pin(0));
// Right shift
connect(ccat->pin(1), psig->pin(0));
connect(ccat->pin(2), zsig->pin(0));
}
@@ -497,7 +519,6 @@ NetNet* NetEBShift::synthesize(Design*des)
osig->data_type(expr_type());
osig->local_flag(true);
assert(op() == 'l');
NetCLShift*dev = new NetCLShift(scope, scope->local_symbol(),
osig->vector_width(),
rsig->vector_width(),
@@ -644,47 +665,37 @@ NetNet* NetEUReduce::synthesize(Design*des)
osig->data_type(expr_type());
osig->local_flag(true);
perm_string oname = scope->local_symbol();
NetLogic*gate;
NetUReduce::TYPE rtype = NetUReduce::NONE;
switch (op()) {
case 'N':
case '!':
gate = new NetLogic(scope, oname, isig->pin_count()+1,
NetLogic::NOR, 1);
rtype = NetUReduce::NOR;
break;
case '&':
gate = new NetLogic(scope, oname, isig->pin_count()+1,
NetLogic::AND, 1);
rtype = NetUReduce::AND;
break;
case '|':
gate = new NetLogic(scope, oname, isig->pin_count()+1,
NetLogic::OR, 1);
rtype = NetUReduce::OR;
break;
case '^':
gate = new NetLogic(scope, oname, isig->pin_count()+1,
NetLogic::XOR, 1);
rtype = NetUReduce::XOR;
break;
case 'A':
gate = new NetLogic(scope, oname, isig->pin_count()+1,
NetLogic::NAND, 1);
rtype = NetUReduce::XNOR;
break;
case 'X':
gate = new NetLogic(scope, oname, isig->pin_count()+1,
NetLogic::XNOR, 1);
rtype = NetUReduce::XNOR;
break;
default:
cerr << get_line() << ": internal error: "
<< "Unable to synthesize " << *this << "." << endl;
return 0;
}
NetUReduce*gate = new NetUReduce(scope, scope->local_symbol(),
rtype, isig->vector_width());
des->add_node(gate);
connect(gate->pin(0), osig->pin(0));
for (unsigned idx = 0 ; idx < isig->pin_count() ; idx += 1)
@@ -693,33 +704,6 @@ NetNet* NetEUReduce::synthesize(Design*des)
return osig;
}
NetNet* NetEMemory::synthesize(Design *des)
{
NetNet*adr = idx_->synthesize(des);
NetScope*scope = adr->scope();
NetRamDq*ram = new NetRamDq(scope, scope->local_symbol(),
mem_, adr->vector_width());
des->add_node(ram);
ram->set_line(*this);
connect(ram->pin_Address(), adr->pin(0));
/* Create an output signal to receive the data. Assume that
memories return LOGIC. */
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, ram->width());
osig->data_type(IVL_VT_LOGIC);
osig->local_flag(true);
osig->set_line(*this);
connect(ram->pin_Q(), osig->pin(0));
return osig;
}
NetNet* NetESelect::synthesize(Design *des)
{
@@ -729,31 +713,15 @@ NetNet* NetESelect::synthesize(Design *des)
NetScope*scope = sub->scope();
unsigned off = 0;
NetNet*off = 0;
// This handles the case that the NetESelect exists to do an
// actual part/bit select. Generate a NetPartSelect object to
// do the work, and replace "sub" with the selected output.
if (base_ != 0) {
// For now, only handle constant part selects in this
// context. NOTE: the elaboration that created the
// NetESelect already translated the part base to
// canonical form, so the base_ is canonical already.
NetEConst*bcon = dynamic_cast<NetEConst*>(base_);
assert(bcon);
off = base_->synthesize(des);
long bval = bcon->value().as_long();
assert(bval >= 0);
off = bval;
}
/* If there is a part select, then generate a PartSelect node
to actually do the part select. This does not expansion,
that is handled later. */
if ((off != 0) || (off+expr_width() < sub->vector_width())) {
unsigned wid = expr_width();
if ((wid + off) > sub->vector_width())
wid = sub->vector_width() - off;
NetPartSelect*sel = new NetPartSelect(sub, off, wid,
NetPartSelect::VP);
NetPartSelect*sel = new NetPartSelect(sub, off, expr_width());
sel->set_line(*this);
des->add_node(sel);
@@ -766,13 +734,25 @@ NetNet* NetESelect::synthesize(Design *des)
connect(sub->pin(0), sel->pin(0));
}
/* Done? Vector is already the right width? then stop now. */
// Now look for the case that the NetESelect actually exists
// to change the width of the expression. (i.e. to do
// padding.) If this was for an actual part select that at
// this point the output vector_width is exactly right, and we
// are done.
if (sub->vector_width() == expr_width())
return sub;
// The vector_width is not exactly right, so the source is
// probably asking for padding. Create nodes to do sign
// extension or 0 extension, depending on the has_sign() mode
// of the expression.
NetNet*net = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, expr_width());
net->data_type(expr_type());
net->local_flag(true);
net->set_line(*this);
if (has_sign()) {
NetSignExtend*pad = new NetSignExtend(scope,
scope->local_symbol(),
@@ -890,6 +870,30 @@ NetNet* NetESignal::synthesize(Design*des)
/*
* $Log: expr_synth.cc,v $
* Revision 1.87 2007/06/02 03:42:12 steve
* Properly evaluate scope path expressions.
*
* Revision 1.86 2007/04/15 01:37:29 steve
* Allow bit/part select of vectors in continuous assignments.
*
* Revision 1.85 2007/04/12 05:21:54 steve
* fix handling of unary reduction logic in certain nets.
*
* Revision 1.84 2007/04/04 02:31:57 steve
* Remove useless assert
*
* Revision 1.83 2007/02/05 01:42:31 steve
* Set some missing local flags.
*
* Revision 1.82 2007/01/20 02:10:45 steve
* Get argument widths right for shift results.
*
* Revision 1.81 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.80 2006/08/08 05:11:37 steve
* Handle 64bit delay constants.
*
+11 -2
View File
@@ -1,4 +1,7 @@
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
@@ -249,7 +252,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 then a
is accepted. Further testing shows that any expression other than a
simple unsized constant is accepted there, even if all the operands of
all the operators that make up the expression are unsized integers.
@@ -498,8 +501,14 @@ of 4-value behavior in the dead zone, and appears more user friendly
when viewed by reasonable viewers.
$Id: ieee1364-notes.txt,v 1.17 2003/07/15 03:49:22 steve Exp $
$Id: ieee1364-notes.txt,v 1.19 2007/04/18 02:36:13 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 -4
View File
@@ -17,12 +17,12 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: iverilog-vpi.sh,v 1.16 2006/09/26 18:54:42 steve Exp $"
#ident "$Id: iverilog-vpi.sh,v 1.17 2007/02/06 05:07:31 steve Exp $"
# These are the variables used for compiling files
CC=gcc
CXX=g++
CFLAGS="@PIC@ -O -I@INCLUDEDIR@"
CC=@IVCC@
CXX=@IVCXX@
CFLAGS="@PIC@ @IVCFLAGS@ -I@INCLUDEDIR@"
# These are used for linking...
LD=gcc
+15 -11
View File
@@ -29,7 +29,6 @@ ivl_expr_bits
ivl_expr_def
ivl_expr_dvalue
ivl_expr_event
ivl_expr_memory
ivl_expr_name
ivl_expr_opcode
ivl_expr_oper1
@@ -62,6 +61,7 @@ ivl_logic_type
ivl_logic_udp
ivl_logic_width
ivl_lpm_array
ivl_lpm_aset_value
ivl_lpm_async_clr
ivl_lpm_async_set
@@ -72,7 +72,6 @@ ivl_lpm_data
ivl_lpm_datab
ivl_lpm_define
ivl_lpm_enable
ivl_lpm_memory
ivl_lpm_name
ivl_lpm_q
ivl_lpm_scope
@@ -88,18 +87,11 @@ ivl_lpm_type
ivl_lpm_width
ivl_lval_idx
ivl_lval_mem
ivl_lval_mux
ivl_lval_part_off
ivl_lval_sig
ivl_lval_width
ivl_memory_basename
ivl_memory_root
ivl_memory_scope
ivl_memory_size
ivl_memory_width
ivl_nexus_get_private
ivl_nexus_name
ivl_nexus_ptrs
@@ -117,6 +109,12 @@ 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
@@ -128,8 +126,6 @@ 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
@@ -142,22 +138,30 @@ ivl_scope_time_units
ivl_scope_type
ivl_scope_tname
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_port
ivl_signal_signed
ivl_signal_type
ivl_signal_width
ivl_path_delay
ivl_path_source
ivl_process_attr_cnt
ivl_process_attr_val
ivl_process_scope
+43
View File
@@ -0,0 +1,43 @@
/*
* 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
+144 -252
View File
@@ -19,10 +19,10 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: ivl_target.h,v 1.171 2006/09/23 04:57:19 steve Exp $"
#ident "$Id: ivl_target.h,v 1.182 2007/04/02 01:12:34 steve Exp $"
#endif
# include <stdint.h>
# include <inttypes.h>
#ifdef __cplusplus
#define _BEGIN_DECL extern "C" {
@@ -59,6 +59,10 @@ _BEGIN_DECL
* The following typedefs list the various cookies that may be passed
* around.
*
* ivl_array_t
* This object represent an array that can be a memory or a net
* array. (They are the same from the perspective of ivl_target.h.)
*
* ivl_design_t
* This object represents the entire elaborated design. Various
* global properties and methods are available from this.
@@ -137,6 +141,7 @@ _BEGIN_DECL
* scope. These names are unique within a scope, but not necessarily
* throughout the design.
*/
typedef struct ivl_array_s *ivl_array_t;
typedef struct ivl_delaypath_s*ivl_delaypath_t;
typedef struct ivl_design_s *ivl_design_t;
typedef struct ivl_event_s *ivl_event_t;
@@ -153,7 +158,7 @@ typedef struct ivl_parameter_s*ivl_parameter_t;
typedef struct ivl_process_s *ivl_process_t;
typedef struct ivl_scope_s *ivl_scope_t;
typedef struct ivl_signal_s *ivl_signal_t;
typedef struct ivl_memory_s *ivl_memory_t;
typedef struct ivl_memory_s *ivl_memory_t; /* DEPRECATED */
typedef struct ivl_statement_s*ivl_statement_t;
/*
@@ -178,7 +183,7 @@ typedef enum ivl_drive_e {
and incompatibilities to be introduced. */
typedef enum ivl_expr_type_e {
IVL_EX_NONE = 0,
/* IVL_EX_BITSEL = 1, */
IVL_EX_ARRAY = 18,
IVL_EX_BINARY = 2,
IVL_EX_CONCAT = 3,
IVL_EX_EVENT = 17,
@@ -225,6 +230,7 @@ typedef enum ivl_logic_e {
/* This is the type of an LPM object. */
typedef enum ivl_lpm_type_e {
IVL_LPM_ADD = 0,
IVL_LPM_ARRAY = 30,
IVL_LPM_CONCAT = 16,
IVL_LPM_CMP_EEQ= 18, /* Case EQ (===) */
IVL_LPM_CMP_EQ = 10,
@@ -252,7 +258,7 @@ typedef enum ivl_lpm_type_e {
IVL_LPM_SHIFTR = 7,
IVL_LPM_SIGN_EXT=27,
IVL_LPM_SUB = 8,
IVL_LPM_RAM = 9,
/* IVL_LPM_RAM = 9, / obsolete */
IVL_LPM_UFUNC = 14
} ivl_lpm_type_t;
@@ -381,10 +387,21 @@ typedef const struct ivl_attribute_s*ivl_attribute_t;
* This returns the nexus that is the source end of the delay
* path. Transitions on the source are the start of the delay time
* for this path.
*
* ivl_path_condit
* This returns the nexus that tracks the condition for the
* delay. If the delay path is unconditional, this returns nil.
*
* ivl_path_srouce_posedge
* ivl_path_source_negedge
* These functions return true if the source is edge sensitive.
*/
extern ivl_nexus_t ivl_path_source(ivl_delaypath_t obj);
extern uint64_t ivl_path_delay(ivl_delaypath_t obj, ivl_path_edge_t pt);
extern ivl_nexus_t ivl_path_condit(ivl_delaypath_t obj);
extern int ivl_path_source_posedge(ivl_delaypath_t obj);
extern int ivl_path_source_negedge(ivl_delaypath_t obj);
/* DESIGN
* When handed a design (ivl_design_t) there are a few things that you
@@ -574,6 +591,14 @@ extern ivl_nexus_t ivl_event_pos(ivl_event_t net, unsigned idx);
*
* SEMANTIC NOTES
*
* - IVL_EX_ARRAY
* This expression type is a special case of the IVL_EX_SIGNAL where
* the target is an array (ivl_signal_t with an array_count) but there
* is no index expression. This is used only in the special situation
* where the array is passed to a system task/function. The function
* ivl_expr_signal returns the ivl_signal_t of the array object, and
* from that all the properties of the array can be determined.
*
* - IVL_EX_BINARY
*
* - IVL_EX_SELECT
@@ -583,6 +608,33 @@ extern ivl_nexus_t ivl_event_pos(ivl_event_t net, unsigned idx);
* is the base of a vector. The compiler has already figured out any
* conversion from signal units to vector units, so the result of
* ivl_expr_oper1 should range from 0 to ivl_expr_width().
*
* - IVL_EX_SIGNAL
* This expression references a signal vector. The ivl_expr_signal
* function gets a handle for the signal that is referenced. The
* signal may be an array (see the ivl_signal_array_count function)
* that is addressed by the expression returned by the ivl_expr_oper1
* function. This expression returns a *canonical* address. The core
* compiler already corrected the expression to account for index
* bases.
*
* The ivl_expr_width function returns the vector width of the signal
* word. The ivl_expr_value returns the data type of the word.
*
* Bit and part selects are not done here. The IVL_EX_SELECT
* expression does bit/part selects on the word read from the signal.
*
* - IVL_EX_STRING
* This expression refers to a string constant. The ivl_expr_string
* function returns a pointer to the first byte of the string. The
* compiler has translated it to a "vvp escaped string" which has
* quoting and escapes eliminated. The string may contain octal
* escapes (\<oct>) so that the string text returned by
* ivl_expr_string will only contain graphical characters. It is up to
* the target to change the escaped \NNN to the proper byte value when
* using this string. No other escape sequences will appear in the
* string. Quote (") and slash (\) characters will be delivered in
* \NNN form.
*/
extern ivl_expr_type_t ivl_expr_type(ivl_expr_t net);
@@ -627,42 +679,7 @@ extern unsigned long ivl_expr_uvalue(ivl_expr_t net);
/* any expression */
extern unsigned ivl_expr_width(ivl_expr_t net);
/*
* Memory.
* Memories are declared in Verilog source as 2 dimensional arrays of
* reg bits. This means that they are simple arrays of vectors. The
* vectors in the array are called "words".
*
* ivl_memory_name (DEPRECATED)
*
* ivl_memory_basename
* This returns the base name of the memory object. The base name
* does not include the name of the scopes that contains the object.
*
* ivl_memory_root
* The root of the memory is the value to add to a calculated
* address to get to a canonical (0-based) address. This value is
* used when external code wishes to access a word. All the
* compiled references to the word within the compiled design are
* converted to canonical form by the compiler.
*
* ivl_memory_size
* ivl_memory_width
* These functions return the dimensions of the memory. The size is
* the number of words in the memory, and the width is the number
* of bits in each word.
*
* ivl_memory_scope
* This returns the scope that contains the memory.
*/
extern const char*ivl_memory_basename(ivl_memory_t net);
extern int ivl_memory_root(ivl_memory_t net);
extern ivl_scope_t ivl_memory_scope(ivl_memory_t net);
extern unsigned ivl_memory_size(ivl_memory_t net);
extern unsigned ivl_memory_width(ivl_memory_t net);
extern ivl_memory_t ivl_expr_memory(ivl_expr_t net);
/* LOGIC
* These types and functions support manipulation of logic gates. The
@@ -750,7 +767,7 @@ extern ivl_memory_t ivl_expr_memory(ivl_expr_t net);
* These devices are grouped as logic devices with zero inputs because
* the outputs have the same characteristics as other logic
* devices. They are special only in that they have zero inputs, and
* their drivers typically have strength other then strong.
* their drivers typically have strength other than strong.
*
* - IVL_LO_UDP
* User defined primitives (UDPs) are like any other logic devices, in
@@ -909,7 +926,7 @@ extern const char* ivl_udp_name(ivl_udp_t net);
* inputs. In fact, the compiler doesn't assure that the widths of the
* inputs add up to the width of the output, but the possibility
* exists. It is *not* an error for the sum of the input widths to be
* more then the width of the output, although the possibility of
* more than the width of the output, although the possibility of
* overflow exists at run time.
*
* Multiply may be signed. If so, the output should be sign extended
@@ -975,7 +992,7 @@ extern const char* ivl_udp_name(ivl_udp_t net);
* single ivl_lpm_data input are the same with, ivl_lpm_width. This
* device carries a vector like other LPM devices.
*
* - Memory port (IVL_LPM_RAM)
* - Memory port (IVL_LPM_RAM) (deprecated in favor of IVL_LPM_ARRAY)
* These are structural ports into a memory device. They represent
* address/data ports of a memory device that the context can hook to
* for read or write. Read devices have an ivl_lpm_q output port that
@@ -1069,34 +1086,33 @@ extern ivl_expr_t ivl_lpm_aset_value(ivl_lpm_t net);
extern ivl_nexus_t ivl_lpm_sync_clr(ivl_lpm_t net);
extern ivl_nexus_t ivl_lpm_sync_set(ivl_lpm_t net);
extern ivl_expr_t ivl_lpm_sset_value(ivl_lpm_t net);
/* IVL_LPM_ARRAY */
extern ivl_signal_t ivl_lpm_array(ivl_lpm_t net);
/* IVL_LPM_PART */
extern unsigned ivl_lpm_base(ivl_lpm_t net);
/* IVL_LPM_FF IVL_LPM_RAM */
/* IVL_LPM_FF */
extern ivl_nexus_t ivl_lpm_clk(ivl_lpm_t net);
/* IVL_LPM_UFUNC */
extern ivl_scope_t ivl_lpm_define(ivl_lpm_t net);
/* IVL_LPM_FF IVL_LPM_RAM */
/* IVL_LPM_FF */
extern ivl_nexus_t ivl_lpm_enable(ivl_lpm_t net);
/* IVL_LPM_ADD IVL_LPM_CONCAT IVL_LPM_FF IVL_LPM_PART IVL_LPM_MULT
IVL_LPM_MUX IVL_LPM_RAM IVL_LPM_SHIFTL IVL_LPM_SHIFTR IVL_LPM_SUB
IVL_LPM_MUX IVL_LPM_SHIFTL IVL_LPM_SHIFTR IVL_LPM_SUB
IVL_LPM_UFUNC */
extern ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx);
/* IVL_LPM_ADD IVL_LPM_MULT IVL_LPM_SUB */
extern ivl_nexus_t ivl_lpm_datab(ivl_lpm_t net, unsigned idx);
/* IVL_LPM_ADD IVL_LPM_FF IVL_LPM_MULT IVL_LPM_PART IVL_LPM_RAM
/* IVL_LPM_ADD IVL_LPM_FF IVL_LPM_MULT IVL_LPM_PART
IVL_LPM_SUB IVL_LPM_UFUNC */
extern ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx);
/* IVL_LPM_MUX IVL_LPM_RAM */
/* IVL_LPM_MUX */
extern unsigned ivl_lpm_selects(ivl_lpm_t net);
/* IVL_LPM_MUX IVL_LPM_RAM */
/* IVL_LPM_MUX */
extern ivl_nexus_t ivl_lpm_select(ivl_lpm_t net);
/* IVL_LPM_CONCAT IVL_LPM_MUX IVL_LPM_REPEAT IVL_LPM_UFUNC */
extern unsigned ivl_lpm_size(ivl_lpm_t net);
/* IVL_LPM_SFUNC */
extern const char*ivl_lpm_string(ivl_lpm_t net);
/* IVL_LPM_RAM */
extern ivl_memory_t ivl_lpm_memory(ivl_lpm_t net);
/* LVAL
* The l-values of assignments are concatenation of ivl_lval_t
@@ -1119,7 +1135,7 @@ extern ivl_memory_t ivl_lpm_memory(ivl_lpm_t net);
*
* (Should this be combined with ivl_lval_idx? -Ed)
*
* ivl_lval_mem
* ivl_lval_mem (deprecated)
* If the l-value is a memory, this method returns an
* ivl_memory_t that represents that memory. Otherwise, it
* returns 0.
@@ -1149,18 +1165,26 @@ extern ivl_memory_t ivl_lpm_memory(ivl_lpm_t net);
* The ivl_lval_part_off is the canonical base of a part or
* bit select.
*
* - Memory words
* - Memory words (Replace this with Array words below)
* If the l-value is a memory word, the ivl_lval_mem function returns
* a non-nil value. The ivl_lval_idx function will return an
* expression that calculates an address for the memory. The compiler
* will assure that the ivl_lval_width will exactly match the
* ivl_memory_width of the memory word.
*
* - Array words
* If the l-value is an array, then ivl_lval_idx function will return
* an expression that calculates the address of the array word. If
* the referenced signal has more than one word, this expression must
* be present. If the signal has exactly one word (it is not an array)
* then the ivl_lval_idx exression must *not* be present.
*
* For array words, the ivl_lval_width is the width of the word.
*/
extern unsigned ivl_lval_width(ivl_lval_t net);
extern ivl_expr_t ivl_lval_mux(ivl_lval_t net); // XXXX Obsolete?
extern ivl_expr_t ivl_lval_idx(ivl_lval_t net);
extern ivl_memory_t ivl_lval_mem(ivl_lval_t net);
extern ivl_expr_t ivl_lval_part_off(ivl_lval_t net);
extern ivl_signal_t ivl_lval_sig(ivl_lval_t net);
@@ -1320,7 +1344,7 @@ extern ivl_expr_t ivl_parameter_expr(ivl_parameter_t net);
* ivl_scope_children
* A scope may in turn contain other scopes. This method iterates
* through all the child scopes of a given scope. If the function
* returns any value other then 0, the iteration stops and the
* returns any value other than 0, the iteration stops and the
* method returns that value. Otherwise, iteration continues until
* the children run out.
*
@@ -1329,7 +1353,9 @@ extern ivl_expr_t ivl_parameter_expr(ivl_parameter_t net);
*
* ivl_scope_def
* Task definition scopes carry a task definition, in the form of
* a statement. This method accesses that definition.
* a statement. This method accesses that definition. The
* ivl_scope_def function must return a statement for scopes that
* are type FUNCTION or TASK, and must return nil otherwise.
*
* ivl_scope_event
* ivl_scope_events
@@ -1407,8 +1433,6 @@ extern unsigned ivl_scope_logs(ivl_scope_t net);
extern ivl_net_logic_t ivl_scope_log(ivl_scope_t net, unsigned idx);
extern unsigned ivl_scope_lpms(ivl_scope_t net);
extern ivl_lpm_t ivl_scope_lpm(ivl_scope_t, unsigned idx);
extern unsigned ivl_scope_mems(ivl_scope_t net);
extern ivl_memory_t ivl_scope_mem(ivl_scope_t net, unsigned idx);
extern const char* ivl_scope_name(ivl_scope_t net);
extern const char* ivl_scope_basename(ivl_scope_t net);
extern unsigned ivl_scope_params(ivl_scope_t net);
@@ -1432,17 +1456,26 @@ extern int ivl_scope_time_units(ivl_scope_t net);
* Signals have a name (obviously) and types. A signal may also be
* signed or unsigned.
*
* ivl_signal_pins (replace these with ivl_signal_nex)
* ivl_signal_pin
* The ivl_signal_pin function returns the nexus connected to the
* signal. If the signal is a vector, the idx can be a non-zero
* value, and the result is the nexus for the specified bit.
*
* ivl_signal_nex
* This is the nexus of the signal. This is used for managing
* connections to the rest of the net. There is exactly one pin for
* a signal. If the signal represents a vector, then the entire
* vector is carried through the single output.
* each word of a signal. Each word may in turn be a vector. The
* word address is the zero-based index for the word. It is up to
* the context to translate different bases to the canonical address.
*
* ivl_signal_array_base
* ivl_signal_array_count
* The signal may be arrayed. If so, the array_count is >1. Each
* word of the array has its own nexus. The array_base is the
* address is the Verilg source for the canonical zero word. This
* may be negative, positive or zero.
*
* Note that arraying of the signal into words is distinct from the
* vectors. The width of a signal is the width of a WORD.
*
* ivl_signal_dimensions
* The signal may be an array (of vectors) in which case this
* function returns >0, the number of dimensions of the array.
*
* ivl_signal_msb
* ivl_signal_lsb
@@ -1503,7 +1536,10 @@ extern int ivl_scope_time_units(ivl_scope_t net);
* key does not exist, the function returns 0.
*/
extern ivl_nexus_t ivl_signal_nex(ivl_signal_t net);
extern ivl_nexus_t ivl_signal_nex(ivl_signal_t net, unsigned word);
extern int ivl_signal_array_base(ivl_signal_t net);
extern unsigned ivl_signal_array_count(ivl_signal_t net);
extern unsigned ivl_signal_dimensions(ivl_signal_t net);
extern int ivl_signal_msb(ivl_signal_t net);
extern int ivl_signal_lsb(ivl_signal_t net);
extern unsigned ivl_signal_width(ivl_signal_t net);
@@ -1568,7 +1604,7 @@ extern ivl_statement_type_t ivl_statement_type(ivl_statement_t net);
/*
* The following functions retrieve specific single values from the
* statement. These values are the bits of data and parameters that
* make up the statement. Many of these functions apply to more then
* make up the statement. Many of these functions apply to more than
* one type of statement, so the comment in front of them tells which
* statement types can be passed to the function.
*
@@ -1587,7 +1623,7 @@ extern ivl_statement_type_t ivl_statement_type(ivl_statement_t net);
* ivl_stmt_lval
* ivl_stmt_lvals
* Return the number of l-values for an assignment statement, or
* the specific l-value. If there is more then 1 l-value, then the
* the specific l-value. If there is more than 1 l-value, then the
* l-values are presumed to be vector values concatenated together
* from msb (idx==0) to lsb.
*
@@ -1634,8 +1670,8 @@ extern ivl_statement_type_t ivl_statement_type(ivl_statement_t net);
* - IVL_ST_DELAY, IVL_ST_DELAYX
* These statement types are delay statements. They are a way to
* attach a delay to a statement. The ivl_stmt_sub_stmt() function
* gets the statment to be executed after the delay. If this an
* ivl_ST_DELAY, then the ivl_stmt_delay_val function gets the
* gets the statement to be executed after the delay. If this is
* IVL_ST_DELAY, then the ivl_stmt_delay_val function gets the
* constant delay. If this is IVL_ST_DELAYX, then the
* ivl_stmt_delay_expr gets the expression of the delay. In this case,
* the expression is not necessarily constant.
@@ -1706,10 +1742,6 @@ extern unsigned ivl_stmt_lvals(ivl_statement_t net);
extern unsigned ivl_stmt_lwidth(ivl_statement_t net);
/* IVL_ST_STASK */
extern const char* ivl_stmt_name(ivl_statement_t net);
#if 0
extern ivl_nexus_t ivl_stmt_nexus(ivl_statement_t net, unsigned idx);
extern unsigned ivl_stmt_nexus_count(ivl_statement_t net);
#endif
/* IVL_ST_STASK */
extern ivl_expr_t ivl_stmt_parm(ivl_statement_t net, unsigned idx);
/* IVL_ST_STASK */
@@ -1752,6 +1784,42 @@ _END_DECL
/*
* $Log: ivl_target.h,v $
* Revision 1.182 2007/04/02 01:12:34 steve
* Seperate arrayness from word count
*
* Revision 1.181 2007/03/22 16:08:16 steve
* Spelling fixes from Larry
*
* Revision 1.180 2007/03/02 06:13:22 steve
* Add support for edge sensitive spec paths.
*
* Revision 1.179 2007/03/01 06:19:38 steve
* Add support for conditional specify delay paths.
*
* Revision 1.178 2007/02/26 19:49:49 steve
* Spelling fixes (larry doolittle)
*
* Revision 1.177 2007/02/25 23:08:24 steve
* Process Verilog escape sequences much earlier.
*
* Revision 1.176 2007/02/02 04:33:00 steve
* Use inttypes.h instead of stdint.h for portability.
*
* Revision 1.175 2007/01/29 01:52:51 steve
* Clarify the use of ivl_scope_def for not-functions.
*
* Revision 1.174 2007/01/17 05:00:12 steve
* Dead code for memories in scopes.
*
* Revision 1.173 2007/01/17 04:39:18 steve
* Remove dead code related to memories.
*
* Revision 1.172 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.171 2006/09/23 04:57:19 steve
* Basic support for specify timing.
*
@@ -1781,181 +1849,5 @@ _END_DECL
*
* Revision 1.162 2005/11/20 15:58:25 steve
* Document the IVL_ST_DELAY statements.
*
* Revision 1.161 2005/09/19 21:45:35 steve
* Spelling patches from Larry.
*
* Revision 1.160 2005/09/01 04:11:37 steve
* Generate code to handle real valued muxes.
*
* Revision 1.159 2005/08/06 17:58:16 steve
* Implement bi-directional part selects.
*
* Revision 1.158 2005/07/11 16:56:50 steve
* Remove NetVariable and ivl_variable_t structures.
*
* Revision 1.157 2005/07/07 16:22:49 steve
* Generalize signals to carry types.
*
* Revision 1.156 2005/06/13 22:25:37 steve
* Document ivl_logic_delay function.
*
* Revision 1.155 2005/05/24 01:44:28 steve
* Do sign extension of structuran nets.
*
* Revision 1.154 2005/05/08 23:44:08 steve
* Add support for variable part select.
*
* Revision 1.153 2005/05/07 03:14:00 steve
* Clarify internal delays for assignments.
*
* Revision 1.152 2005/04/24 23:44:02 steve
* Update DFF support to new data flow.
*
* Revision 1.151 2005/04/13 06:35:11 steve
* Make logic aware of strength.
*
* Revision 1.150 2005/04/08 04:52:31 steve
* Make clear that memory addresses are cannonical.
*
* Revision 1.149 2005/04/06 05:29:08 steve
* Rework NetRamDq and IVL_LPM_RAM nodes.
*
* Revision 1.148 2005/04/01 06:04:30 steve
* Clean up handle of UDPs.
*
* Revision 1.147 2005/03/18 02:56:03 steve
* Add support for LPM_UFUNC user defined functions.
*
* Revision 1.146 2005/03/09 04:53:40 steve
* Generate code for new form of memory ports.
*
* Revision 1.145 2005/03/05 05:47:42 steve
* Handle memory words in l-value concatenations.
*
* Revision 1.144 2005/03/03 04:34:42 steve
* Rearrange how memories are supported as vvp_vector4 arrays.
*
* Revision 1.143 2005/02/19 02:43:38 steve
* Support shifts and divide.
*
* Revision 1.142 2005/02/14 01:51:39 steve
* Handle bit selects in l-values to assignments.
*
* Revision 1.141 2005/02/13 01:15:07 steve
* Replace supply nets with wires connected to pullup/down supply devices.
*
* Revision 1.140 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.139 2005/02/08 00:12:36 steve
* Add the NetRepeat node, and code generator support.
*
* Revision 1.138 2005/02/03 04:56:20 steve
* laborate reduction gates into LPM_RED_ nodes.
*
* Revision 1.137 2005/01/29 18:46:18 steve
* Netlist boolean expressions generate gate vectors.
*
* Revision 1.136 2005/01/29 16:47:20 steve
* Clarify width of nexus.
*
* Revision 1.135 2005/01/28 05:39:33 steve
* Simplified NetMult and IVL_LPM_MULT.
*
* Revision 1.134 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.133 2005/01/22 17:36:59 steve
* stub dump signed flags of magnitude compare.
*
* Revision 1.132 2005/01/22 01:06:55 steve
* Change case compare from logic to an LPM node.
*
* Revision 1.131 2005/01/09 20:16:01 steve
* Use PartSelect/PV and VP to handle part selects through ports.
*
* Revision 1.130 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.129 2004/12/18 18:56:18 steve
* Add ivl_event_scope, and better document ivl_event_X methods.
*
* Revision 1.128 2004/12/15 17:10:40 steve
* Fixup force statement elaboration.
*
* Revision 1.127 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.126 2004/10/04 01:10:53 steve
* Clean up spurious trailing white space.
*
* Revision 1.125 2004/09/25 01:58:12 steve
* Some commentary on ivl_logic_pin.
*
* Revision 1.124 2003/12/03 02:46:24 steve
* Add support for wait on list of named events.
*
* Revision 1.123 2003/11/08 20:06:21 steve
* Spelling fixes in comments.
*
* Revision 1.122 2003/08/22 23:14:26 steve
* Preserve variable ranges all the way to the vpi.
*
* Revision 1.121 2003/08/15 02:23:52 steve
* Add synthesis support for synchronous reset.
*
* Revision 1.120 2003/07/30 01:13:28 steve
* Add support for triand and trior.
*
* Revision 1.119 2003/06/23 01:25:44 steve
* Module attributes make it al the way to ivl_target.
*
* Revision 1.118 2003/05/14 05:26:41 steve
* Support real expressions in case statements.
*
* Revision 1.117 2003/04/22 04:48:29 steve
* Support event names as expressions elements.
*
* Revision 1.116 2003/04/11 05:18:08 steve
* Handle signed magnitude compare all the
* way through to the vvp code generator.
*
* Revision 1.115 2003/03/10 23:40:53 steve
* Keep parameter constants for the ivl_target API.
*
* Revision 1.114 2003/03/06 01:24:37 steve
* Obsolete the ivl_event_name function.
*
* Revision 1.113 2003/03/06 00:28:41 steve
* All NetObj objects have lex_string base names.
*
* Revision 1.112 2003/02/26 01:29:24 steve
* LPM objects store only their base names.
*
* Revision 1.111 2003/01/30 16:23:07 steve
* Spelling fixes.
*
* Revision 1.110 2003/01/26 21:15:58 steve
* Rework expression parsing and elaboration to
* accommodate real/realtime values and expressions.
*
* Revision 1.109 2002/12/21 00:55:58 steve
* The $time system task returns the integer time
* scaled to the local units. Change the internal
* implementation of vpiSystemTime the $time functions
* to properly account for this. Also add $simtime
* to get the simulation time.
*/
#endif
+9 -9
View File
@@ -18,7 +18,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.17 2004/10/04 01:10:56 steve Exp $"
#ident "$Id: Makefile.in,v 1.18 2006/10/30 22:45:37 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
all: ivlpp@EXEEXT@
clean:
rm -f *.o lexor.c parse.c parse.h parse.output ivlpp
rm -f *.o lexor.c parse.c parse.h parse.output ivlpp@EXEEXT@
distclean: clean
rm -f Makefile
O = main.o lexor.o parse.o
ivlpp: $O
$(CC) $(LDFLAGS) $O -o ivlpp @EXTRALIBS@
ivlpp@EXEEXT@: $O
$(CC) $(LDFLAGS) $O -o ivlpp@EXEEXT@ @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
install: all installdirs $(libdir)/ivl/ivlpp@EXEEXT@
$(libdir)/ivl/ivlpp: ivlpp
$(INSTALL_PROGRAM) ./ivlpp $(libdir)/ivl/ivlpp
$(libdir)/ivl/ivlpp@EXEEXT@: ivlpp@EXEEXT@
$(INSTALL_PROGRAM) ./ivlpp@EXEEXT@ $(libdir)/ivl/ivlpp@EXEEXT@
installdirs: ../mkinstalldirs
$(srcdir)/../mkinstalldirs $(libdir)/ivl
uninstall:
rm -f $(libdir)/ivl/ivlpp
rm -f $(libdir)/ivl/ivlpp@EXEEXT@
lexor.o: lexor.c parse.h globals.h
main.o: main.c globals.h
+74 -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: lexor.lex,v 1.46 2004/09/10 00:15:45 steve Exp $"
#ident "$Id: lexor.lex,v 1.48 2007/05/30 23:21:20 steve Exp $"
#endif
# include "config.h"
@@ -70,7 +70,14 @@ 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;
@@ -111,11 +118,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);
istack->path, istack->lineno+1);
fprintf(stderr, "%s:%u: : "
"This is the odd matched `ifdef.\n",
cur->path, cur->lineno);
cur->path, cur->lineno+1);
}
free(cur->path);
@@ -309,7 +316,24 @@ W [ \t\b\f]+
yy_push_state(IFDEF_SUPR);
}
<IFDEF_TRUE>`else { BEGIN(IFDEF_FALSE); }
<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_FALSE>`else { BEGIN(IFDEF_TRUE); }
<IFDEF_SUPR>`else { }
@@ -322,6 +346,42 @@ 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(); }
@@ -759,7 +819,7 @@ static void lexor_done()
ifdef_stack = cur->next;
fprintf(stderr, "%s:%u: error: This `ifdef lacks an `endif.\n",
cur->path, cur->lineno);
cur->path, cur->lineno+1);
free(cur->path);
free(cur);
@@ -777,11 +837,14 @@ 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) {
fclose(isp->file);
/* Delay the close of this file, because the yyrestart
below seems to have some memory of this file. */
delayed_close = isp->file;
free(isp->path);
} else {
/* If I am printing line directives and I just finished
@@ -825,6 +888,7 @@ static int yywrap()
}
yyrestart(istack->file);
if (delayed_close) fclose(delayed_close);
return 0;
}
@@ -833,6 +897,7 @@ 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",
@@ -854,6 +919,7 @@ void reset_lexor(FILE*out, char*paths[])
isp->path = strdup(paths[0]);
isp->file = fopen(paths[0], "r");
isp->str = 0;
isp->lineno = 0;
if (isp->file == 0) {
perror(paths[0]);
exit(1);
@@ -876,8 +942,10 @@ void reset_lexor(FILE*out, char*paths[])
for (idx = 1 ; paths[idx] ; idx += 1) {
isp = malloc(sizeof(struct include_stack_t));
isp->path = strdup(paths[idx]);
isp->file = 0;
isp->str = 0;
isp->next = 0;
isp->lineno = 0;
if (tail)
tail->next = isp;
else
+31 -6
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.92 2006/07/31 03:50:17 steve Exp $"
#ident "$Id: lexor.lex,v 1.96 2007/06/14 03:50:00 steve Exp $"
#endif
# include "config.h"
@@ -53,6 +53,7 @@ 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;
@@ -72,6 +73,13 @@ 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;
}
@@ -101,6 +109,7 @@ static int comment_enter;
%s UDPTABLE
%x PPTIMESCALE
%x PPDEFAULT_NETTYPE
%s EDGES
W [ \t\b\f\r]+
@@ -159,11 +168,12 @@ W [ \t\b\f\r]+
with "*" and return that. */
"("{W}*"*"{W}*")" { return '*'; }
<EDGES>"]" { BEGIN(0); return yytext[0]; }
[}{;:\[\],()#=.@&!?<>%|^~+*/-] { return yytext[0]; }
\" { BEGIN(CSTRING); }
<CSTRING>\\\" { yymore(); }
<CSTRING>\\\\ { yymore(); /* Catch \\, which is a \ escaping itself */ }
<CSTRING>\\\" { yymore(); /* Catch \", which is an escaped quote */ }
<CSTRING>\n { BEGIN(0);
yylval.text = strdup(yytext);
VLerror(yylloc, "Missing close quote of string.");
@@ -201,6 +211,17 @@ 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) {
@@ -221,6 +242,10 @@ W [ \t\b\f\r]+
}
break;
case K_edge:
BEGIN(EDGES);
break;
default:
yylval.text = 0;
break;
@@ -460,7 +485,7 @@ static verinum*make_unsized_binary(const char*txt)
ptr += 1;
}
verinum*out = new verinum(bits, size);
verinum*out = new verinum(bits, size, false);
out->has_sign(sign_flag);
delete[]bits;
return out;
@@ -520,7 +545,7 @@ static verinum*make_unsized_octal(const char*txt)
ptr += 1;
}
verinum*out = new verinum(bits, size);
verinum*out = new verinum(bits, size, false);
out->has_sign(sign_flag);
delete[]bits;
return out;
@@ -590,7 +615,7 @@ static verinum*make_unsized_hex(const char*txt)
ptr += 1;
}
verinum*out = new verinum(bits, size);
verinum*out = new verinum(bits, size, false);
out->has_sign(sign_flag);
delete[]bits;
return out;
+2 -3
View File
@@ -16,7 +16,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.34 2004/10/04 01:10:07 steve Exp $"
#ident "$Id: Makefile.in,v 1.36 2007/02/06 05:07:32 steve Exp $"
#
#
SHELL = /bin/sh
@@ -41,7 +41,6 @@ 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 \
@@ -92,7 +91,7 @@ clean:
rm -rf *.o dep libveriuser.a libveriuser.o bin32
distclean: clean
rm -f Makefile config.status config.log config.cache
rm -f Makefile config.status config.log config.cache config.h
install:: all installdirs $(libdir64)/libveriuser.a $(INSTALL32)
+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: a_next.c,v 1.3 2003/06/17 16:55:07 steve Exp $"
#ident "$Id: a_next.c,v 1.4 2006/10/30 22:45:37 steve Exp $"
#endif
#include <stdio.h>
@@ -34,7 +34,7 @@ handle acc_next(PLI_INT32 *type, handle scope, handle prev)
/* trace */
if (pli_trace) {
int *ip;
PLI_INT32 *ip;
fprintf(pli_trace, "acc_next(%p <", type);
for (ip = type; *ip; ip++) {
fprintf(pli_trace, "%s%d", ip != type ? "," : "", *ip);
@@ -94,6 +94,9 @@ 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
+1 -1
View File
@@ -23,7 +23,7 @@ AC_CHECK_SIZEOF(unsigned)
# may modify CPPFLAGS and CFLAGS
AX_CPP_PRECOMP
# Compiler option for position independent code, needed whan making shared objects.
# Compiler option for position independent code, needed when making shared objects.
AX_C_PICFLAG
AC_SUBST(EXEEXT)
+16 -10
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.15 2004/09/10 23:13:05 steve Exp $"
#ident "$Id: veriusertfs.c,v 1.17 2007/05/08 22:01:26 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 int compiletf(char *);
static int calltf(char *);
static int callback(p_cb_data);
static PLI_INT32 compiletf(char *);
static PLI_INT32 calltf(char *);
static PLI_INT32 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;
char trace_buf[1024];
static 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 int compiletf(char *data)
static PLI_INT32 compiletf(char *data)
{
p_pli_data pli;
p_tfcell tf;
@@ -221,7 +221,7 @@ static int compiletf(char *data)
/*
* This function is the wrapper for the veriusertfs calltf routine.
*/
static int calltf(char *data)
static PLI_INT32 calltf(char *data)
{
int rc = 0;
p_pli_data pli;
@@ -249,13 +249,13 @@ static int calltf(char *data)
*/
extern int async_misctf_enable;
static int callback(p_cb_data data)
static PLI_INT32 callback(p_cb_data data)
{
p_pli_data pli;
p_tfcell tf;
int reason;
int paramvc = 0;
int rc;
PLI_INT32 rc;
/* not enabled */
if (data->reason == cbValueChange && !async_misctf_enable)
@@ -389,6 +389,12 @@ 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.
*
+16 -1
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.17 2004/10/04 01:10:53 steve Exp $"
#ident "$Id: link_const.cc,v 1.18 2007/04/14 03:10:51 steve Exp $"
#endif
# include "config.h"
@@ -132,6 +132,8 @@ 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;
@@ -140,6 +142,16 @@ 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;
}
}
}
@@ -164,6 +176,9 @@ 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.
*
+40 -6
View File
@@ -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.93 2006/09/28 04:35:18 steve Exp $"
#ident "$Id: main.cc,v 1.95 2007/04/19 02:52:53 steve Exp $"
#endif
# include "config.h"
@@ -94,6 +94,7 @@ 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;
@@ -125,6 +126,8 @@ bool debug_synth2 = false;
*/
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.
@@ -277,6 +280,15 @@ static void parm_to_flagmap(const string&flag)
* 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.
*
@@ -367,6 +379,13 @@ 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);
@@ -634,11 +653,20 @@ int main(int argc, char*argv[])
for (mod = pform_modules.begin()
; mod != pform_modules.end()
; mod++) {
if (mentioned_p[(*mod).second->mod_name()] == false) {
if (verbose_flag)
cout << " " << (*mod).second->mod_name();
roots.push_back((*mod).second->mod_name());
}
/* 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 (verbose_flag)
cout << endl;
@@ -787,6 +815,12 @@ 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.94 2007/03/07 04:24:59 steve
* Make integer width controllable.
*
* Revision 1.93 2006/09/28 04:35:18 steve
* Support selective control of specify and xtypes features.
*
+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 then the compiler.
developer tools other than the compiler.
Download the msys-1.x.x.exe and msysdtc-1.x.x.exe binaries. These are
self-installing packages. Install msys first, and then msysDTC. Most
+17 -27
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.21 2006/02/02 02:43:58 steve Exp $"
#ident "$Id: net_assign.cc,v 1.22 2007/01/16 05:44:15 steve Exp $"
#endif
# include "config.h"
@@ -39,20 +39,13 @@ unsigned count_lval_width(const NetAssign_*idx)
}
NetAssign_::NetAssign_(NetNet*s)
: sig_(s), mem_(0), bmux_(0), base_(0)
: sig_(s), word_(0), base_(0)
{
lwid_ = sig_->vector_width();
sig_->incr_lref();
more = 0;
}
NetAssign_::NetAssign_(NetMemory*s)
: sig_(0), mem_(s), bmux_(0), base_(0)
{
lwid_ = mem_->width();
more = 0;
}
NetAssign_::~NetAssign_()
{
if (sig_) {
@@ -62,23 +55,23 @@ NetAssign_::~NetAssign_()
}
assert( more == 0 );
if (bmux_) delete bmux_;
if (word_) delete word_;
}
void NetAssign_::set_bmux(NetExpr*r)
void NetAssign_::set_word(NetExpr*r)
{
assert(bmux_ == 0);
bmux_ = r;
assert(word_ == 0);
word_ = r;
}
NetExpr* NetAssign_::bmux()
NetExpr* NetAssign_::word()
{
return bmux_;
return word_;
}
const NetExpr* NetAssign_::bmux() const
const NetExpr* NetAssign_::word() const
{
return bmux_;
return word_;
}
const NetExpr* NetAssign_::get_base() const
@@ -88,17 +81,13 @@ const NetExpr* NetAssign_::get_base() const
unsigned NetAssign_::lwidth() const
{
if (mem_) return lwid_;
else if (bmux_) return 1;
else return lwid_;
return lwid_;
}
perm_string NetAssign_::name() const
{
if (sig_) {
return sig_->name();
} else if (mem_) {
return mem_->name();
} else {
return perm_string::literal("");
}
@@ -109,11 +98,6 @@ NetNet* NetAssign_::sig() const
return sig_;
}
NetMemory* NetAssign_::mem() const
{
return mem_;
}
void NetAssign_::set_part(NetExpr*base, unsigned wid)
{
base_ = base;
@@ -275,6 +259,12 @@ 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.21 2006/02/02 02:43:58 steve
* Allow part selects of memory words in l-values.
*
+70 -64
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.50 2006/08/08 05:11:37 steve Exp $"
#ident "$Id: net_design.cc,v 1.54 2007/06/05 04:18:09 steve Exp $"
#endif
# include "config.h"
@@ -32,6 +32,7 @@
# include "netlist.h"
# include "util.h"
# include "compiler.h"
# include "netmisc.h"
# include <sstream>
Design:: Design()
@@ -84,7 +85,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, root, NetScope::MODULE);
root_scope_ = new NetScope(0, hname_t(root), NetScope::MODULE);
/* This relies on the fact that the basename return value is
permallocated. */
root_scope_->set_module_name(root_scope_->basename());
@@ -114,26 +115,27 @@ 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 hname_t&path) const
NetScope* Design::find_scope(const std::list<hname_t>&path) const
{
if (path.peek_name(0) == 0)
if (path.empty())
return 0;
for (list<NetScope*>::const_iterator scope = root_scopes_.begin()
; scope != root_scopes_.end(); scope++) {
NetScope*cur = *scope;
if (strcmp(path.peek_name(0), cur->basename()) != 0)
if (path.front() != cur->fullname())
continue;
unsigned hidx = 1;
while (cur) {
const char*name = path.peek_name(hidx);
if (name == 0)
return cur;
std::list<hname_t> tmp = path;
tmp.pop_front();
cur = cur->child(name);
hidx += 1;
while (cur) {
if (tmp.empty()) return cur;
cur = cur->child( tmp.front() );
tmp.pop_front();
}
}
@@ -143,28 +145,34 @@ NetScope* Design::find_scope(const hname_t&path) const
/*
* This is a relative lookup of a scope by name. The starting point is
* the scope parameter is the place within which I start looking for
* the scope. If I do not find the scope within the passed scope,
* start looking in parent scopes until I find it, or I run out of
* parent scopes.
* 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.
*/
NetScope* Design::find_scope(NetScope*scope, const hname_t&path) const
NetScope* Design::find_scope(NetScope*scope, const std::list<hname_t>&path) const
{
assert(scope);
if (path.peek_name(0) == 0)
if (path.empty())
return scope;
for ( ; scope ; scope = scope->parent()) {
unsigned hidx = 0;
const char*key = path.peek_name(hidx);
std::list<hname_t> tmp = path;
NetScope*cur = scope;
do {
cur = cur->child(key);
if (cur == 0) break;
hidx += 1;
key = path.peek_name(hidx);
} while (key);
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());
if (cur) return cur;
}
@@ -196,18 +204,19 @@ void NetScope::run_defparams(Design*des)
}
}
map<hname_t,NetExpr*>::const_iterator pp;
map<pform_name_t,NetExpr*>::const_iterator pp;
for (pp = defparams.begin() ; pp != defparams.end() ; pp ++ ) {
NetExpr*val = (*pp).second;
hname_t path = (*pp).first;
pform_name_t path = (*pp).first;
char*tmp = path.remove_tail_name();
perm_string perm_name = lex_strings.make(tmp);
delete[]tmp;
perm_string perm_name = peek_tail_name(path);
path.pop_back();
list<hname_t> eval_path = eval_scope_path(des, this, path);
/* If there is no path on the name, then the targ_scope
is the current scope. */
NetScope*targ_scope = des->find_scope(this, path);
NetScope*targ_scope = des->find_scope(this, eval_path);
if (targ_scope == 0) {
cerr << val->get_line() << ": warning: scope of " <<
path << "." << perm_name << " not found." << endl;
@@ -218,7 +227,7 @@ void NetScope::run_defparams(Design*des)
if (! flag) {
cerr << val->get_line() << ": warning: parameter "
<< perm_name << " not found in "
<< targ_scope->name() << "." << endl;
<< scope_path(targ_scope) << "." << endl;
}
}
@@ -425,68 +434,52 @@ 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, hname_t path)
NetNet* Design::find_signal(NetScope*scope, pform_name_t path)
{
assert(scope);
char*key = path.remove_tail_name();
if (path.peek_name(0))
scope = find_scope(scope, path);
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);
}
while (scope) {
if (NetNet*net = scope->find_signal(key)) {
delete key;
if (NetNet*net = scope->find_signal(key))
return net;
}
if (scope->type() == NetScope::MODULE)
break;
scope = scope->parent();
}
delete key;
return 0;
}
NetFuncDef* Design::find_function(NetScope*scope, const hname_t&name)
NetFuncDef* Design::find_function(NetScope*scope, const pform_name_t&name)
{
assert(scope);
NetScope*func = find_scope(scope, name);
std::list<hname_t> eval_path = eval_scope_path(this, scope, name);
NetScope*func = find_scope(scope, eval_path);
if (func && (func->type() == NetScope::FUNC))
return func->func_def();
return 0;
}
NetFuncDef* Design::find_function(const hname_t&key)
NetScope* Design::find_task(NetScope*scope, const pform_name_t&name)
{
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);
std::list<hname_t> eval_path = eval_scope_path(this, scope, name);
NetScope*task = find_scope(scope, eval_path);
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);
@@ -562,6 +555,19 @@ 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.
*
+6 -3
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.26 2004/10/04 01:10:54 steve Exp $"
#ident "$Id: net_event.cc,v 1.27 2007/06/02 03:42:13 steve Exp $"
#endif
# include "config.h"
@@ -56,10 +56,10 @@ perm_string NetEvent::name() const
return name_;
}
string NetEvent::full_name() const
NetScope* NetEvent::scope()
{
assert(scope_);
return scope_->name() + "." + string(name_);
return scope_;
}
const NetScope* NetEvent::scope() const
@@ -449,6 +449,9 @@ 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.
*
+10 -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: net_func.cc,v 1.8 2006/06/18 04:15:50 steve Exp $"
#ident "$Id: net_func.cc,v 1.10 2007/06/02 03:42:13 steve Exp $"
#endif
# include "config.h"
@@ -95,14 +95,14 @@ bool PECallFunction::check_call_matches_definition_(Design*des, NetScope*dscope)
if (dscope->type() != NetScope::FUNC) {
cerr << get_line() << ": error: Attempt to call scope "
<< dscope->name() << " as a function." << endl;
<< scope_path(dscope) << " as a function." << endl;
des->errors += 1;
return false;
}
if (parms_count != dscope->func_def()->port_count()) {
cerr << get_line() << ": error: Function " << dscope->name()
<< " expects " << (dscope->func_def()->port_count()-1)
cerr << get_line() << ": error: Function " << scope_path(dscope)
<< " expects " << (dscope->func_def()->port_count())
<< " arguments, you passed " << parms_count << "."
<< endl;
des->errors += 1;
@@ -149,6 +149,12 @@ unsigned NetSysFunc::vector_width() const
/*
* $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.
*
+11 -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: net_link.cc,v 1.19 2006/02/02 02:43:58 steve Exp $"
#ident "$Id: net_link.cc,v 1.21 2007/06/02 03:42:13 steve Exp $"
#endif
# include "config.h"
@@ -304,14 +304,14 @@ const Link* Nexus::first_nlink() const
return list_;
}
void* Nexus::t_cookie() const
ivl_nexus_t Nexus::t_cookie() const
{
return t_cookie_;
}
void* Nexus::t_cookie(void*val)const
ivl_nexus_t Nexus::t_cookie(ivl_nexus_t val)const
{
void*tmp = t_cookie_;
ivl_nexus_t tmp = t_cookie_;
t_cookie_ = val;
return tmp;
}
@@ -391,7 +391,7 @@ const char* Nexus::name() const
}
assert(sig);
ostringstream tmp;
tmp << sig->scope()->name() << "." << sig->name();
tmp << scope_path(sig->scope()) << "." << sig->name();
if (sig->pin_count() > 1)
tmp << "<" << pin << ">";
@@ -525,6 +525,12 @@ 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.20 2007/03/26 18:17:50 steve
* Remove pretense of general use for t_cookie.
*
* Revision 1.19 2006/02/02 02:43:58 steve
* Allow part selects of memory words in l-values.
*
+9 -9
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.15 2006/04/16 00:15:43 steve Exp $"
#ident "$Id: net_nex_input.cc,v 1.16 2007/01/16 05:44:15 steve Exp $"
#endif
# include "config.h"
@@ -78,12 +78,6 @@ 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.
@@ -171,8 +165,8 @@ NexusSet* NetEUnary::nex_input()
NexusSet* NetAssign_::nex_input()
{
NexusSet*result = new NexusSet;
if (bmux_) {
NexusSet*tmp = bmux_->nex_input();
if (word_) {
NexusSet*tmp = word_->nex_input();
result->add(*tmp);
delete tmp;
}
@@ -393,6 +387,12 @@ 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.
*
+20 -1
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.12 2005/02/14 04:58:50 steve Exp $"
#ident "$Id: net_nex_output.cc,v 1.14 2007/04/17 04:34:23 steve Exp $"
#endif
# include "config.h"
@@ -77,6 +77,10 @@ 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);
}
@@ -111,6 +115,15 @@ 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)
@@ -119,6 +132,12 @@ 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.13 2007/04/05 01:53:52 steve
* Probe of case statement inputs can skip nul statements.
*
* Revision 1.12 2005/02/14 04:58:50 steve
* l-value input may be a vector.
*
+21 -83
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_scope.cc,v 1.35 2005/11/27 05:56:20 steve Exp $"
#ident "$Id: net_scope.cc,v 1.38 2007/06/02 03:42:13 steve Exp $"
#endif
# include "config.h"
@@ -35,10 +35,9 @@
* in question.
*/
NetScope::NetScope(NetScope*up, perm_string n, NetScope::TYPE t)
NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t)
: type_(t), up_(up), sib_(0), sub_(0)
{
memories_ = 0;
signals_ = 0;
events_ = 0;
lcounter_ = 0;
@@ -242,15 +241,7 @@ NetNet::Type NetScope::default_nettype() const
perm_string NetScope::basename() const
{
return name_;
}
string NetScope::name() const
{
if (up_)
return up_->name() + "." + string(name_);
else
return string(name_);
return name_.peek_name();
}
void NetScope::add_event(NetEvent*ev)
@@ -337,81 +328,16 @@ NetNet* NetScope::find_signal(const char*key)
return 0;
}
/*
* This method searches for the signal within this scope. If the path
* has hierarchy, I follow the child scopes until I get the base name,
* and look for the key in the deepest scope.
*/
NetNet* NetScope::find_signal_in_child(const hname_t&path)
{
NetScope*cur = this;
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));
}
void NetScope::add_memory(NetMemory*mem)
{
if (memories_ == 0) {
mem->snext_ = mem;
mem->sprev_ = mem;
} else {
mem->snext_ = memories_->snext_;
mem->sprev_ = memories_;
mem->snext_->sprev_ = mem;
mem->sprev_->snext_ = mem;
}
memories_ = mem;
mem->scope_ = this;
}
void NetScope::rem_memory(NetMemory*mem)
{
assert(mem->scope_ == this);
if (memories_ == mem)
memories_ = mem->sprev_;
if (memories_ == mem) {
memories_ = 0;
} else {
mem->sprev_->snext_ = mem->snext_;
mem->snext_->sprev_ = mem->sprev_;
}
mem->scope_ = 0;
}
NetMemory* NetScope::find_memory(const string&key)
{
if (memories_ == 0)
return 0;
NetMemory*cur = memories_;
do {
if (cur->name() == key.c_str())
return cur;
cur = cur->sprev_;
} while (cur != memories_);
return 0;
}
/*
* This method locates a child scope by name. The name is the simple
* name of the child, no hierarchy is searched.
*/
NetScope* NetScope::child(const char*name)
NetScope* NetScope::child(const hname_t&name)
{
if (sub_ == 0) return 0;
NetScope*cur = sub_;
while (strcmp(cur->name_, name) != 0) {
while (cur->name_ != name) {
if (cur->sib_ == 0) return 0;
cur = cur->sib_;
}
@@ -419,12 +345,12 @@ NetScope* NetScope::child(const char*name)
return cur;
}
const NetScope* NetScope::child(const char*name) const
const NetScope* NetScope::child(const hname_t&name) const
{
if (sub_ == 0) return 0;
NetScope*cur = sub_;
while (strcmp(cur->name_, name) != 0) {
while (cur->name_ != name) {
if (cur->sib_ == 0) return 0;
cur = cur->sib_;
}
@@ -448,15 +374,27 @@ perm_string NetScope::local_symbol()
res << "_s" << (lcounter_++);
return lex_strings.make(res.str());
}
#if 0
string NetScope::local_hsymbol()
{
return string(name()) + "." + string(local_symbol());
}
#endif
/*
* $Log: net_scope.cc,v $
* Revision 1.38 2007/06/02 03:42:13 steve
* Properly evaluate scope path expressions.
*
* Revision 1.37 2007/04/26 03:06:22 steve
* Rework hname_t to use perm_strings.
*
* Revision 1.36 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.35 2005/11/27 05:56:20 steve
* Handle bit select of parameter with ranges.
*
+306 -277
View File
@@ -17,18 +17,18 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: netlist.cc,v 1.249 2006/09/23 04:57:19 steve Exp $"
#ident "$Id: netlist.cc,v 1.258 2007/06/02 03:42:13 steve Exp $"
#endif
# include "config.h"
# include <iostream>
# include <cassert>
# include <typeinfo>
# include "compiler.h"
# include "netlist.h"
# include "netmisc.h"
# include "ivl_assert.h"
ostream& operator<< (ostream&o, NetNet::Type t)
@@ -237,13 +237,23 @@ NetBus::~NetBus()
{
}
NetDelaySrc::NetDelaySrc(NetScope*s, perm_string n, unsigned npins)
: NetObj(s, n, npins)
NetDelaySrc::NetDelaySrc(NetScope*s, perm_string n,
unsigned npins, bool condit_src)
: NetObj(s, n, npins + (condit_src?1:0))
{
condit_flag_ = false;
posedge_ = false;
negedge_ = false;
for (unsigned idx = 0 ; idx < npins ; idx += 1) {
pin(idx).set_name(perm_string::literal("I"), idx);
pin(idx).set_dir(Link::INPUT);
}
if (condit_src) {
condit_flag_ = true;
pin(npins).set_name(perm_string::literal("COND"), 0);
pin(npins).set_dir(Link::INPUT);
}
}
NetDelaySrc::~NetDelaySrc()
@@ -330,10 +340,67 @@ uint64_t NetDelaySrc::get_delay(unsigned idx) const
return transition_delays_[idx];
}
void NetDelaySrc::set_posedge()
{
posedge_ = true;
}
void NetDelaySrc::set_negedge()
{
negedge_ = true;
}
bool NetDelaySrc::is_posedge() const
{
return posedge_;
}
bool NetDelaySrc::is_negedge() const
{
return negedge_;
}
unsigned NetDelaySrc::src_count() const
{
if (condit_flag_)
return pin_count() - 1;
else
return pin_count();
}
Link& NetDelaySrc::src_pin(unsigned idx)
{
ivl_assert(*this, idx < src_count());
return pin(idx);
}
const Link& NetDelaySrc::src_pin(unsigned idx) const
{
ivl_assert(*this, idx < src_count());
return pin(idx);
}
bool NetDelaySrc::is_condit() const
{
return condit_flag_;
}
Link& NetDelaySrc::condit_pin()
{
ivl_assert(*this, condit_flag_);
return pin(pin_count()-1);
}
const Link& NetDelaySrc::condit_pin() const
{
ivl_assert(*this, condit_flag_);
return pin(pin_count()-1);
}
NetNet::NetNet(NetScope*s, perm_string n, Type t, unsigned npins)
: NetObj(s, n, 1), sig_next_(0), sig_prev_(0),
type_(t), port_type_(NOT_A_PORT), data_type_(IVL_VT_NO_TYPE),
signed_(false), msb_(npins-1), lsb_(0),
signed_(false), msb_(npins-1), lsb_(0), dimensions_(0), s0_(0), e0_(0),
local_flag_(false), eref_count_(0), lref_count_(0)
{
assert(s);
@@ -367,11 +434,12 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t, unsigned npins)
s->add_signal(this);
}
NetNet::NetNet(NetScope*s, perm_string n, Type t, long ms, long ls)
NetNet::NetNet(NetScope*s, perm_string n, Type t,
long ms, long ls)
: NetObj(s, n, 1),
sig_next_(0), sig_prev_(0), type_(t),
port_type_(NOT_A_PORT), data_type_(IVL_VT_NO_TYPE), signed_(false),
msb_(ms), lsb_(ls),
msb_(ms), lsb_(ls), dimensions_(0), s0_(0), e0_(0),
local_flag_(false), eref_count_(0), lref_count_(0)
{
assert(s);
@@ -397,9 +465,59 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t, long ms, long ls)
break;
}
pin(0).set_name(perm_string::literal("P"), 0);
pin(0).set_dir(dir);
pin(0).set_init(init_value);
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
pin(idx).set_name(perm_string::literal("P"), idx);
pin(idx).set_dir(dir);
pin(idx).set_init(init_value);
}
s->add_signal(this);
}
static unsigned calculate_count(long s, long e)
{
if (s >= e)
return s - e + 1;
else
return e - s + 1;
}
NetNet::NetNet(NetScope*s, perm_string n, Type t,
long ms, long ls, long array_s, long array_e)
: NetObj(s, n, calculate_count(array_s, array_e)),
sig_next_(0), sig_prev_(0), type_(t),
port_type_(NOT_A_PORT), data_type_(IVL_VT_NO_TYPE), signed_(false),
msb_(ms), lsb_(ls), dimensions_(1), s0_(array_s), e0_(array_e),
local_flag_(false), eref_count_(0), lref_count_(0)
{
assert(s);
verinum::V init_value = verinum::Vz;
Link::DIR dir = Link::PASSIVE;
switch (t) {
case REG:
case IMPLICIT_REG:
init_value = verinum::Vx;
dir = Link::OUTPUT;
break;
case SUPPLY0:
init_value = verinum::V0;
dir = Link::OUTPUT;
break;
case SUPPLY1:
init_value = verinum::V1;
dir = Link::OUTPUT;
break;
default:
break;
}
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
pin(idx).set_name(perm_string::literal("P"), idx);
pin(idx).set_dir(dir);
pin(idx).set_init(init_value);
}
s->add_signal(this);
}
@@ -533,6 +651,41 @@ unsigned NetNet::sb_to_idx(long sb) const
return lsb_ - sb;
}
unsigned NetNet::array_dimensions() const
{
return dimensions_;
}
long NetNet::array_first() const
{
if (s0_ < e0_)
return s0_;
else
return e0_;
}
unsigned NetNet::array_count() const
{
return calculate_count(s0_, e0_);
}
bool NetNet::array_index_is_valid(long sb) const
{
if (sb < s0_ && sb < e0_)
return false;
if (sb > e0_ && sb > s0_)
return false;
return true;
}
unsigned NetNet::array_index_to_address(long sb) const
{
if (s0_ <= e0_)
return sb - s0_;
else
return sb - e0_;
}
void NetNet::incr_eref()
{
eref_count_ += 1;
@@ -973,6 +1126,55 @@ const Link& NetAddSub::pin_Result() const
return pin(8);
}
NetArrayDq::NetArrayDq(NetScope*s, perm_string n, NetNet*mem, unsigned awid)
: NetNode(s, n, 2),
mem_(mem), awidth_(awid)
{
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("Address"), 0);
}
NetArrayDq::~NetArrayDq()
{
}
unsigned NetArrayDq::width() const
{
return mem_->vector_width();
}
unsigned NetArrayDq::awidth() const
{
return awidth_;
}
const NetNet* NetArrayDq::mem() const
{
return mem_;
}
Link& NetArrayDq::pin_Result()
{
return pin(0);
}
Link& NetArrayDq::pin_Address()
{
return pin(1);
}
const Link& NetArrayDq::pin_Result() const
{
return pin(0);
}
const Link& NetArrayDq::pin_Address() const
{
return pin(1);
}
/*
* The pinout for the NetCLShift is:
* 0 -- Result
@@ -1428,190 +1630,6 @@ const Link& NetMux::pin_Data(unsigned s) const
return pin(2+s);
}
NetRamDq::NetRamDq(NetScope*s, perm_string n, NetMemory*mem, unsigned awid)
: NetNode(s, n, 6),
mem_(mem), awidth_(awid)
{
pin(0).set_dir(Link::INPUT);
pin(0).set_name(perm_string::literal("InClock"), 0);
pin(1).set_dir(Link::INPUT);
pin(1).set_name(perm_string::literal("OutClock"), 0);
pin(2).set_dir(Link::INPUT);
pin(2).set_name(perm_string::literal("WE"), 0);
pin(3).set_dir(Link::INPUT);
pin(3).set_name(perm_string::literal("Address"), 0);
pin(4).set_dir(Link::INPUT);
pin(4).set_name(perm_string::literal("Data"), 0);
pin(5).set_dir(Link::OUTPUT);
pin(5).set_name(perm_string::literal("Q"), 0);
next_ = mem_->ram_list_;
mem_->ram_list_ = this;
}
NetRamDq::~NetRamDq()
{
if (mem_->ram_list_ == this) {
mem_->ram_list_ = next_;
} else {
NetRamDq*cur = mem_->ram_list_;
while (cur->next_ != this) {
assert(cur->next_);
cur = cur->next_;
}
assert(cur->next_ == this);
cur->next_ = next_;
}
}
unsigned NetRamDq::width() const
{
return mem_->width();
}
unsigned NetRamDq::awidth() const
{
return awidth_;
}
unsigned NetRamDq::size() const
{
return mem_->count();
}
const NetMemory* NetRamDq::mem() const
{
return mem_;
}
unsigned NetRamDq::count_partners() const
{
unsigned count = 0;
for (NetRamDq*cur = mem_->ram_list_ ; cur ; cur = cur->next_)
count += 1;
return count;
}
void NetRamDq::absorb_partners()
{
NetRamDq*cur, *tmp;
for (cur = mem_->ram_list_, tmp = 0
; cur||tmp ; cur = cur? cur->next_ : tmp) {
tmp = 0;
if (cur == this) continue;
bool ok_flag = true;
ok_flag &= pin_Address().is_linked(cur->pin_Address());
if (!ok_flag) continue;
if (pin_InClock().is_linked()
&& cur->pin_InClock().is_linked()
&& ! pin_InClock().is_linked(cur->pin_InClock()))
continue;
if (pin_OutClock().is_linked()
&& cur->pin_OutClock().is_linked()
&& ! pin_OutClock().is_linked(cur->pin_OutClock()))
continue;
if (pin_WE().is_linked()
&& cur->pin_WE().is_linked()
&& ! pin_WE().is_linked(cur->pin_WE()))
continue;
if (pin_Data().is_linked() && cur->pin_Data().is_linked()) {
ok_flag &= pin_Data().is_linked(cur->pin_Data());
}
if (! ok_flag) continue;
if (pin_Q().is_linked() && cur->pin_Q().is_linked()) {
ok_flag &= pin_Q().is_linked(cur->pin_Q());
}
if (! ok_flag) continue;
// I see no other reason to reject cur, so link up all
// my pins and delete it.
connect(pin_InClock(), cur->pin_InClock());
connect(pin_OutClock(), cur->pin_OutClock());
connect(pin_WE(), cur->pin_WE());
connect(pin_Address(), cur->pin_Address());
connect(pin_Data(), cur->pin_Data());
connect(pin_Q(), cur->pin_Q());
tmp = cur->next_;
delete cur;
cur = 0;
}
}
Link& NetRamDq::pin_InClock()
{
return pin(0);
}
const Link& NetRamDq::pin_InClock() const
{
return pin(0);
}
Link& NetRamDq::pin_OutClock()
{
return pin(1);
}
const Link& NetRamDq::pin_OutClock() const
{
return pin(1);
}
Link& NetRamDq::pin_WE()
{
return pin(2);
}
const Link& NetRamDq::pin_WE() const
{
return pin(2);
}
Link& NetRamDq::pin_Address()
{
return pin(3);
}
const Link& NetRamDq::pin_Address() const
{
return pin(3);
}
Link& NetRamDq::pin_Data()
{
return pin(4);
}
const Link& NetRamDq::pin_Data() const
{
return pin(4);
}
Link& NetRamDq::pin_Q()
{
return pin(5);
}
const Link& NetRamDq::pin_Q() const
{
return pin(5);
}
NetSignExtend::NetSignExtend(NetScope*s, perm_string n, unsigned w)
: NetNode(s, n, 2), width_(w)
{
@@ -1752,11 +1770,16 @@ NetFuncDef::NetFuncDef(NetScope*s, NetNet*result, const svector<NetNet*>&po)
NetFuncDef::~NetFuncDef()
{
}
#if 0
const string NetFuncDef::name() const
{
return scope_->name();
}
#endif
const NetScope* NetFuncDef::scope() const
{
return scope_;
}
void NetFuncDef::set_proc(NetProc*st)
{
@@ -1832,12 +1855,12 @@ NetEUFunc::~NetEUFunc()
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1)
delete parms_[idx];
}
#if 0
const string NetEUFunc::name() const
{
return func_->name();
}
#endif
const NetESignal*NetEUFunc::result_sig() const
{
return result_sig_;
@@ -1875,12 +1898,12 @@ NetUTask::NetUTask(NetScope*def)
NetUTask::~NetUTask()
{
}
#if 0
const string NetUTask::name() const
{
return task_->name();
}
#endif
const NetScope* NetUTask::task() const
{
return task_;
@@ -2027,68 +2050,6 @@ const NetScope* NetEConstParam::scope() const
return scope_;
}
NetEMemory::NetEMemory(NetMemory*m, NetExpr*i)
: NetExpr(m->width()), mem_(m), idx_(i)
{
}
NetEMemory::~NetEMemory()
{
}
perm_string NetEMemory::name() const
{
return mem_->name();
}
const NetExpr* NetEMemory::index() const
{
return idx_;
}
NetMemory::NetMemory(NetScope*sc, perm_string n, long w, long s, long e)
: width_(w), idxh_(s), idxl_(e), ram_list_(0), scope_(sc)
{
name_ = n;
scope_->add_memory(this);
}
NetMemory::~NetMemory()
{
assert(scope_);
scope_->rem_memory(this);
}
unsigned NetMemory::count() const
{
if (idxh_ < idxl_)
return idxl_ - idxh_ + 1;
else
return idxh_ - idxl_ + 1;
}
perm_string NetMemory::name() const
{
return name_;
}
long NetMemory::index_to_address(long idx) const
{
if (idxh_ < idxl_)
return idx - idxh_;
else
return idx - idxl_;
}
NetEMemory* NetEMemory::dup_expr() const
{
assert(0);
return 0;
}
NetEEvent::NetEEvent(NetEvent*e)
: event_(e)
{
@@ -2119,25 +2080,20 @@ const NetScope* NetEScope::scope() const
}
NetESignal::NetESignal(NetNet*n)
: NetExpr(n->vector_width()), net_(n)
: NetExpr(n->vector_width()), net_(n), word_(0)
{
net_->incr_eref();
set_line(*n);
cast_signed(net_->get_signed());
}
#if 0
NetESignal::NetESignal(NetNet*n, unsigned m, unsigned l)
: NetExpr(m - l + 1), net_(n)
NetESignal::NetESignal(NetNet*n, NetExpr*w)
: NetExpr(n->vector_width()), net_(n), word_(w)
{
assert(m >= l);
msi_ = m;
lsi_ = l;
net_->incr_eref();
set_line(*n);
cast_signed(net_->get_signed());
}
#endif
NetESignal::~NetESignal()
{
@@ -2149,18 +2105,22 @@ perm_string NetESignal::name() const
return net_->name();
}
unsigned NetESignal::bit_count() const
const NetExpr* NetESignal::word_index() const
{
return word_;
}
unsigned NetESignal::vector_width() const
{
return net_->vector_width();
}
Link& NetESignal::bit(unsigned idx)
const NetNet* NetESignal::sig() const
{
assert(idx <= 0);
return net_->pin(idx);
return net_;
}
const NetNet* NetESignal::sig() const
NetNet* NetESignal::sig()
{
return net_;
}
@@ -2180,6 +2140,12 @@ ivl_variable_type_t NetESignal::expr_type() const
return net_->data_type();
}
/*
* Make a ternary operator from all the sub-expressions. The condition
* expression is self-determined, but the true and false expressions
* should have the same width. NOTE: This matching of the widths really
* has to be done in elaboration.
*/
NetETernary::NetETernary(NetExpr*c, NetExpr*t, NetExpr*f)
: cond_(c), true_val_(t), false_val_(f)
{
@@ -2213,6 +2179,19 @@ const NetExpr* NetETernary::false_expr() const
return false_val_;
}
ivl_variable_type_t NetETernary::expr_type() const
{
ivl_variable_type_t tru = true_val_->expr_type();
ivl_variable_type_t fal = false_val_->expr_type();
if (tru == IVL_VT_LOGIC && fal == IVL_VT_BOOL)
return IVL_VT_LOGIC;
if (tru == IVL_VT_BOOL && fal == IVL_VT_LOGIC)
return IVL_VT_LOGIC;
ivl_assert(*this, tru == fal);
return tru;
}
NetEUnary::NetEUnary(char op, NetExpr*ex)
: NetExpr(ex->expr_width()), op_(op), expr_(ex)
{
@@ -2236,6 +2215,11 @@ NetEUnary::~NetEUnary()
delete expr_;
}
ivl_variable_type_t NetEUnary::expr_type() const
{
return expr_->expr_type();
}
NetEUBits::NetEUBits(char op, NetExpr*ex)
: NetEUnary(op, ex)
{
@@ -2245,6 +2229,11 @@ NetEUBits::~NetEUBits()
{
}
ivl_variable_type_t NetEUBits::expr_type() const
{
return expr_->expr_type();
}
NetEUReduce::NetEUReduce(char op, NetExpr*ex)
: NetEUnary(op, ex)
{
@@ -2255,6 +2244,11 @@ NetEUReduce::~NetEUReduce()
{
}
ivl_variable_type_t NetEUReduce::expr_type() const
{
return expr_->expr_type();
}
NetLogic::NetLogic(NetScope*s, perm_string n, unsigned pins,
TYPE t, unsigned wid)
: NetNode(s, n, pins), type_(t), width_(wid)
@@ -2297,8 +2291,8 @@ unsigned NetUReduce::width() const
return width_;
}
NetTaskDef::NetTaskDef(const string&n, const svector<NetNet*>&po)
: name_(n), proc_(0), ports_(po)
NetTaskDef::NetTaskDef(NetScope*n, const svector<NetNet*>&po)
: scope_(n), proc_(0), ports_(po)
{
}
@@ -2323,11 +2317,16 @@ NetNet* NetTaskDef::port(unsigned idx)
assert(idx < ports_.count());
return ports_[idx];
}
#if 0
const string& NetTaskDef::name() const
{
return name_;
}
#endif
const NetScope* NetTaskDef::scope() const
{
return scope_;
}
const NetProc*NetTaskDef::proc() const
{
@@ -2336,6 +2335,36 @@ const NetProc*NetTaskDef::proc() const
/*
* $Log: netlist.cc,v $
* Revision 1.258 2007/06/02 03:42:13 steve
* Properly evaluate scope path expressions.
*
* Revision 1.257 2007/04/02 01:12:34 steve
* Seperate arrayness from word count
*
* Revision 1.256 2007/03/02 06:13:22 steve
* Add support for edge sensitive spec paths.
*
* Revision 1.255 2007/03/01 06:19:38 steve
* Add support for conditional specify delay paths.
*
* Revision 1.254 2007/02/20 05:58:36 steve
* Handle unary minus of real valued expressions.
*
* Revision 1.253 2007/02/14 05:59:46 steve
* Handle type of ternary expressions properly.
*
* Revision 1.252 2007/01/19 04:25:37 steve
* Fix missing passive setting for array word pins.
*
* Revision 1.251 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.250 2006/11/10 04:54:26 steve
* Add test_width methods for PETernary and PEString.
*
* Revision 1.249 2006/09/23 04:57:19 steve
* Basic support for specify timing.
*
+220 -222
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: netlist.h,v 1.363 2006/10/03 05:06:00 steve Exp $"
#ident "$Id: netlist.h,v 1.380 2007/06/02 03:42:13 steve Exp $"
#endif
/*
@@ -32,8 +32,9 @@
# include <map>
# include <list>
# include <vector>
# include <stdint.h>
# include "ivl_target.h"
# include "pform_types.h"
# include "config.h"
# include "verinum.h"
# include "verireal.h"
# include "StringHeap.h"
@@ -275,8 +276,8 @@ class Nexus {
the value that has been driven. */
verinum::V driven_value() const;
void* t_cookie() const;
void* t_cookie(void*) const;
ivl_nexus_t t_cookie() const;
ivl_nexus_t t_cookie(ivl_nexus_t) const;
private:
Link*list_;
@@ -284,7 +285,7 @@ class Nexus {
void relink(Link*);
mutable char* name_; /* Cache the calculated name for the Nexus. */
mutable void* t_cookie_;
mutable ivl_nexus_t t_cookie_;
enum VALUE { NO_GUESS, V0, V1, Vx, Vz, VAR };
mutable VALUE driven_;
@@ -379,7 +380,8 @@ class NetNode : public NetObj {
class NetDelaySrc : public NetObj {
public:
explicit NetDelaySrc(NetScope*s, perm_string n, unsigned npins);
explicit NetDelaySrc(NetScope*s, perm_string n,
unsigned nsrc, bool condit_src);
~NetDelaySrc();
// These functions set the delays from the values in the
@@ -401,10 +403,26 @@ class NetDelaySrc : public NetObj {
uint64_t get_delay(unsigned pe) const;
void set_posedge();
void set_negedge();
bool is_posedge() const;
bool is_negedge() const;
unsigned src_count() const;
Link&src_pin(unsigned);
const Link&src_pin(unsigned) const;
bool is_condit() const;
Link&condit_pin();
const Link&condit_pin() const;
void dump(ostream&, unsigned ind) const;
private:
uint64_t transition_delays_[12];
bool condit_flag_;
bool posedge_;
bool negedge_;
private: // Not implemented
NetDelaySrc(const NetDelaySrc&);
@@ -447,7 +465,14 @@ class NetNet : public NetObj {
// that passed through.
explicit NetNet(NetScope*s, perm_string n, Type t, unsigned width =1);
explicit NetNet(NetScope*s, perm_string n, Type t, long ms, long ls);
// This form supports an array of vectors. The [ms:ls] define
// the base vector, and the [s0:e0] define the array
// dimensions. If s0==e0, then this is not an array after
// all.
explicit NetNet(NetScope*s, perm_string n, Type t,
long ms, long ls);
explicit NetNet(NetScope*s, perm_string n, Type t,
long ms, long ls, long s0, long e0);
virtual ~NetNet();
@@ -488,6 +513,21 @@ class NetNet : public NetObj {
the pin# from the index. */
bool sb_is_valid(long sb) const;
/* This method returns 0 for scalers and vectors, and greater
for arrays. The value is the number of array
indices. (Currently only one array index is supported.) */
unsigned array_dimensions() const;
long array_first() const;
// This is the number of array elements.
unsigned array_count() const;
// This method returns a 0 based address of an array entry as
// indexed by idx. The Verilog source may give index ranges
// that are not zero based.
bool array_index_is_valid(long idx) const;
unsigned array_index_to_address(long idx) const;
bool local_flag() const { return local_flag_; }
void local_flag(bool f) { local_flag_ = f; }
@@ -524,6 +564,8 @@ class NetNet : public NetObj {
bool isint_; // original type of integer
long msb_, lsb_;
const unsigned dimensions_;
long s0_, e0_;
bool local_flag_;
unsigned eref_count_;
@@ -571,6 +613,37 @@ class NetAddSub : public NetNode {
unsigned width_;
};
/*
* The NetArrayDq node represents an array dereference. The NetNet
* that this object refers to is an array, and the Address pin selects
* which word of the array to place on the Result.
*/
class NetArrayDq : public NetNode {
public:
NetArrayDq(NetScope*s, perm_string name, NetNet*mem, unsigned awid);
~NetArrayDq();
unsigned width() const;
unsigned awidth() const;
unsigned size() const;
const NetNet*mem() const;
Link& pin_Address();
Link& pin_Result();
const Link& pin_Address() const;
const Link& pin_Result() const;
virtual void dump_node(ostream&, unsigned ind) const;
virtual bool emit_node(struct target_t*) const;
private:
NetNet*mem_;
unsigned awidth_;
};
/*
* This type represents the LPM_CLSHIFT device.
*/
@@ -819,62 +892,6 @@ class NetFF : public NetNode {
verinum sset_value_;
};
/*
* This class represents the declared memory object. The parser
* creates one of these for each declared memory in the elaborated
* design. A reference to one of these is handled by the NetEMemory
* object, which is derived from NetExpr. This is not a node because
* memory objects can only be accessed by behavioral code.
*/
class NetMemory {
public:
NetMemory(NetScope*sc, perm_string n, long w, long s, long e);
~NetMemory();
// This is the BASE name of the memory object. It does not
// include scope name, get that from the scope itself.
perm_string name() const;
// This is the width (in bits) of a single memory position.
unsigned width() const { return width_; }
// This is the number of dimensions for the memory. A baseline
// verilog memory has always 1 dimension, but N-dimensional
// arrays have N.
unsigned dimensions() const { return 1; }
const NetScope*scope() const { return scope_; };
// This is the number of memory positions.
unsigned count() const;
// This method returns a 0 based address of a memory entry as
// indexed by idx. The Verilog source may give index ranges
// that are not zero based.
long index_to_address(long idx) const;
void dump(ostream&o, unsigned lm) const;
private:
perm_string name_;
unsigned width_;
long idxh_;
long idxl_;
friend class NetRamDq;
NetRamDq* ram_list_;
friend class NetScope;
NetMemory*snext_, *sprev_;
NetScope*scope_;
private: // not implemented
NetMemory(const NetMemory&);
NetMemory& operator= (const NetMemory&);
};
/*
* This class implements a basic LPM_MULT combinational multiplier. It
* is used as a structural representation of the * operator. The
@@ -965,57 +982,6 @@ class NetMux : public NetNode {
unsigned swidth_;
};
/*
* This device represents an LPM_RAM_DQ device. The actual content is
* represented by a NetMemory object allocated elsewhere, but that
* object fixes the width and size of the device. The pin count of the
* address input is given in the constructor.
*/
class NetRamDq : public NetNode {
public:
NetRamDq(NetScope*s, perm_string name, NetMemory*mem, unsigned awid);
~NetRamDq();
unsigned width() const;
unsigned awidth() const;
unsigned size() const;
const NetMemory*mem() const;
Link& pin_InClock();
Link& pin_OutClock();
Link& pin_WE();
Link& pin_Address();
Link& pin_Data();
Link& pin_Q();
const Link& pin_InClock() const;
const Link& pin_OutClock() const;
const Link& pin_WE() const;
const Link& pin_Address() const;
const Link& pin_Data() const;
const Link& pin_Q() const;
virtual void dump_node(ostream&, unsigned ind) const;
virtual bool emit_node(struct target_t*) const;
// Use this method to absorb other NetRamDq objects that are
// connected to the same memory, and have compatible pin
// connections.
void absorb_partners();
// Use this method to count the partners (including myself)
// that are ports to the attached memory.
unsigned count_partners() const;
private:
NetMemory*mem_;
NetRamDq*next_;
unsigned awidth_;
};
/*
* The NetReplicate node takes a vector input and makes it into a larger
@@ -1154,7 +1120,10 @@ class NetExpr : public LineInfo {
// equivalent expression that is reduced as far as compile
// time knows how. Essentially, this is designed to fold
// constants.
virtual NetExpr*eval_tree();
//
// The prune_to_width is the maximum width that the result
// should be. If it is -1, then do not prune the result.
virtual NetExpr*eval_tree(int prune_to_width = -1);
// Make a duplicate of myself, and subexpressions if I have
// any. This is a deep copy operation.
@@ -1565,7 +1534,7 @@ class NetUReduce : public NetNode {
* N -- (1x)
*
* It also takes one of the following glob letters to represent more
* then one item.
* than one item.
*
* p -- 01, 0x or x1 // check this with the lexer
* n -- 10, 1x or x0 // check this with the lexer
@@ -1578,7 +1547,7 @@ class NetUReduce : public NetNode {
* SEQUENTIAL
* These objects have a single bit of memory. The logic table includes
* an entry for the current value, and allows edges on the inputs. In
* canonical form, inly then entries that generate 0, 1 or - (no change)
* canonical form, only the entries that generate 0, 1 or - (no change)
* are listed.
*
* COMBINATIONAL
@@ -1710,20 +1679,18 @@ class NetAssign_ {
public:
NetAssign_(NetNet*sig);
NetAssign_(NetMemory*mem);
~NetAssign_();
// If this expression exists, then only a single bit is to be
// set from the rval, and the value of this expression selects
// the pin that gets the value.
NetExpr*bmux();
const NetExpr*bmux() const;
// If this expression exists, then it is used to select a word
// from an array/memory.
NetExpr*word();
const NetExpr*word() const;
// Get the base index of the part select, or 0 if there is no
// part select.
const NetExpr* get_base() const;
void set_bmux(NetExpr*);
void set_word(NetExpr*);
void set_part(NetExpr* loff, unsigned wid);
// Get the width of the r-value that this node expects. This
@@ -1735,7 +1702,6 @@ class NetAssign_ {
perm_string name() const;
NetNet* sig() const;
NetMemory*mem() const;
// Mark that the synthesizer has worked with this l-value, so
// when it is released, the l-value signal should be turned
@@ -1755,9 +1721,8 @@ class NetAssign_ {
private:
NetNet *sig_;
NetMemory*mem_;
// Memory word index
NetExpr*bmux_;
NetExpr*word_;
bool turn_sig_to_wire_on_release_;
// indexed part select base
@@ -2095,7 +2060,6 @@ class NetEvent : public LineInfo {
~NetEvent();
perm_string name() const;
string full_name() const;
// Get information about probes connected to me.
unsigned nprobe() const;
@@ -2302,8 +2266,9 @@ class NetFuncDef {
void set_proc(NetProc*st);
const string name() const;
//const string name() const;
const NetProc*proc() const;
const NetScope*scope() const;
NetScope*scope();
unsigned port_count() const;
@@ -2441,12 +2406,13 @@ class NetSTask : public NetProc {
class NetTaskDef {
public:
NetTaskDef(const string&n, const svector<NetNet*>&po);
NetTaskDef(NetScope*n, const svector<NetNet*>&po);
~NetTaskDef();
void set_proc(NetProc*p);
const string& name() const;
//const string& name() const;
const NetScope* scope() const;
const NetProc*proc() const;
unsigned port_count() const;
@@ -2455,7 +2421,7 @@ class NetTaskDef {
void dump(ostream&, unsigned) const;
private:
string name_;
NetScope*scope_;
NetProc*proc_;
svector<NetNet*>ports_;
@@ -2472,11 +2438,9 @@ class NetTaskDef {
class NetEUFunc : public NetExpr {
public:
NetEUFunc(NetScope*, NetESignal*, svector<NetExpr*>&);
NetEUFunc(NetScope*, NetESignal*, svector<NetExpr*>&);
~NetEUFunc();
const string name() const;
const NetESignal*result_sig() const;
unsigned parm_count() const;
@@ -2518,6 +2482,7 @@ class NetUTask : public NetProc {
const NetScope* task() const;
virtual NexusSet* nex_input();
virtual void nex_output(NexusSet&);
virtual bool emit_proc(struct target_t*) const;
virtual void dump(ostream&, unsigned ind) const;
@@ -2658,6 +2623,7 @@ class NetEBinary : public NetExpr {
NetExpr* right_;
void eval_sub_tree_();
bool get_real_arguments_(verireal&lv, verireal&rv);
};
/*
@@ -2677,8 +2643,11 @@ class NetEBAdd : public NetEBinary {
virtual bool set_width(unsigned w, bool last_chance);
virtual NetEBAdd* dup_expr() const;
virtual NetEConst* eval_tree();
virtual NetExpr* eval_tree(int prune_to_width = -1);
virtual NetNet* synthesize(Design*);
private:
NetECReal* eval_tree_real_();
};
/*
@@ -2696,7 +2665,7 @@ class NetEBDiv : public NetEBinary {
virtual bool set_width(unsigned w, bool last_chance);
virtual NetEBDiv* dup_expr() const;
virtual NetExpr* eval_tree();
virtual NetExpr* eval_tree(int prune_to_width = -1);
virtual NetNet* synthesize(Design*);
};
@@ -2722,7 +2691,7 @@ class NetEBBits : public NetEBinary {
virtual bool set_width(unsigned w, bool last_chance);
virtual NetEBBits* dup_expr() const;
virtual NetEConst* eval_tree();
virtual NetEConst* eval_tree(int prune_to_width = -1);
virtual NetNet* synthesize(Design*);
};
@@ -2753,7 +2722,7 @@ class NetEBComp : public NetEBinary {
virtual bool has_width() const;
virtual ivl_variable_type_t expr_type() const;
virtual NetEBComp* dup_expr() const;
virtual NetEConst* eval_tree();
virtual NetEConst* eval_tree(int prune_to_width = -1);
virtual NetNet* synthesize(Design*);
@@ -2783,7 +2752,7 @@ class NetEBLogic : public NetEBinary {
virtual bool set_width(unsigned w, bool last_chance);
virtual NetEBLogic* dup_expr() const;
virtual NetEConst* eval_tree();
virtual NetEConst* eval_tree(int prune_to_width = -1);
virtual NetNet* synthesize(Design*);
private:
@@ -2803,7 +2772,7 @@ class NetEBMult : public NetEBinary {
virtual bool set_width(unsigned w, bool last_chance);
virtual NetEBMult* dup_expr() const;
virtual NetExpr* eval_tree();
virtual NetExpr* eval_tree(int prune_to_width = -1);
virtual NetNet* synthesize(Design*);
private:
@@ -2825,7 +2794,7 @@ class NetEBPow : public NetEBinary {
virtual bool set_width(unsigned w, bool last_chance);
virtual NetEBPow* dup_expr() const;
virtual NetExpr* eval_tree();
virtual NetExpr* eval_tree(int prune_to_width = -1);
virtual NetNet* synthesize(Design*);
private:
@@ -2856,7 +2825,7 @@ class NetEBShift : public NetEBinary {
virtual bool has_width() const;
virtual NetEBShift* dup_expr() const;
virtual NetEConst* eval_tree();
virtual NetEConst* eval_tree(int prune_to_width = -1);
virtual NetNet* synthesize(Design*);
@@ -2891,7 +2860,7 @@ class NetEConcat : public NetExpr {
virtual bool has_width() const;
virtual bool set_width(unsigned w, bool last_chance =false);
virtual NetEConcat* dup_expr() const;
virtual NetEConst* eval_tree();
virtual NetEConst* eval_tree(int prune_to_width = -1);
virtual NetNet*synthesize(Design*);
virtual void expr_scan(struct expr_scan_t*) const;
virtual void dump(ostream&) const;
@@ -2923,7 +2892,7 @@ class NetEParam : public NetExpr {
virtual bool set_width(unsigned w, bool last_chance);
virtual bool has_width() const;
virtual void expr_scan(struct expr_scan_t*) const;
virtual NetExpr* eval_tree();
virtual NetExpr* eval_tree(int prune_to_width = -1);
virtual NetEParam* dup_expr() const;
virtual void dump(ostream&) const;
@@ -2962,7 +2931,7 @@ class NetESelect : public NetExpr {
virtual bool set_width(unsigned w, bool last_chance =false);
virtual bool has_width() const;
virtual void expr_scan(struct expr_scan_t*) const;
virtual NetEConst* eval_tree();
virtual NetEConst* eval_tree(int prune_to_width = -1);
virtual NetESelect* dup_expr() const;
virtual NetNet*synthesize(Design*des);
virtual void dump(ostream&) const;
@@ -3072,8 +3041,9 @@ class NetETernary : public NetExpr {
const NetExpr*false_expr() const;
virtual NetETernary* dup_expr() const;
virtual NetExpr* eval_tree();
virtual NetExpr* eval_tree(int prune_to_width = -1);
virtual ivl_variable_type_t expr_type() const;
virtual NexusSet* nex_input();
virtual void expr_scan(struct expr_scan_t*) const;
virtual void dump(ostream&) const;
@@ -3112,8 +3082,9 @@ class NetEUnary : public NetExpr {
virtual bool set_width(unsigned w, bool last_chance);
virtual NetEUnary* dup_expr() const;
virtual NetEConst* eval_tree();
virtual NetEConst* eval_tree(int prune_to_width = -1);
virtual ivl_variable_type_t expr_type() const;
virtual NexusSet* nex_input();
virtual void expr_scan(struct expr_scan_t*) const;
virtual void dump(ostream&) const;
@@ -3133,7 +3104,8 @@ class NetEUBits : public NetEUnary {
virtual NetNet* synthesize(Design*);
virtual NetEConst* eval_tree();
virtual NetEConst* eval_tree(int prune_to_width = -1);
virtual ivl_variable_type_t expr_type() const;
};
class NetEUReduce : public NetEUnary {
@@ -3145,56 +3117,25 @@ class NetEUReduce : public NetEUnary {
virtual bool set_width(unsigned w, bool last_chance);
virtual NetNet* synthesize(Design*);
virtual NetEUReduce* dup_expr() const;
virtual NetEConst* eval_tree();
};
/*
* A reference to a memory is represented by this expression. If the
* index is not supplied, then the node is only valid in certain
* specific contexts.
*/
class NetEMemory : public NetExpr {
public:
NetEMemory(NetMemory*mem, NetExpr*idx =0);
virtual ~NetEMemory();
perm_string name () const;
const NetExpr* index() const;
virtual bool set_width(unsigned, bool last_chance);
virtual NetNet* synthesize(Design*des);
NetExpr* eval_tree();
virtual NetEMemory*dup_expr() const;
virtual NexusSet* nex_input();
virtual void expr_scan(struct expr_scan_t*) const;
virtual void dump(ostream&) const;
const NetMemory*memory() const { return mem_; };
private:
NetMemory*mem_;
NetExpr* idx_;
virtual NetEConst* eval_tree(int prune_to_width = -1);
virtual ivl_variable_type_t expr_type() const;
};
/*
* When a signal shows up in an expression, this type represents
* it. From this the expression can get any kind of access to the
* structural signal.
* structural signal, including arrays.
*
* A signal shows up as a node in the netlist so that structural
* activity can invoke the expression. This node also supports part
* select by indexing a range of the NetNet that is associated with
* it. The msi() is the more significant index, and lsi() the least
* significant index.
* The NetESignal may refer to an array, if the word_index is
* included. This expression calculates the index of the word in the
* array. It may only be nil if the expression refers to the whole
* array, and that is legal only in limited situation.
*/
class NetESignal : public NetExpr {
public:
NetESignal(NetNet*n);
NetESignal(NetNet*n, NetExpr*word_index);
~NetESignal();
perm_string name() const;
@@ -3204,12 +3145,16 @@ class NetESignal : public NetExpr {
NetNet* synthesize(Design*des);
NexusSet* nex_input();
// These methods actually reference the properties of the
// NetNet object that I point to.
unsigned bit_count() const;
Link& bit(unsigned idx);
// This is the expression for selecting an array word, if this
// signal refers to an array.
const NetExpr* word_index() const;
// This is the width of the vector that this signal refers to.
unsigned vector_width() const;
// Point back to the signal that this expression node references.
const NetNet* sig() const;
NetNet* sig();
// Declared vector dimensions for the signal.
unsigned msi() const;
unsigned lsi() const;
@@ -3220,6 +3165,8 @@ class NetESignal : public NetExpr {
private:
NetNet*net_;
// Expression to select a word from the net.
NetExpr*word_;
};
@@ -3235,7 +3182,7 @@ class NetScope : public Attrib {
/* Create a new scope, and attach it to the given parent. The
name is expected to have been permallocated. */
NetScope(NetScope*up, perm_string name, TYPE t);
NetScope(NetScope*up, const hname_t&name, TYPE t);
~NetScope();
/* Parameters exist within a scope, and these methods allow
@@ -3273,26 +3220,14 @@ class NetScope : public Attrib {
void add_signal(NetNet*);
void rem_signal(NetNet*);
NetNet* find_signal(const char*name);
NetNet* find_signal_in_child(const hname_t&name);
/* ... and these methods manage memory the same way as signals
are managed above. */
void add_memory(NetMemory*);
void rem_memory(NetMemory*);
NetMemory* find_memory(const string&name);
/* The parent and child() methods allow users of NetScope
objects to locate nearby scopes. */
NetScope* parent();
NetScope* child(const char*name);
NetScope* child(const hname_t&name);
const NetScope* parent() const;
const NetScope* child(const char*name) const;
const NetScope* child(const hname_t&name) const;
TYPE type() const;
@@ -3331,7 +3266,7 @@ class NetScope : public Attrib {
name, whereas the basename is just my name within my parent
scope. */
perm_string basename() const;
string name() const;
const hname_t& fullname() const { return name_; }
void run_defparams(class Design*);
void evaluate_parameters(class Design*);
@@ -3339,9 +3274,6 @@ class NetScope : public Attrib {
/* This method generates a non-hierarchical name that is
guaranteed to be unique within this scope. */
perm_string local_symbol();
/* This method generates a hierarchical name that is
guaranteed to be unique globally. */
string local_hsymbol();
void dump(ostream&) const;
void emit_scope(struct target_t*tgt) const;
@@ -3356,7 +3288,7 @@ class NetScope : public Attrib {
assignments from the scope pass to the parameter evaluation
step. After that, it is not used. */
map<hname_t,NetExpr*>defparams;
map<pform_name_t,NetExpr*>defparams;
public:
/* After everything is all set up, the code generators like
@@ -3392,15 +3324,13 @@ class NetScope : public Attrib {
private:
TYPE type_;
perm_string name_;
hname_t name_;
signed char time_unit_, time_prec_;
NetNet::Type default_nettype_;
NetEvent *events_;
NetNet *signals_;
NetMemory*memories_;
perm_string module_name_;
union {
NetTaskDef*task_;
@@ -3458,8 +3388,8 @@ class Design {
path is taken as an absolute scope name. Otherwise, the
scope is located starting at the passed scope and working
up if needed. */
NetScope* find_scope(const hname_t&path) const;
NetScope* find_scope(NetScope*, const hname_t&path) const;
NetScope* find_scope(const std::list<hname_t>&path) const;
NetScope* find_scope(NetScope*, const std::list<hname_t>&path) const;
// PARAMETERS
@@ -3471,15 +3401,13 @@ class Design {
this method, unlike the NetScope::find_signal method,
handles global name binding. */
NetNet*find_signal(NetScope*scope, hname_t path);
NetNet*find_signal(NetScope*scope, pform_name_t path);
// Functions
NetFuncDef* find_function(NetScope*scope, const hname_t&key);
NetFuncDef* find_function(const hname_t&path);
NetFuncDef* find_function(NetScope*scope, const pform_name_t&key);
// Tasks
NetScope* find_task(NetScope*scope, const hname_t&name);
NetScope* find_task(const hname_t&key);
NetScope* find_task(NetScope*scope, const pform_name_t&name);
// NODES
void add_node(NetNode*);
@@ -3565,8 +3493,78 @@ inline ostream& operator << (ostream&o, const NetExpr&exp)
extern ostream& operator << (ostream&, NetNet::Type);
/*
* Manipulator to dump a scope complete path to the output. The
* manipulator is "scope_path" and works like this:
*
* out << .... << scope_path(sc) << ... ;
*/
struct __ScopePathManip { const NetScope*scope; };
inline __ScopePathManip scope_path(const NetScope*scope)
{ __ScopePathManip tmp; tmp.scope = scope; return tmp; }
extern ostream& operator << (ostream&o, __ScopePathManip);
/*
* $Log: netlist.h,v $
* Revision 1.380 2007/06/02 03:42:13 steve
* Properly evaluate scope path expressions.
*
* Revision 1.379 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.378 2007/04/26 03:06:22 steve
* Rework hname_t to use perm_strings.
*
* Revision 1.377 2007/04/17 04:34:23 steve
* Fix handling calls to tasks in combinational always block
*
* Revision 1.376 2007/04/07 04:46:18 steve
* Handle evaluate of addition of real valued constants.
*
* Revision 1.375 2007/04/02 01:12:34 steve
* Seperate arrayness from word count
*
* Revision 1.374 2007/03/26 18:17:50 steve
* Remove pretense of general use for t_cookie.
*
* Revision 1.373 2007/03/22 16:08:16 steve
* Spelling fixes from Larry
*
* Revision 1.372 2007/03/08 05:30:03 steve
* Limit the calculated widths of constants.
*
* Revision 1.371 2007/03/02 06:13:22 steve
* Add support for edge sensitive spec paths.
*
* Revision 1.370 2007/03/01 06:19:38 steve
* Add support for conditional specify delay paths.
*
* Revision 1.369 2007/02/20 05:58:36 steve
* Handle unary minus of real valued expressions.
*
* Revision 1.368 2007/02/14 05:59:46 steve
* Handle type of ternary expressions properly.
*
* Revision 1.367 2007/02/02 04:33:00 steve
* Use inttypes.h instead of stdint.h for portability.
*
* Revision 1.366 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.365 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.364 2006/10/30 05:44:49 steve
* Expression widths with unsized literals are pseudo-infinite width.
*
* Revision 1.363 2006/10/03 05:06:00 steve
* Support real valued specify delays, properly scaled.
*
+43 -34
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: netmisc.cc,v 1.12 2006/06/02 04:48:50 steve Exp $"
#ident "$Id: netmisc.cc,v 1.14 2007/06/02 03:42:13 steve Exp $"
#endif
# include "config.h"
@@ -25,6 +25,8 @@
# include "netlist.h"
# include "netmisc.h"
# include "PExpr.h"
# include "pform_types.h"
# include "ivl_assert.h"
NetNet* add_to_net(Design*des, NetNet*sig, long val)
{
@@ -124,13 +126,13 @@ NetExpr* make_sub_expr(long val, NetExpr*expr)
}
NetExpr* elab_and_eval(Design*des, NetScope*scope,
const PExpr*pe, int expr_wid)
const PExpr*pe, int expr_wid, int prune_width)
{
NetExpr*tmp = pe->elaborate_expr(des, scope, expr_wid, false);
if (tmp == 0)
return 0;
if (NetExpr*tmp2 = tmp->eval_tree()) {
if (NetExpr*tmp2 = tmp->eval_tree(prune_width)) {
delete tmp;
tmp = tmp2;
}
@@ -138,9 +140,47 @@ NetExpr* elab_and_eval(Design*des, NetScope*scope,
return tmp;
}
std::list<hname_t> eval_scope_path(Design*des, NetScope*scope,
const pform_name_t&path)
{
list<hname_t> res;
typedef pform_name_t::const_iterator pform_path_it;
for (pform_path_it cur = path.begin() ; cur != path.end(); cur++) {
const name_component_t&comp = *cur;
if (comp.index.empty()) {
res.push_back(hname_t(comp.name));
continue;
}
assert(comp.index.size() == 1);
const index_component_t&index = comp.index.front();
assert(index.sel == index_component_t::SEL_BIT);
NetExpr*tmp = elab_and_eval(des, scope, index.msb, -1);
ivl_assert(*index.msb, tmp);
if (NetEConst*ctmp = dynamic_cast<NetEConst*>(tmp)) {
res.push_back(hname_t(comp.name, ctmp->value().as_long()));
delete ctmp;
continue;
}
return res;
}
return res;
}
/*
* $Log: netmisc.cc,v $
* Revision 1.14 2007/06/02 03:42:13 steve
* Properly evaluate scope path expressions.
*
* Revision 1.13 2007/03/08 05:30:03 steve
* Limit the calculated widths of constants.
*
* Revision 1.12 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
@@ -153,36 +193,5 @@ NetExpr* elab_and_eval(Design*des, NetScope*scope,
* Remove the NetEBitSel and combine all bit/part select
* behavior into the NetESelect node and IVL_EX_SELECT
* ivl_target expression type.
*
* Revision 1.9 2004/12/11 02:31:27 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.8 2004/02/20 18:53:35 steve
* Addtrbute keys are perm_strings.
*
* Revision 1.7 2004/02/18 17:11:57 steve
* Use perm_strings for named langiage items.
*
* Revision 1.6 2003/03/06 00:28:42 steve
* All NetObj objects have lex_string base names.
*
* Revision 1.5 2003/02/26 01:29:24 steve
* LPM objects store only their base names.
*
* Revision 1.4 2002/08/31 03:48:50 steve
* Fix reverse bit ordered bit select in continuous assignment.
*
* Revision 1.3 2002/08/12 01:35:00 steve
* conditional ident string using autoconfig.
*
* Revision 1.2 2001/07/25 03:10:49 steve
* Create a config.h.in file to hold all the config
* junk, and support gcc 3.0. (Stephan Boettcher)
*
* Revision 1.1 2001/02/11 02:15:52 steve
* Add the netmisc.cc source file.
*
*/
+36 -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: netmisc.h,v 1.26 2006/09/28 00:29:49 steve Exp $"
#ident "$Id: netmisc.h,v 1.31 2007/06/02 03:42:13 steve Exp $"
#endif
# include "netlist.h"
@@ -39,23 +39,21 @@
* ex2 is the lsb expression for the range. If there is no range, then
* these values are set to 0.
*/
extern NetScope* symbol_search(const Design*des,
NetScope*start, hname_t path,
extern NetScope* symbol_search(Design*des,
NetScope*start, pform_name_t path,
NetNet*&net, /* net/reg */
NetMemory*&mem, /* memory */
const NetExpr*&par,/* parameter */
NetEvent*&eve, /* named event */
const NetExpr*&ex1, const NetExpr*&ex2);
inline NetScope* symbol_search(const Design*des,
NetScope*start, const hname_t&path,
inline NetScope* symbol_search(Design*des,
NetScope*start, const pform_name_t&path,
NetNet*&net, /* net/reg */
NetMemory*&mem, /* memory */
const NetExpr*&par,/* parameter */
NetEvent*&eve /* named event */)
{
const NetExpr*ex1, *ex2;
return symbol_search(des, start, path, net, mem, par, eve, ex1, ex2);
return symbol_search(des, start, path, net, par, eve, ex1, ex2);
}
/*
@@ -89,7 +87,7 @@ extern NetNet*add_to_net(Design*des, NetNet*sig, long val);
* where order matters.
*
* make_add_expr
* Make a NetEBAdd expresion with <expr> the first argument and
* Make a NetEBAdd expression with <expr> the first argument and
* <val> the second. This may get turned into a subtract if <val> is
* less then zero. If val is exactly zero, then return <expr> as is.
*
@@ -114,14 +112,41 @@ extern unsigned count_lval_width(const class NetAssign_*first);
* it can. If the expression cannot be elaborated, return 0.
*
* The expr_width is the width of the context where the expression is
* being elaborated, or -1 if the expression is self-determinted width.
* being elaborated, or -1 if the expression is self-determined width.
*
* Also, the prune_width is the maximum width of the result, and it
* passed to the eval_tree method of the expression to limit constant
* results if possible.
*/
class PExpr;
extern NetExpr* elab_and_eval(Design*des, NetScope*scope,
const PExpr*pe, int expr_wid);
const PExpr*pe, int expr_wid,
int prune_width =-1);
extern std::list<hname_t> eval_scope_path(Design*des, NetScope*scope,
const pform_name_t&path);
/*
* $Log: netmisc.h,v $
* Revision 1.31 2007/06/02 03:42:13 steve
* Properly evaluate scope path expressions.
*
* Revision 1.30 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.29 2007/03/08 05:30:03 steve
* Limit the calculated widths of constants.
*
* Revision 1.28 2007/02/26 19:49:49 steve
* Spelling fixes (larry doolittle)
*
* Revision 1.27 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.26 2006/09/28 00:29:49 steve
* Allow specparams as constants in expressions.
*
+490 -341
View File
File diff suppressed because it is too large Load Diff
+138 -58
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2004 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-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
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: pform.cc,v 1.137 2006/09/23 04:57:19 steve Exp $"
#ident "$Id: pform.cc,v 1.148 2007/06/12 04:05:45 steve Exp $"
#endif
# include "config.h"
@@ -33,6 +33,7 @@
# include <list>
# include <map>
# include <assert.h>
# include <stack>
# include <typeinfo>
# include <sstream>
@@ -50,6 +51,9 @@ extern int VLparse();
exactly one module currently being parsed, since verilog does not
allow nested module definitions. */
static Module*pform_cur_module = 0;
bool pform_library_flag = false;
/* increment this for generate schemes within a module, and set it
to zero when a new module starts. */
static unsigned scope_generate_counter = 1;
@@ -77,35 +81,34 @@ static unsigned pform_timescale_line = 0;
* and named blocks causes scope to be pushed and popped. The module
* name is not included in this scope stack.
*
* The hier_name function, therefore, converts the name to the scope
* of the module currently in progress.
* The hier_name function, therefore, converts the name to the scoped
* name within the module currently in progress. It never includes an
* instance name.
*
* The scope stack does not include any scope created by a generate
* scheme.
*/
static hname_t scope_stack;
static pform_name_t scope_stack;
void pform_push_scope(char*name)
{
scope_stack.append(name);
scope_stack.push_back(name_component_t(lex_strings.make(name)));
}
void pform_pop_scope()
{
char*tmp = scope_stack.remove_tail_name();
assert(tmp);
free(tmp);
scope_stack.pop_back();
}
static hname_t hier_name(const char*tail)
static pform_name_t hier_name(const char*tail)
{
hname_t name = scope_stack;
name.append(tail);
pform_name_t name = scope_stack;
name.push_back(name_component_t(lex_strings.make(tail)));
return name;
}
static PWire*get_wire_in_module(const hname_t&name)
static PWire*get_wire_in_module(const pform_name_t&name)
{
/* Note that if we are processing a generate, then the
scope depth will be empty because generate schemes
@@ -199,7 +202,7 @@ verinum* pform_verinum_with_size(verinum*siz, verinum*val,
break;
}
verinum*res = new verinum(pad, size);
verinum*res = new verinum(pad, size, true);
unsigned copy = val->len();
if (res->len() < copy)
@@ -242,6 +245,7 @@ void pform_startmodule(const char*name, const char*file, unsigned lineno,
pform_cur_module->set_file(file);
pform_cur_module->set_lineno(lineno);
pform_cur_module->library_flag = pform_library_flag;
/* The generate scheme numbering starts with *1*, not
zero. That's just the way it is, thanks to the standard. */
@@ -274,7 +278,7 @@ Module::port_t* pform_module_port_reference(char*name,
unsigned lineno)
{
Module::port_t*ptmp = new Module::port_t;
PEIdent*tmp = new PEIdent(hname_t(name));
PEIdent*tmp = new PEIdent(lex_strings.make(name));
tmp->set_file(file);
tmp->set_lineno(lineno);
ptmp->name = lex_strings.make(name);
@@ -344,7 +348,7 @@ void pform_start_generate_for(const struct vlltype&li,
gen->set_lineno(li.first_line);
// For now, assume that generates do not nest.
assert(pform_cur_generate == 0);
gen->parent = pform_cur_generate;
pform_cur_generate = gen;
pform_cur_generate->scheme_type = PGenerate::GS_LOOP;
@@ -371,8 +375,13 @@ void pform_endgenerate()
assert(pform_cur_generate != 0);
assert(pform_cur_module);
pform_cur_module->generate_schemes.push_back(pform_cur_generate);
pform_cur_generate = 0;
PGenerate*cur = pform_cur_generate;
pform_cur_generate = cur->parent;
if (pform_cur_generate != 0)
pform_cur_generate->generates.push_back(cur);
else
pform_cur_module->generate_schemes.push_back(cur);
}
bool pform_expression_is_constant(const PExpr*ex)
@@ -508,9 +517,10 @@ void pform_make_udp(perm_string name, list<string>*parms,
map<string,PWire*> defs;
for (unsigned idx = 0 ; idx < decl->count() ; idx += 1) {
hname_t pname = (*decl)[idx]->path();
pform_name_t pname = (*decl)[idx]->path();
string port_name = peek_tail_name(pname).str();
if (PWire*cur = defs[pname.peek_name(0)]) {
if (PWire*cur = defs[port_name]) {
bool rc = true;
assert((*decl)[idx]);
if ((*decl)[idx]->get_port_type() != NetNet::PIMPLICIT) {
@@ -523,7 +533,7 @@ void pform_make_udp(perm_string name, list<string>*parms,
}
} else {
defs[pname.peek_name(0)] = (*decl)[idx];
defs[port_name] = (*decl)[idx];
}
}
@@ -669,7 +679,7 @@ void pform_make_udp(perm_string name, list<string>*parms,
// Make the port list for the UDP
for (unsigned idx = 0 ; idx < pins.count() ; idx += 1)
udp->ports[idx] = pins[idx]->path().peek_name(0);
udp->ports[idx] = peek_tail_name(pins[idx]->path());
process_udp_table(udp, table, file, lineno);
udp->initial = init;
@@ -753,7 +763,7 @@ void pform_make_udp(perm_string name, bool synchronous_flag,
// Make the port list for the UDP
for (unsigned idx = 0 ; idx < pins.count() ; idx += 1)
udp->ports[idx] = pins[idx]->path().peek_name(0);
udp->ports[idx] = peek_tail_name(pins[idx]->path());
assert(udp);
assert(table);
@@ -910,6 +920,14 @@ void pform_makegates(PGBuiltin::Type type,
* constraints, and sometimes different syntax. The X_modgate
* functions handle the instantiations of modules (and UDP objects) by
* making PGModule objects.
*
* The first pform_make_modgate handles the case of a module
* instantiated with ports passed by position. The "wires" is an
* ordered array of port expressions.
*
* The second pform_make_modgate handles the case of a module
* instantiated with ports passed by name. The "bind" argument is the
* ports matched with names.
*/
static void pform_make_modgate(perm_string type,
perm_string name,
@@ -982,7 +1000,11 @@ static void pform_make_modgate(perm_string type,
cur->set_parameters(overrides->by_order);
}
pform_cur_module->add_gate(cur);
if (pform_cur_generate)
pform_cur_generate->add_gate(cur);
else
pform_cur_module->add_gate(cur);
}
void pform_make_modgates(perm_string type,
@@ -1087,7 +1109,7 @@ void pform_make_pgassign_list(svector<PExpr*>*alist,
void pform_make_reginit(const struct vlltype&li,
const char*name, PExpr*expr)
{
const hname_t sname = hier_name(name);
const pform_name_t sname = hier_name(name);
PWire*cur = pform_cur_module->get_wire(sname);
if (cur == 0) {
VLerror(li, "internal error: reginit to non-register?");
@@ -1126,11 +1148,11 @@ void pform_module_define_port(const struct vlltype&li,
svector<PExpr*>*range,
svector<named_pexpr_t*>*attr)
{
hname_t name = hier_name(nm);
pform_name_t name = hier_name(nm);
PWire*cur = pform_cur_module->get_wire(name);
if (cur) {
ostringstream msg;
msg << name << " definition conflicts with "
msg << nm << " definition conflicts with "
<< "definition at " << cur->get_line()
<< ".";
VLerror(msg.str().c_str());
@@ -1193,28 +1215,25 @@ void pform_makewire(const vlltype&li, const char*nm,
ivl_variable_type_t dt,
svector<named_pexpr_t*>*attr)
{
hname_t name = hier_name(nm);
pform_name_t name = hier_name(nm);
PWire*cur = get_wire_in_module(name);
if (cur) {
if ((cur->get_wire_type() != NetNet::IMPLICIT)
&& (cur->get_wire_type() != NetNet::IMPLICIT_REG)) {
// If this is not implicit ("implicit" meaning we don't know
// what the type is yet) then set thay type now.
if (cur && type != NetNet::IMPLICIT) {
bool rc = cur->set_wire_type(type);
if (rc == false) {
ostringstream msg;
msg << name << " previously defined at " <<
cur->get_line() << ".";
msg << nm << " definition conflicts with "
<< "definition at " << cur->get_line()
<< ".";
VLerror(msg.str().c_str());
} else {
bool rc = cur->set_wire_type(type);
if (rc == false) {
ostringstream msg;
msg << name << " definition conflicts with "
<< "definition at " << cur->get_line()
<< ".";
VLerror(msg.str().c_str());
}
cerr << "XXXX type=" << type <<", curtype=" << cur->get_wire_type() << endl;
}
}
if (cur) {
cur->set_file(li.text);
cur->set_lineno(li.first_line);
return;
@@ -1285,10 +1304,11 @@ void pform_makewire(const vlltype&li,
pform_makewire(li, first->name, type, NetNet::NOT_A_PORT, dt, 0);
pform_set_net_range(first->name, range, signed_flag, dt);
hname_t name = hier_name(first->name);
perm_string first_name = lex_strings.make(first->name);
pform_name_t name = hier_name(first_name);
PWire*cur = get_wire_in_module(name);
if (cur != 0) {
PEIdent*lval = new PEIdent(hname_t(first->name));
PEIdent*lval = new PEIdent(first_name);
lval->set_file(li.text);
lval->set_lineno(li.first_line);
PGAssign*ass = pform_make_pgassign(lval, first->expr,
@@ -1306,7 +1326,7 @@ void pform_makewire(const vlltype&li,
void pform_set_port_type(perm_string nm, NetNet::PortType pt,
const char*file, unsigned lineno)
{
hname_t name = hier_name(nm);
pform_name_t name = hier_name(nm);
PWire*cur = pform_cur_module->get_wire(name);
if (cur == 0) {
cur = new PWire(name, NetNet::IMPLICIT, NetNet::PIMPLICIT, IVL_VT_LOGIC);
@@ -1323,14 +1343,14 @@ void pform_set_port_type(perm_string nm, NetNet::PortType pt,
case NetNet::NOT_A_PORT:
cerr << file << ":" << lineno << ": error: "
<< "port " << name << " is not in the port list."
<< "port " << nm << " is not in the port list."
<< endl;
error_count += 1;
break;
default:
cerr << file << ":" << lineno << ": error: "
<< "port " << name << " already has a port declaration."
<< "port " << nm << " already has a port declaration."
<< endl;
error_count += 1;
break;
@@ -1391,7 +1411,7 @@ svector<PWire*>*pform_make_task_ports(NetNet::PortType pt,
; cur != names->end() ; cur ++ ) {
perm_string txt = *cur;
hname_t name = hier_name(txt);
pform_name_t name = hier_name(txt);
/* Look for a preexisting wire. If it exists, set the
port direction. If not, create it. */
@@ -1436,7 +1456,7 @@ void pform_set_function(perm_string name, PFunction*func)
void pform_set_attrib(perm_string name, perm_string key, char*value)
{
hname_t path (name);
pform_name_t path = hier_name(name);
if (PWire*cur = pform_cur_module->get_wire(path)) {
cur->attributes[key] = new PEString(value);
@@ -1529,7 +1549,7 @@ void pform_set_specparam(perm_string name, PExpr*expr)
pform_cur_module->specparams[name] = expr;
}
void pform_set_defparam(const hname_t&name, PExpr*expr)
void pform_set_defparam(const pform_name_t&name, PExpr*expr)
{
assert(expr);
pform_cur_module->defparms[name] = expr;
@@ -1565,8 +1585,23 @@ extern PSpecPath* pform_make_specify_path(const struct vlltype&li,
return path;
}
extern PSpecPath*pform_make_specify_edge_path(const struct vlltype&li,
int edge_flag, /*posedge==true */
list<perm_string>*src, char pol,
bool full_flag, list<perm_string>*dst,
PExpr*data_source_expression)
{
PSpecPath*tmp = pform_make_specify_path(li, src, pol, full_flag, dst);
tmp->edge = edge_flag;
tmp->data_source_expression = data_source_expression;
return tmp;
}
extern PSpecPath* pform_assign_path_delay(PSpecPath*path, svector<PExpr*>*del)
{
if (path == 0)
return 0;
assert(path->delays.size() == 0);
path->delays.resize(del->count());
@@ -1581,6 +1616,8 @@ extern PSpecPath* pform_assign_path_delay(PSpecPath*path, svector<PExpr*>*del)
extern void pform_module_specify_path(PSpecPath*obj)
{
if (obj == 0)
return;
pform_cur_module->specify_paths.push_back(obj);
}
@@ -1606,7 +1643,7 @@ void pform_set_port_type(const struct vlltype&li,
static void pform_set_reg_integer(const char*nm)
{
hname_t name = hier_name(nm);
pform_name_t name = hier_name(nm);
PWire*cur = pform_cur_module->get_wire(name);
if (cur == 0) {
cur = new PWire(name, NetNet::INTEGER,
@@ -1622,8 +1659,8 @@ static void pform_set_reg_integer(const char*nm)
}
assert(cur);
cur->set_range(new PENumber(new verinum(INTEGER_WIDTH-1, INTEGER_WIDTH)),
new PENumber(new verinum((uint64_t)0, INTEGER_WIDTH)));
cur->set_range(new PENumber(new verinum(integer_width-1, integer_width)),
new PENumber(new verinum((uint64_t)0, integer_width)));
cur->set_signed(true);
}
@@ -1640,7 +1677,7 @@ void pform_set_reg_integer(list<perm_string>*names)
static void pform_set_reg_time(const char*nm)
{
hname_t name = hier_name(nm);
pform_name_t name = hier_name(nm);
PWire*cur = pform_cur_module->get_wire(name);
if (cur == 0) {
cur = new PWire(name, NetNet::REG, NetNet::NOT_A_PORT, IVL_VT_LOGIC);
@@ -1653,8 +1690,8 @@ static void pform_set_reg_time(const char*nm)
}
assert(cur);
cur->set_range(new PENumber(new verinum(TIME_WIDTH-1, INTEGER_WIDTH)),
new PENumber(new verinum((uint64_t)0, INTEGER_WIDTH)));
cur->set_range(new PENumber(new verinum(TIME_WIDTH-1, integer_width)),
new PENumber(new verinum((uint64_t)0, integer_width)));
}
void pform_set_reg_time(list<perm_string>*names)
@@ -1677,7 +1714,9 @@ svector<PWire*>* pform_make_udp_input_ports(list<perm_string>*names)
; cur != names->end()
; cur ++ ) {
perm_string txt = *cur;
PWire*pp = new PWire(hname_t(txt),
pform_name_t tmp;
tmp.push_back(name_component_t(txt));
PWire*pp = new PWire(tmp,
NetNet::IMPLICIT,
NetNet::PINPUT,
IVL_VT_LOGIC);
@@ -1702,7 +1741,11 @@ PProcess* pform_make_behavior(PProcess::Type type, Statement*st,
delete attr;
}
pform_cur_module->add_behavior(pp);
if (pform_cur_generate)
pform_cur_generate->add_behavior(pp);
else
pform_cur_module->add_behavior(pp);
return pp;
}
@@ -1747,6 +1790,43 @@ int pform_parse(const char*path, FILE*file)
/*
* $Log: pform.cc,v $
* Revision 1.148 2007/06/12 04:05:45 steve
* Put instantiated modules in the proper generated scope.
*
* Revision 1.147 2007/06/02 03:42:13 steve
* Properly evaluate scope path expressions.
*
* Revision 1.146 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.145 2007/04/26 03:06:22 steve
* Rework hname_t to use perm_strings.
*
* Revision 1.144 2007/04/19 02:52:53 steve
* Add support for -v flag in command file.
*
* Revision 1.143 2007/04/13 02:34:35 steve
* Parse edge sensitive paths without edge specifier.
*
* Revision 1.142 2007/03/07 04:24:59 steve
* Make integer width controllable.
*
* Revision 1.141 2007/03/05 05:59:10 steve
* Handle processes within generate loops.
*
* Revision 1.140 2007/02/12 01:52:21 steve
* Parse all specify paths to pform.
*
* Revision 1.139 2007/01/27 05:36:11 steve
* Fix padding of x when literal is sized and unsigned.
*
* Revision 1.138 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.137 2006/09/23 04:57:19 steve
* Basic support for specify timing.
*
+27 -2
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: pform.h,v 1.87 2006/09/23 04:57:19 steve Exp $"
#ident "$Id: pform.h,v 1.91 2007/05/24 04:07:12 steve Exp $"
#endif
# include "netlist.h"
@@ -69,6 +69,12 @@ extern enum MIN_TYP_MAX { MIN, TYP, MAX } min_typ_max_flag;
extern unsigned min_typ_max_warn;
PExpr* pform_select_mtm_expr(PExpr*min, PExpr*typ, PExpr*max);
/*
* This flag is true if the lexor thinks we are in a library source
* file.
*/
extern bool pform_library_flag;
/*
* These type are lexical types -- that is, types that are used as
* lexical values to decorate the parse tree during parsing. They are
@@ -255,7 +261,7 @@ extern void pform_set_localparam(perm_string name,
bool signed_flag,
svector<PExpr*>*range,
PExpr*expr);
extern void pform_set_defparam(const hname_t&name, PExpr*expr);
extern void pform_set_defparam(const pform_name_t&name, PExpr*expr);
/*
* Functions related to specify blocks.
@@ -265,7 +271,13 @@ extern void pform_set_specparam(perm_string name, PExpr*expr);
extern PSpecPath*pform_make_specify_path(const struct vlltype&li,
list<perm_string>*src, char pol,
bool full_flag, list<perm_string>*dst);
extern PSpecPath*pform_make_specify_edge_path(const struct vlltype&li,
int edge_flag, /*posedge==true */
list<perm_string>*src, char pol,
bool full_flag, list<perm_string>*dst,
PExpr*data_source_expression);
extern PSpecPath*pform_assign_path_delay(PSpecPath*obj, svector<PExpr*>*delays);
extern void pform_module_specify_path(PSpecPath*obj);
/*
@@ -328,6 +340,19 @@ extern void pform_dump(ostream&out, Module*mod);
/*
* $Log: pform.h,v $
* Revision 1.91 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.90 2007/04/19 02:52:53 steve
* Add support for -v flag in command file.
*
* Revision 1.89 2007/04/13 02:34:35 steve
* Parse edge sensitive paths without edge specifier.
*
* Revision 1.88 2007/02/12 01:52:21 steve
* Parse all specify paths to pform.
*
* Revision 1.87 2006/09/23 04:57:19 steve
* Basic support for specify timing.
*
+121 -33
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: pform_dump.cc,v 1.94 2006/09/23 04:57:19 steve Exp $"
#ident "$Id: pform_dump.cc,v 1.101 2007/06/04 02:19:07 steve Exp $"
#endif
# include "config.h"
@@ -72,6 +72,65 @@ ostream& operator<< (ostream&o, PGate::strength_t str)
return o;
}
ostream& operator<< (ostream&out, perm_string that)
{
out << that.str();
return out;
}
ostream& operator<< (ostream&out, const index_component_t&that)
{
out << "[";
switch (that.sel) {
case index_component_t::SEL_BIT:
out << *that.msb;
break;
case index_component_t::SEL_PART:
out << *that.msb << ":" << *that.lsb;
break;
case index_component_t::SEL_IDX_UP:
out << *that.msb << "+:" << *that.lsb;
break;
case index_component_t::SEL_IDX_DO:
out << *that.msb << "-:" << *that.lsb;
break;
default:
out << "???";
break;
}
out << "]";
return out;
}
ostream& operator<< (ostream&out, const name_component_t&that)
{
out << that.name.str();
typedef std::list<index_component_t>::const_iterator index_it_t;
for (index_it_t idx = that.index.begin()
; idx != that.index.end() ; idx++) {
out << *idx;
}
return out;
}
ostream& operator<< (ostream&o, const pform_name_t&that)
{
pform_name_t::const_iterator cur;
cur = that.begin();
o << *cur;
cur++;
while (cur != that.end()) {
o << "." << *cur;
cur++;
}
return o;
}
void PExpr::dump(ostream&out) const
{
out << typeid(*this).name();
@@ -145,29 +204,6 @@ void PENumber::dump(ostream&out) const
void PEIdent::dump(ostream&out) const
{
out << path_;
if (msb_) {
out << "[" << *msb_;
if (lsb_) switch (sel_) {
case SEL_IDX_UP:
out << "+:" << *lsb_;
break;
case SEL_IDX_DO:
out << "-:" << *lsb_;
break;
case SEL_PART:
out << ":" << *lsb_;
break;
default:
out << ":?:" << *lsb_;
break;
}
out << "]";
}
typedef std::vector<PExpr*>::const_iterator vector_it_t;
for (vector_it_t cur = idx_.begin() ; cur != idx_.end() ; cur++) {
out << "[" << *(*cur) << "]";
}
}
void PEString::dump(ostream&out) const
@@ -629,6 +665,9 @@ void PFunction::dump(ostream&out, unsigned ind) const
case PTF_REG:
out << "reg ";
break;
case PTF_REG_S:
out << "reg_s ";
break;
case PTF_INTEGER:
out << "integer ";
break;
@@ -742,7 +781,18 @@ void PProcess::dump(ostream&out, unsigned ind) const
void PSpecPath::dump(std::ostream&out, unsigned ind) const
{
out << setw(ind) << "" << "specify path (";
out << setw(ind) << "" << "specify path ";
if (condition)
out << "if (" << *condition << ") ";
out << "(";
if (edge) {
if (edge > 0)
out << "posedge ";
else
out << "negedge ";
}
for (unsigned idx = 0 ; idx < src.size() ; idx += 1) {
if (idx > 0) out << ", ";
@@ -752,12 +802,18 @@ void PSpecPath::dump(std::ostream&out, unsigned ind) const
out << " => ";
if (data_source_expression)
out << "(";
for (unsigned idx = 0 ; idx < dst.size() ; idx += 1) {
if (idx > 0) out << ", ";
assert(dst[idx]);
out << dst[idx];
}
if (data_source_expression)
out << " : " << *data_source_expression << ")";
out << ") = (";
for (unsigned idx = 0 ; idx < delays.size() ; idx += 1) {
if (idx > 0) out << ", ";
@@ -767,9 +823,9 @@ void PSpecPath::dump(std::ostream&out, unsigned ind) const
out << ");" << endl;
}
void PGenerate::dump(ostream&out) const
void PGenerate::dump(ostream&out, unsigned indent) const
{
out << " generate(" << id_number << ")";
out << setw(indent) << "" << "generate(" << id_number << ")";
switch (scheme_type) {
case GS_NONE:
@@ -791,15 +847,25 @@ void PGenerate::dump(ostream&out) const
out << endl;
for (map<hname_t,PWire*>::const_iterator idx = wires.begin()
for (map<pform_name_t,PWire*>::const_iterator idx = wires.begin()
; idx != wires.end() ; idx++) {
(*idx).second->dump(out, 6);
(*idx).second->dump(out, indent+2);
}
for (list<PGate*>::const_iterator idx = gates.begin()
; idx != gates.end() ; idx++) {
(*idx)->dump(out, 6);
(*idx)->dump(out, indent+2);
}
for (list<PProcess*>::const_iterator idx = behaviors.begin()
; idx != behaviors.end() ; idx++) {
(*idx)->dump(out, indent+2);
}
for (list<PGenerate*>::const_iterator idx = generates.begin()
; idx != generates.end() ; idx++) {
(*idx)->dump(out, indent+2);
}
out << " endgenerate" << endl;
@@ -841,7 +907,7 @@ void Module::dump(ostream&out) const
}
typedef map<perm_string,param_expr_t>::const_iterator parm_iter_t;
typedef map<hname_t,PExpr*>::const_iterator parm_hiter_t;
typedef map<pform_name_t,PExpr*>::const_iterator parm_hiter_t;
for (parm_iter_t cur = parameters.begin()
; cur != parameters.end() ; cur ++) {
out << " parameter ";
@@ -879,7 +945,7 @@ void Module::dump(ostream&out) const
typedef list<PGenerate*>::const_iterator genscheme_iter_t;
for (genscheme_iter_t cur = generate_schemes.begin()
; cur != generate_schemes.end() ; cur++) {
(*cur)->dump(out);
(*cur)->dump(out, 4);
}
typedef map<perm_string,PExpr*>::const_iterator specparm_iter_t;
@@ -906,7 +972,7 @@ void Module::dump(ostream&out) const
}
// Iterate through and display all the wires.
for (map<hname_t,PWire*>::const_iterator wire = wires_.begin()
for (map<pform_name_t,PWire*>::const_iterator wire = wires_.begin()
; wire != wires_.end()
; wire ++ ) {
@@ -1007,6 +1073,28 @@ void PUdp::dump(ostream&out) const
/*
* $Log: pform_dump.cc,v $
* Revision 1.101 2007/06/04 02:19:07 steve
* Handle bit/part select of array words in nets.
*
* Revision 1.100 2007/06/02 03:42:13 steve
* Properly evaluate scope path expressions.
*
* Revision 1.99 2007/05/31 18:35:50 steve
* Missing return value to perm_string dump
*
* Revision 1.98 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.97 2007/03/07 00:38:15 steve
* Lint fixes.
*
* Revision 1.96 2007/03/05 05:59:10 steve
* Handle processes within generate loops.
*
* Revision 1.95 2007/02/12 01:52:21 steve
* Parse all specify paths to pform.
*
* Revision 1.94 2006/09/23 04:57:19 steve
* Basic support for specify timing.
*
+32
View File
@@ -0,0 +1,32 @@
/*
* 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: pform_types.cc,v 1.1 2007/05/24 04:07:12 steve Exp $"
#endif
# include "pform_types.h"
bool operator < (const name_component_t&lef, const name_component_t&rig)
{
if (lef.name < rig.name)
return true;
return false;
}
+74
View File
@@ -0,0 +1,74 @@
#ifndef __pform_types_H
#define __pform_types_H
/*
* 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: pform_types.h,v 1.2 2007/06/04 02:19:07 steve Exp $"
#endif
// This for the perm_string type.
# include "StringHeap.h"
# include <iostream>
# include <list>
/*
* parse-form types.
*/
struct index_component_t {
enum ctype_t { SEL_NONE, SEL_BIT, SEL_PART, SEL_IDX_UP, SEL_IDX_DO };
index_component_t() : sel(SEL_NONE), msb(0), lsb(0) { };
~index_component_t() { }
ctype_t sel;
class PExpr*msb;
class PExpr*lsb;
};
struct name_component_t {
explicit name_component_t(perm_string n) : name(n) { }
~name_component_t() { }
perm_string name;
std::list<index_component_t>index;
};
extern bool operator < (const name_component_t&lef, const name_component_t&rig);
/*
* The pform_name_t is the general form for a heirarchical identifier.
*/
typedef std::list<name_component_t> pform_name_t;
inline perm_string peek_head_name(const pform_name_t&that)
{
return that.front().name;
}
inline perm_string peek_tail_name(const pform_name_t&that)
{
return that.back().name;
}
extern std::ostream& operator<< (std::ostream&out, const pform_name_t&);
extern std::ostream& operator<< (std::ostream&out, const name_component_t&that);
extern std::ostream& operator<< (std::ostream&out, const index_component_t&that);
#endif
+20 -5
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2003 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-2006 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: set_width.cc,v 1.39 2006/07/31 03:50:17 steve Exp $"
#ident "$Id: set_width.cc,v 1.42 2007/01/16 05:44:15 steve Exp $"
#endif
# include "config.h"
@@ -33,6 +33,7 @@
*/
# include "netlist.h"
# include "netmisc.h"
# include "compiler.h"
# include <typeinfo>
@@ -339,7 +340,7 @@ bool NetECReal::set_width(unsigned w, bool)
expr_width(w);
return true;
}
#if 0
bool NetEMemory::set_width(unsigned w, bool)
{
if (w != mem_->width())
@@ -348,7 +349,7 @@ bool NetEMemory::set_width(unsigned w, bool)
expr_width(w);
return true;
}
#endif
bool NetEParam::set_width(unsigned, bool)
{
return false;
@@ -373,7 +374,7 @@ bool NetESFunc::set_width(unsigned w, bool)
*/
bool NetESignal::set_width(unsigned w, bool)
{
if (w != bit_count())
if (w != vector_width())
return false;
return true;
@@ -440,6 +441,20 @@ bool NetEUReduce::set_width(unsigned w, bool)
/*
* $Log: set_width.cc,v $
* Revision 1.42 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.41 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.40 2006/10/30 05:44:49 steve
* Expression widths with unsized literals are pseudo-infinite width.
*
* Revision 1.39 2006/07/31 03:50:17 steve
* Add support for power in constant expressions.
*
+4 -4
View File
@@ -1,8 +1,8 @@
# $Id: README-solaris_pkg.txt,v 1.2 2004/10/04 01:10:56 steve Exp $
# $Id: README-solaris_pkg.txt,v 1.3 2007/02/26 19:49:49 steve Exp $
Notes about the solaris package.
I. Installing a prebuild solaris package
I. Installing a prebuilt solaris package
-----------------------------------------
To install the solaris package do the following as root on your machine:
@@ -24,10 +24,10 @@ To install the solaris package do the following as root on your machine:
this will install the package. The package will be registered under the
name "IVLver"
II. Deinstalling the solaris package
II. Uninstalling the solaris package
-------------------------------------
To deinstall an installed solaris package do the following as root on your machine:
To uninstall an installed solaris package do the following as root on your machine:
pkgrm IVLver
+5 -2
View File
@@ -21,7 +21,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: svector.h,v 1.10 2005/06/14 19:13:43 steve Exp $"
#ident "$Id: svector.h,v 1.11 2007/03/22 16:08:17 steve Exp $"
#endif
# include "config.h"
@@ -31,7 +31,7 @@
/*
* This is a way simplified vector class that cannot grow or shrink,
* and is really only able to handle values. It is intended to be
* lighter weight then the STL list class.
* lighter weight than the STL list class.
*/
template <class TYPE> class svector {
@@ -109,6 +109,9 @@ template <> inline svector<std::string>::svector(unsigned size)
/*
* $Log: svector.h,v $
* Revision 1.11 2007/03/22 16:08:17 steve
* Spelling fixes from Larry
*
* Revision 1.10 2005/06/14 19:13:43 steve
* gcc3/4 compile errors.
*
+30 -22
View File
@@ -17,19 +17,19 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: symbol_search.cc,v 1.3 2005/11/27 05:56:20 steve Exp $"
#ident "$Id: symbol_search.cc,v 1.7 2007/06/02 03:42:13 steve Exp $"
#endif
# include "netlist.h"
# include "netmisc.h"
# include <assert.h>
/*
* Search for the hierarchical name.
*/
NetScope*symbol_search(const Design*des, NetScope*scope, hname_t path,
NetScope*symbol_search(Design*des, NetScope*scope, pform_name_t path,
NetNet*&net,
NetMemory*&mem,
const NetExpr*&par,
NetEvent*&eve,
const NetExpr*&ex1, const NetExpr*&ex2)
@@ -37,39 +37,31 @@ NetScope*symbol_search(const Design*des, NetScope*scope, hname_t path,
assert(scope);
/* Get the tail name of the object we are looking for. */
char*key = path.remove_tail_name();
perm_string key = peek_tail_name(path);
path.pop_back();
/* Initialize output argument to cleared. */
net = 0;
mem = 0;
par = 0;
eve = 0;
/* If the path has a scope part, then search for the specified
scope that we are supposed to search. */
if (path.peek_name(0))
scope = des->find_scope(scope, path);
if (! path.empty()) {
list<hname_t> path_list = eval_scope_path(des, scope, path);
assert(path_list.size() == path.size());
scope = des->find_scope(scope, path_list);
}
while (scope) {
if ( (net = scope->find_signal(key)) ) {
delete key;
if ( (net = scope->find_signal(key)) )
return scope;
}
if ( (mem = scope->find_memory(key)) ) {
delete key;
if ( (eve = scope->find_event(key)) )
return scope;
}
if ( (eve = scope->find_event(key)) ) {
delete key;
if ( (par = scope->get_parameter(key, ex1, ex2)) )
return scope;
}
if ( (par = scope->get_parameter(key, ex1, ex2)) ) {
delete key;
return scope;
}
if (scope->type() == NetScope::MODULE)
scope = 0;
@@ -77,12 +69,28 @@ NetScope*symbol_search(const Design*des, NetScope*scope, hname_t path,
scope = scope->parent();
}
delete key;
return 0;
}
/*
* $Log: symbol_search.cc,v $
* Revision 1.7 2007/06/02 03:42:13 steve
* Properly evaluate scope path expressions.
*
* Revision 1.6 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.5 2007/04/26 03:06:22 steve
* Rework hname_t to use perm_strings.
*
* Revision 1.4 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.3 2005/11/27 05:56:20 steve
* Handle bit select of parameter with ranges.
*
+3 -45
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: syn-rules.y,v 1.33 2005/04/24 23:44:02 steve Exp $"
#ident "$Id: syn-rules.y,v 1.34 2007/01/16 05:44:15 steve Exp $"
#endif
# include "config.h"
@@ -118,7 +118,7 @@ static void hookup_DFF_CE(NetFF*ff, NetESignal*d, NetEvProbe*pclk,
// where lval is really a "reg [7:0]". In other words, part
// selects in the l-value are handled by loff and the lwidth().
connect(ff->pin_Data(), d->bit(0));
connect(ff->pin_Data(), d->sig()->pin(0));
connect(ff->pin_Q(), a->sig()->pin(0));
connect(ff->pin_Clock(), pclk->pin(0));
@@ -137,41 +137,6 @@ static void hookup_DFF_CE(NetFF*ff, NetESignal*d, NetEvProbe*pclk,
a->turn_sig_to_wire_on_release();
}
static void hookup_RAMDQ(NetRamDq*ram, NetESignal*d, NetNet*adr,
NetEvProbe*pclk, NetNet*ce,
NetAssign_*a, unsigned rval_pinoffset)
{
assert(d);
assert(a);
/* Connect the input Data bits of the RAM, from the r-value of
the assignment. */
connect(ram->pin_Data(), d->bit(rval_pinoffset));
/* Connect the Address pins from the addr net discovered by the
caller. */
connect(ram->pin_Address(), adr->pin(0));
/* Connect the input clock and the WE of the RAM. */
assert(pclk);
connect(ram->pin_InClock(), pclk->pin(0));
if (ce) {
connect(ram->pin_WE(), ce->pin(0));
} /* XXX does ram CE default to true if not connected? */
/* This notices any other NetRamDq objects connected to the
same NetMemory, that have the same address pins and are
otherwise compatible. This absorbs them into this object. */
ram->absorb_partners();
/* This lval_ represents a reg that is a WIRE in the
synthesized results. This function signals the destructor
to change the REG that this l-value refers to into a
WIRE. It is done then, at the last minute, so that pending
synthesis can continue to work with it as a WIRE. */
a->turn_sig_to_wire_on_release();
}
static void make_DFF_CE(Design*des, NetProcTop*top, NetEvWait*wclk,
NetEvent*eclk, NetExpr*cexp, NetAssignBase*asn)
{
@@ -207,13 +172,6 @@ static void make_DFF_CE(Design*des, NetProcTop*top, NetEvWait*wclk,
a->sig()->vector_width());
hookup_DFF_CE(ff, d, pclk, ce, a, rval_pinoffset);
des->add_node(ff);
} else if (a->mem()) {
NetMemory *m=a->mem();
NetNet *adr = a->bmux()->synthesize(des);
NetRamDq*ram = new NetRamDq(top->scope(), m->name(),
m, adr->pin_count());
hookup_RAMDQ(ram, d, adr, pclk, ce, a, rval_pinoffset);
des->add_node(ram);
}
rval_pinoffset += a->lwidth();
}
@@ -233,7 +191,7 @@ static void make_initializer(Design*des, NetProcTop*top, NetAssignBase*asn)
for (unsigned idx = 0 ; idx < asn->l_val(0)->lwidth() ; idx += 1) {
verinum::V bit = rsig->bit(idx).nexus()->driven_value();
verinum::V bit = rsig->sig()->pin(idx).nexus()->driven_value();
Nexus*nex = asn->l_val(0)->sig()->pin(idx).nexus();
for (Link*cur = nex->first_nlink()
+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: synth2.cc,v 1.45 2005/08/27 04:32:08 steve Exp $"
#ident "$Id: synth2.cc,v 1.46 2007/03/22 16:08:17 steve Exp $"
#endif
# include "config.h"
@@ -766,7 +766,7 @@ bool NetEvWait::synth_sync(Design*des, NetScope*scope, NetFF*ff,
assert(events_in.count() == 0);
/* This can't be other then one unless there are named events,
/* This can't be other than one unless there are named events,
which I cannot synthesize. */
assert(nevents_ == 1);
NetEvent*ev = events_[0];
@@ -1000,6 +1000,9 @@ void synth2(Design*des)
/*
* $Log: synth2.cc,v $
* Revision 1.46 2007/03/22 16:08:17 steve
* Spelling fixes from Larry
*
* Revision 1.45 2005/08/27 04:32:08 steve
* Handle synthesis of fully packed case statements.
*
+103 -90
View File
@@ -17,10 +17,11 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: t-dll-api.cc,v 1.137 2006/09/23 04:57:19 steve Exp $"
#ident "$Id: t-dll-api.cc,v 1.144 2007/04/02 01:12:34 steve Exp $"
#endif
# include "config.h"
# include "StringHeap.h"
# include "t-dll.h"
# include <stdlib.h>
# include <string.h>
@@ -28,6 +29,8 @@
# include <malloc.h>
#endif
static StringHeap api_strings;
/* THE FOLLOWING ARE FUNCTIONS THAT ARE CALLED FROM THE TARGET. */
extern "C" const char*ivl_design_flag(ivl_design_t des, const char*key)
@@ -96,33 +99,6 @@ inline static const char *basename(ivl_scope_t scope, const char *inst)
return inst+1;
}
extern "C" const char* ivl_memory_basename(ivl_memory_t net)
{
return net->basename_;
}
extern "C" ivl_scope_t ivl_memory_scope(ivl_memory_t net)
{
assert(net);
return net->scope_;
}
extern "C" int ivl_memory_root(ivl_memory_t net)
{
return net->root_;
}
extern "C" unsigned ivl_memory_size(ivl_memory_t net)
{
return net->size_;
}
extern "C" unsigned ivl_memory_width(ivl_memory_t net)
{
return net->width_;
}
extern "C" ivl_variable_type_t ivl_const_type(ivl_net_const_t net)
{
assert(net);
@@ -317,6 +293,9 @@ extern "C" ivl_expr_t ivl_expr_oper1(ivl_expr_t net)
case IVL_EX_MEMORY:
return net->u_.memory_.idx_;
case IVL_EX_SIGNAL:
return net->u_.signal_.word;
case IVL_EX_TERNARY:
return net->u_.ternary_.cond;
@@ -443,6 +422,7 @@ extern "C" ivl_signal_t ivl_expr_signal(ivl_expr_t net)
switch (net->type_) {
case IVL_EX_SIGNAL:
case IVL_EX_ARRAY:
return net->u_.signal_.sig;
default:
@@ -498,12 +478,6 @@ extern "C" unsigned ivl_expr_width(ivl_expr_t net)
return net->width_;
}
extern "C" ivl_memory_t ivl_expr_memory(ivl_expr_t net)
{
assert(net->type_ == IVL_EX_MEMORY);
return net->u_.memory_.mem_;
}
extern "C" const char* ivl_logic_attr(ivl_net_logic_t net, const char*key)
{
assert(net);
@@ -707,6 +681,18 @@ extern "C" ivl_nexus_t ivl_lpm_sync_set(ivl_lpm_t net)
}
}
extern "C" ivl_signal_t ivl_lpm_array(ivl_lpm_t net)
{
assert(net);
switch (net->type) {
case IVL_LPM_ARRAY:
return net->u_.array.sig;
default:
assert(0);
return 0;
}
}
extern "C" unsigned ivl_lpm_base(ivl_lpm_t net)
{
assert(net);
@@ -726,7 +712,6 @@ extern "C" ivl_nexus_t ivl_lpm_clk(ivl_lpm_t net)
assert(net);
switch (net->type) {
case IVL_LPM_FF:
case IVL_LPM_RAM:
return net->u_.ff.clk;
default:
assert(0);
@@ -739,7 +724,6 @@ extern "C" ivl_expr_t ivl_lpm_aset_value(ivl_lpm_t net)
assert(net);
switch (net->type) {
case IVL_LPM_FF:
case IVL_LPM_RAM:
return net->u_.ff.aset_value;
default:
assert(0);
@@ -751,7 +735,6 @@ extern "C" ivl_expr_t ivl_lpm_sset_value(ivl_lpm_t net)
assert(net);
switch (net->type) {
case IVL_LPM_FF:
case IVL_LPM_RAM:
return net->u_.ff.sset_value;
default:
assert(0);
@@ -775,7 +758,6 @@ extern "C" ivl_nexus_t ivl_lpm_enable(ivl_lpm_t net)
{
assert(net);
switch (net->type) {
case IVL_LPM_RAM:
case IVL_LPM_FF:
return net->u_.ff.we;
default:
@@ -827,10 +809,6 @@ extern "C" ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx)
else
return net->u_.shift.s;
case IVL_LPM_RAM:
assert(idx == 0);
return net->u_.ff.d.pin;
case IVL_LPM_FF:
assert(idx == 0);
return net->u_.ff.d.pin;
@@ -945,10 +923,6 @@ extern "C" ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx)
assert(idx == 0);
return net->u_.arith.q;
case IVL_LPM_RAM:
assert(idx == 0);
return net->u_.ff.q.pin;
case IVL_LPM_FF:
assert(idx == 0);
return net->u_.ff.q.pin;
@@ -993,6 +967,10 @@ extern "C" ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx)
assert(idx == 0);
return net->u_.repeat.q;
case IVL_LPM_ARRAY:
assert(idx == 0);
return net->u_.array.q;
default:
assert(0);
return 0;
@@ -1008,12 +986,13 @@ extern "C" ivl_scope_t ivl_lpm_scope(ivl_lpm_t net)
extern "C" ivl_nexus_t ivl_lpm_select(ivl_lpm_t net)
{
switch (net->type) {
case IVL_LPM_RAM:
return net->u_.ff.s.pin;
case IVL_LPM_MUX:
return net->u_.mux.s;
case IVL_LPM_ARRAY:
return net->u_.array.a;
default:
assert(0);
return 0;
@@ -1023,10 +1002,10 @@ extern "C" ivl_nexus_t ivl_lpm_select(ivl_lpm_t net)
extern "C" unsigned ivl_lpm_selects(ivl_lpm_t net)
{
switch (net->type) {
case IVL_LPM_RAM:
return net->u_.ff.swid;
case IVL_LPM_MUX:
return net->u_.mux.swid;
case IVL_LPM_ARRAY:
return net->u_.array.swid;
case IVL_LPM_CONCAT:
return net->u_.concat.inputs;
default:
@@ -1040,7 +1019,6 @@ extern "C" int ivl_lpm_signed(ivl_lpm_t net)
assert(net);
switch (net->type) {
case IVL_LPM_FF:
case IVL_LPM_RAM:
case IVL_LPM_MUX:
return 0;
case IVL_LPM_ADD:
@@ -1079,6 +1057,8 @@ extern "C" int ivl_lpm_signed(ivl_lpm_t net)
return net->u_.part.signed_flag;
case IVL_LPM_REPEAT:
return 0;
case IVL_LPM_ARRAY: // Array ports take the signedness of the array.
return net->u_.array.sig->signed_;
default:
assert(0);
return 0;
@@ -1119,18 +1099,6 @@ extern "C" unsigned ivl_lpm_width(ivl_lpm_t net)
return net->width;
}
extern "C" ivl_memory_t ivl_lpm_memory(ivl_lpm_t net)
{
assert(net);
switch (net->type) {
case IVL_LPM_RAM:
return net->u_.ff.mem;
default:
assert(0);
return 0;
}
}
extern "C" ivl_expr_t ivl_lval_mux(ivl_lval_t net)
{
assert(net);
@@ -1142,16 +1110,9 @@ extern "C" ivl_expr_t ivl_lval_mux(ivl_lval_t net)
extern "C" ivl_expr_t ivl_lval_idx(ivl_lval_t net)
{
assert(net);
if (net->type_ == IVL_LVAL_MEM)
return net->idx;
return 0x0;
}
extern "C" ivl_memory_t ivl_lval_mem(ivl_lval_t net)
{
assert(net);
if (net->type_ == IVL_LVAL_MEM)
return net->n.mem;
if (net->type_ == IVL_LVAL_ARR)
return net->idx;
return 0x0;
}
@@ -1174,15 +1135,23 @@ extern "C" ivl_signal_t ivl_lval_sig(ivl_lval_t net)
case IVL_LVAL_REG:
case IVL_LVAL_NET:
case IVL_LVAL_MUX:
case IVL_LVAL_ARR:
return net->n.sig;
default:
return 0;
}
}
/*
* The nexus name is rarely needed. (Shouldn't be needed at all!) This
* function will calculate the name if it is not already calculated.
*/
extern "C" const char* ivl_nexus_name(ivl_nexus_t net)
{
assert(net);
if (net->name_ == 0) {
net->name_ = api_strings.add(net->nexus_->name());
}
return net->name_;
}
@@ -1283,6 +1252,12 @@ extern "C" ivl_scope_t ivl_parameter_scope(ivl_parameter_t net)
return net->scope;
}
extern "C" ivl_nexus_t ivl_path_condit(ivl_delaypath_t obj)
{
assert(obj);
return obj->condit;
}
extern uint64_t ivl_path_delay(ivl_delaypath_t obj, ivl_path_edge_t edg)
{
assert(obj);
@@ -1294,6 +1269,16 @@ extern ivl_nexus_t ivl_path_source(ivl_delaypath_t net)
return net->src;
}
extern int ivl_path_source_posedge(ivl_delaypath_t net)
{
return net->posedge ? 1 : 0;
}
extern int ivl_path_source_negedge(ivl_delaypath_t net)
{
return net->negedge ? 1 : 0;
}
extern "C" ivl_process_type_t ivl_process_type(ivl_process_t net)
{
return net->type_;
@@ -1399,19 +1384,6 @@ extern "C" ivl_lpm_t ivl_scope_lpm(ivl_scope_t net, unsigned idx)
return net->lpm_[idx];
}
extern "C" unsigned ivl_scope_mems(ivl_scope_t net)
{
assert(net);
return net->nmem_;
}
extern "C" ivl_memory_t ivl_scope_mem(ivl_scope_t net, unsigned idx)
{
assert(net);
assert(idx < net->nmem_);
return net->mem_[idx];
}
static unsigned scope_name_len(ivl_scope_t net)
{
unsigned len = 0;
@@ -1520,6 +1492,21 @@ extern "C" const char* ivl_scope_tname(ivl_scope_t net)
return net->tname_;
}
extern "C" int ivl_signal_array_base(ivl_signal_t net)
{
return net->array_base;
}
extern "C" unsigned ivl_signal_array_count(ivl_signal_t net)
{
return net->array_words;
}
extern "C" unsigned ivl_signal_dimensions(ivl_signal_t net)
{
return net->array_dimensions_;
}
extern "C" const char* ivl_signal_attr(ivl_signal_t net, const char*key)
{
if (net->nattr == 0)
@@ -1571,9 +1558,13 @@ extern "C" const char* ivl_signal_name(ivl_signal_t net)
return name_buffer;
}
extern "C" ivl_nexus_t ivl_signal_nex(ivl_signal_t net)
extern "C" ivl_nexus_t ivl_signal_nex(ivl_signal_t net, unsigned word)
{
return net->pin_;
assert(word < net->array_words);
if (net->array_words > 1)
return net->pins[word];
else
return net->pin;
}
extern "C" int ivl_signal_msb(ivl_signal_t net)
@@ -1889,11 +1880,9 @@ extern "C" unsigned ivl_stmt_lwidth(ivl_statement_t net)
sum += 1;
break;
case IVL_LVAL_REG:
case IVL_LVAL_ARR:
sum += ivl_lval_width(cur);
break;
case IVL_LVAL_MEM:
sum += ivl_memory_width(ivl_lval_mem(cur));
break;
default:
assert(0);
}
@@ -1976,6 +1965,30 @@ extern "C" ivl_statement_t ivl_stmt_sub_stmt(ivl_statement_t net)
/*
* $Log: t-dll-api.cc,v $
* Revision 1.144 2007/04/02 01:12:34 steve
* Seperate arrayness from word count
*
* Revision 1.143 2007/03/26 16:51:48 steve
* do not calculate nexus name unless needed.
*
* Revision 1.142 2007/03/02 06:13:22 steve
* Add support for edge sensitive spec paths.
*
* Revision 1.141 2007/03/01 06:19:39 steve
* Add support for conditional specify delay paths.
*
* Revision 1.140 2007/01/17 05:00:12 steve
* Dead code for memories in scopes.
*
* Revision 1.139 2007/01/17 04:39:18 steve
* Remove dead code related to memories.
*
* Revision 1.138 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.137 2006/09/23 04:57:19 steve
* Basic support for specify timing.
*
+41 -25
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: t-dll-expr.cc,v 1.43 2005/09/14 02:53:15 steve Exp $"
#ident "$Id: t-dll-expr.cc,v 1.47 2007/03/22 16:08:18 steve Exp $"
#endif
# include "config.h"
@@ -200,27 +200,6 @@ void dll_target::expr_concat(const NetEConcat*net)
expr_ = cur;
}
void dll_target::expr_memory(const NetEMemory*net)
{
assert(expr_ == 0);
if (net->index()) {
net->index()->expr_scan(this);
assert(expr_);
}
ivl_expr_t cur = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
assert(cur);
cur->type_ = IVL_EX_MEMORY;
cur->value_ = IVL_VT_VECTOR;
cur->width_= net->expr_width();
cur->signed_ = net->has_sign()? 1 : 0;
cur->u_.memory_.mem_ = find_memory(des_, net->memory());
cur->u_.memory_.idx_ = expr_;
expr_ = cur;
}
void dll_target::expr_const(const NetEConst*net)
{
assert(expr_ == 0);
@@ -387,7 +366,7 @@ void dll_target::expr_ternary(const NetETernary*net)
assert(expr);
expr->type_ = IVL_EX_TERNARY;
expr->value_= IVL_VT_VECTOR;
expr->value_= net->expr_type();
expr->width_ = net->expr_width();
expr->signed_ = net->has_sign()? 1 : 0;
@@ -410,8 +389,19 @@ void dll_target::expr_ternary(const NetETernary*net)
void dll_target::expr_signal(const NetESignal*net)
{
ivl_signal_t sig = find_signal(des_, net->sig());
assert(expr_ == 0);
/* If there is a word expression, generate it. */
ivl_expr_t word_expr = 0;
if (const NetExpr*word = net->word_index()) {
word->expr_scan(this);
assert(expr_);
word_expr = expr_;
expr_ = 0;
}
expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
assert(expr_);
@@ -419,7 +409,18 @@ void dll_target::expr_signal(const NetESignal*net)
expr_->value_= net->expr_type();
expr_->width_= net->expr_width();
expr_->signed_ = net->has_sign()? 1 : 0;
expr_->u_.signal_.sig = find_signal(des_, net->sig());
expr_->u_.signal_.word = word_expr;
expr_->u_.signal_.sig = sig;
/* Make account for the special case that this is a reference
to an array as a whole. We detect this case by noting that
this is an array (more than 1 word) and there is no word
select expression. In that case, this is an IVL_EX_ARRAY
expression instead of a SIGNAL expression. */
if (sig->array_words > 1 && word_expr == 0) {
expr_->type_ = IVL_EX_ARRAY;
expr_->width_ = 0; // Doesn't make much sense for arrays.
}
}
@@ -464,7 +465,7 @@ void dll_target::expr_unary(const NetEUnary*net)
expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
expr_->type_ = IVL_EX_UNARY;
expr_->value_= IVL_VT_VECTOR;
expr_->value_= net->expr_type();
expr_->width_ = net->expr_width();
expr_->signed_ = net->has_sign()? 1 : 0;
expr_->u_.unary_.op_ = net->op();
@@ -473,6 +474,21 @@ void dll_target::expr_unary(const NetEUnary*net)
/*
* $Log: t-dll-expr.cc,v $
* Revision 1.47 2007/03/22 16:08:18 steve
* Spelling fixes from Larry
*
* Revision 1.46 2007/02/20 05:58:36 steve
* Handle unary minus of real valued expressions.
*
* Revision 1.45 2007/02/14 05:59:46 steve
* Handle type of ternary expressions properly.
*
* 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 2005/09/14 02:53:15 steve
* Support bool expressions and compares handle them optimally.
*
+27 -19
View File
@@ -18,7 +18,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: t-dll-proc.cc,v 1.68 2006/02/02 02:43:59 steve Exp $"
#ident "$Id: t-dll-proc.cc,v 1.71 2007/06/02 03:42:13 steve Exp $"
#endif
# include "config.h"
@@ -131,7 +131,7 @@ bool dll_target::func_def(const NetScope*net)
}
cerr << "?:0" << ": internal error: "
<< "Function " << net->name() << " has a return type"
<< "Function " << net->basename() << " has a return type"
<< " that I do not understand." << endl;
return false;
@@ -171,30 +171,24 @@ void dll_target::make_assign_lvals_(const NetAssignBase*net)
cur->n.sig = find_signal(des_, asn->sig());
cur->idx = 0;
if (asn->bmux()) {
// If there is a word select expression, it is
// really an array index. Note that the word index
// expression is already converted to canonical
// form by elaboration.
if (asn->word()) {
assert(expr_ == 0);
asn->bmux()->expr_scan(this);
if (cur->n.sig->lsb_index != 0)
sub_off_from_expr_(asn->sig()->lsb());
asn->word()->expr_scan(this);
// lsb_dist is the distance for this
// index. If this is >1, then this may be an
// array of arrays, so we need to multiply
// to get the canonical index.
if (cur->n.sig->lsb_dist != 1)
mul_expr_by_const_(cur->n.sig->lsb_dist);
cur->type_ = IVL_LVAL_MUX;
cur->type_ = IVL_LVAL_ARR;
cur->idx = expr_;
expr_ = 0;
}
} else if (asn->mem()) {
assert(asn->mem());
cur->type_ = IVL_LVAL_MEM;
cur->n.mem = find_memory(des_, asn->mem());
assert(cur->n.mem);
cur->width_ = ivl_memory_width(cur->n.mem);
assert(expr_ == 0);
asn->bmux()->expr_scan(this);
cur->idx = expr_;
expr_ = 0;
} else {
assert(0);
}
@@ -647,6 +641,8 @@ bool dll_target::proc_wait(const NetEvWait*net)
ivl_scope_t ev_scope = lookup_scope_(ev->scope());
ivl_event_t ev_tmp=0;
assert(ev_scope);
assert(ev_scope->nevent_ > 0);
for (unsigned idx = 0 ; idx < ev_scope->nevent_ ; idx += 1) {
const char*ename = ivl_event_basename(ev_scope->event_[idx]);
if (strcmp(ev->name(), ename) == 0) {
@@ -741,6 +737,18 @@ void dll_target::proc_while(const NetWhile*net)
/*
* $Log: t-dll-proc.cc,v $
* Revision 1.71 2007/06/02 03:42:13 steve
* Properly evaluate scope path expressions.
*
* Revision 1.70 2007/04/04 01:50:38 steve
* t-dll should not canonicalize word addresses, elaboration already does it.
*
* Revision 1.69 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.68 2006/02/02 02:43:59 steve
* Allow part selects of memory words in l-values.
*
+306 -251
View File
File diff suppressed because it is too large Load Diff
+65 -31
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: t-dll.h,v 1.133 2006/09/23 04:57:19 steve Exp $"
#ident "$Id: t-dll.h,v 1.143 2007/06/02 03:42:13 steve Exp $"
#endif
# include "target.h"
@@ -74,6 +74,7 @@ struct dll_target : public target_t, public expr_scan_t {
void net_case_cmp(const NetCaseCmp*);
void udp(const NetUDP*);
void lpm_add_sub(const NetAddSub*);
bool lpm_array_dq(const NetArrayDq*);
void lpm_clshift(const NetCLShift*);
void lpm_compare(const NetCompare*);
void lpm_divide(const NetDivide*);
@@ -81,7 +82,6 @@ struct dll_target : public target_t, public expr_scan_t {
void lpm_modulo(const NetModulo*);
void lpm_mult(const NetMult*);
void lpm_mux(const NetMux*);
void lpm_ram_dq(const NetRamDq*);
bool concat(const NetConcat*);
bool part_select(const NetPartSelect*);
bool replicate(const NetReplicate*);
@@ -96,8 +96,7 @@ struct dll_target : public target_t, public expr_scan_t {
bool process(const NetProcTop*);
void scope(const NetScope*);
void signal(const NetNet*);
void memory(const NetMemory*);
bool signal_paths(const NetNet*);
ivl_dll_t dll_;
ivl_design_s des_;
@@ -133,7 +132,6 @@ struct dll_target : public target_t, public expr_scan_t {
struct ivl_expr_s*expr_;
void expr_binary(const NetEBinary*);
void expr_concat(const NetEConcat*);
void expr_memory(const NetEMemory*);
void expr_const(const NetEConst*);
void expr_creal(const NetECReal*);
void expr_param(const NetEConstParam*);
@@ -156,8 +154,6 @@ struct dll_target : public target_t, public expr_scan_t {
static ivl_scope_t find_scope(ivl_design_s &des, const NetScope*cur);
static ivl_signal_t find_signal(ivl_design_s &des, const NetNet*net);
static ivl_memory_t find_memory(ivl_design_s &des, const NetMemory*net);
static ivl_parameter_t scope_find_param(ivl_scope_t scope,
const char*name);
@@ -169,6 +165,7 @@ struct dll_target : public target_t, public expr_scan_t {
void make_logic_delays_(struct ivl_net_logic_s*obj, const NetObj*net);
void make_scope_parameters(ivl_scope_t scope, const NetScope*net);
void make_scope_param_expr(ivl_parameter_t cur_par, NetExpr*etmp);
static ivl_expr_t expr_from_value_(const verinum&that);
};
@@ -179,6 +176,9 @@ struct dll_target : public target_t, public expr_scan_t {
struct ivl_delaypath_s {
ivl_nexus_t src;
ivl_nexus_t condit;
bool posedge;
bool negedge;
uint64_t delay[12];
};
@@ -230,6 +230,7 @@ struct ivl_expr_s {
struct {
ivl_signal_t sig;
ivl_expr_t word;
} signal_;
struct {
@@ -293,7 +294,6 @@ struct ivl_lpm_s {
union {
struct ivl_lpm_ff_s {
unsigned swid; // ram only
ivl_nexus_t clk;
ivl_nexus_t we;
ivl_nexus_t aclr;
@@ -308,11 +308,6 @@ struct ivl_lpm_s {
ivl_nexus_t*pins;
ivl_nexus_t pin;
} d;
union { // ram only
ivl_nexus_t*pins;
ivl_nexus_t pin;
} s;
ivl_memory_t mem; // ram only
ivl_expr_t aset_value;
ivl_expr_t sset_value;
} ff;
@@ -335,6 +330,12 @@ struct ivl_lpm_s {
ivl_nexus_t q, a, b;
} arith;
struct ivl_lpm_array_s {
ivl_signal_t sig;
unsigned swid;
ivl_nexus_t q, a;
} array;
struct ivl_concat_s {
unsigned inputs;
ivl_nexus_t*pins;
@@ -379,8 +380,9 @@ struct ivl_lpm_s {
enum ivl_lval_type_t {
IVL_LVAL_REG = 0,
IVL_LVAL_MUX = 1,
IVL_LVAL_MEM = 2,
IVL_LVAL_NET = 3 /* Only force can have NET l-values */
/* IVL_LVAL_MEM = 2, / Deprecated in favor of LVAL_ARR? */
IVL_LVAL_NET = 3, /* Only force can have NET l-values */
IVL_LVAL_ARR = 4
};
struct ivl_lval_s {
@@ -476,24 +478,18 @@ struct ivl_nexus_ptr_s {
# define __NEXUS_PTR_CON 2
# define __NEXUS_PTR_LPM 3
/*
* NOTE: ONLY allocat ivl_nexus_s objects with the included "new" operator.
*/
struct ivl_nexus_s {
unsigned nptr_;
struct ivl_nexus_ptr_s*ptrs_;
const Nexus*nexus_;
const char*name_;
void*private_data;
};
/*
* Memory.
*/
struct ivl_memory_s {
perm_string basename_;
ivl_scope_t scope_;
unsigned width_;
unsigned signed_ : 1;
unsigned size_;
int root_;
void* operator new (size_t s);
void operator delete(void*obj, size_t s); // Not implemented
};
/*
@@ -546,9 +542,6 @@ struct ivl_scope_s {
unsigned nlpm_;
ivl_lpm_t* lpm_;
unsigned nmem_;
ivl_memory_t* mem_;
unsigned nparam_;
ivl_parameter_t param_;
@@ -580,6 +573,9 @@ struct ivl_signal_s {
unsigned isint_ : 1;
unsigned local_ : 1;
/* For now, support only 0 or 1 array dimensions. */
unsigned array_dimensions_ : 1;
/* These encode the run-time index for the least significant
bit, and the distance to the second bit. */
signed lsb_index;
@@ -588,7 +584,12 @@ struct ivl_signal_s {
perm_string name_;
ivl_scope_t scope_;
ivl_nexus_t pin_;
unsigned array_words;
int array_base;
union {
ivl_nexus_t pin;
ivl_nexus_t*pins;
};
ivl_delaypath_s*path;
unsigned npath;
@@ -679,6 +680,39 @@ struct ivl_statement_s {
/*
* $Log: t-dll.h,v $
* Revision 1.143 2007/06/02 03:42:13 steve
* Properly evaluate scope path expressions.
*
* Revision 1.142 2007/04/02 01:12:34 steve
* Seperate arrayness from word count
*
* Revision 1.141 2007/03/26 20:32:47 steve
* More efficient allocate of ivl_nexus_t objects.
*
* Revision 1.140 2007/03/26 16:51:49 steve
* do not calculate nexus name unless needed.
*
* Revision 1.139 2007/03/02 06:13:22 steve
* Add support for edge sensitive spec paths.
*
* Revision 1.138 2007/03/01 06:19:39 steve
* Add support for conditional specify delay paths.
*
* Revision 1.137 2007/01/17 05:00:12 steve
* Dead code for memories in scopes.
*
* Revision 1.136 2007/01/17 04:39:18 steve
* Remove dead code related to memories.
*
* Revision 1.135 2007/01/16 05:44:16 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.134 2006/11/10 05:44:45 steve
* Process delay paths in second path over signals.
*
* Revision 1.133 2006/09/23 04:57:19 steve
* Basic support for specify timing.
*
+23 -20
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: target.cc,v 1.78 2006/06/18 04:15:50 steve Exp $"
#ident "$Id: target.cc,v 1.81 2007/06/02 03:42:13 steve Exp $"
#endif
# include "config.h"
@@ -38,15 +38,13 @@ void target_t::scope(const NetScope*)
void target_t::event(const NetEvent*ev)
{
cerr << ev->get_line() << ": error: target (" << typeid(*this).name()
<< "): Unhandled event <" << ev->full_name() << ">." << endl;
<< "): Unhandled event <" << ev->name() << ">." << endl;
}
void target_t::memory(const NetMemory*)
bool target_t::signal_paths(const NetNet*)
{
cerr << "target (" << typeid(*this).name() << "): "
"Unhandled memory." << endl;
return true;
}
bool target_t::func_def(const NetScope*)
{
cerr << "target (" << typeid(*this).name() << "): "
@@ -92,6 +90,13 @@ void target_t::lpm_add_sub(const NetAddSub*)
"Unhandled NetAddSub." << endl;
}
bool target_t::lpm_array_dq(const NetArrayDq*)
{
cerr << "target (" << typeid(*this).name() << "): "
"Unhandled NetArrayDq." << endl;
return false;
}
void target_t::lpm_clshift(const NetCLShift*)
{
cerr << "target (" << typeid(*this).name() << "): "
@@ -133,13 +138,6 @@ void target_t::lpm_mux(const NetMux*)
cerr << "target (" << typeid(*this).name() << "): "
"Unhandled NetMux." << endl;
}
void target_t::lpm_ram_dq(const NetRamDq*)
{
cerr << "target (" << typeid(*this).name() << "): "
"Unhandled NetRamDq." << endl;
}
bool target_t::concat(const NetConcat*)
{
cerr << "target (" << typeid(*this).name() << "): "
@@ -375,13 +373,6 @@ void expr_scan_t::expr_concat(const NetEConcat*that)
cerr << that->get_line() << ": expr_scan_t (" <<
typeid(*this).name() << "): unhandled expr_concat." << endl;
}
void expr_scan_t::expr_memory(const NetEMemory*)
{
cerr << "expr_scan_t (" << typeid(*this).name() << "): "
"unhandled expr_memory." << endl;
}
void expr_scan_t::expr_event(const NetEEvent*)
{
cerr << "expr_scan_t (" << typeid(*this).name() << "): "
@@ -438,6 +429,18 @@ void expr_scan_t::expr_binary(const NetEBinary*ex)
/*
* $Log: target.cc,v $
* Revision 1.81 2007/06/02 03:42:13 steve
* Properly evaluate scope path expressions.
*
* Revision 1.80 2007/01/16 05:44:16 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.79 2006/11/10 05:44:45 steve
* Process delay paths in second path over signals.
*
* Revision 1.78 2006/06/18 04:15:50 steve
* Add support for system functions in continuous assignments.
*
+12 -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: target.h,v 1.75 2006/06/18 04:15:50 steve Exp $"
#ident "$Id: target.h,v 1.77 2007/01/16 05:44:16 steve Exp $"
#endif
# include "netlist.h"
@@ -64,9 +64,7 @@ struct target_t {
/* Output a signal (called for each signal) */
virtual void signal(const NetNet*) =0;
/* Output a memory (called for each memory object) */
virtual void memory(const NetMemory*);
virtual bool signal_paths(const NetNet*);
/* Output a defined task. */
virtual void task_def(const NetScope*);
@@ -74,6 +72,7 @@ struct target_t {
/* LPM style components are handled here. */
virtual void lpm_add_sub(const NetAddSub*);
virtual bool lpm_array_dq(const NetArrayDq*);
virtual void lpm_clshift(const NetCLShift*);
virtual void lpm_compare(const NetCompare*);
virtual void lpm_divide(const NetDivide*);
@@ -81,7 +80,6 @@ struct target_t {
virtual void lpm_ff(const NetFF*);
virtual void lpm_mult(const NetMult*);
virtual void lpm_mux(const NetMux*);
virtual void lpm_ram_dq(const NetRamDq*);
virtual bool concat(const NetConcat*);
virtual bool part_select(const NetPartSelect*);
@@ -138,7 +136,6 @@ struct expr_scan_t {
virtual void expr_rparam(const NetECRealParam*);
virtual void expr_creal(const NetECReal*);
virtual void expr_concat(const NetEConcat*);
virtual void expr_memory(const NetEMemory*);
virtual void expr_event(const NetEEvent*);
virtual void expr_scope(const NetEScope*);
virtual void expr_select(const NetESelect*);
@@ -171,6 +168,15 @@ extern const struct target *target_table[];
/*
* $Log: target.h,v $
* Revision 1.77 2007/01/16 05:44:16 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.76 2006/11/10 05:44:45 steve
* Process delay paths in second path over signals.
*
* Revision 1.75 2006/06/18 04:15:50 steve
* Add support for system functions in continuous assignments.
*
+1 -1
View File
@@ -17,7 +17,7 @@ AC_CHECK_HEADERS(malloc.h)
# may modify CPPFLAGS and CFLAGS
AX_CPP_PRECOMP
# Compiler option for position independent code, needed whan making shared objects.
# Compiler option for position independent code, needed when making shared objects.
AX_C_PICFLAG
# linker options when building a shared library
+5 -2
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: device.h,v 1.14 2003/11/12 03:20:14 steve Exp $"
#ident "$Id: device.h,v 1.15 2007/02/26 19:49:49 steve Exp $"
#endif
# include <ivl_target.h>
@@ -72,7 +72,7 @@ struct device_s {
* Return the device_t cookie given the name of the architecture. If
* the device is not found, return 0.
*
* This function is used if the user specifies the archetecture
* This function is used if the user specifies the architecture
* explicitly, with the -parch=name flag.
*/
extern device_t device_from_arch(const char*arch);
@@ -80,6 +80,9 @@ extern device_t device_from_arch(const char*arch);
/*
* $Log: device.h,v $
* Revision 1.15 2007/02/26 19:49:49 steve
* Spelling fixes (larry doolittle)
*
* Revision 1.14 2003/11/12 03:20:14 steve
* devices need show_cmp_gt
*
+6 -3
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: edif.h,v 1.7 2003/09/03 23:34:09 steve Exp $"
#ident "$Id: edif.h,v 1.8 2007/02/26 19:49:49 steve Exp $"
#endif
# include <stdio.h>
@@ -47,7 +47,7 @@
*
* Declare external libraries with edif_xlibrary_create
* Normally, this is the single technology library that contains
* the primitive cells that the code generator intendes to
* the primitive cells that the code generator intends to
* use. The library is given a name, such as VIRTEX or whatever
* the implementation tools expect. Cells are attached to the
* library later. An edif netlist may include multiple external
@@ -196,7 +196,7 @@ extern edif_cellref_t edif_cellref_create(edif_t edf, edif_cell_t cell);
/* Instances can have properties attached to them. The name and value
given here are turned into a (property <name> (string "val"))
sexpression attached to the instance.
expression attached to the instance.
Examples of string properties commonly attached to cellref devices
include such things as the INIT=<value> to initialize LUT cells in
@@ -231,6 +231,9 @@ extern void edif_print(FILE*fd, edif_t design);
/*
* $Log: edif.h,v $
* Revision 1.8 2007/02/26 19:49:49 steve
* Spelling fixes (larry doolittle)
*
* Revision 1.7 2003/09/03 23:34:09 steve
* Support synchronous set of LPM_FF devices.
*
+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: xilinx.c,v 1.12 2004/02/15 18:03:30 steve Exp $"
#ident "$Id: xilinx.c,v 1.13 2007/02/26 19:49:50 steve Exp $"
#endif
# include "edif.h"
@@ -273,7 +273,7 @@ edif_cell_t xilinx_cell_xorcy(edif_xlibrary_t xlib)
/*
* This function does a lot of the stuff common to the header
* functions of various Xilinx familes. This includes creating the edf
* functions of various Xilinx families. This includes creating the edf
* object that holds the netlist.
*/
void xilinx_common_header(ivl_design_t des)
@@ -835,14 +835,14 @@ void xilinx_shiftl(ivl_lpm_t net)
/* Allocate a matrix of edif_cellref_t variables. A devices
will be addressed by the expression table[sdx][qdx];
This should make the algorighm code easier to read. */
This should make the algorithm code easier to read. */
cells = calloc(nsel * width, sizeof(edif_cellref_t));
table = calloc(nsel, sizeof(edif_cellref_t*));
for (sdx = 0 ; sdx < nsel ; sdx += 1)
table[sdx] = cells + sdx*width;
/* Make a 0 valued pad bit. I wlil use this for all the shifin
/* Make a 0 valued pad bit. I will use this for all the shift in
values that are beyond the input. */
pad0_cell = edif_cellref_create(edf, cell_0);
pad0 = edif_joint_create(edf);
@@ -951,6 +951,9 @@ void xilinx_shiftl(ivl_lpm_t net)
/*
* $Log: xilinx.c,v $
* Revision 1.13 2007/02/26 19:49:50 steve
* Spelling fixes (larry doolittle)
*
* Revision 1.12 2004/02/15 18:03:30 steve
* Cleanup of warnings.
*

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