Compare commits

...
135 Commits
Author SHA1 Message Date
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
steve 168b3f2743 Fix packaging of man directories. 2006-10-09 18:56:17 +00:00
steve 0d71b1cc18 Prepare for 20061009 snapshot. 2006-10-09 18:31:56 +00:00
steve ec23bb0367 Remove dead code. 2006-10-05 01:37:34 +00:00
steve 26e2e85ffa Handle non-constant delays on indexed non-blocking assignments. 2006-10-05 01:23:53 +00:00
steve 4af28e2b77 no-specify turns of specparam elaboration. 2006-10-03 15:33:49 +00:00
steve 69cd007a71 Support real valued specify delays, properly scaled. 2006-10-03 05:06:00 +00:00
steve cbe1a6a3ca Save dep_path because arg space is overrun. 2006-10-02 18:16:18 +00:00
steve 1a0d48c346 Fix handling of dep path in new argument passing method. 2006-10-02 18:15:47 +00:00
steve 549f226c6e Modpath is input to net, draw .modpath to account. 2006-10-01 23:51:15 +00:00
steve e1f712356f Allow rosync events to create new rosync events. 2006-09-29 16:55:04 +00:00
steve 6593b603ad Modpath delay chooses correct delay for edge. 2006-09-29 03:57:01 +00:00
steve 852d10500d Man files go into /usr/share/man. 2006-09-29 01:32:17 +00:00
steve 44ca0fe798 rwsync callback fixes from Ben Staveley (with modifications.) 2006-09-29 01:24:34 +00:00
steve 35ce5f3e2a Improved mingw.txt instructions. 2006-09-28 23:45:20 +00:00
steve d6be82f748 Support selective control of specify and xtypes features. 2006-09-28 04:35:18 +00:00
steve 7e3ea2ffe8 Allow specparams as constants in expressions. 2006-09-28 00:29:49 +00:00
steve b658a3b41f Missing PSpec.cc file. 2006-09-26 19:48:40 +00:00
steve d3ceae7ee0 Accept .cpp source. 2006-09-26 18:54:42 +00:00
steve 0edb5a7547 Basic support for specify timing. 2006-09-23 04:57:19 +00:00
steve ceb6bf4afd Correct return code for vpi_put_userdata. 2006-09-22 22:33:00 +00:00
steve 0e2c6544b9 Proper error message when logic array pi count is bad. 2006-09-22 22:14:27 +00:00
steve b4893dc16f Configure scripts in general need canonical host. 2006-09-22 22:13:07 +00:00
steve f49039a3d6 Missing declaration for Windows. 2006-09-22 15:15:27 +00:00
steve 3617f0346e Bring ivl.def up to date. 2006-09-20 22:31:57 +00:00
steve f20191e6f5 tgt-verilog is not buildable for now. 2006-09-20 22:31:45 +00:00
steve 182734fd4d Remove dead code. 2006-09-20 22:31:23 +00:00
steve 431eee16e4 Do not pass -D__ICARUS__ to ivlpp. 2006-09-20 22:30:52 +00:00
steve 92cb1d4e2d Use elab_and_eval for bit select expressions. 2006-09-19 23:00:15 +00:00
steve 6f34dfc8e5 Scanf formats for character and string. 2006-08-12 04:16:07 +00:00
steve 2c7e96caec scanf support for real values. 2006-08-12 03:38:12 +00:00
steve 54c7ef72cb Snapshot 20060809 2006-08-10 01:23:29 +00:00
steve 50800fd3a1 Add support for real valued modulus. 2006-08-09 05:19:08 +00:00
steve fc0695beb6 Handle 64bit delay constants. 2006-08-08 05:11:37 +00:00
steve 00891db0d2 Fix typo in initialize of new event_time cell. 2006-08-06 18:17:00 +00:00
steve 898b0e0365 Support release of a for/linked reg. 2006-08-04 04:37:37 +00:00
steve 382c4d74fd Add the scanf functions. 2006-08-03 05:06:04 +00:00
steve 5bcf083662 Better comments for vpi_fopen function. 2006-08-03 05:05:31 +00:00
steve 1bd530c144 Fix infinite loop padding binary string to result. 2006-08-03 05:05:06 +00:00
steve 82a85131a8 Use compiletf to check arguments. 2006-08-03 05:02:46 +00:00
steve 49b65e86fe Add support for power in constant expressions. 2006-07-31 03:50:17 +00:00
steve 06d6ac4b33 Fix/implement signed right shift. 2006-07-30 02:51:35 +00:00
steve 2037650080 Pass depfiles through temp defines file. 2006-07-26 00:11:40 +00:00
steve 61f3a84557 Pass defines and includes through temp file. 2006-07-26 00:02:48 +00:00
steve ed70db84ce Handle real valued literals in net contexts. 2006-07-08 21:48:46 +00:00
steve 5348ac14a5 Delay object supports real valued delays. 2006-07-08 21:48:00 +00:00
steve aab6fefd8a Fix context determined with of constants. 2006-07-07 04:06:37 +00:00
steve 1b8e2a17c7 Change the Copyright tag to License. 2006-06-24 05:21:07 +00:00
steve 33a391cb71 Sign extend operands of signed addition. 2006-06-20 05:06:47 +00:00
steve bcc08112aa Snapshot 20060618 2006-06-18 23:56:23 +00:00
steve 80f30be9d0 Add support for system functions in continuous assignments. 2006-06-18 04:15:50 +00:00
steve 71faebd6df Make elaborate_expr methods aware of the width that the context
requires of it. In the process, fix sizing of the width of unary
 minus is context determined sizes.
2006-06-02 04:48:49 +00:00
steve 53ae1f29c9 Fix broken subtraction of small constants. 2006-06-01 03:54:51 +00:00
steve 857b3e15b6 Fix handling of ternary-to-bufif0 constant propagation. 2006-05-24 04:32:57 +00:00
steve 019d61f633 Get self-determined unary - width right. 2006-05-19 04:44:55 +00:00
steve d37b6599f4 eval_const is not strict. 2006-05-19 04:07:24 +00:00
steve 68e52ce6b7 Synchronous primitives only follow edges. 2006-05-18 05:13:45 +00:00
steve 4c885f65e1 Error message if concat expression cannot evaluate. 2006-05-17 16:49:30 +00:00
steve f0e114d59f Lexor os never interactive. 2006-05-17 04:15:12 +00:00
steve aaaa042f73 Add port list format for task arguments. 2006-05-11 03:26:57 +00:00
steve 044da54b41 Be more stubborn about widths. 2006-05-02 04:29:42 +00:00
steve a8b86ea3bb More explicit datatype setup. 2006-05-01 20:47:58 +00:00
steve e98aad1e9b Cleaner rule for parse.h and parse.cc 2006-05-01 20:47:29 +00:00
steve 1ef91f800f Forgot to invert nand output. 2006-05-01 20:47:03 +00:00
steve a19efe181b Install stub target. 2006-05-01 18:48:24 +00:00
steve 81bfbd1549 Reduce steps to make logic output. 2006-05-01 18:44:08 +00:00
steve dc2898cc73 fix net type of multiply output. 2006-05-01 05:40:21 +00:00
steve 0c9fb766b6 Get the data type of part select results right. 2006-04-30 05:17:48 +00:00
steve 10f8c66f4a Dump *all* the reduction operator gates. 2006-04-30 05:16:53 +00:00
steve 56f70ec702 Include math.h with lround implementation. 2006-04-28 15:44:37 +00:00
steve 949054e000 lround takes double, not float. 2006-04-28 15:40:30 +00:00
steve 47b72c3b74 Handle padding of MUX net results. 2006-04-28 05:09:51 +00:00
steve a2c036d5ab Allow concatenations as arguments to inout ports. 2006-04-28 04:28:35 +00:00
steve 0d17e57656 Dump indexes of ident expressions 2006-04-28 04:19:31 +00:00
steve fd94268315 Detect missing lround function. 2006-04-27 05:04:59 +00:00
steve 36039e13ec schedule takes relative, not absolute, time. 2006-04-27 04:38:00 +00:00
steve a702f99c04 Dump function type as string. 2006-04-27 04:26:38 +00:00
steve 4493e3f928 Chop down assign r-values that elaborate too wide. 2006-04-26 04:43:50 +00:00
steve 3727052000 Include bit value in assertion message. 2006-04-26 04:39:23 +00:00
steve 39ff233cf1 Detect the presence of stdint.h 2006-04-25 22:41:10 +00:00
steve 58118bddc5 Warning when file is inadequate for requested range. 2006-04-25 05:00:12 +00:00
steve c2ff3d501c Fix support for indexed part select in continuous assign l-values. 2006-04-24 05:15:07 +00:00
steve 46d86ad276 Get tail counts right in nested concatenations. 2006-04-22 04:27:36 +00:00
steve 4dd1308eb0 Parse specify ifnone statements. 2006-04-17 04:35:49 +00:00
steve a978bb1e14 Cleanup lval part select handling. 2006-04-16 00:54:04 +00:00
steve 707af782b3 Fix part selects in l-values. 2006-04-16 00:15:43 +00:00
steve fc5cf55400 Use elab_and_eval to evaluate genvar expressions. 2006-04-12 05:05:03 +00:00
steve 6a74a090f0 Configure for stub. 2006-04-10 03:07:07 +00:00
steve c448b75f2c fpga target is not installed. 2006-04-10 03:05:54 +00:00
157 changed files with 9542 additions and 3872 deletions
+9 -8
View File
@@ -16,7 +16,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.175 2006/04/10 00:37:42 steve Exp $"
#ident "$Id: Makefile.in,v 1.179 2006/10/30 22:45:36 steve Exp $"
#
#
SHELL = /bin/sh
@@ -62,7 +62,7 @@ LDFLAGS = @rdynamic@ @LDFLAGS@
all: dep ivl@EXEEXT@
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) $@); done
for dir in ivlpp tgt-verilog ; \
for dir in ivlpp ; \
do (cd $$dir ; $(MAKE) $@); done
cd driver ; $(MAKE) VERSION=$(VERSION) $@
@@ -84,17 +84,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
rm -f lexor_keyword.cc libivl.a libvpi.a iverilog-vpi syn-rules.cc*
rm -rf dep ivl@EXEEXT@
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
@@ -111,7 +114,7 @@ parse.o parse_misc.o pform.o pform_dump.o \
set_width.o symbol_search.o sync.o sys_funcs.o \
verinum.o verireal.o target.o targets.o \
Attrib.o HName.o LineInfo.o Module.o PDelays.o PEvent.o \
PExpr.o PGate.o PGenerate.o \
PExpr.o PGate.o PGenerate.o PSpec.o \
PTask.o PUdp.o PFunction.o PWire.o Statement.o StringHeap.o \
$(FF) $(TT)
@@ -161,10 +164,8 @@ lexor.o: lexor.cc parse.h
parse.o: parse.cc
parse.cc: $(srcdir)/parse.y
parse.cc parse.h: $(srcdir)/parse.y
$(YACC) --verbose -t -p VL -d -o parse.cc $(srcdir)/parse.y
parse.h: parse.cc
mv parse.cc.h parse.h 2>/dev/null || mv parse.hh parse.h
syn-rules.cc: $(srcdir)/syn-rules.y
+7 -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: Module.h,v 1.40 2006/04/10 00:37:42 steve Exp $"
#ident "$Id: Module.h,v 1.41 2006/09/23 04:57:19 steve Exp $"
#endif
# include <list>
@@ -35,6 +35,7 @@ class PExpr;
class PEIdent;
class PGate;
class PGenerate;
class PSpecPath;
class PTask;
class PFunction;
class PWire;
@@ -122,6 +123,8 @@ class Module : public LineInfo {
the module definition. These are used at elaboration time. */
list<PGenerate*> generate_schemes;
list<PSpecPath*> specify_paths;
perm_string mod_name() const { return name_; }
void add_gate(PGate*gate);
@@ -173,6 +176,9 @@ class Module : public LineInfo {
/*
* $Log: Module.h,v $
* Revision 1.41 2006/09/23 04:57:19 steve
* Basic support for specify timing.
*
* Revision 1.40 2006/04/10 00:37:42 steve
* Add support for generate loops w/ wires and gates.
*
+16 -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: PDelays.cc,v 1.13 2006/01/03 05:22:14 steve Exp $"
#ident "$Id: PDelays.cc,v 1.15 2006/07/08 21:48:46 steve Exp $"
#endif
# include "config.h"
@@ -65,7 +65,7 @@ void PDelays::set_delays(const svector<PExpr*>*del, bool df)
static NetExpr*calculate_val(Design*des, NetScope*scope, const PExpr*expr)
{
NetExpr*dex = expr->elaborate_expr(des, scope);
NetExpr*dex = expr->elaborate_expr(des, scope, -1, false);
if (NetExpr*tmp = dex->eval_tree()) {
delete dex;
dex = tmp;
@@ -115,6 +115,12 @@ static NetExpr* make_delay_nets(Design*des, NetExpr*expr)
return expr;
NetNet*sig = expr->synthesize(des);
if (sig == 0) {
cerr << expr->get_line() << ": error: Expression " << *expr
<< " is not suitable for delay expression." << endl;
return 0;
}
expr = new NetESignal(sig);
return expr;
}
@@ -163,6 +169,14 @@ void PDelays::eval_delays(Design*des, NetScope*scope,
/*
* $Log: PDelays.cc,v $
* Revision 1.15 2006/07/08 21:48:46 steve
* Handle real valued literals in net contexts.
*
* Revision 1.14 2006/06/02 04:48:49 steve
* Make elaborate_expr methods aware of the width that the context
* requires of it. In the process, fix sizing of the width of unary
* minus is context determined sizes.
*
* Revision 1.13 2006/01/03 05:22:14 steve
* Handle complex net node delays.
*
+22 -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: PExpr.cc,v 1.37 2005/10/04 04:09:25 steve Exp $"
#ident "$Id: PExpr.cc,v 1.38 2006/10/30 05:44:49 steve Exp $"
#endif
# include "config.h"
@@ -75,6 +75,24 @@ bool PEBinary::is_constant(Module*mod) const
return left_->is_constant(mod) && right_->is_constant(mod);
}
PEBComp::PEBComp(char op, PExpr*l, PExpr*r)
: PEBinary(op, l, r)
{
}
PEBComp::~PEBComp()
{
}
PEBShift::PEBShift(char op, PExpr*l, PExpr*r)
: PEBinary(op, l, r)
{
}
PEBShift::~PEBShift()
{
}
PECallFunction::PECallFunction(const hname_t&n, const svector<PExpr *> &parms)
: path_(n), parms_(parms)
{
@@ -270,6 +288,9 @@ bool PEUnary::is_constant(Module*m) const
/*
* $Log: PExpr.cc,v $
* 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.
*
+173 -32
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.78 2006/03/25 02:36:26 steve Exp $"
#ident "$Id: PExpr.h,v 1.87 2007/01/16 05:44:14 steve Exp $"
#endif
# include <string>
@@ -51,11 +51,38 @@ class PExpr : public LineInfo {
virtual void dump(ostream&) const;
// Procedural elaboration of the expression. Set the
// bare_memory_ok flag if the result is allowed to be a
// NetEMemory without an index.
// This method tests the width that the expression wants to
// be. It is used by elaboration of assignments to figure out
// the width of the expression.
//
// The "min" is the width of the local context, so it the
// minimum width that this function should return. Initially
// this is the same as the lval width.
//
// The "lval" is the width of the destination where this
// result is going to go. This can be used to constrain the
// amount that an expression can reasonably expand. For
// example, there is no point expanding an addition to beyond
// the lval. This extra bit of information allows the
// expression to optimize itself a bit. If the lval==0, then
// the subexpression should not make l-value related
// optimizations.
//
// The unsigned_flag is set to true if the expression is
// unsized and therefore expandable. This happens if a
// sub-expression is an unsized literal. Some expressions make
// special use of that.
virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
bool&unsized_flag) const;
// Procedural elaboration of the expression. The expr_width is
// the width of the context of the expression (i.e. the
// l-value width of an assignment) or -1 if the expression is
// self-determinted. The sys_task_arg flag is true if
// expressions are allowed to be incomplete.
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
bool sys_task_arg =false) const;
int expr_width, bool sys_task_arg) const;
// Elaborate expressions that are the r-value of parameter
// assignments. This elaboration follows the restrictions of
@@ -128,6 +155,7 @@ class PEConcat : public PExpr {
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope,
bool implicit_net_ok =false) const;
virtual NetNet* elaborate_bi_net(Design*des, NetScope*scope) const;
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned width,
const NetExpr* rise,
@@ -136,13 +164,17 @@ class PEConcat : public PExpr {
Link::strength_t drive0,
Link::strength_t drive1) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
bool sys_task_arg =false) const;
int expr_width, bool sys_task_arg) const;
virtual NetEConcat*elaborate_pexpr(Design*des, NetScope*) const;
virtual NetAssign_* elaborate_lval(Design*des,
NetScope*scope,
bool is_force) const;
virtual bool is_constant(Module*) const;
private:
NetNet* elaborate_lnet_common_(Design*des, NetScope*scope,
bool implicit_net_ok,
bool bidirectional_flag) const;
private:
svector<PExpr*>parms_;
PExpr*repeat_;
@@ -195,7 +227,7 @@ class PEFNumber : public PExpr {
virtual bool is_constant(Module*) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
bool sys_task_arg =false) const;
int expr_width, bool sys_task_arg) const;
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
@@ -219,6 +251,9 @@ class PEIdent : public PExpr {
~PEIdent();
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,
@@ -241,7 +276,7 @@ class PEIdent : public PExpr {
Link::strength_t drive1) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
bool sys_task_arg =false) const;
int expr_width, bool sys_task_arg) const;
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
// Elaborate the PEIdent as a port to a module. This method
@@ -253,6 +288,17 @@ class PEIdent : public PExpr {
const hname_t& path() const;
private:
// Common functions to calculate parts of part/bit selects.
bool calculate_parts_(Design*, NetScope*, long&msb, long&lsb) const;
bool calculate_up_do_width_(Design*, NetScope*, unsigned long&wid) const;
private:
NetAssign_*elaborate_lval_net_word_(Design*, NetScope*, NetNet*) const;
bool elaborate_lval_net_part_(Design*, NetScope*, NetAssign_*) const;
bool elaborate_lval_net_idx_up_(Design*, NetScope*, NetAssign_*) const;
bool elaborate_lval_net_idx_do_(Design*, NetScope*, NetAssign_*) const;
private:
NetExpr*elaborate_expr_param(Design*des,
NetScope*scope,
@@ -261,24 +307,30 @@ 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_;
@@ -293,12 +345,13 @@ class PEIdent : public PExpr {
// 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,
@@ -309,9 +362,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 +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,
@@ -340,7 +394,7 @@ class PENumber : public PExpr {
Link::strength_t drive0,
Link::strength_t drive1) const;
virtual NetEConst*elaborate_expr(Design*des, NetScope*,
bool sys_task_arg =false) const;
int expr_width, bool) const;
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
virtual NetAssign_* elaborate_lval(Design*des,
NetScope*scope,
@@ -370,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,
@@ -378,7 +437,7 @@ class PEString : public PExpr {
Link::strength_t drive0,
Link::strength_t drive1) const;
virtual NetEConst*elaborate_expr(Design*des, NetScope*,
bool sys_task_arg =false) const;
int expr_width, bool) const;
virtual NetEConst*elaborate_pexpr(Design*des, NetScope*sc) const;
verinum* eval_const(const Design*, NetScope*) const;
@@ -395,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,
@@ -403,7 +463,7 @@ class PEUnary : public PExpr {
Link::strength_t drive0,
Link::strength_t drive1) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
bool sys_task_arg =false) const;
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;
@@ -423,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,
@@ -431,17 +496,19 @@ class PEBinary : public PExpr {
Link::strength_t drive0,
Link::strength_t drive1) const;
virtual NetEBinary*elaborate_expr(Design*des, NetScope*,
bool sys_task_arg =false) const;
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;
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,
@@ -484,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.
@@ -497,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,
@@ -505,7 +604,7 @@ class PETernary : public PExpr {
Link::strength_t drive0,
Link::strength_t drive1) const;
virtual NetETernary*elaborate_expr(Design*des, NetScope*,
bool sys_task_arg =false) const;
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;
@@ -527,6 +626,7 @@ class PECallFunction : public PExpr {
~PECallFunction();
virtual void dump(ostream &) const;
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned width,
const NetExpr* rise,
@@ -535,7 +635,7 @@ class PECallFunction : public PExpr {
Link::strength_t drive0,
Link::strength_t drive1) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
bool sys_task_arg =false) const;
int expr_wid, bool sys_task_arg) const;
private:
hname_t path_;
@@ -544,10 +644,51 @@ class PECallFunction : public PExpr {
bool check_call_matches_definition_(Design*des, NetScope*dscope) const;
NetExpr* elaborate_sfunc_(Design*des, NetScope*scope) const;
NetNet* elaborate_net_sfunc_(Design*des, NetScope*scope,
unsigned width,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const;
};
/*
* $Log: PExpr.h,v $
* Revision 1.87 2007/01/16 05:44:14 steve
* Major rework of array handling. Memories are replaced with the
* more general concept of arrays. The NetMemory and NetEMemory
* classes are removed from the ivl core program, and the IVL_LPM_RAM
* lpm type is removed from the ivl_target API.
*
* Revision 1.86 2006/11/10 04:54:26 steve
* Add test_width methods for PETernary and PEString.
*
* Revision 1.85 2006/11/04 06:19:24 steve
* Remove last bits of relax_width methods, and use test_width
* to calculate the width of an r-value expression that may
* contain unsized numbers.
*
* Revision 1.84 2006/10/30 05:44:49 steve
* Expression widths with unsized literals are pseudo-infinite width.
*
* Revision 1.83 2006/06/18 04:15:50 steve
* Add support for system functions in continuous assignments.
*
* Revision 1.82 2006/06/02 04:48:49 steve
* Make elaborate_expr methods aware of the width that the context
* requires of it. In the process, fix sizing of the width of unary
* minus is context determined sizes.
*
* Revision 1.81 2006/04/28 04:28:35 steve
* Allow concatenations as arguments to inout ports.
*
* Revision 1.80 2006/04/16 00:54:04 steve
* Cleanup lval part select handling.
*
* Revision 1.79 2006/04/16 00:15:43 steve
* Fix part selects in l-values.
*
* Revision 1.78 2006/03/25 02:36:26 steve
* Get rid of excess PESTring:: prefix within class declaration.
*
+32
View File
@@ -0,0 +1,32 @@
/*
* Copyright (c) 2006 Stephen Williams <[email protected]>
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: PSpec.cc,v 1.1 2006/09/26 19:48:40 steve Exp $"
#endif
# include "PSpec.h"
PSpecPath::PSpecPath(unsigned src_cnt, unsigned dst_cnt)
: src(src_cnt), dst(dst_cnt)
{
}
PSpecPath::~PSpecPath()
{
}
+48
View File
@@ -0,0 +1,48 @@
#ifndef __PSpec_H
#define __PSpec_H
/*
* Copyright (c) 2006 Stephen Williams <[email protected]>
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
* General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: PSpec.h,v 1.1 2006/09/23 04:57:19 steve Exp $"
#endif
# include "LineInfo.h"
# include "StringHeap.h"
# include <vector>
class PSpecPath : public LineInfo {
public:
PSpecPath(unsigned src_cnt, unsigned dst_cnt);
~PSpecPath();
void elaborate(class Design*des, class NetScope*scope) const;
void dump(std::ostream&out, unsigned ind) const;
public:
// 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;
std::vector<class PExpr*>delays;
};
#endif
+7 -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: PWire.cc,v 1.11 2005/07/07 16:22:49 steve Exp $"
#ident "$Id: PWire.cc,v 1.12 2007/01/16 05:44:14 steve Exp $"
#endif
# include "config.h"
@@ -154,13 +154,18 @@ 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.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.
*
+3 -3
View File
@@ -7,12 +7,12 @@
# to just run this script to autoconf wherever needed.
#
echo "Autoconf in root..."
autoconf
autoconf -f
for dir in vpip vpi vvp tgt-vvp tgt-fpga libveriuser cadpli
for dir in vpip vpi vvp tgt-vvp tgt-fpga tgt-stub libveriuser cadpli
do
echo "Autoconf in $dir..."
( cd ./$dir ; autoconf --include=.. )
( cd ./$dir ; autoconf -f --include=.. )
done
echo "Precompiling lexor_keyword.gperf"
+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: compiler.h,v 1.30 2005/07/11 16:56:50 steve Exp $"
#ident "$Id: compiler.h,v 1.31 2006/09/28 04:35:18 steve Exp $"
#endif
# include <list>
@@ -104,12 +104,17 @@ enum generation_t {
};
extern generation_t generation_flag;
extern bool gn_cadence_types_flag;
/* These functions test that specific features are enabled. */
inline bool gn_cadence_types_enabled()
{ return gn_cadence_types_flag && generation_flag==GN_VER2001X; }
/* If this flag is true, then elaborate specify blocks. If this flag
is false, then skip elaboration of specify behavior. */
extern bool gn_specify_blocks_flag;
/* This is the string to use to invoke the preprocessor. */
extern char*ivlpp_string;
@@ -143,6 +148,9 @@ extern int load_sys_func_table(const char*path);
/*
* $Log: compiler.h,v $
* Revision 1.31 2006/09/28 04:35:18 steve
* Support selective control of specify and xtypes features.
*
* Revision 1.30 2005/07/11 16:56:50 steve
* Remove NetVariable and ivl_variable_t structures.
*
+48 -53
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.54 2005/07/15 19:22:52 steve Exp $"
#ident "$Id: cprop.cc,v 1.55 2006/05/24 04:32:57 steve Exp $"
#endif
# include "config.h"
@@ -738,6 +738,48 @@ v }
}
}
static void replace_with_bufif(Design*des, NetMux*obj, NetLogic::TYPE type)
{
NetScope*scope = obj->scope();
NetLogic*tmp = new NetLogic(obj->scope(),
scope->local_symbol(),
3, type, obj->width());
des->add_node(tmp);
connect(obj->pin_Result(), tmp->pin(0));
connect(obj->pin_Data(type==NetLogic::BUFIF0? 0 : 1), tmp->pin(1));
if (obj->width() == 1) {
/* Special case that the expression is 1 bit
wide. Connect the select directly to the enable. */
connect(obj->pin_Sel(), tmp->pin(2));
} else {
/* General case that the expression is arbitrarily
wide. Replicate the enable signal (which we
assume is 1 bit wide) to match the expression,
and connect the enable vector to the enable
input of the gate. */
NetReplicate*rtmp = new NetReplicate(scope,
scope->local_symbol(),
obj->width(),
obj->width());
des->add_node(rtmp);
connect(obj->pin_Sel(), rtmp->pin(1));
connect(tmp->pin(2), rtmp->pin(0));
NetNet*rsig = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, obj->width());
rsig->local_flag(true);
rsig->data_type(IVL_VT_LOGIC);
connect(tmp->pin(2), rsig->pin(0));
}
delete obj;
}
/*
* This detects the case where the mux selects between a value and
* Vz. In this case, replace the device with a bufif with the sel
@@ -764,47 +806,8 @@ void cprop_functor::lpm_mux(Design*des, NetMux*obj)
}
if (flag) {
NetScope*scope = obj->scope();
NetLogic*tmp = new NetLogic(obj->scope(),
scope->local_symbol(),
3, NetLogic::BUFIF1, obj->width());
des->add_node(tmp);
connect(obj->pin_Result(), tmp->pin(0));
connect(obj->pin_Data(1), tmp->pin(1));
if (obj->width() == 1) {
/* Special case that the expression is 1 bit
wide. Connect the select directly to the
enable. */
connect(obj->pin_Sel(), tmp->pin(2));
} else {
/* General case that the expression is arbitrarily
wide. Replicate the enable signal (which we
assume is 1 bit wide) to match the expression,
and connect the enable vector to the enable
input of the gate. */
NetReplicate*rtmp = new NetReplicate(scope,
scope->local_symbol(),
obj->width(),
obj->width());
des->add_node(rtmp);
connect(obj->pin_Sel(), rtmp->pin(1));
connect(tmp->pin(2), rtmp->pin(0));
NetNet*rsig = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, obj->width());
rsig->local_flag(true);
rsig->data_type(IVL_VT_LOGIC);
connect(tmp->pin(2), rsig->pin(0));
}
replace_with_bufif(des, obj, NetLogic::BUFIF1);
count += 1;
delete obj;
return;
}
@@ -821,19 +824,8 @@ void cprop_functor::lpm_mux(Design*des, NetMux*obj)
}
if (flag) {
NetScope*scope = obj->scope();
NetLogic*tmp = new NetLogic(obj->scope(),
scope->local_symbol(),
3, NetLogic::BUFIF0, obj->width());
connect(obj->pin_Result(), tmp->pin(0));
connect(obj->pin_Data(0), tmp->pin(1));
connect(obj->pin_Sel(), tmp->pin(2));
des->add_node(tmp);
replace_with_bufif(des, obj, NetLogic::BUFIF0);
count += 1;
delete obj;
return;
}
}
@@ -956,6 +948,9 @@ void cprop(Design*des)
/*
* $Log: cprop.cc,v $
* Revision 1.55 2006/05/24 04:32:57 steve
* Fix handling of ternary-to-bufif0 constant propagation.
*
* Revision 1.54 2005/07/15 19:22:52 steve
* bufif enable is LOGIC.
*
+99 -49
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.165 2006/04/10 00:37:42 steve Exp $"
#ident "$Id: design_dump.cc,v 1.172 2007/01/16 05:44:14 steve Exp $"
#endif
# include "config.h"
@@ -29,7 +29,7 @@
# include <iostream>
# include <iomanip>
# include "netlist.h"
# include "compiler.h"
static ostream& operator<< (ostream&o, NetBlock::Type t)
{
@@ -90,11 +90,30 @@ ostream& operator << (ostream&o, ivl_variable_type_t val)
return o;
}
void NetDelaySrc::dump(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << "specify delay src "
<< "(" << transition_delays_[IVL_PE_01]
<< "," << transition_delays_[IVL_PE_10]
<< "," << transition_delays_[IVL_PE_0z]
<< "/" << transition_delays_[IVL_PE_z1]
<< "," << transition_delays_[IVL_PE_1z]
<< "," << transition_delays_[IVL_PE_z0]
<< "/" << transition_delays_[IVL_PE_0x]
<< "," << transition_delays_[IVL_PE_x1]
<< "," << transition_delays_[IVL_PE_1x]
<< "/" << transition_delays_[IVL_PE_x0]
<< "," << transition_delays_[IVL_PE_xz]
<< "," << transition_delays_[IVL_PE_zx]
<< "): " << endl;
dump_node_pins(o, ind+4);
}
/* Dump a net. This can be a wire or register. */
void NetNet::dump_net(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << type() << ": " << name() << "[" <<
pin_count() << "]";
o << setw(ind) << "" << type() << ": " << name()
<< "[" << s0_ << ":" << e0_ << " count=" << pin_count() << "]";
if (local_flag_)
o << " (local)";
o << " " << data_type_;
@@ -139,16 +158,15 @@ void NetNet::dump_net(ostream&o, unsigned ind) const
o << setw(ind+4) << "" << "[" << idx << "]: " << nex
<< " " << nex->name() << endl;
}
for (unsigned idx = 0 ; idx < delay_paths_.size() ; idx += 1) {
const NetDelaySrc*cur = delay_paths_[idx];
cur->dump(o, ind+4);
}
dump_obj_attr(o, ind+4);
}
void 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. */
@@ -214,6 +232,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): " <<
@@ -402,14 +429,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: "
@@ -462,6 +481,13 @@ void NetUReduce::dump_node(ostream&o, unsigned ind) const
dump_obj_attr(o, ind+4);
}
void NetSysFunc::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << def_->name << "(...)" << endl;
dump_node_pins(o, ind+4);
dump_obj_attr(o, ind+4);
}
void NetUserFunc::dump_node(ostream&o, unsigned ind) const
{
o << setw(ind) << "" << def_->name() << "(";
@@ -534,21 +560,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_ << "]";
}
@@ -874,13 +888,25 @@ 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()
; cur != specparams.end() ; cur ++ ) {
o << " specparam " << (*cur).first
<< " = ";
spec_val_t value = (*cur).second;
switch (value.type) {
case IVL_VT_REAL:
o << "R:" << value.real_val;
break;
case IVL_VT_BOOL:
o << "I:" << value.integer;
break;
default:
o << "<bad type>";
break;
}
o << endl;
}
switch (type_) {
@@ -984,6 +1010,9 @@ void NetEBinary::dump(ostream&o) const
case 'O':
o << "~|";
break;
case 'p':
o << "**";
break;
case 'r':
o << ">>";
break;
@@ -1092,22 +1121,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
else if (name_)
o << "<" << name_ << ">";
else
o << "<" "???" ">";
}
void NetETernary::dump(ostream&o) const
@@ -1173,6 +1199,30 @@ void Design::dump(ostream&o) const
/*
* $Log: design_dump.cc,v $
* 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.
*
* Revision 1.169 2006/09/26 19:48:40 steve
* Missing PSpec.cc file.
*
* Revision 1.168 2006/09/23 04:57:19 steve
* Basic support for specify timing.
*
* Revision 1.167 2006/07/31 03:50:17 steve
* Add support for power in constant expressions.
*
* Revision 1.166 2006/06/18 04:15:50 steve
* Add support for system functions in continuous assignments.
*
* Revision 1.165 2006/04/10 00:37:42 steve
* Add support for generate loops w/ wires and gates.
*
+8
View File
@@ -277,6 +277,7 @@ static int parse(int argc, char *argv[])
char dot_c_ext[] = ".c";
char dot_cc_ext[] = ".cc";
char dot_cpp_ext[] = ".cpp";
char dot_o_ext[] = ".o";
char name_option[] = "--name=";
char lib_option[] = "-l";
@@ -301,6 +302,13 @@ static int parse(int argc, char *argv[])
if (!*gstr.pOUT)
assignn(&gstr.pOUT,argv[idx],strlen(argv[idx])-strlen(dot_cc_ext));
}
else if (endsIn(dot_cpp_ext,argv[idx])) { /* check for C++ source files */
++srcFileCnt;
append(&gstr.pCXSRC,argv[idx]);
append(&gstr.pCXSRC," ");
if (!*gstr.pOUT)
assignn(&gstr.pOUT,argv[idx],strlen(argv[idx])-strlen(dot_cpp_ext));
}
else if (endsIn(dot_o_ext,argv[idx])) { /* check for compiled object files */
++srcFileCnt;
append(&gstr.pOBJ,argv[idx]);
+2 -2
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.25 2006/10/30 22:45:37 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
+41 -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.9 2006/11/30 06:00:28 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
%%
@@ -112,17 +114,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 then "/" */
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;
+17 -2
View File
@@ -1,10 +1,10 @@
.TH iverilog 1 "$Date: 2005/06/28 04:25:55 $" Version "$Date: 2005/06/28 04:25:55 $"
.TH iverilog 1 "$Date: 2006/09/28 04:35:18 $" Version "$Date: 2006/09/28 04:35:18 $"
.SH NAME
iverilog - Icarus Verilog compiler
.SH SYNOPSIS
.B iverilog
[-ESVv] [-Bpath] [-ccmdfile] [-g1|-g2|-g2x] [-Dmacro[=defn]] [-pflag=value]
[-ESVv] [-Bpath] [-ccmdfile] [-g1|-g2|-g2x|-gspecify-gxtypes] [-Dmacro[=defn]] [-pflag=value]
[-Iincludedir] [-mmodule] [-Mfile] [-Nfile] [-ooutputfilename]
[-stopmodule] [-ttype] [-Tmin/typ/max] [-Wclass] [-ypath] sourcefile
@@ -57,6 +57,21 @@ language. This flag is most useful to restrict the language to a set
supported by tools of specific generations, for compatibility with
other tools.
.TP 8
.B -gspecify\fI|\fP-gno-specify
Enable (default) or disable specify block support. When enabled,
specify block code is elaborated. When disabled, specify blocks are
parsed but ignored. Specify blocks are commonly not needed for RTL
simulation, and in fact can hurt performance of the
simulation. However, disabling specify blocks reduces acuracy of
full-timing simulations.
.TP 8
.B -gxtypes\fI|\fP-gno-xtypes
Enable (default) or disable support for extended types. Enabling
extended types allows for new types that are supported by Icarus
Verilog as extensions beyond the baseline verilog. It may be necessary
to disable extended types if compiling code that clashes with the few
new keywords used to implement the type system.
.TP 8
.B -I\fIincludedir\fP
Append directory \fIincludedir\fP to list of directories searched
for Verilog include files. The \fB-I\fP switch may be used many times
+73 -53
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.67 2005/07/14 23:38:44 steve Exp $"
#ident "$Id: main.c,v 1.72 2006/10/02 18:15:47 steve Exp $"
#endif
# include "config.h"
@@ -108,11 +108,11 @@ const char*targ = "vvp";
const char*depfile = 0;
const char*generation = "2x";
const char*gen_specify = "specify";
const char*gen_xtypes = "xtypes";
char warning_flags[16] = "";
char*inc_list = 0;
char*def_list = 0;
char*mod_list = 0;
char*command_filename = 0;
@@ -123,6 +123,9 @@ char*source_path = 0;
FILE*source_file = 0;
unsigned source_count = 0;
char*defines_path = 0;
FILE*defines_file = 0;
char*iconfig_path = 0;
FILE*iconfig_file = 0;
@@ -268,9 +271,12 @@ static int t_default(char*cmd, unsigned ncmd)
rc = system(cmd);
remove(source_path);
if ( ! getenv("IVERILOG_ICONFIG"))
if ( ! getenv("IVERILOG_ICONFIG")) {
remove(source_path);
remove(iconfig_path);
remove(defines_path);
}
if (rc != 0) {
if (rc == 127) {
fprintf(stderr, "Failed to execute: %s\n", cmd);
@@ -340,32 +346,12 @@ void process_library2_switch(const char *name)
void process_include_dir(const char *name)
{
if (inc_list == 0) {
inc_list = malloc(strlen(" -I")+strlen(name)+1);
strcpy(inc_list, " -I");
strcat(inc_list, name);
} else {
inc_list = realloc(inc_list, strlen(inc_list)
+ strlen(" -I")
+ strlen(name) + 1);
strcat(inc_list, " -I");
strcat(inc_list, name);
}
fprintf(defines_file, "I:%s\n", name);
}
void process_define(const char*name)
{
if (def_list == 0) {
def_list = malloc(strlen(" -D")+strlen(name)+1);
strcpy(def_list, " -D");
strcat(def_list, name);
} else {
def_list = realloc(def_list, strlen(def_list)
+ strlen(" -D")
+ strlen(name) + 1);
strcat(def_list, " -D");
strcat(def_list, name);
}
fprintf(defines_file,"D:%s\n", name);
}
/*
@@ -396,13 +382,28 @@ int process_generation(const char*name)
else if (strcmp(name,"2x") == 0)
generation = "2x";
else if (strcmp(name,"xtypes") == 0)
gen_xtypes = "xtypes";
else if (strcmp(name,"no-xtypes") == 0)
gen_xtypes = "no-xtypes";
else if (strcmp(name,"specify") == 0)
gen_specify = "specify";
else if (strcmp(name,"no-specify") == 0)
gen_specify = "no-specify";
else {
fprintf(stderr, "Unknown/Unsupported Language generation "
"%s\n", name);
fprintf(stderr, "Supported generations are:\n");
fprintf(stderr, " 1 -- IEEE1364-1995 (Verilog 1)\n"
" 2 -- IEEE1364-2001 (Verilog 2001)\n"
" 2x -- Verilog with extensions\n");
" 2x -- Verilog with extensions\n"
"Other generation flags:\n"
" specify | no-specify\n"
" xtypes | no-xtypes\n");
return 1;
}
@@ -465,6 +466,19 @@ int main(int argc, char **argv)
return 1;
}
defines_path = strdup(my_tempfile("ivrlg2", &defines_file));
if (NULL == defines_file) {
fprintf(stderr, "%s: Error opening temporary file %s\n",
argv[0], defines_path);
fprintf(stderr, "%s: Please check TMP or TMPDIR.\n", argv[0]);
fclose(source_file);
remove(source_path);
return 1;
}
fprintf(defines_file, "D:__ICARUS__=1\n");
/* Create another temporary file for passing configuration
information to ivl. */
@@ -485,6 +499,9 @@ int main(int argc, char **argv)
fprintf(stderr, "%s: Please check TMP or TMPDIR.\n", argv[0]);
fclose(source_file);
remove(source_path);
fclose(defines_file);
remove(defines_path);
return 1;
}
@@ -616,6 +633,8 @@ int main(int argc, char **argv)
if (mtm != 0) fprintf(iconfig_file, "-T:%s\n", mtm);
fprintf(iconfig_file, "generation:%s\n", generation);
fprintf(iconfig_file, "generation:%s\n", gen_specify);
fprintf(iconfig_file, "generation:%s\n", gen_xtypes);
fprintf(iconfig_file, "warnings:%s\n", warning_flags);
fprintf(iconfig_file, "out:%s\n", opath);
if (depfile) fprintf(iconfig_file, "depfile:%s\n", depfile);
@@ -638,6 +657,10 @@ int main(int argc, char **argv)
}
}
if (depfile) {
fprintf(defines_file, "M:%s\n", depfile);
}
/* Finally, process all the remaining words on the command
line as file names. */
for (idx = optind ; idx < argc ; idx += 1)
@@ -647,6 +670,9 @@ int main(int argc, char **argv)
fclose(source_file);
source_file = 0;
fclose(defines_file);
defines_file = 0;
if (source_count == 0) {
fprintf(stderr, "%s: No input files.\n", argv[0]);
fprintf(stderr, "%s\n", HELP);
@@ -656,33 +682,14 @@ int main(int argc, char **argv)
/* Start building the preprocess command line. */
sprintf(tmp, "%s%civlpp %s%s -D__ICARUS__=1 -f%s ", pbase,sep,
sprintf(tmp, "%s%civlpp %s%s -F%s -f%s ", pbase,sep,
verbose_flag?" -v":"",
e_flag?"":" -L", source_path);
e_flag?"":" -L", defines_path, source_path);
ncmd = strlen(tmp);
cmd = malloc(ncmd + 1);
strcpy(cmd, tmp);
if (inc_list) {
cmd = realloc(cmd, ncmd + strlen(inc_list) + 1);
strcat(cmd, inc_list);
ncmd += strlen(inc_list);
}
if (def_list) {
cmd = realloc(cmd, ncmd + strlen(def_list) + 1);
strcat(cmd, def_list);
ncmd += strlen(def_list);
}
if (depfile) {
cmd = realloc(cmd, ncmd + strlen(depfile) + 5);
strcat(cmd, " -M ");
strcat(cmd, depfile);
ncmd += strlen(depfile) + 4;
}
/* If the -E flag was given on the command line, then all we
do is run the preprocessor and put the output where the
user wants it. */
@@ -720,10 +727,8 @@ int main(int argc, char **argv)
/* Write the preprocessor command needed to preprocess a
single file. This may be used to preprocess library
files. */
fprintf(iconfig_file, "ivlpp:%s%civlpp -D__ICARUS__ -L %s %s\n",
pbase, sep,
inc_list? inc_list : "",
def_list? def_list : "");
fprintf(iconfig_file, "ivlpp:%s%civlpp -L -F%s\n",
pbase, sep, defines_path);
/* Done writing to the iconfig file. Close it now. */
fclose(iconfig_file);
@@ -735,6 +740,21 @@ int main(int argc, char **argv)
/*
* $Log: main.c,v $
* Revision 1.72 2006/10/02 18:15:47 steve
* Fix handling of dep path in new argument passing method.
*
* Revision 1.71 2006/09/28 04:35:18 steve
* Support selective control of specify and xtypes features.
*
* Revision 1.70 2006/09/20 22:30:52 steve
* Do not pass -D__ICARUS__ to ivlpp.
*
* Revision 1.69 2006/07/26 00:11:40 steve
* Pass depfiles through temp defines file.
*
* Revision 1.68 2006/07/26 00:02:48 steve
* Pass defines and includes through temp file.
*
* Revision 1.67 2005/07/14 23:38:44 steve
* Display as version 0.9.devel
*
+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.
*
+7 -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: elab_anet.cc,v 1.11 2005/07/11 16:56:50 steve Exp $"
#ident "$Id: elab_anet.cc,v 1.12 2006/05/01 20:47:58 steve Exp $"
#endif
# include "config.h"
@@ -89,10 +89,13 @@ NetNet* PEConcat::elaborate_anet(Design*des, NetScope*scope) const
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT_REG, pins);
/* Assume that all the data types are the same. */
osig->data_type(nets[0]->data_type());
pins = 0;
for (unsigned idx = nets.count() ; idx > 0 ; idx -= 1) {
NetNet*cur = nets[idx-1];
assert(cur->data_type() == osig->data_type());
for (unsigned pin = 0; pin < cur->pin_count(); pin += 1) {
connect(osig->pin(pins), cur->pin(pin));
pins += 1;
@@ -166,6 +169,9 @@ NetNet* PEIdent::elaborate_anet(Design*des, NetScope*scope) const
/*
* $Log: elab_anet.cc,v $
* Revision 1.12 2006/05/01 20:47:58 steve
* More explicit datatype setup.
*
* Revision 1.11 2005/07/11 16:56:50 steve
* Remove NetVariable and ivl_variable_t structures.
*
+572 -264
View File
File diff suppressed because it is too large Load Diff
+176 -123
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.33 2006/02/02 02:43:57 steve Exp $"
#ident "$Id: elab_lval.cc,v 1.38 2007/01/16 05:44:15 steve Exp $"
#endif
# include "config.h"
@@ -25,7 +25,7 @@
# include "PExpr.h"
# include "netlist.h"
# include "netmisc.h"
# include "compiler.h"
# include <iostream>
/*
@@ -149,25 +149,10 @@ 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() <<
@@ -179,6 +164,27 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
assert(reg);
if (reg->array_dimensions() > 0)
return elaborate_lval_net_word_(des, scope, reg);
if (sel_ == SEL_PART) {
NetAssign_*lv = new NetAssign_(reg);
elaborate_lval_net_part_(des, scope, lv);
return lv;
}
if (sel_ == SEL_IDX_UP) {
NetAssign_*lv = new NetAssign_(reg);
elaborate_lval_net_idx_up_(des, scope, lv);
return lv;
}
if (sel_ == 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. */
@@ -192,54 +198,22 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
return 0;
}
assert(msb_ == 0);
assert(lsb_ == 0);
long msb, lsb;
NetExpr*mux;
if (msb_ || lsb_) {
assert(msb_ && lsb_);
/* This handles part selects. In this case, there are
two bit select expressions, and both must be
constant. Evaluate them and pass the results back to
the caller. */
verinum*vl = lsb_->eval_const(des, scope);
if (vl == 0) {
cerr << lsb_->get_line() << ": error: "
"Part select expressions must be constant."
<< endl;
cerr << lsb_->get_line() << ": : This lsb expression "
"violates the rule: " << *lsb_ << endl;
des->errors += 1;
return 0;
}
verinum*vm = msb_->eval_const(des, scope);
if (vm == 0) {
cerr << msb_->get_line() << ": error: "
"Part select expressions must be constant."
<< endl;
cerr << msb_->get_line() << ": : This msb expression "
"violates the rule: " << *msb_ << endl;
des->errors += 1;
return 0;
}
msb = vm->as_long();
lsb = vl->as_long();
mux = 0;
} else if (! idx_.empty()) {
if (! idx_.empty()) {
/* 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(msb_ == 0);
assert(lsb_ == 0);
assert(idx_.size() == 1);
verinum*v = idx_[0]->eval_const(des, scope);
if (v == 0) {
NetExpr*m = idx_[0]->elaborate_expr(des, scope);
NetExpr*m = idx_[0]->elaborate_expr(des, scope, -1, false);
assert(m);
msb = 0;
lsb = 0;
@@ -257,8 +231,6 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
/* No select expressions, so presume a part select the
width of the register. */
assert(msb_ == 0);
assert(lsb_ == 0);
msb = reg->msb();
lsb = reg->lsb();
mux = 0;
@@ -273,7 +245,13 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
bmux to select the target bit. */
lv = new NetAssign_(reg);
lv->set_bmux(mux);
/* Correct the mux for the range of the vector. */
if (reg->msb() < reg->lsb())
mux = make_sub_expr(reg->lsb(), mux);
else if (reg->lsb() != 0)
mux = make_add_expr(mux, - reg->lsb());
lv->set_part(mux, 1);
} else if (msb == reg->msb() && lsb == reg->lsb()) {
@@ -319,94 +297,147 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
return lv;
}
NetAssign_* PEIdent::elaborate_mem_lval_(Design*des, NetScope*scope,
NetMemory*mem) const
NetAssign_* PEIdent::elaborate_lval_net_word_(Design*des,
NetScope*scope,
NetNet*reg) 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]);
if (ix == 0)
return 0;
NetExpr*word = elab_and_eval(des, scope, idx_[0], -1);
NetAssign_*lv = new NetAssign_(mem);
lv->set_bmux(ix);
// 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()) {
/* If there is no extra part select, then we are done. */
if (msb_ == 0 && lsb_ == 0) {
lv->set_part(0U, mem->width());
return lv;
word = make_add_expr(word, 0-base);
if (NetExpr*tmp = word->eval_tree()) {
word = tmp;
}
}
assert(sel_ != SEL_NONE);
assert(msb_ && lsb_);
NetAssign_*lv = new NetAssign_(reg);
lv->set_word(word);
if (sel_ == SEL_PART) {
NetExpr*le = elab_and_eval(des, scope, lsb_);
NetExpr*me = elab_and_eval(des, scope, msb_);
if (debug_elaborate)
cerr << get_line() << ": debug: Set array word=" << *word << endl;
NetEConst*lec = dynamic_cast<NetEConst*>(le);
NetEConst*mec = dynamic_cast<NetEConst*>(me);
/* An array word may also have part selects applied to them. */
if (lec == 0 || mec == 0) {
cerr << get_line() << ": error: Part select "
<< "expressions must be constant." << endl;
if (sel_ == SEL_PART)
elaborate_lval_net_part_(des, scope, lv);
if (sel_ == SEL_IDX_UP)
elaborate_lval_net_idx_up_(des, scope, lv);
if (sel_ == SEL_IDX_DO)
elaborate_lval_net_idx_do_(des, scope, lv);
return lv;
}
bool PEIdent::elaborate_lval_net_part_(Design*des,
NetScope*scope,
NetAssign_*lv) const
{
long msb, lsb;
bool flag = calculate_parts_(des, scope, msb, lsb);
if (!flag)
return false;
NetNet*reg = lv->sig();
assert(reg);
if (msb == reg->msb() && lsb == reg->lsb()) {
/* No bit select, and part select covers the entire
vector. Simplest case. */
} else {
/* If the bit/part select is constant, then make the
NetAssign_ only as wide as it needs to be and connect
only to the selected bits of the reg. */
unsigned loff = reg->sb_to_idx(lsb);
unsigned moff = reg->sb_to_idx(msb);
unsigned wid = moff - loff + 1;
if (moff < loff) {
cerr << get_line() << ": error: part select "
<< reg->name() << "[" << msb<<":"<<lsb<<"]"
<< " is reversed." << endl;
des->errors += 1;
delete le;
delete me;
return lv;
return false;
}
verinum wedv = mec->value() - lec->value();
unsigned wid = wedv.as_long() + 1;
/* If the part select extends beyond the extreme of the
variable, then report an error. Note that loff is
converted to normalized form so is relative the
variable pins. */
lv->set_part(lec, wid);
return lv;
if ((wid + loff) > reg->vector_width()) {
cerr << get_line() << ": error: bit/part select "
<< reg->name() << "[" << msb<<":"<<lsb<<"]"
<< " is out of range." << endl;
des->errors += 1;
return false;
}
lv->set_part(new NetEConst(verinum(loff)), wid);
}
assert(sel_ == SEL_IDX_UP || sel_ == SEL_IDX_DO);
return true;
}
NetExpr*wid_ex = elab_and_eval(des, scope, lsb_);
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;
bool PEIdent::elaborate_lval_net_idx_up_(Design*des,
NetScope*scope,
NetAssign_*lv) const
{
assert(lsb_);
assert(msb_);
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() <<
"." << endl;
cerr << reg->get_line() << ": : " << path_ <<
" is declared here as " << reg->type() << "." << endl;
des->errors += 1;
return lv;
return false;
}
unsigned wid = wid_ec->value().as_ulong();
unsigned long wid;
calculate_up_do_width_(des, scope, wid);
NetExpr*base_ex = elab_and_eval(des, scope, msb_);
if (base_ex == 0) {
return 0;
}
NetExpr*base = elab_and_eval(des, scope, msb_, -1);
if (sel_ == SEL_IDX_DO && wid > 1) {
base_ex = make_add_expr(base_ex, 1-(long)wid);
}
/* Correct the mux for the range of the vector. */
if (reg->msb() < reg->lsb())
base = make_sub_expr(reg->lsb(), base);
else if (reg->lsb() != 0)
base = make_add_expr(base, - reg->lsb());
lv->set_part(base_ex, wid);
return lv;
if (debug_elaborate)
cerr << get_line() << ": debug: Set part select width="
<< wid << ", base=" << *base << endl;
lv->set_part(base, wid);
return true;
}
bool PEIdent::elaborate_lval_net_idx_do_(Design*des,
NetScope*scope,
NetAssign_*lv) const
{
assert(lsb_);
assert(msb_);
cerr << get_line() << ": internal error: don't know how to "
"deal with SEL_IDX_DO in lval?" << endl;
des->errors += 1;
return false;
}
NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*, bool) const
@@ -419,6 +450,28 @@ NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*, bool) const
/*
* $Log: elab_lval.cc,v $
* Revision 1.38 2007/01/16 05:44:15 steve
* Major rework of array handling. Memories are replaced with the
* more general concept of arrays. The NetMemory and NetEMemory
* classes are removed from the ivl core program, and the IVL_LPM_RAM
* lpm type is removed from the ivl_target API.
*
* Revision 1.37 2006/11/04 06:19:25 steve
* Remove last bits of relax_width methods, and use test_width
* to calculate the width of an r-value expression that may
* contain unsized numbers.
*
* Revision 1.36 2006/06/02 04:48:50 steve
* Make elaborate_expr methods aware of the width that the context
* requires of it. In the process, fix sizing of the width of unary
* minus is context determined sizes.
*
* Revision 1.35 2006/04/16 00:54:04 steve
* Cleanup lval part select handling.
*
* Revision 1.34 2006/04/16 00:15:43 steve
* Fix part selects in l-values.
*
* Revision 1.33 2006/02/02 02:43:57 steve
* Allow part selects of memory words in l-values.
*
+466 -184
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999-2005 Stephen Williams (steve@icarus.com)
* Copyright (c) 1999-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: elab_net.cc,v 1.179 2006/04/10 00:32:14 steve Exp $"
#ident "$Id: elab_net.cc,v 1.194 2007/01/20 02:10:45 steve Exp $"
#endif
# include "config.h"
@@ -209,14 +209,21 @@ NetNet* PEBinary::elaborate_net_add_(Design*des, NetScope*scope,
assert(0);
}
bool expr_signed = lsig->get_signed() && rsig->get_signed();
// Pad out the operands, if necessary, the match the width of
// the adder device.
if (lsig->vector_width() < width)
lsig = pad_to_width(des, lsig, width);
if (expr_signed)
lsig = pad_to_width_signed(des, lsig, width);
else
lsig = pad_to_width(des, lsig, width);
if (rsig->vector_width() < width)
rsig = pad_to_width(des, rsig, width);
if (expr_signed)
rsig = pad_to_width_signed(des, rsig, width);
else
rsig = pad_to_width(des, rsig, width);
// Check that the argument types match.
if (lsig->data_type() != rsig->data_type()) {
@@ -232,6 +239,7 @@ NetNet* PEBinary::elaborate_net_add_(Design*des, NetScope*scope,
osig = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, owidth);
osig->data_type(lsig->data_type());
osig->set_signed(expr_signed);
osig->local_flag(true);
if (debug_elaborate) {
cerr << get_line() << ": debug: Elaborate NetAddSub "
@@ -383,6 +391,7 @@ static NetNet* compare_eq_constant(Design*des, NetScope*scope,
1);
NetEConst*ogate = new NetEConst(oval);
NetNet*osig = ogate->synthesize(des);
osig->data_type(lsig->data_type());
delete ogate;
if (debug_elaborate)
@@ -437,7 +446,7 @@ static NetNet* compare_eq_constant(Design*des, NetScope*scope,
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, 0, 0);
tmp->data_type(IVL_VT_LOGIC);
tmp->data_type(lsig->data_type());
tmp->local_flag(true);
tmp->set_line(*lsig);
@@ -473,7 +482,7 @@ NetNet* PEBinary::elaborate_net_cmp_(Design*des, NetScope*scope,
(so that the eval_tree method can reduce constant
expressions, including parameters) then turn those results
into synthesized nets. */
NetExpr*lexp = elab_and_eval(des, scope, left_);
NetExpr*lexp = elab_and_eval(des, scope, left_, lwidth);
if (lexp == 0) {
cerr << get_line() << ": error: Cannot elaborate ";
left_->dump(cerr);
@@ -481,7 +490,7 @@ NetNet* PEBinary::elaborate_net_cmp_(Design*des, NetScope*scope,
return 0;
}
NetExpr*rexp = elab_and_eval(des, scope, right_);
NetExpr*rexp = elab_and_eval(des, scope, right_, lwidth);
if (rexp == 0) {
cerr << get_line() << ": error: Cannot elaborate ";
right_->dump(cerr);
@@ -872,6 +881,7 @@ NetNet* PEBinary::elaborate_net_log_(Design*des, NetScope*scope,
temporary signal to represent it. */
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, 1);
tmp->data_type(IVL_VT_LOGIC);
tmp->local_flag(true);
connect(gate->pin(1), tmp->pin(0));
@@ -893,6 +903,7 @@ NetNet* PEBinary::elaborate_net_log_(Design*des, NetScope*scope,
temporary signal to represent it. */
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, 1);
tmp->data_type(IVL_VT_LOGIC);
tmp->local_flag(true);
connect(gate->pin(2), tmp->pin(0));
@@ -942,6 +953,7 @@ NetNet* PEBinary::elaborate_net_mul_(Design*des, NetScope*scope,
connect(odev->pin(idx), osig->pin(idx));
des->add_node(odev);
osig->data_type(IVL_VT_LOGIC);
osig->local_flag(true);
return osig;
}
@@ -1129,6 +1141,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(),
@@ -1205,39 +1224,11 @@ NetNet* PECallFunction::elaborate_net(Design*des, NetScope*scope,
unsigned errors = 0;
unsigned func_pins = 0;
/* 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 ((parms_.count() != 1) || (parms_[0] == 0)) {
cerr << get_line() << ": error: The $signed() function "
<< "takes exactly one(1) argument." << endl;
des->errors += 1;
return 0;
}
if (path_.peek_name(0)[0] == '$')
return elaborate_net_sfunc_(des, scope,
width, rise, fall, decay,
drive0, drive1);
PExpr*expr = parms_[0];
NetNet*sub = expr->elaborate_net(des, scope, width, rise,
fall, decay, drive0, drive1);
sub->set_signed(true);
return sub;
}
/* handle $unsigned like $signed */
if (strcmp(path_.peek_name(0), "$unsigned") == 0) {
if ((parms_.count() != 1) || (parms_[0] == 0)) {
cerr << get_line() << ": error: The $unsigned() function "
<< "takes exactly one(1) argument." << endl;
des->errors += 1;
return 0;
}
PExpr*expr = parms_[0];
NetNet*sub = expr->elaborate_net(des, scope, width, rise,
fall, decay, drive0, drive1);
sub->set_signed(false);
return sub;
}
/* Look up the function definition. */
NetFuncDef*def = des->find_function(scope, path_);
@@ -1298,6 +1289,7 @@ NetNet* PECallFunction::elaborate_net(Design*des, NetScope*scope,
NetNet::WIRE,
def->return_sig()->vector_width());
osig->local_flag(true);
osig->data_type(def->return_sig()->data_type());
connect(net->pin(0), osig->pin(0));
@@ -1314,6 +1306,87 @@ NetNet* PECallFunction::elaborate_net(Design*des, NetScope*scope,
return osig;
}
NetNet* PECallFunction::elaborate_net_sfunc_(Design*des, NetScope*scope,
unsigned width,
const NetExpr* rise,
const NetExpr* fall,
const NetExpr* decay,
Link::strength_t drive0,
Link::strength_t drive1) const
{
/* 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 ((parms_.count() != 1) || (parms_[0] == 0)) {
cerr << get_line() << ": error: The $signed() function "
<< "takes exactly one(1) argument." << endl;
des->errors += 1;
return 0;
}
PExpr*expr = parms_[0];
NetNet*sub = expr->elaborate_net(des, scope, width, rise,
fall, decay, drive0, drive1);
sub->set_signed(true);
return sub;
}
/* handle $unsigned like $signed */
if (strcmp(path_.peek_name(0), "$unsigned") == 0) {
if ((parms_.count() != 1) || (parms_[0] == 0)) {
cerr << get_line() << ": error: The $unsigned() function "
<< "takes exactly one(1) argument." << endl;
des->errors += 1;
return 0;
}
PExpr*expr = parms_[0];
NetNet*sub = expr->elaborate_net(des, scope, width, rise,
fall, decay, drive0, drive1);
sub->set_signed(false);
return sub;
}
const struct sfunc_return_type*def = lookup_sys_func(path_.peek_name(0));
if (def == 0) {
cerr << get_line() << ": error: System function "
<< path_.peek_name(0) << " not defined." << endl;
des->errors += 1;
return 0;
}
NetSysFunc*net = new NetSysFunc(scope, scope->local_symbol(),
def, 1+parms_.count());
des->add_node(net);
net->set_line(*this);
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, def->wid);
osig->local_flag(true);
osig->data_type(def->type);
osig->set_line(*this);
connect(net->pin(0), osig->pin(0));
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) {
NetNet*tmp = parms_[idx]->elaborate_net(des, scope, 0,
0, 0, 0,
Link::STRONG, Link::STRONG);
if (tmp == 0) {
cerr << get_line() << ": error: Unable to elaborate "
<< "port " << idx << " of call to " << path_ <<
"." << endl;
continue;
}
connect(net->pin(1+idx), tmp->pin(0));
}
return osig;
}
/*
* The concatenation operator, as a net, is a wide signal that is
@@ -1336,7 +1409,7 @@ NetNet* PEConcat::elaborate_net(Design*des, NetScope*scope,
constant. This is used to generate the width of the
concatenation. */
if (repeat_) {
NetExpr*etmp = elab_and_eval(des, scope, repeat_);
NetExpr*etmp = elab_and_eval(des, scope, repeat_, -1);
assert(etmp);
NetEConst*erep = dynamic_cast<NetEConst*>(etmp);
@@ -1474,7 +1547,7 @@ NetNet* PEIdent::elaborate_net_bitmux_(Design*des, NetScope*scope,
NetNet*sel;
if (sig->msb() < sig->lsb()) {
NetExpr*sel_expr = idx_[0]->elaborate_expr(des, scope);
NetExpr*sel_expr = idx_[0]->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;
@@ -1484,7 +1557,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);
NetExpr*sel_expr = idx_[0]->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;
@@ -1528,18 +1601,10 @@ NetNet* PEIdent::elaborate_net(Design*des, NetScope*scope,
assert(scope);
NetNet* sig = 0;
NetMemory* mem = 0;
const NetExpr*par = 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. */
@@ -1553,14 +1618,14 @@ NetNet* PEIdent::elaborate_net(Design*des, NetScope*scope,
constant value, extend the value to fit the desired
output. */
if (lwidth > pvalue.len()) {
verinum tmp (0UL, lwidth);
verinum tmp ((uint64_t)0, lwidth);
for (unsigned idx = 0 ; idx < pvalue.len() ; idx += 1)
tmp.set(idx, pvalue.get(idx));
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);
@@ -1615,6 +1680,13 @@ NetNet* PEIdent::elaborate_net(Design*des, NetScope*scope,
assert(sig);
/* Handle the case that this is an array elsewhere. */
if (sig->array_dimensions() > 0) {
return elaborate_net_array_(des, scope, sig, lwidth,
rise, fall, decay,
drive0, drive1);
}
/* Catch the case of a non-constant bit select. That should be
handled elsewhere. */
if (! idx_.empty()) {
@@ -1662,68 +1734,83 @@ 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::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
{
assert(scope);
if (idx_.empty()) {
cerr << get_line() << ": error: memory reference without"
" the required index expression." << endl;
des->errors += 1;
return 0;
}
assert(msb_ == 0);
assert(lsb_ == 0);
assert(idx_.size() == 1);
/* 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;
NetExpr*adr_expr = elab_and_eval(des, scope, idx_[0]);
/* 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*adr = adr_expr->synthesize(des);
delete adr_expr;
must_be_self_determined_flag = must_be_self_determined_save;
if (adr == 0)
NetExpr*index_ex = elab_and_eval(des, scope, idx_[0], -1);
if (index_ex == 0)
return 0;
NetRamDq*ram = new NetRamDq(scope, scope->local_symbol(),
mem, adr->vector_width());
des->add_node(ram);
if (NetEConst*index_co = dynamic_cast<NetEConst*> (index_ex)) {
long index = index_co->value().as_long();
connect(ram->pin_Address(), adr->pin(0));
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*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), con_n->pin(0));
return tmp;
}
connect(ram->pin_Q(), osig->pin(0));
assert(sig->array_index_is_valid(index));
index = sig->array_index_to_address(index);
return osig;
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));
return tmp;
}
unsigned selwid = index_ex->expr_width();
NetArrayDq*mux = new NetArrayDq(scope, scope->local_symbol(),
sig, selwid);
mux->set_line(*this);
des->add_node(mux);
// 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);
}
NetNet*index_net = index_ex->synthesize(des);
connect(mux->pin_Address(), index_net->pin(0));
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());
return tmp;
}
/*
@@ -1733,8 +1820,9 @@ NetNet* PEIdent::elaborate_net_ram_(Design*des, NetScope*scope,
* destination. The caller can connect gate outputs to this signal to
* make the l-value connections.
*/
NetNet* PEConcat::elaborate_lnet(Design*des, NetScope*scope,
bool implicit_net_ok) const
NetNet* PEConcat::elaborate_lnet_common_(Design*des, NetScope*scope,
bool implicit_net_ok,
bool bidirectional_flag) const
{
assert(scope);
@@ -1764,8 +1852,12 @@ NetNet* PEConcat::elaborate_lnet(Design*des, NetScope*scope,
continue;
}
nets[idx] = parms_[idx]->elaborate_lnet(des, scope,
implicit_net_ok);
if (bidirectional_flag) {
nets[idx] = parms_[idx]->elaborate_bi_net(des, scope);
} else {
nets[idx] = parms_[idx]->elaborate_lnet(des, scope,
implicit_net_ok);
}
if (nets[idx] == 0)
errors += 1;
else
@@ -1790,6 +1882,9 @@ NetNet* PEConcat::elaborate_lnet(Design*des, NetScope*scope,
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, width);
/* 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());
if (debug_elaborate) {
cerr << get_line() << ": debug: Generating part selects "
@@ -1797,11 +1892,14 @@ NetNet* PEConcat::elaborate_lnet(Design*des, NetScope*scope,
<< endl;
}
NetPartSelect::dir_t part_dir = bidirectional_flag
? NetPartSelect::BI
: NetPartSelect::VP;
for (unsigned idx = 0 ; idx < nets.count() ; idx += 1) {
unsigned wid = nets[idx]->vector_width();
unsigned off = width - wid;
NetPartSelect*ps = new NetPartSelect(osig, off, wid,
NetPartSelect::VP);
NetPartSelect*ps = new NetPartSelect(osig, off, wid, part_dir);
des->add_node(ps);
connect(ps->pin(1), osig->pin(0));
@@ -1812,10 +1910,22 @@ NetNet* PEConcat::elaborate_lnet(Design*des, NetScope*scope,
}
assert(width == 0);
osig->data_type(nets[0]->data_type());
osig->local_flag(true);
return osig;
}
NetNet* PEConcat::elaborate_lnet(Design*des, NetScope*scope,
bool implicit_net_ok) const
{
return elaborate_lnet_common_(des, scope, implicit_net_ok, false);
}
NetNet* PEConcat::elaborate_bi_net(Design*des, NetScope*scope) const
{
return elaborate_lnet_common_(des, scope, true, true);
}
/*
* Elaborate a number as a NetConst object.
*/
@@ -1884,69 +1994,143 @@ 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
{
if (msb_ && lsb_) {
verinum*mval = msb_->eval_const(des, scope);
assert(mval);
verinum*lval = lsb_->eval_const(des, scope);
assert(lval);
switch (sel_) {
default:
cerr << get_line() << ": internal error: "
<< "Unexpected sel_ value = " << sel_ << endl;
assert(0);
break;
midx = sig->sb_to_idx(mval->as_long());
lidx = sig->sb_to_idx(lval->as_long());
case PEIdent::SEL_IDX_DO:
case PEIdent::SEL_IDX_UP: {
assert(msb_);
assert(lsb_);
assert(idx_.empty());
/* Detect reversed indices of a part select. */
if (lidx > midx) {
cerr << get_line() << ": error: Part select "
<< sig->name() << "[" << mval->as_long() << ":"
<< lval->as_long() << "] indices reversed." << endl;
cerr << get_line() << ": : Did you mean "
<< sig->name() << "[" << lval->as_long() << ":"
<< mval->as_long() << "]?" << endl;
unsigned tmp = midx;
midx = lidx;
lidx = tmp;
des->errors += 1;
}
NetExpr*tmp_ex = elab_and_eval(des, scope, msb_, -1);
NetEConst*tmp = dynamic_cast<NetEConst*>(tmp_ex);
assert(tmp);
/* Detect a part select out of range. */
if (midx >= sig->vector_width()) {
cerr << get_line() << ": error: Part select "
<< sig->name() << "[" << mval->as_long() << ":"
<< lval->as_long() << "] out of range." << endl;
long midx_val = tmp->value().as_long();
midx = sig->sb_to_idx(midx_val);
delete tmp_ex;
tmp_ex = elab_and_eval(des, scope, 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)
lidx = sig->sb_to_idx(midx_val+wid-1);
else
lidx = sig->sb_to_idx(midx_val-wid+1);
if (midx < lidx) {
long tmp = midx;
midx = lidx;
lidx = tmp;
}
break;
}
case PEIdent::SEL_PART: {
assert(msb_);
assert(lsb_);
assert(idx_.empty());
NetExpr*tmp_ex = elab_and_eval(des, scope, msb_, -1);
NetEConst*tmp = dynamic_cast<NetEConst*>(tmp_ex);
assert(tmp);
long midx_val = tmp->value().as_long();
midx = sig->sb_to_idx(midx_val);
delete tmp_ex;
tmp_ex = elab_and_eval(des, scope, lsb_, -1);
tmp = dynamic_cast<NetEConst*>(tmp_ex);
if (tmp == 0) {
cerr << get_line() << ": internal error: "
<< "lsb expression is not constant?: "
<< *tmp_ex << ", " << *lsb_ << endl;
}
assert(tmp);
long lidx_val = tmp->value().as_long();
lidx = sig->sb_to_idx(lidx_val);
delete tmp_ex;
/* Detect reversed indices of a part select. */
if (lidx > midx) {
cerr << get_line() << ": error: Part select "
<< sig->name() << "[" << midx_val << ":"
<< lidx_val << "] indices reversed." << endl;
cerr << get_line() << ": : Did you mean "
<< sig->name() << "[" << lidx_val << ":"
<< midx_val << "]?" << endl;
unsigned tmp = midx;
midx = lidx;
lidx = tmp;
des->errors += 1;
}
/* Detect a part select out of range. */
if (midx >= sig->vector_width()) {
cerr << get_line() << ": error: Part select "
<< sig->name() << "[" << midx_val << ":"
<< midx_val << "] out of range." << endl;
midx = sig->vector_width() - 1;
lidx = 0;
des->errors += 1;
}
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);
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;
des->errors += 1;
return false;
}
assert(mval);
midx = sig->sb_to_idx(mval->as_long());
if (midx >= sig->vector_width()) {
cerr << get_line() << ": error: Index " << sig->name()
<< "[" << mval->as_long() << "] out of range."
<< endl;
des->errors += 1;
midx = 0;
}
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);
midx = sig->vector_width() - 1;
lidx = 0;
des->errors += 1;
}
} else if (!idx_.empty()) {
assert(msb_ == 0);
assert(lsb_ == 0);
assert(idx_.size() == 1);
verinum*mval = idx_[0]->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;
des->errors += 1;
return false;
}
assert(mval);
midx = sig->sb_to_idx(mval->as_long());
if (midx >= sig->vector_width()) {
cerr << get_line() << ": error: Index " << sig->name()
<< "[" << mval->as_long() << "] out of range."
<< endl;
des->errors += 1;
midx = 0;
}
lidx = midx;
} else {
assert(msb_ == 0 && lsb_ == 0);
midx = sig->vector_width() - 1;
lidx = 0;
break;
}
return true;
@@ -1964,19 +2148,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_
@@ -2021,12 +2196,44 @@ 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;
if (sig->array_dimensions() > 0) {
assert(!idx_.empty());
NetExpr*tmp_ex = elab_and_eval(des, scope, idx_[0], -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 (! 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
@@ -2296,6 +2503,7 @@ NetNet* PEString::elaborate_net(Design*des, NetScope*scope,
net = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, strbits);
}
net->data_type(IVL_VT_BOOL);
net->local_flag(true);
/* Make a verinum that is filled with the 0 pad. */
@@ -2396,6 +2604,7 @@ NetNet* PETernary::elaborate_net(Design*des, NetScope*scope,
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, 1);
tmp->data_type(IVL_VT_LOGIC);
tmp->local_flag(true);
connect(log->pin(0), tmp->pin(0));
@@ -2406,7 +2615,10 @@ NetNet* PETernary::elaborate_net(Design*des, NetScope*scope,
/* This is the width of the LPM_MUX device that I'm about to
create. It may be smaller then the desired output, but I'll
handle padding below.
handle padding below. Note that in principle the
alternatives should be padded to the output width first,
but it is more efficient to pad them only just enough to
prevent loss, and do the finished padding later.
Create a NetNet object wide enough to hold the
result. Also, pad the result values (if necessary) so that
@@ -2415,7 +2627,7 @@ NetNet* PETernary::elaborate_net(Design*des, NetScope*scope,
unsigned dwidth = (iwidth > width)? width : iwidth;
NetNet*sig = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, width);
NetNet::WIRE, dwidth);
sig->data_type(expr_type);
sig->local_flag(true);
@@ -2425,6 +2637,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
@@ -2446,6 +2663,7 @@ 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);
NetBUFZ*tmpz = new NetBUFZ(scope, scope->local_symbol(), dwidth);
tmpz->rise_time(rise);
@@ -2466,10 +2684,18 @@ NetNet* PETernary::elaborate_net(Design*des, NetScope*scope,
/* If the MUX device result is too narrow to fill out the
desired result, pad with zeros... */
assert(dwidth == width);
assert(dwidth <= width);
des->add_node(mux);
/* 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
padding inside, and is cheaper. */
if (dwidth < width)
sig = pad_to_width(des, sig, width);
return sig;
}
@@ -2580,6 +2806,11 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
reduction=true; rtype = NetUReduce::XNOR; break;
case '-': // Unary 2's complement.
// If this expression is self determined, get its width
// from the sub_expression.
if (owidth == 0)
owidth = sub_sig->vector_width();
sig = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, owidth);
sig->data_type(sub_sig->data_type());
@@ -2624,6 +2855,7 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
NetNet*tmp_sig = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE,
sub_sig->vector_width());
tmp_sig->data_type(sub_sig->data_type());
tmp_sig->local_flag(true);
connect(tmp_sig->pin(0), sub->pin_DataA());
@@ -2662,6 +2894,56 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
/*
* $Log: elab_net.cc,v $
* 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.
*
* Revision 1.188 2006/06/20 05:06:47 steve
* Sign extend operands of signed addition.
*
* Revision 1.187 2006/06/18 04:15:50 steve
* Add support for system functions in continuous assignments.
*
* Revision 1.186 2006/06/02 04:48:50 steve
* Make elaborate_expr methods aware of the width that the context
* requires of it. In the process, fix sizing of the width of unary
* minus is context determined sizes.
*
* Revision 1.185 2006/05/19 04:44:55 steve
* Get self-determined unary - width right.
*
* Revision 1.184 2006/05/01 20:47:58 steve
* More explicit datatype setup.
*
* Revision 1.183 2006/04/30 05:17:48 steve
* Get the data type of part select results right.
*
* Revision 1.182 2006/04/28 05:09:51 steve
* Handle padding of MUX net results.
*
* Revision 1.181 2006/04/28 04:28:35 steve
* Allow concatenations as arguments to inout ports.
*
* Revision 1.180 2006/04/24 05:15:07 steve
* Fix support for indexed part select in continuous assign l-values.
*
* Revision 1.179 2006/04/10 00:32:14 steve
* Clean up index expression error message.
*
+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: elab_pexpr.cc,v 1.23 2006/02/02 02:43:58 steve Exp $"
#ident "$Id: elab_pexpr.cc,v 1.25 2006/11/04 06:19:25 steve Exp $"
#endif
# include "config.h"
@@ -53,7 +53,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;
}
@@ -119,7 +119,7 @@ NetEConcat* PEConcat::elaborate_pexpr(Design*des, NetScope*scope) const
NetExpr*PEFNumber::elaborate_pexpr(Design*des, NetScope*scope) const
{
return elaborate_expr(des, scope);
return elaborate_expr(des, scope, -1, false);
}
/*
@@ -181,13 +181,13 @@ NetExpr*PEIdent::elaborate_pexpr(Design*des, NetScope*scope) const
*/
NetExpr*PENumber::elaborate_pexpr(Design*des, NetScope*sc) const
{
return elaborate_expr(des, sc);
return elaborate_expr(des, sc, -1, false);
}
NetEConst* PEString::elaborate_pexpr(Design*des, NetScope*scope) const
{
return elaborate_expr(des, scope);
return elaborate_expr(des, scope, -1, false);
}
NetETernary* PETernary::elaborate_pexpr(Design*des, NetScope*scope) const
@@ -236,6 +236,16 @@ NetExpr*PEUnary::elaborate_pexpr (Design*des, NetScope*scope) const
/*
* $Log: elab_pexpr.cc,v $
* Revision 1.25 2006/11/04 06:19:25 steve
* Remove last bits of relax_width methods, and use test_width
* to calculate the width of an r-value expression that may
* contain unsized numbers.
*
* Revision 1.24 2006/06/02 04:48:50 steve
* Make elaborate_expr methods aware of the width that the context
* requires of it. In the process, fix sizing of the width of unary
* minus is context determined sizes.
*
* Revision 1.23 2006/02/02 02:43:58 steve
* Allow part selects of memory words in l-values.
*
+25 -11
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: elab_scope.cc,v 1.39 2006/04/10 00:37:42 steve Exp $"
#ident "$Id: elab_scope.cc,v 1.41 2006/06/02 04:48:50 steve Exp $"
#endif
# include "config.h"
@@ -325,7 +325,7 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
// The initial value for the genvar does not need (nor can it
// use) the genvar itself, so we can evaluate this expression
// the same way any other paramter value is evaluated.
NetExpr*init_ex = elab_and_eval(des, container, loop_init);
NetExpr*init_ex = elab_and_eval(des, container, loop_init, -1);
NetEConst*init = dynamic_cast<NetEConst*> (init_ex);
if (init == 0) {
cerr << get_line() << ": error: Cannot evaluate genvar"
@@ -342,9 +342,10 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
container->genvar_tmp = loop_index;
container->genvar_tmp_val = 0;
verinum*test = loop_test->eval_const(des, container);
NetExpr*test_ex = elab_and_eval(des, container, loop_test, -1);
NetEConst*test = dynamic_cast<NetEConst*>(test_ex);
assert(test);
while (test->as_long()) {
while (test->value().as_long()) {
// The actual name of the scope includes the genvar so
// that each instance has a unique name in the
@@ -378,19 +379,24 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
scope_list_.push_back(scope);
// Calculate the step for the loop variable.
verinum*step = loop_step->eval_const(des, container);
NetExpr*step_ex = elab_and_eval(des, container, loop_step, -1);
NetEConst*step = dynamic_cast<NetEConst*>(step_ex);
assert(step);
if (debug_elaborate)
cerr << get_line() << ": debug: genvar step from "
<< genvar << " to " << step->as_long() << endl;
<< genvar << " to " << step->value().as_long() << endl;
genvar = step->as_long();
genvar = step->value().as_long();
container->genvar_tmp_val = genvar;
delete step;
delete test;
test = loop_test->eval_const(des, container);
delete test_ex;
test_ex = elab_and_eval(des, container, loop_test, -1);
test = dynamic_cast<NetEConst*>(test_ex);
assert(test);
}
// Clear the genvar_tmp field in the scope to reflect that the
// genvar is no longer value for evaluating expressions.
container->genvar_tmp = perm_string();
return true;
@@ -442,8 +448,8 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
return;
}
NetExpr*mse = msb_ ? elab_and_eval(des, sc, msb_) : 0;
NetExpr*lse = lsb_ ? elab_and_eval(des, sc, lsb_) : 0;
NetExpr*mse = msb_ ? elab_and_eval(des, sc, msb_, -1) : 0;
NetExpr*lse = lsb_ ? elab_and_eval(des, sc, lsb_, -1) : 0;
NetEConst*msb = dynamic_cast<NetEConst*> (mse);
NetEConst*lsb = dynamic_cast<NetEConst*> (lse);
@@ -742,6 +748,14 @@ void PWhile::elaborate_scope(Design*des, NetScope*scope) const
/*
* $Log: elab_scope.cc,v $
* Revision 1.41 2006/06/02 04:48:50 steve
* Make elaborate_expr methods aware of the width that the context
* requires of it. In the process, fix sizing of the width of unary
* minus is context determined sizes.
*
* Revision 1.40 2006/04/12 05:05:03 steve
* Use elab_and_eval to evaluate genvar expressions.
*
* Revision 1.39 2006/04/10 00:37:42 steve
* Add support for generate loops w/ wires and gates.
*
+79 -70
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.41 2006/04/10 00:37:42 steve Exp $"
#ident "$Id: elab_sig.cc,v 1.43 2007/01/16 05:44:15 steve Exp $"
#endif
# include "config.h"
@@ -318,10 +318,10 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
case PTF_REG:
if (return_type_.range) {
NetExpr*me = elab_and_eval(des, scope,
(*return_type_.range)[0]);
(*return_type_.range)[0], -1);
assert(me);
NetExpr*le = elab_and_eval(des, scope,
(*return_type_.range)[1]);
(*return_type_.range)[1], -1);
assert(le);
long mnum = 0, lnum = 0;
@@ -548,7 +548,7 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
}
NetEConst*tmp;
NetExpr*texpr = elab_and_eval(des, scope, msb_[idx]);
NetExpr*texpr = elab_and_eval(des, scope, msb_[idx], -1);
tmp = dynamic_cast<NetEConst*>(texpr);
if (tmp == 0) {
@@ -562,7 +562,7 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
mnum[idx] = tmp->value().as_long();
delete texpr;
texpr = elab_and_eval(des, scope, lsb_[idx]);
texpr = elab_and_eval(des, scope, lsb_[idx], -1);
tmp = dynamic_cast<NetEConst*>(texpr);
if (tmp == 0) {
cerr << msb_[idx]->get_line() << ": error: "
@@ -616,6 +616,9 @@ 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;
/* 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,
@@ -623,8 +626,8 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
if (lidx_ || ridx_) {
assert(lidx_ && ridx_);
NetExpr*lexp = elab_and_eval(des, scope, lidx_);
NetExpr*rexp = elab_and_eval(des, scope, ridx_);
NetExpr*lexp = elab_and_eval(des, scope, lidx_, -1);
NetExpr*rexp = elab_and_eval(des, scope, ridx_, -1);
if ((lexp == 0) || (rexp == 0)) {
cerr << get_line() << ": internal error: There is "
@@ -639,7 +642,7 @@ 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 ``"
<< "are not constant for array ``"
<< hname_.peek_tail_name() << "''." << endl;
des->errors += 1;
return;
@@ -653,73 +656,79 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
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_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 = 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,
array_s0, array_e0);
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);
}
/*
* $Log: elab_sig.cc,v $
* Revision 1.43 2007/01/16 05:44:15 steve
* Major rework of array handling. Memories are replaced with the
* more general concept of arrays. The NetMemory and NetEMemory
* classes are removed from the ivl core program, and the IVL_LPM_RAM
* lpm type is removed from the ivl_target API.
*
* Revision 1.42 2006/06/02 04:48:50 steve
* Make elaborate_expr methods aware of the width that the context
* requires of it. In the process, fix sizing of the width of unary
* minus is context determined sizes.
*
* Revision 1.41 2006/04/10 00:37:42 steve
* Add support for generate loops w/ wires and gates.
*
+349 -45
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998-2004 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-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: elaborate.cc,v 1.336 2006/04/10 00:37:42 steve Exp $"
#ident "$Id: elaborate.cc,v 1.357 2007/01/21 04:26:36 steve Exp $"
#endif
# include "config.h"
@@ -35,6 +35,7 @@
# include "pform.h"
# include "PEvent.h"
# include "PGenerate.h"
# include "PSpec.h"
# include "netlist.h"
# include "netmisc.h"
# include "util.h"
@@ -180,6 +181,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) {
@@ -267,6 +279,22 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
if (lval->vector_width() > rval->vector_width())
rval = pad_to_width(des, rval, lval->vector_width());
/* If, on the other hand, the r-value insists on being
LARGER then the l-value, use a part select to chop it down
down to size. */
if (lval->vector_width() < rval->vector_width()) {
NetPartSelect*tmp = new NetPartSelect(rval, 0,lval->vector_width(),
NetPartSelect::VP);
des->add_node(tmp);
tmp->set_line(*this);
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::TRI, lval->vector_width());
osig->set_line(*this);
osig->data_type(rval->data_type());
connect(osig->pin(0), tmp->pin(0));
rval = osig;
}
connect(lval->pin(0), rval->pin(0));
if (lval->local_flag())
@@ -292,8 +320,8 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
gates, then I am expected to make more then one
gate. Figure out how many are desired. */
if (msb_) {
NetExpr*msb_exp = elab_and_eval(des, scope, msb_);
NetExpr*lsb_exp = elab_and_eval(des, scope, lsb_);
NetExpr*msb_exp = elab_and_eval(des, scope, msb_, -1);
NetExpr*lsb_exp = elab_and_eval(des, scope, lsb_, -1);
NetEConst*msb_con = dynamic_cast<NetEConst*>(msb_exp);
NetEConst*lsb_con = dynamic_cast<NetEConst*>(lsb_exp);
@@ -506,7 +534,7 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
/* Handle the case where there is one gate that
carries the whole vector width. */
if (instance_width != sig->vector_width()) {
if (1 == sig->vector_width() && instance_width != 1) {
assert(sig->vector_width() == 1);
NetReplicate*rep
@@ -520,9 +548,21 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
sig = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, instance_width);
sig->data_type(IVL_VT_LOGIC);
sig->local_flag(true);
sig->set_line(*this);
connect(rep->pin(0), sig->pin(0));
}
if (instance_width != sig->vector_width()) {
cerr << get_line() << ": error: "
<< "Expression width " << sig->vector_width()
<< " does not match width " << instance_width
<< " of logic gate array port " << idx
<< "." << endl;
des->errors += 1;
}
connect(cur[0]->pin(idx), sig->pin(0));
@@ -556,6 +596,8 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
NetNet*tmp2 = new NetNet(scope,
scope->local_symbol(),
NetNet::WIRE, 1);
tmp2->local_flag(true);
tmp2->data_type(IVL_VT_LOGIC);
connect(cc->pin(gdx+1), tmp2->pin(0));
}
@@ -569,6 +611,8 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
connect(tmp1->pin(1), sig->pin(0));
NetNet*tmp2 = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, 1);
tmp2->local_flag(true);
tmp2->data_type(sig->data_type());
connect(tmp1->pin(0), tmp2->pin(0));
connect(cur[gdx]->pin(idx), tmp1->pin(0));
}
@@ -1312,7 +1356,7 @@ NetAssign_* PAssign_::elaborate_lval(Design*des, NetScope*scope) const
*/
static NetExpr*elaborate_delay_expr(PExpr*expr, Design*des, NetScope*scope)
{
NetExpr*dex = elab_and_eval(des, scope, expr);
NetExpr*dex = elab_and_eval(des, scope, expr, -1);
/* If the delay expression is a real constant or vector
constant, then evaluate it, scale it to the local time
@@ -1322,7 +1366,7 @@ static NetExpr*elaborate_delay_expr(PExpr*expr, Design*des, NetScope*scope)
verireal fn = tmp->value();
int shift = scope->time_unit() - des->get_precision();
long delay = fn.as_long(shift);
int64_t delay = fn.as_long64(shift);
if (delay < 0)
delay = 0;
@@ -1334,8 +1378,8 @@ static NetExpr*elaborate_delay_expr(PExpr*expr, Design*des, NetScope*scope)
if (NetEConst*tmp = dynamic_cast<NetEConst*>(dex)) {
verinum fn = tmp->value();
unsigned long delay =
des->scale_to_precision(fn.as_ulong(), scope);
uint64_t delay =
des->scale_to_precision(fn.as_ulong64(), scope);
delete tmp;
return new NetEConst(verinum(delay));
@@ -1347,7 +1391,7 @@ static NetExpr*elaborate_delay_expr(PExpr*expr, Design*des, NetScope*scope)
return that expression. */
int shift = scope->time_unit() - des->get_precision();
if (shift > 0) {
unsigned long scale = 1;
uint64_t scale = 1;
while (shift > 0) {
scale *= 10;
shift -= 1;
@@ -1386,10 +1430,19 @@ 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());
/* 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. */
NetExpr*rv = elab_and_eval(des, scope, rval(), use_width);
if (rv == 0) return 0;
assert(rv);
@@ -1427,6 +1480,7 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::REG, wid);
tmp->set_line(*this);
tmp->data_type(rv->expr_type());
NetESignal*sig = new NetESignal(tmp);
@@ -1508,7 +1562,7 @@ NetProc* PAssignNB::elaborate(Design*des, NetScope*scope) const
assert(rval());
/* Elaborate and precalculate the r-value. */
NetExpr*rv = elab_and_eval(des, scope, rval());
NetExpr*rv = elab_and_eval(des, scope, rval(), count_lval_width(lv));
if (rv == 0)
return 0;
@@ -1616,7 +1670,7 @@ NetProc* PCase::elaborate(Design*des, NetScope*scope) const
{
assert(scope);
NetExpr*expr = elab_and_eval(des, scope, expr_);
NetExpr*expr = elab_and_eval(des, scope, expr_, -1);
if (expr == 0) {
cerr << get_line() << ": error: Unable to elaborate this case"
" expression." << endl;
@@ -1668,7 +1722,7 @@ NetProc* PCase::elaborate(Design*des, NetScope*scope) const
NetExpr*gu = 0;
NetProc*st = 0;
assert(cur->expr[e]);
gu = elab_and_eval(des, scope, cur->expr[e]);
gu = elab_and_eval(des, scope, cur->expr[e], -1);
if (cur->stat)
st = cur->stat->elaborate(des, scope);
@@ -1686,7 +1740,7 @@ NetProc* PCondit::elaborate(Design*des, NetScope*scope) const
assert(scope);
// Elaborate and try to evaluate the conditional expression.
NetExpr*expr = elab_and_eval(des, scope, expr_);
NetExpr*expr = elab_and_eval(des, scope, expr_, -1);
if (expr == 0) {
cerr << get_line() << ": error: Unable to elaborate"
" condition expression." << endl;
@@ -1705,9 +1759,19 @@ 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
@@ -1793,14 +1857,13 @@ NetProc* PCallTask::elaborate_sys(Design*des, NetScope*scope) const
for (unsigned idx = 0 ; idx < parm_count ; idx += 1) {
PExpr*ex = parm(idx);
eparms[idx] = ex? ex->elaborate_expr(des, scope, true) : 0;
eparms[idx] = ex? ex->elaborate_expr(des, scope, -1, true) : 0;
/* 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;
}
@@ -1907,7 +1970,7 @@ NetProc* PCallTask::elaborate_usr(Design*des, NetScope*scope) const
NetAssign_*lv = new NetAssign_(port);
unsigned wid = count_lval_width(lv);
NetExpr*rv = elab_and_eval(des, scope, parms_[idx]);
NetExpr*rv = elab_and_eval(des, scope, parms_[idx], wid);
rv->set_width(wid);
rv = pad_to_width(rv, wid);
NetAssign*pr = new NetAssign(lv, rv);
@@ -1987,12 +2050,12 @@ NetCAssign* PCAssign::elaborate(Design*des, NetScope*scope) const
if (lval == 0)
return 0;
NetExpr*rexp = elab_and_eval(des, scope, expr_);
unsigned lwid = count_lval_width(lval);
NetExpr*rexp = elab_and_eval(des, scope, expr_, lwid);
if (rexp == 0)
return 0;
unsigned lwid = count_lval_width(lval);
rexp->set_width(lwid);
rexp = pad_to_width(rexp, lwid);
@@ -2041,7 +2104,7 @@ NetProc* PDelayStatement::elaborate(Design*des, NetScope*scope) const
if (NetEConst*tmp = dynamic_cast<NetEConst*>(dex)) {
if (statement_)
return new NetPDelay(tmp->value().as_ulong(),
return new NetPDelay(tmp->value().as_ulong64(),
statement_->elaborate(des, scope));
else
return new NetPDelay(tmp->value().as_ulong(), 0);
@@ -2204,8 +2267,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;
}
@@ -2230,12 +2294,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);
@@ -2335,7 +2398,7 @@ NetProc* PEventStatement::elaborate_wait(Design*des, NetScope*scope,
/* Elaborate wait expression. Don't eval yet, we will do that
shortly, after we apply a reduction or. */
NetExpr*expr = pe->elaborate_expr(des, scope);
NetExpr*expr = pe->elaborate_expr(des, scope, -1, false);
if (expr == 0) {
cerr << get_line() << ": error: Unable to elaborate"
" wait condition expression." << endl;
@@ -2515,12 +2578,12 @@ NetForce* PForce::elaborate(Design*des, NetScope*scope) const
if (lval == 0)
return 0;
NetExpr*rexp = elab_and_eval(des, scope, expr_);
unsigned lwid = count_lval_width(lval);
NetExpr*rexp = elab_and_eval(des, scope, expr_, lwid);
if (rexp == 0)
return 0;
unsigned lwid = count_lval_width(lval);
rexp->set_width(lwid, true);
rexp = pad_to_width(rexp, lwid);
@@ -2576,11 +2639,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_);
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: "
@@ -2621,8 +2690,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);
etmp->set_width(lv->lwidth());
etmp = elab_and_eval(des, scope, expr2_, lv->lwidth());
NetAssign*step = new NetAssign(lv, etmp);
step->set_line(*this);
@@ -2632,7 +2700,7 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const
/* Elaborate the condition expression. Try to evaluate it too,
in case it is a constant. This is an interesting case
worthy of a warning. */
NetExpr*ce = elab_and_eval(des, scope, cond_);
NetExpr*ce = elab_and_eval(des, scope, cond_, -1);
if (ce == 0) {
delete top;
return 0;
@@ -2713,7 +2781,7 @@ NetProc* PRepeat::elaborate(Design*des, NetScope*scope) const
{
assert(scope);
NetExpr*expr = elab_and_eval(des, scope, expr_);
NetExpr*expr = elab_and_eval(des, scope, expr_, -1);
if (expr == 0) {
cerr << get_line() << ": Unable to elaborate"
" repeat expression." << endl;
@@ -2803,12 +2871,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_ << ">"
@@ -2834,11 +2901,127 @@ NetProc* PTrigger::elaborate(Design*des, NetScope*scope) const
*/
NetProc* PWhile::elaborate(Design*des, NetScope*scope) const
{
NetWhile*loop = new NetWhile(elab_and_eval(des, scope, cond_),
NetWhile*loop = new NetWhile(elab_and_eval(des, scope, cond_, -1),
statement_->elaborate(des, scope));
return loop;
}
void PSpecPath::elaborate(Design*des, NetScope*scope) const
{
uint64_t delay_value[12];
unsigned ndelays = 0;
/* Do not elaborate specify delay paths if this feature is
turned off. */
if (!gn_specify_blocks_flag)
return;
ndelays = delays.size();
if (ndelays > 12)
ndelays = 12;
int shift = scope->time_unit() - des->get_precision();
/* Elaborate the delay values themselves. Remember to scale
them for the timescale/precision of the scope. */
for (unsigned idx = 0 ; idx < ndelays ; idx += 1) {
PExpr*exp = delays[idx];
NetExpr*cur = elab_and_eval(des, scope, exp, 0);
if (NetEConst*cur_con = dynamic_cast<NetEConst*> (cur)) {
delay_value[idx] = cur_con->value().as_ulong();
for (int tmp = 0 ; tmp < shift ; tmp += 1)
delay_value[idx] *= 10;
} else if (NetECReal*cur_rcon = dynamic_cast<NetECReal*>(cur)) {
delay_value[idx] = cur_rcon->value().as_long(shift);
} else {
cerr << get_line() << ": error: Path delay value "
<< "must be constant." << endl;
delay_value[idx] = 0;
des->errors += 1;
}
delete cur;
}
switch (ndelays) {
case 1:
case 2:
case 3:
case 6:
case 12:
break;
default:
cerr << get_line() << ": error: Incorrect delay configuration."
<< endl;
ndelays = 1;
des->errors += 1;
break;
}
/* 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;
}
NetNet*dst_sig = scope->find_signal(*cur);
if (dst_sig == 0) {
cerr << get_line() << ": error: No such wire "
<< *cur << " in this module." << endl;
des->errors += 1;
continue;
}
NetDelaySrc*path = new NetDelaySrc(scope, scope->local_symbol(),
src.size());
path->set_line(*this);
switch (ndelays) {
case 12:
path->set_delays(delay_value[0], delay_value[1],
delay_value[2], delay_value[3],
delay_value[4], delay_value[5],
delay_value[6], delay_value[7],
delay_value[8], delay_value[9],
delay_value[10], delay_value[11]);
break;
case 6:
path->set_delays(delay_value[0], delay_value[1],
delay_value[2], delay_value[3],
delay_value[4], delay_value[5]);
break;
case 3:
path->set_delays(delay_value[0], delay_value[1],
delay_value[2]);
break;
case 2:
path->set_delays(delay_value[0], delay_value[1]);
break;
case 1:
path->set_delays(delay_value[0]);
break;
}
unsigned idx = 0;
for (str_vector_iter cur_src = src.begin()
; cur_src != src.end() ; cur_src ++) {
NetNet*src_sig = scope->find_signal(*cur_src);
assert(src_sig);
connect(src_sig->pin(0), path->pin(idx));
idx += 1;
}
dst_sig->add_delay_path(path);
}
}
/*
* When a module is instantiated, it creates the scope then uses this
* method to elaborate the contents of the module.
@@ -2847,6 +3030,49 @@ bool Module::elaborate(Design*des, NetScope*scope) const
{
bool result_flag = true;
if (gn_specify_blocks_flag) {
// Elaborate specparams
typedef map<perm_string,PExpr*>::const_iterator specparam_it_t;
for (specparam_it_t cur = specparams.begin()
; cur != specparams.end() ; cur ++ ) {
NetExpr*val = elab_and_eval(des, scope, (*cur).second, -1);
NetScope::spec_val_t value;
if (NetECReal*val_c = dynamic_cast<NetECReal*> (val)) {
value.type = IVL_VT_REAL;
value.real_val = val_c->value().as_double();
if (debug_elaborate)
cerr << get_line() << ": debug: Elaborate "
<< "specparam " << (*cur).first
<< " value=" << value.real_val << endl;
} else if (NetEConst*val_c = dynamic_cast<NetEConst*> (val)) {
value.type = IVL_VT_BOOL;
value.integer = val_c->value().as_long();
if (debug_elaborate)
cerr << get_line() << ": debug: Elaborate "
<< "specparam " << (*cur).first
<< " 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;
des->errors += 1;
}
assert(val);
delete val;
scope->specparams[(*cur).first] = value;
}
}
// Elaborate within the generate blocks.
typedef list<PGenerate*>::const_iterator generate_it_t;
for (generate_it_t cur = generate_schemes.begin()
@@ -2970,6 +3196,14 @@ bool Module::elaborate(Design*des, NetScope*scope) const
}
// Elaborate the specify paths of the module.
for (list<PSpecPath*>::const_iterator sp = specify_paths.begin()
; sp != specify_paths.end() ; sp ++) {
(*sp)->elaborate(des, scope);
}
return result_flag;
}
@@ -3111,6 +3345,76 @@ Design* elaborate(list<perm_string>roots)
/*
* $Log: elaborate.cc,v $
* 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.
*
* Revision 1.346 2006/10/03 05:06:00 steve
* Support real valued specify delays, properly scaled.
*
* Revision 1.345 2006/09/28 04:35:18 steve
* Support selective control of specify and xtypes features.
*
* Revision 1.344 2006/09/26 19:48:40 steve
* Missing PSpec.cc file.
*
* Revision 1.343 2006/09/23 04:57:19 steve
* Basic support for specify timing.
*
* Revision 1.342 2006/09/22 22:14:27 steve
* Proper error message when logic array pi count is bad.
*
* Revision 1.341 2006/08/08 05:11:37 steve
* Handle 64bit delay constants.
*
* Revision 1.340 2006/06/02 04:48:50 steve
* Make elaborate_expr methods aware of the width that the context
* requires of it. In the process, fix sizing of the width of unary
* minus is context determined sizes.
*
* Revision 1.339 2006/05/01 20:47:59 steve
* More explicit datatype setup.
*
* Revision 1.338 2006/04/30 05:17:48 steve
* Get the data type of part select results right.
*
* Revision 1.337 2006/04/26 04:43:50 steve
* Chop down assign r-values that elaborate too wide.
*
* Revision 1.336 2006/04/10 00:37:42 steve
* Add support for generate loops w/ wires and gates.
*
+33 -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.86 2005/07/11 16:56: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);
@@ -146,6 +145,10 @@ bool NetUReduce::emit_node(struct target_t*tgt) const
return tgt->ureduce(this);
}
bool NetSysFunc::emit_node(struct target_t*tgt) const
{
return tgt->net_sysfunction(this);
}
bool NetUserFunc::emit_node(struct target_t*tgt) const
{
@@ -340,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
@@ -457,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."
@@ -525,6 +527,18 @@ 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.
*
* Revision 1.86 2005/07/11 16:56:50 steve
* Remove NetVariable and ivl_variable_t structures.
*
+23 -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: eval.cc,v 1.40 2006/04/10 00:37:42 steve Exp $"
#ident "$Id: eval.cc,v 1.44 2007/01/16 05:44:15 steve Exp $"
#endif
# include "config.h"
@@ -150,7 +150,12 @@ verinum* PEConcat::eval_const(const Design*des, NetScope*scope) const
return 0;
for (unsigned idx = 1 ; idx < parms_.count() ; idx += 1) {
verinum*tmp = parms_[idx]->eval_const(des, scope);
if (tmp == 0) {
delete accum;
return 0;
}
assert(tmp);
*accum = concat(*accum, *tmp);
@@ -169,7 +174,6 @@ verinum* PEIdent::eval_const(const Design*des, NetScope*scope) const
{
assert(scope);
NetNet*net;
NetMemory*mem;
NetEvent*eve;
const NetExpr*expr;
@@ -182,7 +186,7 @@ verinum* PEIdent::eval_const(const Design*des, NetScope*scope) const
}
NetScope*found_in = symbol_search(des, scope, path_,
net, mem, expr, eve);
net, expr, eve);
if (expr == 0)
return 0;
@@ -254,7 +258,7 @@ verinum* PEUnary::eval_const(const Design*des, NetScope*scope) const
/* We need to expand the value a bit if we are
taking the 2's complement so that we are
guaranteed to not overflow. */
verinum tmp (0UL, val->len()+1);
verinum tmp ((uint64_t)0, val->len()+1);
for (unsigned idx = 0 ; idx < val->len() ; idx += 1)
tmp.set(idx, val->get(idx));
@@ -271,6 +275,21 @@ verinum* PEUnary::eval_const(const Design*des, NetScope*scope) const
/*
* $Log: eval.cc,v $
* Revision 1.44 2007/01/16 05:44:15 steve
* Major rework of array handling. Memories are replaced with the
* more general concept of arrays. The NetMemory and NetEMemory
* classes are removed from the ivl core program, and the IVL_LPM_RAM
* lpm type is removed from the ivl_target API.
*
* Revision 1.43 2006/08/08 05:11:37 steve
* Handle 64bit delay constants.
*
* Revision 1.42 2006/05/19 04:07:24 steve
* eval_const is not strict.
*
* Revision 1.41 2006/05/17 16:49:30 steve
* Error message if concat expression cannot evaluate.
*
* Revision 1.40 2006/04/10 00:37:42 steve
* Add support for generate loops w/ wires and gates.
*
+138 -57
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.68 2006/03/18 22:52:27 steve Exp $"
#ident "$Id: eval_tree.cc,v 1.73 2007/01/16 05:44:15 steve Exp $"
#endif
# include "config.h"
@@ -937,6 +937,80 @@ NetExpr* NetEBMult::eval_tree()
return new NetEConst(lval * rval);
}
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);
}
NetECReal*res = new NetECReal( pow(lval,rval) );
res->set_line(*this);
return res;
}
NetExpr* NetEBPow::eval_tree()
{
eval_sub_tree_();
if (expr_type() == IVL_VT_REAL)
return eval_tree_real_();
assert(expr_type() == IVL_VT_LOGIC);
NetEConst*lc = dynamic_cast<NetEConst*>(left_);
if (lc == 0) return 0;
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
if (rc == 0) return 0;
verinum lval = lc->value();
verinum rval = rc->value();
return new NetEConst( pow(lval,rval) );
}
/*
* Evaluate the shift operator if possible. For this to work, both
* operands must be constant.
@@ -964,6 +1038,13 @@ NetEConst* NetEBShift::eval_tree()
unsigned shift = rv.as_ulong();
if (debug_eval_tree) {
cerr << get_line() << ": debug: "
<< "Evaluate " << lv << "<<" << op() << ">> "
<< rv << ", wid=" << wid << ", shift=" << shift
<< ", lv.las_len()=" << lv.has_len() << endl;
}
if ((wid == 0) || ! lv.has_len()) {
/* If the caller doesn't care what the width is,
then calcuate a width from the trimmed left
@@ -1109,54 +1190,17 @@ NetEConst* NetEConcat::eval_tree()
return res;
}
/*
* There are limits to our ability to evaluate a memory reference
* expression, because the content of a memory is never
* constant. However, the index expression may be precalculated, and
* there are certain index values that do give us constant results.
*/
NetExpr* NetEMemory::eval_tree()
{
/* Attempt to evaluate the index expression to a constant, if
it is not already. */
if (idx_ && !dynamic_cast<NetEConst*>(idx_)) {
NetExpr* tmp = idx_->eval_tree();
if (tmp) {
delete idx_;
idx_ = tmp;
}
}
NetEConst*itmp = dynamic_cast<NetEConst*>(idx_);
if (itmp == 0)
return 0;
verinum ival = itmp->value();
/* If the index expression has any x or z bits, then we know
already that the expression result is a constant x. */
if (! ival.is_defined()) {
verinum xres (verinum::Vx, mem_->width(), false);
NetEConst*res = new NetEConst(xres);
return res;
}
/* If the index expression is outside the range of the memory,
then the result is a constant x. */
unsigned norm_idx = mem_->index_to_address(ival.as_long());
if (norm_idx >= mem_->count()) {
verinum xres (verinum::Vx, mem_->width(), false);
NetEConst*res = new NetEConst(xres);
return res;
}
return 0;
}
NetExpr* NetEParam::eval_tree()
{
if (des_ == 0)
if (des_ == 0) {
assert(scope_ == 0);
return 0;
}
if (debug_elaborate) {
cerr << get_line() << ": debug: evaluating expression: "
<< *this << endl;
}
assert(scope_);
const NetExpr*expr_msb;
@@ -1266,31 +1310,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;
}
@@ -1589,6 +1652,24 @@ NetEConst* NetEUReduce::eval_tree()
/*
* $Log: eval_tree.cc,v $
* Revision 1.73 2007/01/16 05:44:15 steve
* Major rework of array handling. Memories are replaced with the
* more general concept of arrays. The NetMemory and NetEMemory
* classes are removed from the ivl core program, and the IVL_LPM_RAM
* lpm type is removed from the ivl_target API.
*
* Revision 1.72 2006/11/04 06:16:27 steve
* Fix padding of constant eval of NetESelect.
*
* Revision 1.71 2006/10/30 05:44:49 steve
* Expression widths with unsized literals are pseudo-infinite width.
*
* Revision 1.70 2006/09/19 23:00:15 steve
* Use elab_and_eval for bit select expressions.
*
* Revision 1.69 2006/07/31 03:50:17 steve
* Add support for power in constant expressions.
*
* Revision 1.68 2006/03/18 22:52:27 steve
* Properly handle signedness in compare.
*
+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.
*
+105 -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: expr_synth.cc,v 1.74 2006/01/03 05:15:33 steve Exp $"
#ident "$Id: expr_synth.cc,v 1.82 2007/01/20 02:10:45 steve Exp $"
#endif
# include "config.h"
@@ -57,6 +57,7 @@ NetNet* NetEBAdd::synthesize(Design*des)
perm_string path = lsig->scope()->local_symbol();
NetNet*osig = new NetNet(lsig->scope(), path, NetNet::IMPLICIT, width);
osig->local_flag(true);
osig->data_type(expr_type());
perm_string oname = osig->scope()->local_symbol();
NetAddSub *adder = new NetAddSub(lsig->scope(), oname, width);
@@ -107,6 +108,7 @@ NetNet* NetEBBits::synthesize(Design*des)
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, lsig->vector_width());
osig->local_flag(true);
osig->data_type(expr_type());
perm_string oname = scope->local_symbol();
unsigned wid = lsig->vector_width();
@@ -232,6 +234,14 @@ NetNet* NetEBComp::synthesize(Design*des)
return osig;
}
NetNet* NetEBPow::synthesize(Design*des)
{
cerr << get_line() << ": internal error: Do not yet know how to handle"
<< " power operator in this context." << endl;
des->errors += 1;
return 0;
}
NetNet* NetEBMult::synthesize(Design*des)
{
NetNet*lsig = left_->synthesize(des);
@@ -260,7 +270,9 @@ NetNet* NetEBMult::synthesize(Design*des)
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, expr_width());
osig->data_type(lsig->data_type());
osig->set_line(*this);
osig->data_type(expr_type());
osig->local_flag(true);
connect(mult->pin_Result(), osig->pin(0));
@@ -341,6 +353,7 @@ NetNet* NetEBLogic::synthesize(Design*des)
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, 1);
osig->data_type(expr_type());
osig->local_flag(true);
@@ -433,12 +446,17 @@ NetNet* NetEBShift::synthesize(Design*des)
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, expr_width());
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);
@@ -454,8 +472,23 @@ NetNet* NetEBShift::synthesize(Design*des)
NetNet*zsig = new NetNet(scope, scope->local_symbol(),
NetNet::WIRE, znum.len());
zsig->data_type(osig->data_type());
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);
@@ -463,10 +496,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));
}
@@ -479,6 +514,7 @@ NetNet* NetEBShift::synthesize(Design*des)
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, expr_width());
osig->data_type(expr_type());
osig->local_flag(true);
assert(op() == 'l');
@@ -556,12 +592,28 @@ NetNet* NetEConst::synthesize(Design*des)
return osig;
}
/*
* Create a NetLiteral object to represent real valued constants.
*/
NetNet* NetECReal::synthesize(Design*des)
{
cerr << get_line() << ": error: Real constants are "
<< "not synthesizable." << endl;
des->errors += 1;
return 0;
NetScope*scope = des->find_root_scope();
assert(scope);
perm_string path = scope->local_symbol();
NetNet*osig = new NetNet(scope, path, NetNet::WIRE, 1);
osig->local_flag(true);
osig->data_type(IVL_VT_REAL);
osig->set_signed(has_sign());
osig->set_line(*this);
NetLiteral*con = new NetLiteral(scope, scope->local_symbol(), value_);
des->add_node(con);
con->set_line(*this);
connect(osig->pin(0), con->pin(0));
return osig;
}
/*
@@ -578,6 +630,7 @@ NetNet* NetEUBits::synthesize(Design*des)
unsigned width = isig->vector_width();
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, width);
osig->data_type(expr_type());
osig->local_flag(true);
perm_string oname = scope->local_symbol();
@@ -608,6 +661,7 @@ NetNet* NetEUReduce::synthesize(Design*des)
NetNet*osig = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, 1);
osig->data_type(expr_type());
osig->local_flag(true);
perm_string oname = scope->local_symbol();
@@ -658,7 +712,7 @@ NetNet* NetEUReduce::synthesize(Design*des)
return osig;
}
#if 0
NetNet* NetEMemory::synthesize(Design *des)
{
NetNet*adr = idx_->synthesize(des);
@@ -685,7 +739,7 @@ NetNet* NetEMemory::synthesize(Design *des)
return osig;
}
#endif
NetNet* NetESelect::synthesize(Design *des)
{
@@ -699,12 +753,15 @@ NetNet* NetESelect::synthesize(Design *des)
if (base_ != 0) {
// For now, only handle constant part selects in this
// context.
// 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);
long bval = bcon->value().as_long();
off = sub->sb_to_idx(bval);
assert(bval >= 0);
off = bval;
}
/* If there is a part select, then generate a PartSelect node
@@ -720,10 +777,12 @@ NetNet* NetESelect::synthesize(Design *des)
sel->set_line(*this);
des->add_node(sel);
sub = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, expr_width());
sub->local_flag(true);
sub->set_line(*this);
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, expr_width());
tmp->data_type(sub->data_type());
tmp->local_flag(true);
tmp->set_line(*this);
sub = tmp;
connect(sub->pin(0), sel->pin(0));
}
@@ -733,6 +792,7 @@ NetNet* NetESelect::synthesize(Design *des)
NetNet*net = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, expr_width());
net->data_type(expr_type());
if (has_sign()) {
NetSignExtend*pad = new NetSignExtend(scope,
scope->local_symbol(),
@@ -752,7 +812,7 @@ NetNet* NetESelect::synthesize(Design *des)
assert(expr_width() > sub->vector_width());
unsigned pad_width = expr_width() - sub->vector_width();
verinum pad(0UL, pad_width);
verinum pad((uint64_t)0, pad_width);
NetConst*con = new NetConst(scope, scope->local_symbol(),
pad);
con->set_line(*this);
@@ -760,6 +820,7 @@ NetNet* NetESelect::synthesize(Design *des)
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
NetNet::IMPLICIT, pad_width);
tmp->data_type(expr_type());
tmp->local_flag(true);
tmp->set_line(*this);
connect(tmp->pin(0), con->pin(0));
@@ -790,6 +851,7 @@ NetNet* NetETernary::synthesize(Design *des)
unsigned width=expr_width();
NetNet*osig = new NetNet(csig->scope(), path, NetNet::IMPLICIT, width);
osig->data_type(expr_type());
osig->local_flag(true);
/* Make sure both value operands are the right width. */
@@ -848,6 +910,33 @@ NetNet* NetESignal::synthesize(Design*des)
/*
* $Log: expr_synth.cc,v $
* 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.
*
* Revision 1.79 2006/07/31 03:50:17 steve
* Add support for power in constant expressions.
*
* Revision 1.78 2006/07/08 21:48:46 steve
* Handle real valued literals in net contexts.
*
* Revision 1.77 2006/05/01 20:47:59 steve
* More explicit datatype setup.
*
* Revision 1.76 2006/05/01 05:40:21 steve
* fix net type of multiply output.
*
* Revision 1.75 2006/04/30 05:17:48 steve
* Get the data type of part select results right.
*
* Revision 1.74 2006/01/03 05:15:33 steve
* Fix the return type of a synthesized divide.
*
+8 -1
View File
@@ -17,7 +17,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: iverilog-vpi.sh,v 1.15 2006/02/21 02:38:44 steve Exp $"
#ident "$Id: iverilog-vpi.sh,v 1.16 2006/09/26 18:54:42 steve Exp $"
# These are the variables used for compiling files
CC=gcc
@@ -69,6 +69,13 @@ do
fi
;;
*.cpp) CXSRC="$CXSRC $parm"
LD=$CXX
if [ x$OUT = x ]; then
OUT=`basename $parm .cpp`
fi
;;
*.o) OBJ="$OBJ $parm"
if [ x$OUT = x ]; then
OUT=`basename $parm .o`
+26 -35
View File
@@ -9,9 +9,10 @@ ivl_design_roots
ivl_design_time_precision
ivl_const_bits
ivl_const_pin
ivl_const_pins
ivl_const_real
ivl_const_signed
ivl_const_type
ivl_const_width
ivl_event_any
ivl_event_basename
@@ -21,14 +22,13 @@ ivl_event_neg
ivl_event_nneg
ivl_event_npos
ivl_event_pos
ivl_event_scope
ivl_expr_type
ivl_expr_bits
ivl_expr_def
ivl_expr_dvalue
ivl_expr_event
ivl_expr_lsi
ivl_expr_memory
ivl_expr_name
ivl_expr_opcode
ivl_expr_oper1
@@ -44,21 +44,24 @@ ivl_expr_signed
ivl_expr_string
ivl_expr_uvalue
ivl_expr_value
ivl_expr_variable
ivl_expr_width
ivl_logic_attr
ivl_logic_attr_cnt
ivl_logic_attr_val
ivl_logic_delay
ivl_logic_name
ivl_logic_basename
ivl_logic_scope
ivl_logic_type
ivl_logic_delay
ivl_logic_drive0
ivl_logic_drive1
ivl_logic_name
ivl_logic_pin
ivl_logic_pins
ivl_logic_scope
ivl_logic_type
ivl_logic_udp
ivl_logic_width
ivl_lpm_array
ivl_lpm_aset_value
ivl_lpm_async_clr
ivl_lpm_async_set
@@ -67,11 +70,8 @@ ivl_lpm_basename
ivl_lpm_clk
ivl_lpm_data
ivl_lpm_datab
ivl_lpm_data2
ivl_lpm_data2_width
ivl_lpm_define
ivl_lpm_enable
ivl_lpm_memory
ivl_lpm_name
ivl_lpm_q
ivl_lpm_scope
@@ -80,25 +80,17 @@ ivl_lpm_selects
ivl_lpm_signed
ivl_lpm_size
ivl_lpm_sset_value
ivl_lpm_string
ivl_lpm_sync_clr
ivl_lpm_sync_set
ivl_lpm_type
ivl_lpm_width
ivl_lval_idx
ivl_lval_mem
ivl_lval_mux
ivl_lval_part_off
ivl_lval_pin
ivl_lval_pins
ivl_lval_sig
ivl_lval_var
ivl_memory_basename
ivl_memory_root
ivl_memory_scope
ivl_memory_size
ivl_memory_width
ivl_lval_width
ivl_nexus_get_private
ivl_nexus_name
@@ -128,8 +120,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
@@ -141,23 +131,29 @@ ivl_scope_sig
ivl_scope_time_units
ivl_scope_type
ivl_scope_tname
ivl_scope_var
ivl_scope_vars
ivl_signal_array_base
ivl_signal_array_count
ivl_signal_attr
ivl_signal_attr_cnt
ivl_signal_attr_val
ivl_signal_basename
ivl_signal_data_type
ivl_signal_integer
ivl_signal_local
ivl_signal_lsb
ivl_signal_msb
ivl_signal_pin
ivl_signal_pins
ivl_signal_name
ivl_signal_nex
ivl_signal_npath
ivl_signal_path
ivl_signal_port
ivl_signal_signed
ivl_signal_type
ivl_signal_name
ivl_signal_basename
ivl_signal_width
ivl_path_delay
ivl_path_source
ivl_process_attr_cnt
ivl_process_attr_val
@@ -185,8 +181,6 @@ ivl_stmt_lvals
ivl_stmt_lwidth
ivl_stmt_name
ivl_stmt_nevent
ivl_stmt_nexus
ivl_stmt_nexus_count
ivl_stmt_parm
ivl_stmt_parm_count
ivl_stmt_rval
@@ -198,6 +192,3 @@ ivl_udp_nin
ivl_udp_row
ivl_udp_rows
ivl_udp_sequ
ivl_variable_name
ivl_variable_type
+154 -257
View File
@@ -19,9 +19,11 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: ivl_target.h,v 1.166 2006/04/10 00:37:42 steve Exp $"
#ident "$Id: ivl_target.h,v 1.174 2007/01/17 05:00:12 steve Exp $"
#endif
# include <stdint.h>
#ifdef __cplusplus
#define _BEGIN_DECL extern "C" {
#define _END_DECL }
@@ -57,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.
@@ -135,6 +141,8 @@ _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;
typedef struct ivl_expr_s *ivl_expr_t;
@@ -150,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;
/*
@@ -175,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,
@@ -222,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,
@@ -244,14 +253,25 @@ typedef enum ivl_lpm_type_e {
IVL_LPM_RE_XNOR= 24,
IVL_LPM_RE_XOR = 25,
IVL_LPM_REPEAT = 26,
IVL_LPM_SFUNC = 29,
IVL_LPM_SHIFTL = 6,
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;
/* The path edge type is the edge type used to select a specific
delay. */
typedef enum ivl_path_edge_e {
IVL_PE_01 = 0, IVL_PE_10, IVL_PE_0z,
IVL_PE_z1, IVL_PE_1z, IVL_PE_z0,
IVL_PE_0x, IVL_PE_x1, IVL_PE_1x,
IVL_PE_x0, IVL_PE_xz, IVL_PE_zx,
IVL_PE_COUNT
} ivl_path_edge_t;
/* Processes are initial or always blocks with a statement. This is
the type of the ivl_process_t object. */
typedef enum ivl_process_type_e {
@@ -358,6 +378,19 @@ struct ivl_attribute_s {
};
typedef const struct ivl_attribute_s*ivl_attribute_t;
/* DELAYPATH
* Delaypath objects represent delay paths called out by a specify
* block in the verilog source file. The destination signal references
* the path object, which in turn points to the source for the path.
*
* ivl_path_source
* 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.
*/
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);
/* DESIGN
* When handed a design (ivl_design_t) there are a few things that you
@@ -547,6 +580,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
@@ -556,6 +597,21 @@ 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.
*/
extern ivl_expr_type_t ivl_expr_type(ivl_expr_t net);
@@ -600,42 +656,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
@@ -948,7 +969,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
@@ -985,12 +1006,29 @@ extern const char* ivl_udp_name(ivl_udp_t net);
* input must be signed, and the output will be a vector sign extended
* to the desired width. The ivl_lpm_width() value is the output
* width, the input will be whatever it wants to be.
*
* - Shifts (IVL_LPM_SHIFTL/SHIFTR)
* This node takes two inputs, a vector and a shift distance. The
* ivl_lpm_data(0) nexus is the vector input, and the ivl_lpm_data(1)
* the shift distance. The vector input is the same width as the
* output, but the distance has its own width.
*
* The ivl_lpm_signed() flag means for IVL_LPM_SHIFTR that the right
* shift is *signed*. For SHIFTL, then signed-ness is emaningless.
*
* - System function call (IVL_LPM_SFUNC)
* This device represents a netlist call to a system function. The
* inputs to the device are passed to a system function, and the
* result is sent via the output. The ivl_lpm_q function returns the
* output nexus.
*
* The ivl_lpm_size function returns the number of arguments, and the
* ivl_lpm_data(net,N) returns the nexa for the argument.
*
* The ivl_lpm_string(net) function returns the name of the system
* function (i.e. "$display") that was found in the source code. The
* compiler does little checking of that name.
*
* - User Function Call (IVL_LPM_UFUNC)
* This device is special as it represents a call to a user defined
* function (behavioral code) within a netlist. The inputs to the
@@ -1025,40 +1063,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);
#if 0
/* IVL_LPM_UFUNC */
extern ivl_nexus_t ivl_lpm_data2(ivl_lpm_t net, unsigned sdx, unsigned idx);
#endif
#if 0
/* IVL_LPM_UFUNC */
extern unsigned ivl_lpm_data2_width(ivl_lpm_t net, unsigned sdx);
#endif
/* 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_RAM */
extern ivl_memory_t ivl_lpm_memory(ivl_lpm_t net);
/* IVL_LPM_SFUNC */
extern const char*ivl_lpm_string(ivl_lpm_t net);
/* LVAL
* The l-values of assignments are concatenation of ivl_lval_t
@@ -1081,7 +1112,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.
@@ -1108,23 +1139,29 @@ extern ivl_memory_t ivl_lpm_memory(ivl_lpm_t net);
* signal (or even 1) if only a part of the l-value signal is to be
* assigned.
*
* The ivl_lval_part_off is the canonical base of a constant part or
* bit select. If the bit select base is non-constant, then the
* ivl_lval_mux will contain an expression. If there is a mux
* expression, then the ivl_lval_part_off result can be ignored.
* 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 then 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);
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);
@@ -1371,8 +1408,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);
@@ -1396,17 +1431,22 @@ 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_msb
* ivl_signal_lsb
@@ -1438,6 +1478,12 @@ extern int ivl_scope_time_units(ivl_scope_t net);
* etc. All the signals connected to a nexus should have the same
* data type
*
* ivl_signal_npath
* ivl_signal_path
* This function returns the delay path object for the signal. The
* delay path has this signal as the output, the source is attached
* to the delay path itself.
*
* ivl_signal_name (DEPRECATED)
* This function returns the fully scoped hierarchical name for the
* signal. The name refers to the entire vector that is the signal.
@@ -1461,7 +1507,9 @@ 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 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);
@@ -1469,6 +1517,8 @@ extern ivl_signal_port_t ivl_signal_port(ivl_signal_t net);
extern int ivl_signal_signed(ivl_signal_t net);
extern int ivl_signal_integer(ivl_signal_t net);
extern int ivl_signal_local(ivl_signal_t net);
extern unsigned ivl_signal_npath(ivl_signal_t net);
extern ivl_delaypath_t ivl_signal_path(ivl_signal_t net, unsigned idx);
extern ivl_signal_type_t ivl_signal_type(ivl_signal_t net);
extern ivl_variable_type_t ivl_signal_data_type(ivl_signal_t net);
extern const char* ivl_signal_name(ivl_signal_t net);
@@ -1648,7 +1698,7 @@ extern ivl_statement_t ivl_stmt_cond_true(ivl_statement_t net);
/* IVL_ST_ASSIGN IVL_ST_ASSIGN_NB IVL_ST_DELAYX */
extern ivl_expr_t ivl_stmt_delay_expr(ivl_statement_t net);
/* IVL_ST_DELAY */
extern unsigned long ivl_stmt_delay_val(ivl_statement_t net);
extern uint64_t ivl_stmt_delay_val(ivl_statement_t net);
/* IVL_ST_WAIT IVL_ST_TRIGGER */
extern unsigned ivl_stmt_nevent(ivl_statement_t net);
extern ivl_event_t ivl_stmt_events(ivl_statement_t net, unsigned idx);
@@ -1662,10 +1712,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 */
@@ -1708,6 +1754,33 @@ _END_DECL
/*
* $Log: ivl_target.h,v $
* 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.
*
* Revision 1.170 2006/08/08 05:11:37 steve
* Handle 64bit delay constants.
*
* Revision 1.169 2006/07/30 02:51:35 steve
* Fix/implement signed right shift.
*
* Revision 1.168 2006/06/18 04:15:50 steve
* Add support for system functions in continuous assignments.
*
* Revision 1.167 2006/04/16 00:15:43 steve
* Fix part selects in l-values.
*
* Revision 1.166 2006/04/10 00:37:42 steve
* Add support for generate loops w/ wires and gates.
*
@@ -1722,181 +1795,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
+88 -34
View File
@@ -17,7 +17,7 @@ const char COPYRIGHT[] =
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: main.c,v 1.20 2004/09/10 00:15:45 steve Exp $"
#ident "$Id: main.c,v 1.23 2006/10/02 18:16:18 steve Exp $"
#endif
# include "config.h"
@@ -58,6 +58,8 @@ extern int getopt(int argc, char*argv[], const char*fmt);
extern int optind;
extern const char*optarg;
#endif
/* Path to the dependency file, if there is one. */
char *dep_path = NULL;
/*
* Keep in source_list an array of pointers to file names. The array
@@ -89,6 +91,76 @@ int line_direct_flag = 0;
unsigned error_count = 0;
FILE *depend_file = NULL;
static int flist_read_flags(const char*path)
{
char line_buf[2048];
FILE*fd = fopen(path, "r");
if (fd == 0) {
fprintf(stderr, "%s: unable to open for reading.\n", path);
return -1;
}
while (fgets(line_buf, sizeof line_buf, fd) != 0) {
/* Skip leading white space. */
char*cp = line_buf + strspn(line_buf, " \t\r\b\f");
/* Remove trailing white space. */
char*tail = cp + strlen(cp);
while (tail > cp) {
if (! isspace(tail[-1]))
break;
tail -= 1;
tail[0] = 0;
}
/* Skip empty lines */
if (*cp == 0)
continue;
/* Skip comment lines */
if (cp[0] == '#')
continue;
/* The arg points to the argument to the keyword. */
char*arg = strchr(cp, ':');
if (arg) *arg++ = 0;
if (strcmp(cp,"D") == 0) {
char*val = strchr(arg, '=');
if (val)
*val++ = 0;
else
val = "1";
define_macro(arg, val, 0);
} else if (strcmp(cp,"I") == 0) {
include_dir = realloc(include_dir,
(include_cnt+1)*sizeof(char*));
include_dir[include_cnt] = strdup(arg);
include_cnt += 1;
} else if (strcmp(cp,"keyword") == 0) {
char*buf = malloc(strlen(arg) + 2);
buf[0] = '`';
strcpy(buf+1, optarg);
define_macro(optarg, buf, 1);
free(buf);
} else if (strcmp(cp,"M") == 0) {
if (dep_path) {
fprintf(stderr, "duplicate -M flag.\n");
} else {
dep_path = strdup(arg);
}
} else {
fprintf(stderr, "%s: Invalid keyword %s\n", path, cp);
}
}
fclose(fd);
return 0;
}
/*
* This function reads from a file a list of file names. Each name
* starts with the first non-space character, and ends with the last
@@ -127,7 +199,6 @@ int main(int argc, char*argv[])
const char*flist_path = 0;
unsigned flag_errors = 0;
char*out_path = 0;
char *dep_path = NULL;
FILE*out;
/* Define preprocessor keywords that I plan to just pass. */
@@ -153,20 +224,11 @@ int main(int argc, char*argv[])
include_dir[0] = strdup(".");
include_cnt = 1;
while ((opt = getopt(argc, argv, "D:f:I:K:LM:o:v")) != EOF) switch (opt) {
while ((opt=getopt(argc, argv, "F:f:K:Lo:v")) != EOF) switch (opt) {
case 'D': {
char*tmp = strdup(optarg);
char*val = strchr(tmp, '=');
if (val)
*val++ = 0;
else
val = "1";
define_macro(tmp, val, 0);
free(tmp);
break;
}
case 'F':
flist_read_flags(optarg);
break;
case 'f':
if (flist_path) {
@@ -176,13 +238,6 @@ int main(int argc, char*argv[])
flist_path = optarg;
break;
case 'I':
include_dir = realloc(include_dir,
(include_cnt+1)*sizeof(char*));
include_dir[include_cnt] = strdup(optarg);
include_cnt += 1;
break;
case 'K': {
char*buf = malloc(strlen(optarg) + 2);
buf[0] = '`';
@@ -196,14 +251,6 @@ int main(int argc, char*argv[])
line_direct_flag = 1;
break;
case 'M':
if (dep_path) {
fprintf(stderr, "duplicate -M flag.\n");
} else {
dep_path = optarg;
}
break;
case 'o':
if (out_path) {
fprintf(stderr, "duplicate -o flag.\n");
@@ -225,13 +272,11 @@ int main(int argc, char*argv[])
}
if (flag_errors) {
fprintf(stderr, "\nUsage: %s [-v][-L][-I<dir>][-D<def>] <file>...\n"
" -D<def> - Predefine a value.\n"
fprintf(stderr, "\nUsage: %s [-v][-L][-F<fil>][-f<fil>] <file>...\n"
" -F<fil> - Get defines and includes from file\n"
" -f<fil> - Read the sources listed in the file\n"
" -I<dir> - Add an include file search directory\n"
" -K<def> - Define a keyword macro that I just pass\n"
" -L - Emit line number directives\n"
" -M<fil> - Write dependencies to <fil>\n"
" -o<fil> - Send the output to <fil>\n"
" -v - Print version information\n",
argv[0]);
@@ -290,6 +335,15 @@ int main(int argc, char*argv[])
/*
* $Log: main.c,v $
* Revision 1.23 2006/10/02 18:16:18 steve
* Save dep_path because arg space is overrun.
*
* Revision 1.22 2006/07/26 00:11:40 steve
* Pass depfiles through temp defines file.
*
* Revision 1.21 2006/07/26 00:02:48 steve
* Pass defines and includes through temp file.
*
* Revision 1.20 2004/09/10 00:15:45 steve
* Remove bad casts.
*
+4 -1
View File
@@ -1,4 +1,6 @@
%option never-interactive
%{
/*
* Copyright (c) 1998-2000 Stephen Williams ([email protected])
@@ -19,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.90 2006/03/30 05:44:36 steve Exp $"
#ident "$Id: lexor.lex,v 1.92 2006/07/31 03:50:17 steve Exp $"
#endif
# include "config.h"
@@ -132,6 +134,7 @@ W [ \t\b\f\r]+
"<<<" { return K_LS; /* Note: Functionally, <<< is the same as <<. */}
">>" { return K_RS; }
">>>" { return K_RSS; }
"**" { return K_POW; }
"<=" { return K_LE; }
">=" { return K_GE; }
"=>" { return K_EG; }
+1
View File
@@ -48,6 +48,7 @@ genvar, K_genvar
highz0, K_highz0
highz1, K_highz1
if, K_if
ifnone, K_ifnone
initial, K_initial
inout, K_inout
input, K_input
+2 -2
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.35 2006/10/30 22:45:37 steve Exp $"
#
#
SHELL = /bin/sh
@@ -92,7 +92,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
+2
View File
@@ -1,6 +1,8 @@
AC_INIT(Makefile.in)
AC_CONFIG_HEADER(config.h)
AC_CANONICAL_HOST
AC_PROG_CC
AC_PROG_INSTALL
AC_PROG_RANLIB
+11 -8
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.16 2006/10/30 22:45:37 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
@@ -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,9 @@ PLI_INT32 tf_setrealdelay(double dly)
}
/*
* $Log: veriusertfs.c,v $
* 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.
*
+33 -7
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.92 2005/07/14 23:38:43 steve Exp $"
#ident "$Id: main.cc,v 1.93 2006/09/28 04:35:18 steve Exp $"
#endif
# include "config.h"
@@ -88,6 +88,7 @@ const char*target = "null";
*/
generation_t generation_flag = GN_DEFAULT;
bool gn_cadence_types_flag = true;
bool gn_specify_blocks_flag = true;
map<string,const char*> flags;
char*vpi_module_list = 0;
@@ -186,17 +187,29 @@ const char *net_func_to_name(const net_func func)
static void process_generation_flag(const char*gen)
{
if (strcmp(gen,"1") == 0)
if (strcmp(gen,"1") == 0) {
generation_flag = GN_VER1995;
else if (strcmp(gen,"2") == 0)
} else if (strcmp(gen,"2") == 0) {
generation_flag = GN_VER2001;
else if (strcmp(gen,"2x") == 0)
} else if (strcmp(gen,"2x") == 0) {
generation_flag = GN_VER2001X;
else
generation_flag = GN_DEFAULT;
} else if (strcmp(gen,"xtypes") == 0) {
gn_cadence_types_flag = true;
} else if (strcmp(gen,"no-xtypes") == 0) {
gn_cadence_types_flag = false;
} else if (strcmp(gen,"specify") == 0) {
gn_specify_blocks_flag = true;
} else if (strcmp(gen,"no-specify") == 0) {
gn_specify_blocks_flag = false;
} else {
}
}
static void parm_to_flagmap(const string&flag)
@@ -257,7 +270,7 @@ static void parm_to_flagmap(const string&flag)
* functor:<name>
* Append a named functor to the processing path.
*
* generation:<1|2|3.0>
* generation:<1|2|2x|xtypes|no-xtypes|specify|no-specify>
* This is the generation flag
*
* ivlpp:<preprocessor command>
@@ -559,6 +572,16 @@ int main(int argc, char*argv[])
break;
}
if (gn_specify_blocks_flag)
cout << ",specify";
else
cout << ",no-specify";
if (gn_cadence_types_flag)
cout << ",xtypes";
else
cout << ",no-xtypes";
cout << endl << "PARSING INPUT" << endl;
}
@@ -764,6 +787,9 @@ int main(int argc, char*argv[])
/*
* $Log: main.cc,v $
* Revision 1.93 2006/09/28 04:35:18 steve
* Support selective control of specify and xtypes features.
*
* Revision 1.92 2005/07/14 23:38:43 steve
* Display as version 0.9.devel
*
+109 -108
View File
@@ -2,7 +2,7 @@
MINGW PORT OF ICARUS VERILOG
Copyright 2003 Stephen Williams <[email protected]>
Copyright 2006 Stephen Williams <[email protected]>
Icarus Verilog source can be compiled with the mingw C/C++ compilers
@@ -12,13 +12,13 @@ or without Cygwin, so this is the preferred Windows distribution form.
The configure scripts automatically detect that the compilers in use
are the mingw compilers and will configure the Makefiles appropriately.
However, the mingw tools do not include all the other tools around the
compiler, including the shell interpreter for the configure script,
bison, flex, gperf, etc. Therefore, you still need Cygwin to compile
Icarus Verilog, even if you don't need the Cygwin compilers. There are
also a few precompiled library prerequisites that you need.
The mingw patch doesn't contain tools beyond the compiler, but there
is the "msys" package that the makers of Mingw publish that has enough
extra tools to get most everything else working. There are a few extra
packages needed beyond mingw and msys, and the following instructions
explain how to get them and install them.
* Some Preliminary Comments
* Some Preliminary Comments -- PLEASE READ ME --
The Windows port of Icarus Verilog is the most difficult of all the
ports. The Windows system off the shelf is completely stripped, devoid
@@ -26,7 +26,15 @@ of any support for software development. Everything needed to compile
Icarus Verilog must be collected from various sources and stitched
together by hand. Normal human beings with a basic understanding of
software development can do this, but some patience (and access to the
Internet) is required. You may choose to print these instructions.
Internet) is required. You may choose to print these instructions. FOR
BEST RESULTS, FOLLOW THESE INSTRUCTIONS CAREFULLY.
NOTE that if you have Cygwin installed, it is best to not use a cygwin
window to do the build, as the Cygwin tools will intermix with the
mingw tools such that it is hard to be sure you are using the right
compiler. Thus, it is recommended that these steps be *not* done in a
Cygwin window. Use an MSYS window instead, and be careful that your
msys/mingw tools are not masked by paths that point to Cygwin binaries.
I have no plans to intentionally support MSVC++ compilation. Don't ask.
@@ -36,13 +44,15 @@ This is a brief list of prerequisite packages, along with the URL
where each can be found. In most cases, the specific version is not
critical, but these are the versions I use.
Cygwin <http://cygwin.com>
Mingw32-2.0.0 <http://www.mingw.org>
msys-1.0 <http://www.mingw/org>
msysDTK-1.0 <http://www.mingw.org>
Mingw32-5.x <http://www.mingw.org>
readline-4.2-20010727.zip <http://mingwrep.sourceforge.net>
bzip2-1.0.2-bin.zip <http://gnuwin32.sourceforge.net>
zlib-1.1.4-bin.zip <http://gnuwin32.sourceforge.net>
bzip2-1.0.2-lib.zip <http://gnuwin32.sourceforge.net>
zlib-1.1.4-lib.zip <http://gnuwin32.sourceforge.net>
bzip2-1.0.3 <http://gnuwin32.sourceforge.net>
zlib-1.2.3 <http://gnuwin32.sourceforge.net>
gperf-3.0.1 <http://gnuwin32.sourceforge.net>
bison-2.1 <http://gnuwin32.sourceforge.net>
flex-2.5.4a <http://gnuwin32.sourceforge.net>
The above table lists the packages required. It is convenient to
install them in the above order. Many of these packages are also
@@ -55,59 +65,38 @@ installation of Icarus Verilog is complete. These are only needed to
build the compiler. The Mingw32 package can be used to compile VPI
modules if you choose.
* Install Cygwin
* Install MSYS and msysDTK
So, step 1 is "Download and Install Cygwin." See the web page
http://www.cygwin.com for instructions and the files to do
this. Cygwin *is* a kool package, and is worth having anyhow. There is
a convenient setup program that you download first. You execute the
setup program, and that prompts you to select the package you want.
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.
You need in particular the Cygwin base, bison (see notes) flex, make
and gperf. If you are compiling from CVS, you also need cvs, rcs and
automake packages. You will also need tar and gunzip, but these are
hard to not install. I recommend installing the "which" package as
well. Beyond the basics, be sure to install these Cygwin packages:
Download the msys-1.x.x.exe and msysdtc-1.x.x.exe binaries. These are
self-installing packages. Install msys first, and then msysDTC. Most
likely, you want to install them in c:/msys. (The msysDTK is installed
in the same location, as it is an add-on.)
bison (*not* 1.875. See Notes.)
flex
ghostscript (makes the documentation)
gperf
gzip
make
strip
tar (tar and gunzip for unpacking the source)
unzip (For unpacking zip compressed packages.)
which
This install should be easy and reliable.
NOTES:
bison-1.875 is broken, it generates invalid C/C++ code. You
don't want that version for anything you do. If you have that
version (use "bison -V" to check the version) then use the
Cygwin setup program to get a different version. I've downgraded
to 1.75 and couldn't be happier. In fact, a whole host of insane
bison bugs can be avoided that way.
There is a mingw32 runtime package included in the Cygwin
distribution. You do *not* need that, as you will be getting
everything from the mingw32 distribution itself.
Other then the install of mingw32, most of the remaining steps are
best done in a Cygwin window. When you installed Cygwin, a start menu
entry was created to allow you to start up the Cygwin window. I'll use
the string "$ " to represent a command prompt in this window, because
that is the usual bash prompt.
The installation will leave an "msys" icon on your desktop and in the
mingw sub-menu of your Start menu. This icon brings up a shell window
(a command line) that has paths all set up for executing msys and
mingw commands. This is what you will want to use while executing
commands below.
* Install Mingw32
The obvious step 2, then, is install the mingw compilers. These can be
found at the web page <http://www.mingw.org>. The Mingw-2.x.x version
comes prepackaged in a convenient, Windows style, installer. I
recommend you download this package instead of picking and choosing
bits.
found at the web page <http://www.mingw.org>. The Mingw-5.x.x package
is a convenient remote installer. Download this program and run
it. The installer will ask wich components you want to install. You
need only the base C compiler and the C++ compiler. (You may install
other languages if you wish.)
When I install Mingw32 (using the installer) I typically set a
destination directory of d:\mingw-2.0.0 or the like. You will be using
destination directory of d:\mingw or the like. You will be using
that path later.
NOTES:
@@ -115,6 +104,10 @@ that path later.
need Mingw32, even if you are using a precompiled binary. VPI
modules only require Mingw32, and none of the other libraries.
Finally, as part of installing the mingw32 compilers, remember to add
the mingw/bin directory to your path. You will need that to be able to
find the compilers later.
* Install Mingw32 Packages
There is a collection of precompiled libraries and add-on packages
@@ -123,86 +116,94 @@ with simplified Windows installers, but they are pretty easy to
install by hand. Icarus Verilog uses the readline-4.2 package from
that collection.
Since I installed Mingw32 in d:\mingw-2.0.0, I also created a
Mingw-packages directory called d:\mingw-packages. The install, then,
Since I installed Mingw32 in c:\mingw, I also created a
Mingw-packages directory called c:\mingw-packages. The install, then,
is as easy as this:
<cygwin shell>
$ cd d:/mingw-packages
<msys shell>
$ cd c:/mingw-packages
$ unzip readline-4.2-20010727.zip
[lots of inflating...]
There is no need to adjust your execution path for this package as we
are only using a library out of here. However, do remember the
directory name, as you will need it later.
Done. On to the next packages.
* Install GnuWin32 Packages
The GnuWin32 project is a collections of open source programs and
libraries ported to Windows. These also work well with the Mingw
compiler, and in fact Icarus Verilog uses a few libraries from this
compiler, and in fact Icarus Verilog uses a few pieces from this
collection.
You will need these gnuwin32 packages to compile Icarus Verilog:
<http://gnuwin32.sourceforge.net>
bzip2-1.0.2-lib.zip
bzip2-1.0.2-bin.zip
zlib-1.1.4-lib.zip
zlib-1.1.4-bin.zip
bzip2-1.0.3.exe
zlib-1.2.3.exe
gperf-3.0.1.exe
bison-2.1.exe
flex-2.5.4a.exe
I suggest creating a common directory for holding all your gnuwin32
packages. I use D:\gnuwin32.
packages. I use C:\gnuwin32. The download page at the gnuwin32 site
has a "setup" link for each of these packages. Click the setup to
download the installer for each of the desired programes, then execute
the downloaded .exe files to invoke the installer. Install into the
c:\gunwin32 directory.
After downloading these packages, put the .zip files in your gnuwin32
directory and install them like so:
NOTES:
You need the binaries and the developer files, but you do not
need the source to these packages. The installer gives you the
choice.
<cygwin shell>
$ cd d:/gnuwin32
$ unzip bzip2-1.0.2-bin.zip
[lots of inflating...]
$ unzip bzip2-1.0.2-lib.zip
[lots of inflating...]
$ unzip zlib-1.1.4-bin.zip
[lots of inflating...]
$ unzip zlib-1.1.4-lib.zip
[lots of inflating...]
Done.
After you are done installing the gnuwin32 tools, you should add the
c:\gnuwin32\bin directory (assuming you installed in c:\gnuwin32) to
your Windows path. The msys shell will pick up your Windows path.
* Unpack Icarus Verilog source
Unpack the compressed tar file (.tar.gz) of the source with a command
like this:
$ gunzip -d verilog-20030303.tar.gz | tar xvf -
$ gunzip -d verilog-xxxxxxxx.tar.gz | tar xvf -
This will create a directory "verilog-20030303" that contains all the
This will create a directory "verilog-xxxxxxxx" that contains all the
source for Icarus Verilog. Descend into that directory, as that is
where we will work from now on.
$ cd verilog-20030303
$ cd verilog-xxxxxxxx
NOTE:
NOTES:
The exact name of the file will vary according to the
snapshot. The 20030303 name is only an example.
* Select the mingw compilers
Unpack the source into a directory that has no spaces. The
makefiles included in the source get confused by white space in
directory names.
In your cygwin window, if you type "which c++" you might get the
response path "/usr/bin/c++" which is the cygwin compiler. This is not
the one we want to use, however. Tell the shell where the mingw
compilers are by setting the search path like so:
* Preconfigure Icarus Verilog (Not normally needed)
$ PATH=/cygdrive/d/mingw-2.0.0/bin:$PATH
Under certain cases, you may need to "preconfigure" the Icarus Verilog
source tree. You should only need to do this if you are getting the
Icarus Verilog source tree from CVS, or you are using an existing
source tree that you've patched to cause configure.in files to change.
This assumes that you installed mingw in D:\mingw-2.0.0. The actual
programs are in the bin directory under the root. After this command,
check that you are now getting the right compilers with this "which"
command:
NOTE: If you are building from a fresh, bundled source tree that
you downloaded from an FTP site, then SKIP THIS STEP. Go on to
the "Configure Icarus Verilog" step below.
$ which c++
/cygdrive/d/mingw-2.0.0/bin/c++
First, remove any autom4te.cache directories that may exist in your
source tree. These can make a mess of autoconf runs. Then, generate
configure scripts with this command:
Good!
$ sh autoconf.sh
This script will run the "autoconf" command (part of the msysDTK) to
generate all the necessary "configure" scripts. This will take a few
minutes. This should go smoothly.
* Configure Icarus Verilog
@@ -215,10 +216,10 @@ without white space.
Now, configure the source to make the makefiles and configuration
details. Run these commands:
$ CPPFLAGS="-Id:/gnuwin32/include -Id:/mingw-packages/include"
$ LDFLAGS="-Ld:/gnuwin32/lib -Ld:/mingw-packages/include"
$ CPPFLAGS="-Ic:/gnuwin32/include -Ic:/mingw-packages/include"
$ LDFLAGS="-Lc:/gnuwin32/lib -Lc:/mingw-packages/lib"
$ export CPPFLAGS LDFLAGS
$ ./configure --prefix=d:/iverilog
$ ./configure --prefix=c:/iverilog
NOTES:
The CPPFLAGS and LDFLAGS variables tell configure where
@@ -267,10 +268,10 @@ directory you chose) and away you go.
You may find that you need to put some of the prerequisite DLLs into
the d:\iverilog\bin directory. These include:
d:\mingw-2.0.0\bin\mingw10.dll
d:\mingw-packages\bin\libreadline.dll
d:\gnuwin32\bin\bzip2.dll
d:\gnuwin32\bin\zlib.dll
c:\mingw\bin\mingw10.dll
c:\mingw-packages\bin\libreadline.dll
c:\gnuwin32\bin\bzip2.dll
c:\gnuwin32\bin\zlib.dll
If you already have these in your Windows path (i.e. your system32
directory) then you do not need to copy them into the iverilog
@@ -279,14 +280,14 @@ files.
* Running Icarus Verilog
Finally, put the D:\iverilog\bin directory in your Windows path, and
Finally, put the C:\iverilog\bin directory in your Windows path, and
you should be able to run the iverilog and vvp commands to your
heart's content.
Currently, the iverilog.exe uses the path to itself to locate the
libraries and modules associated with itself. In other words, if you
execute the D:\iverilog\bin\iverilog.exe program, it will locate its
subparts in the D:\iverilog directory and subdirectories below
execute the C:\iverilog\bin\iverilog.exe program, it will locate its
subparts in the C:\iverilog directory and subdirectories below
that. This means you can move the Icarus Verilog installation by
simply moving the root directory and all its contents.
+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.
*
+23 -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_design.cc,v 1.48 2005/11/27 05:56:20 steve Exp $"
#ident "$Id: net_design.cc,v 1.50 2006/08/08 05:11:37 steve Exp $"
#endif
# include "config.h"
@@ -67,8 +67,8 @@ int Design::get_precision() const
return des_precision_;
}
unsigned long Design::scale_to_precision(unsigned long val,
const NetScope*scope) const
uint64_t Design::scale_to_precision(uint64_t val,
const NetScope*scope) const
{
int units = scope->time_unit();
assert( units >= des_precision_ );
@@ -327,12 +327,20 @@ void NetScope::evaluate_parameters(Design*des)
switch (expr->expr_type()) {
case IVL_VT_REAL:
if (! dynamic_cast<const NetECReal*>(expr)) {
cerr << (*cur).second.expr->get_line()
<< ": internal error: "
"unable to evaluate real parameter values: " <<
*expr << endl;
des->errors += 1;
continue;
NetExpr*nexpr = expr->eval_tree();
if (nexpr == 0) {
cerr << (*cur).second.expr->get_line()
<< ": internal error: "
<< "unable to evaluate real parameter value: "
<< *expr << endl;
des->errors += 1;
continue;
}
assert(nexpr);
delete expr;
(*cur).second.expr = nexpr;
}
break;
@@ -554,6 +562,12 @@ void Design::delete_process(NetProcTop*top)
/*
* $Log: net_design.cc,v $
* Revision 1.50 2006/08/08 05:11:37 steve
* Handle 64bit delay constants.
*
* Revision 1.49 2006/07/31 03:50:17 steve
* Add support for power in constant expressions.
*
* Revision 1.48 2005/11/27 05:56:20 steve
* Handle bit select of parameter with ranges.
*
+38 -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_expr.cc,v 1.26 2005/11/26 00:35:43 steve Exp $"
#ident "$Id: net_expr.cc,v 1.27 2006/07/31 03:50:17 steve Exp $"
#endif
# include "config.h"
@@ -248,6 +248,40 @@ ivl_variable_type_t NetEBMult::expr_type() const
return IVL_VT_LOGIC;
}
NetEBPow::NetEBPow(char op, NetExpr*l, NetExpr*r)
: NetEBinary(op, l, r)
{
assert(op == 'p');
expr_width(l->expr_width());
cast_signed(l->has_sign() || r->has_sign());
}
NetEBPow::~NetEBPow()
{
}
NetEBPow* NetEBPow::dup_expr() const
{
NetEBPow*result = new NetEBPow(op_, left_->dup_expr(),
right_->dup_expr());
result->set_line(*this);
return result;
}
ivl_variable_type_t NetEBPow::expr_type() const
{
if (right_->expr_type() == IVL_VT_REAL)
return IVL_VT_REAL;
if (left_->expr_type() == IVL_VT_REAL)
return IVL_VT_REAL;
if (left_->has_sign())
return IVL_VT_REAL;
if (right_->has_sign())
return IVL_VT_REAL;
return IVL_VT_LOGIC;
}
NetEBShift::NetEBShift(char op, NetExpr*l, NetExpr*r)
: NetEBinary(op, l, r)
{
@@ -526,6 +560,9 @@ ivl_variable_type_t NetESFunc::expr_type() const
/*
* $Log: net_expr.cc,v $
* Revision 1.27 2006/07/31 03:50:17 steve
* Add support for power in constant expressions.
*
* Revision 1.26 2005/11/26 00:35:43 steve
* More precise about r-value width of constants.
*
+39 -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_func.cc,v 1.7 2005/03/18 02:56:03 steve Exp $"
#ident "$Id: net_func.cc,v 1.8 2006/06/18 04:15:50 steve Exp $"
#endif
# include "config.h"
@@ -112,8 +112,46 @@ bool PECallFunction::check_call_matches_definition_(Design*des, NetScope*dscope)
return true;
}
NetSysFunc::NetSysFunc(NetScope*s, perm_string n,
const struct sfunc_return_type*def,
unsigned ports)
: NetNode(s, n, ports)
{
def_ = def;
pin(0).set_dir(Link::OUTPUT);
pin(0).set_name(perm_string::literal("Q"), 0);
for (unsigned idx = 1 ; idx < pin_count() ; idx += 1) {
pin(idx).set_dir(Link::INPUT);
pin(idx).set_name(perm_string::literal("D"), idx-1);
pin(idx).drive0(Link::HIGHZ);
pin(idx).drive1(Link::HIGHZ);
}
}
NetSysFunc::~NetSysFunc()
{
}
const char*NetSysFunc::func_name() const
{
return def_->name;
}
unsigned NetSysFunc::vector_width() const
{
return def_->wid;
}
/*
* $Log: net_func.cc,v $
* Revision 1.8 2006/06/18 04:15:50 steve
* Add support for system functions in continuous assignments.
*
* Revision 1.7 2005/03/18 02:56:03 steve
* Add support for LPM_UFUNC user defined functions.
*
+23 -11
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: net_nex_input.cc,v 1.14 2005/07/11 16:56:50 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.
@@ -170,10 +164,19 @@ NexusSet* NetEUnary::nex_input()
NexusSet* NetAssign_::nex_input()
{
if (bmux_ == 0)
return new NexusSet;
else
return bmux_->nex_input();
NexusSet*result = new NexusSet;
if (word_) {
NexusSet*tmp = word_->nex_input();
result->add(*tmp);
delete tmp;
}
if (base_) {
NexusSet*tmp = base_->nex_input();
result->add(*tmp);
delete tmp;
}
return result;
}
NexusSet* NetAssignBase::nex_input()
@@ -384,6 +387,15 @@ NexusSet* NetWhile::nex_input()
/*
* $Log: net_nex_input.cc,v $
* Revision 1.16 2007/01/16 05:44:15 steve
* Major rework of array handling. Memories are replaced with the
* more general concept of arrays. The NetMemory and NetEMemory
* classes are removed from the ivl core program, and the IVL_LPM_RAM
* lpm type is removed from the ivl_target API.
*
* Revision 1.15 2006/04/16 00:15:43 steve
* Fix part selects in l-values.
*
* Revision 1.14 2005/07/11 16:56:50 steve
* Remove NetVariable and ivl_variable_t structures.
*
+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_proc.cc,v 1.6 2002/08/12 01:34:59 steve Exp $"
#ident "$Id: net_proc.cc,v 1.7 2006/08/08 05:11:37 steve Exp $"
#endif
# include "config.h"
@@ -131,7 +131,7 @@ NetForever::~NetForever()
delete statement_;
}
NetPDelay::NetPDelay(unsigned long d, NetProc*st)
NetPDelay::NetPDelay(uint64_t d, NetProc*st)
: delay_(d), expr_(0), statement_(st)
{
}
@@ -146,7 +146,7 @@ NetPDelay::~NetPDelay()
if (expr_) delete expr_;
}
unsigned long NetPDelay::delay() const
uint64_t NetPDelay::delay() const
{
assert(expr_ == 0);
return delay_;
@@ -177,6 +177,9 @@ const NetExpr* NetRepeat::expr() const
/*
* $Log: net_proc.cc,v $
* Revision 1.7 2006/08/08 05:11:37 steve
* Handle 64bit delay constants.
*
* Revision 1.6 2002/08/12 01:34:59 steve
* conditional ident string using autoconfig.
*
+7 -46
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.36 2007/01/16 05:44:15 steve Exp $"
#endif
# include "config.h"
@@ -38,7 +38,6 @@
NetScope::NetScope(NetScope*up, perm_string n, NetScope::TYPE t)
: type_(t), up_(up), sib_(0), sub_(0)
{
memories_ = 0;
signals_ = 0;
events_ = 0;
lcounter_ = 0;
@@ -358,50 +357,6 @@ NetNet* NetScope::find_signal_in_child(const hname_t&path)
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.
@@ -457,6 +412,12 @@ string NetScope::local_hsymbol()
/*
* $Log: net_scope.cc,v $
* 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.
*
+246 -267
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: netlist.cc,v 1.248 2005/09/14 02:53:14 steve Exp $"
#ident "$Id: netlist.cc,v 1.252 2007/01/19 04:25:37 steve Exp $"
#endif
# include "config.h"
@@ -237,10 +237,103 @@ NetBus::~NetBus()
{
}
NetDelaySrc::NetDelaySrc(NetScope*s, perm_string n, unsigned npins)
: NetObj(s, n, npins)
{
for (unsigned idx = 0 ; idx < npins ; idx += 1) {
pin(idx).set_name(perm_string::literal("I"), idx);
pin(idx).set_dir(Link::INPUT);
}
}
NetDelaySrc::~NetDelaySrc()
{
}
void NetDelaySrc::set_delays(uint64_t del)
{
for (unsigned idx = 0 ; idx < 12 ; idx += 1)
transition_delays_[idx] = del;
}
void NetDelaySrc::set_delays(uint64_t trise, uint64_t tfall)
{
transition_delays_[IVL_PE_01] = trise;
transition_delays_[IVL_PE_10] = tfall;
transition_delays_[IVL_PE_0z] = trise;
transition_delays_[IVL_PE_z1] = trise;
transition_delays_[IVL_PE_1z] = tfall;
transition_delays_[IVL_PE_z0] = tfall;
transition_delays_[IVL_PE_0x] = trise;
transition_delays_[IVL_PE_x1] = trise;
transition_delays_[IVL_PE_1x] = tfall;
transition_delays_[IVL_PE_x0] = tfall;
transition_delays_[IVL_PE_xz] = max(trise,tfall);
transition_delays_[IVL_PE_zx] = min(trise,tfall);
}
void NetDelaySrc::set_delays(uint64_t trise, uint64_t tfall, uint64_t tz)
{
transition_delays_[IVL_PE_01] = trise;
transition_delays_[IVL_PE_10] = tfall;
transition_delays_[IVL_PE_0z] = tz;
transition_delays_[IVL_PE_z1] = trise;
transition_delays_[IVL_PE_1z] = tz;
transition_delays_[IVL_PE_z0] = tfall;
transition_delays_[IVL_PE_0x] = min(trise,tz);
transition_delays_[IVL_PE_x1] = trise;
transition_delays_[IVL_PE_1x] = min(tfall,tz);
transition_delays_[IVL_PE_x0] = tfall;
transition_delays_[IVL_PE_xz] = tz;
transition_delays_[IVL_PE_zx] = min(trise,tfall);
}
void NetDelaySrc::set_delays(uint64_t t01, uint64_t t10, uint64_t t0z,
uint64_t tz1, uint64_t t1z, uint64_t tz0)
{
transition_delays_[IVL_PE_01] = t01;
transition_delays_[IVL_PE_10] = t10;
transition_delays_[IVL_PE_0z] = t0z;
transition_delays_[IVL_PE_z1] = tz1;
transition_delays_[IVL_PE_1z] = t1z;
transition_delays_[IVL_PE_z0] = tz0;
transition_delays_[IVL_PE_0x] = min(t01,t0z);
transition_delays_[IVL_PE_x1] = max(t01,tz1);
transition_delays_[IVL_PE_1x] = min(t10,t1z);
transition_delays_[IVL_PE_x0] = max(t10,tz0);
transition_delays_[IVL_PE_xz] = max(t1z,t0z);
transition_delays_[IVL_PE_zx] = min(tz1,tz0);
}
void NetDelaySrc::set_delays(uint64_t t01, uint64_t t10, uint64_t t0z,
uint64_t tz1, uint64_t t1z, uint64_t tz0,
uint64_t t0x, uint64_t tx1, uint64_t t1x,
uint64_t tx0, uint64_t txz, uint64_t tzx)
{
transition_delays_[IVL_PE_01] = t01;
transition_delays_[IVL_PE_10] = t10;
transition_delays_[IVL_PE_0z] = t0z;
transition_delays_[IVL_PE_z1] = tz1;
transition_delays_[IVL_PE_1z] = t1z;
transition_delays_[IVL_PE_z0] = tz0;
transition_delays_[IVL_PE_0x] = t0x;
transition_delays_[IVL_PE_x1] = tx1;
transition_delays_[IVL_PE_1x] = t1x;
transition_delays_[IVL_PE_x0] = tx0;
transition_delays_[IVL_PE_xz] = txz;
transition_delays_[IVL_PE_zx] = tzx;
}
uint64_t NetDelaySrc::get_delay(unsigned idx) const
{
assert(idx < 12);
return transition_delays_[idx];
}
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), s0_(0), e0_(0),
local_flag_(false), eref_count_(0), lref_count_(0)
{
assert(s);
@@ -274,11 +367,20 @@ 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)
: NetObj(s, n, 1),
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),
msb_(ms), lsb_(ls), s0_(array_s), e0_(array_e),
local_flag_(false), eref_count_(0), lref_count_(0)
{
assert(s);
@@ -304,9 +406,11 @@ 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);
}
@@ -440,6 +544,43 @@ unsigned NetNet::sb_to_idx(long sb) const
return lsb_ - sb;
}
unsigned NetNet::array_dimensions() const
{
if (s0_ == e0_)
return 0;
return 1;
}
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;
@@ -477,6 +618,21 @@ unsigned NetNet::get_refs() const
return lref_count_ + eref_count_;
}
void NetNet::add_delay_path(NetDelaySrc*path)
{
delay_paths_.push_back(path);
}
unsigned NetNet::delay_paths(void)const
{
return delay_paths_.size();
}
const NetDelaySrc* NetNet::delay_path(unsigned idx) const
{
assert(idx < delay_paths_.size());
return delay_paths_[idx];
}
NetPartSelect::NetPartSelect(NetNet*sig, unsigned off, unsigned wid,
NetPartSelect::dir_t dir)
@@ -865,6 +1021,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
@@ -1320,190 +1525,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)
{
@@ -1919,68 +1940,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)
{
@@ -2011,25 +1970,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()
{
@@ -2041,18 +1995,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_;
}
@@ -2072,6 +2030,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)
{
@@ -2228,6 +2192,21 @@ const NetProc*NetTaskDef::proc() const
/*
* $Log: netlist.cc,v $
* 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.
*
* Revision 1.248 2005/09/14 02:53:14 steve
* Support bool expressions and compares handle them optimally.
*
+216 -176
View File
@@ -1,7 +1,7 @@
#ifndef __netlist_H
#define __netlist_H
/*
* Copyright (c) 1998-2003 Stephen Williams (steve@icarus.com)
* Copyright (c) 1998-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
@@ -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.357 2006/04/10 00:37:42 steve Exp $"
#ident "$Id: netlist.h,v 1.366 2007/01/16 05:44:15 steve Exp $"
#endif
/*
@@ -31,6 +31,8 @@
# include <string>
# include <map>
# include <list>
# include <vector>
# include <stdint.h>
# include "ivl_target.h"
# include "verinum.h"
# include "verireal.h"
@@ -368,6 +370,46 @@ class NetNode : public NetObj {
Design*design_;
};
/*
* A NetDelaySrc is an input-only device that calculates a path delay
* based on the time that the inputs change. This class is used by the
* NetNet class, and NetDelaySrc objects cannot exist outside of its
* association with NetNet objects.
*/
class NetDelaySrc : public NetObj {
public:
explicit NetDelaySrc(NetScope*s, perm_string n, unsigned npins);
~NetDelaySrc();
// These functions set the delays from the values in the
// source. These set_delays functions implement the various
// rules wrt collections of transitions.
// One transition specified.
void set_delays(uint64_t del);
// Two transitions: rise and fall
void set_delays(uint64_t rise, uint64_t fall);
// Three transitions
void set_delays(uint64_t rise, uint64_t fall, uint64_t tz);
void set_delays(uint64_t t01, uint64_t t10, uint64_t t0z,
uint64_t tz1, uint64_t t1z, uint64_t tz0);
void set_delays(uint64_t t01, uint64_t t10, uint64_t t0z,
uint64_t tz1, uint64_t t1z, uint64_t tz0,
uint64_t t0x, uint64_t tx1, uint64_t t1x,
uint64_t tx0, uint64_t txz, uint64_t tzx);
uint64_t get_delay(unsigned pe) const;
void dump(ostream&, unsigned ind) const;
private:
uint64_t transition_delays_[12];
private: // Not implemented
NetDelaySrc(const NetDelaySrc&);
NetDelaySrc& operator= (const NetDelaySrc&);
};
/*
* NetNet is a special kind of NetObj that doesn't really do anything,
@@ -405,7 +447,12 @@ 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, long s0 =0, long e0 =0);
virtual ~NetNet();
@@ -446,6 +493,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; }
@@ -462,6 +524,11 @@ class NetNet : public NetObj {
unsigned get_refs() const;
/* Manage path delays */
void add_delay_path(class NetDelaySrc*path);
unsigned delay_paths(void) const;
const class NetDelaySrc*delay_path(unsigned idx) const;
virtual void dump_net(ostream&, unsigned) const;
private:
@@ -477,10 +544,13 @@ class NetNet : public NetObj {
bool isint_; // original type of integer
long msb_, lsb_;
long s0_, e0_;
bool local_flag_;
unsigned eref_count_;
unsigned lref_count_;
vector<class NetDelaySrc*> delay_paths_;
};
/*
@@ -522,6 +592,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.
*/
@@ -770,62 +871,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
@@ -916,57 +961,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
@@ -1020,6 +1014,28 @@ class NetUserFunc : public NetNode {
NetScope*def_;
};
/*
* The number of ports includes the return value, so will always be at
* least 1.
*/
class NetSysFunc : public NetNode {
public:
NetSysFunc(NetScope*s, perm_string n,
const struct sfunc_return_type*def,
unsigned ports);
~NetSysFunc();
unsigned vector_width() const;
const char* func_name() const;
virtual void dump_node(ostream&, unsigned ind) const;
virtual bool emit_node(struct target_t*) const;
private:
const struct sfunc_return_type*def_;
};
/* =========
* There are cases where expressions need to be represented. The
* NetExpr class is the root of a hierarchy that serves that purpose.
@@ -1639,20 +1655,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
@@ -1664,7 +1678,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
@@ -1684,9 +1697,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
@@ -2266,11 +2278,11 @@ class NetFuncDef {
class NetPDelay : public NetProc {
public:
NetPDelay(unsigned long d, NetProc*st);
NetPDelay(uint64_t d, NetProc*st);
NetPDelay(NetExpr* d, NetProc*st);
~NetPDelay();
unsigned long delay() const;
uint64_t delay() const;
const NetExpr*expr() const;
virtual NexusSet* nex_input();
@@ -2282,7 +2294,7 @@ class NetPDelay : public NetProc {
bool emit_proc_recurse(struct target_t*) const;
private:
unsigned long delay_;
uint64_t delay_;
NetExpr*expr_;
NetProc*statement_;
};
@@ -2537,6 +2549,7 @@ class NetProcTop : public LineInfo, public Attrib {
* * -- Arithmetic multiply
* / -- Arithmetic divide
* % -- Arithmetic modulus
* p -- Arithmetic power (**)
* & -- Bit-wise AND
* | -- Bit-wise OR
* < -- Less then
@@ -2740,6 +2753,28 @@ class NetEBMult : public NetEBinary {
};
/*
* Support the binary multiplication (*) operator.
*/
class NetEBPow : public NetEBinary {
public:
NetEBPow(char op, NetExpr*l, NetExpr*r);
~NetEBPow();
virtual ivl_variable_type_t expr_type() const;
virtual bool set_width(unsigned w, bool last_chance);
virtual NetEBPow* dup_expr() const;
virtual NetExpr* eval_tree();
virtual NetNet* synthesize(Design*);
private:
NetExpr* eval_tree_real_();
};
/*
* The binary logical operators are those that return boolean
@@ -3055,52 +3090,21 @@ class NetEUReduce : public NetEUnary {
};
/*
* 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_;
};
/*
* 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;
@@ -3110,12 +3114,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;
@@ -3126,6 +3134,8 @@ class NetESignal : public NetExpr {
private:
NetNet*net_;
// Expression to select a word from the net.
NetExpr*word_;
};
@@ -3184,15 +3194,6 @@ class NetScope : public Attrib {
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();
@@ -3276,6 +3277,15 @@ class NetScope : public Attrib {
map<perm_string,param_expr_t>parameters;
map<perm_string,param_expr_t>localparams;
struct spec_val_t {
ivl_variable_type_t type;
union {
double real_val; // type == IVL_VT_REAL
long integer; // type == IVL_VT_BOOL
};
};
map<perm_string,spec_val_t>specparams;
/* Module instance arrays are collected here for access during
the multiple elaboration passes. */
typedef svector<NetScope*> scope_vec_t;
@@ -3296,8 +3306,6 @@ class NetScope : public Attrib {
NetEvent *events_;
NetNet *signals_;
NetMemory*memories_;
perm_string module_name_;
union {
NetTaskDef*task_;
@@ -3349,7 +3357,7 @@ class Design {
/* This function takes a delay value and a scope, and returns
the delay value scaled to the precision of the design. */
unsigned long scale_to_precision(unsigned long, const NetScope*)const;
uint64_t scale_to_precision(uint64_t, const NetScope*)const;
/* Look up a scope. If no starting scope is passed, then the
path is taken as an absolute scope name. Otherwise, the
@@ -3464,6 +3472,38 @@ extern ostream& operator << (ostream&, NetNet::Type);
/*
* $Log: netlist.h,v $
* 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.
*
* Revision 1.362 2006/09/26 19:48:40 steve
* Missing PSpec.cc file.
*
* Revision 1.361 2006/09/23 04:57:19 steve
* Basic support for specify timing.
*
* Revision 1.360 2006/08/08 05:11:37 steve
* Handle 64bit delay constants.
*
* Revision 1.359 2006/07/31 03:50:17 steve
* Add support for power in constant expressions.
*
* Revision 1.358 2006/06/18 04:15:50 steve
* Add support for system functions in continuous assignments.
*
* Revision 1.357 2006/04/10 00:37:42 steve
* Add support for generate loops w/ wires and gates.
*
+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: netmisc.cc,v 1.11 2005/04/08 04:50:31 steve Exp $"
#ident "$Id: netmisc.cc,v 1.12 2006/06/02 04:48:50 steve Exp $"
#endif
# include "config.h"
@@ -123,9 +123,10 @@ NetExpr* make_sub_expr(long val, NetExpr*expr)
return res;
}
NetExpr* elab_and_eval(Design*des, NetScope*scope, const PExpr*pe)
NetExpr* elab_and_eval(Design*des, NetScope*scope,
const PExpr*pe, int expr_wid)
{
NetExpr*tmp = pe->elaborate_expr(des, scope);
NetExpr*tmp = pe->elaborate_expr(des, scope, expr_wid, false);
if (tmp == 0)
return 0;
@@ -140,6 +141,11 @@ NetExpr* elab_and_eval(Design*des, NetScope*scope, const PExpr*pe)
/*
* $Log: netmisc.cc,v $
* 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
* minus is context determined sizes.
*
* Revision 1.11 2005/04/08 04:50:31 steve
* Don not give to make_add express an unwanted width.
*
+21 -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: netmisc.h,v 1.24 2005/11/27 05:56:20 steve Exp $"
#ident "$Id: netmisc.h,v 1.27 2007/01/16 05:44:15 steve Exp $"
#endif
# include "netlist.h"
@@ -42,7 +42,6 @@
extern NetScope* symbol_search(const Design*des,
NetScope*start, hname_t path,
NetNet*&net, /* net/reg */
NetMemory*&mem, /* memory */
const NetExpr*&par,/* parameter */
NetEvent*&eve, /* named event */
const NetExpr*&ex1, const NetExpr*&ex2);
@@ -50,12 +49,11 @@ extern NetScope* symbol_search(const Design*des,
inline NetScope* symbol_search(const Design*des,
NetScope*start, const hname_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, /*mem,*/ par, eve, ex1, ex2);
}
/*
@@ -112,12 +110,30 @@ extern unsigned count_lval_width(const class NetAssign_*first);
* right away. If the expression can be evaluated, this returns a
* constant expression. If it cannot be evaluated, it returns whatever
* 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.
*/
class PExpr;
extern NetExpr* elab_and_eval(Design*des, NetScope*scope, const PExpr*pe);
extern NetExpr* elab_and_eval(Design*des, NetScope*scope,
const PExpr*pe, int expr_wid);
/*
* $Log: netmisc.h,v $
* 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.
*
* Revision 1.25 2006/06/02 04:48:50 steve
* Make elaborate_expr methods aware of the width that the context
* requires of it. In the process, fix sizing of the width of unary
* minus is context determined sizes.
*
* Revision 1.24 2005/11/27 05:56:20 steve
* Handle bit select of parameter with ranges.
*
+285 -50
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: parse.y,v 1.213 2006/04/10 00:37:42 steve Exp $"
#ident "$Id: parse.y,v 1.224 2007/01/16 05:44:15 steve Exp $"
#endif
# include "config.h"
@@ -30,6 +30,8 @@
# include "Statement.h"
# include <sstream>
class PSpecPath;
extern void lex_start_table();
extern void lex_end_table();
@@ -68,6 +70,22 @@ static struct {
*/
const static struct str_pair_t pull_strength = { PGate::PULL, PGate::PULL };
const static struct str_pair_t str_strength = { PGate::STRONG, PGate::STRONG };
static list<perm_string>* list_from_identifier(char*id)
{
list<perm_string>*tmp = new list<perm_string>;
tmp->push_back(lex_strings.make(id));
delete id;
return tmp;
}
static list<perm_string>* list_from_identifier(list<perm_string>*tmp, char*id)
{
tmp->push_back(lex_strings.make(id));
delete id;
return tmp;
}
%}
%union {
@@ -125,6 +143,8 @@ const static struct str_pair_t str_strength = { PGate::STRONG, PGate::STRONG };
verinum* number;
verireal* realtime;
PSpecPath* specpath;
};
%token <text> IDENTIFIER SYSTEM_IDENTIFIER STRING
@@ -132,7 +152,7 @@ const static struct str_pair_t str_strength = { PGate::STRONG, PGate::STRONG };
%token <number> BASED_NUMBER DEC_NUMBER
%token <realtime> REALTIME
%token K_LE K_GE K_EG K_EQ K_NE K_CEQ K_CNE K_LS K_RS K_RSS K_SG
%token K_PO_POS K_PO_NEG
%token K_PO_POS K_PO_NEG K_POW
%token K_PSTAR K_STARP
%token K_LOR K_LAND K_NAND K_NOR K_NXOR K_TRIGGER
%token K_always K_and K_assign K_begin K_bool K_buf K_bufif0 K_bufif1 K_case
@@ -140,7 +160,7 @@ const static struct str_pair_t str_strength = { PGate::STRONG, PGate::STRONG };
%token K_edge K_else K_end K_endcase K_endfunction K_endgenerate K_endmodule
%token K_endprimitive K_endspecify K_endtable K_endtask K_event K_for
%token K_force K_forever K_fork K_function K_generate K_genvar
%token K_highz0 K_highz1 K_if
%token K_highz0 K_highz1 K_if K_ifnone
%token K_initial K_inout K_input K_integer K_join K_large K_localparam
%token K_logic K_macromodule
%token K_medium K_module K_nand K_negedge K_nmos K_nor K_not K_notif0
@@ -171,8 +191,8 @@ const static struct str_pair_t str_strength = { PGate::STRONG, PGate::STRONG };
%type <expr> udp_initial_expr_opt
%type <hier> identifier
%type <text> register_variable
%type <perm_strings> register_variable_list list_of_identifiers
%type <text> register_variable net_variable
%type <perm_strings> register_variable_list net_variable_list list_of_identifiers
%type <net_decl_assign> net_decl_assign net_decl_assigns
@@ -181,6 +201,7 @@ const static struct str_pair_t str_strength = { PGate::STRONG, PGate::STRONG };
%type <mports> list_of_ports module_port_list_opt list_of_port_declarations
%type <wires> task_item task_item_list task_item_list_opt
%type <wires> task_port_item task_port_decl task_port_decl_list
%type <wires> function_item function_item_list
%type <named_pexpr> port_name parameter_value_byname
@@ -198,7 +219,7 @@ const static struct str_pair_t str_strength = { PGate::STRONG, PGate::STRONG };
%type <expr> expression expr_primary
%type <expr> lpvalue
%type <expr> delay_value delay_value_simple
%type <exprs> delay1 delay3 delay3_opt
%type <exprs> delay1 delay3 delay3_opt delay_value_list
%type <exprs> expression_list
%type <exprs> assign assign_list
%type <indexed_identifier> indexed_identifier
@@ -220,6 +241,8 @@ const static struct str_pair_t str_strength = { PGate::STRONG, PGate::STRONG };
%type <letter> spec_polarity
%type <perm_strings> specify_path_identifiers
%type <specpath> specify_simple_path specify_simple_path_decl
%token K_TAND
%right '?' ':'
%left K_LOR
@@ -232,13 +255,13 @@ const static struct str_pair_t str_strength = { PGate::STRONG, PGate::STRONG };
%left K_LS K_RS K_RSS
%left '+' '-'
%left '*' '/' '%'
%left K_POW
%left UNARY_PREC
/* to resolve dangling else ambiguity. */
%nonassoc less_than_K_else
%nonassoc K_else
%%
/* A degenerate source file can be completely empty. */
@@ -533,6 +556,19 @@ delay3_opt
| { $$ = 0; }
;
delay_value_list
: delay_value
{ svector<PExpr*>*tmp = new svector<PExpr*>(1);
(*tmp)[0] = $1;
$$ = tmp;
}
| delay_value_list ',' delay_value
{ svector<PExpr*>*tmp = new svector<PExpr*>(*$1, $3);
delete $1;
$$ = tmp;
}
;
delay_value
: expression
{ PExpr*tmp = $1;
@@ -776,6 +812,12 @@ expression
tmp->set_lineno(@2.first_line);
$$ = tmp;
}
| expression K_POW expression
{ PEBinary*tmp = new PEBinary('p', $1, $3);
tmp->set_file(@2.text);
tmp->set_lineno(@2.first_line);
$$ = tmp;
}
| expression '*' expression
{ PEBinary*tmp = new PEBinary('*', $1, $3);
tmp->set_file(@2.text);
@@ -837,67 +879,67 @@ expression
$$ = tmp;
}
| expression '<' expression
{ PEBinary*tmp = new PEBinary('<', $1, $3);
{ PEBinary*tmp = new PEBComp('<', $1, $3);
tmp->set_file(@2.text);
tmp->set_lineno(@2.first_line);
$$ = tmp;
}
| expression '>' expression
{ PEBinary*tmp = new PEBinary('>', $1, $3);
{ PEBinary*tmp = new PEBComp('>', $1, $3);
tmp->set_file(@2.text);
tmp->set_lineno(@2.first_line);
$$ = tmp;
}
| expression K_LS expression
{ PEBinary*tmp = new PEBinary('l', $1, $3);
{ PEBinary*tmp = new PEBShift('l', $1, $3);
tmp->set_file(@2.text);
tmp->set_lineno(@2.first_line);
$$ = tmp;
}
| expression K_RS expression
{ PEBinary*tmp = new PEBinary('r', $1, $3);
{ PEBinary*tmp = new PEBShift('r', $1, $3);
tmp->set_file(@2.text);
tmp->set_lineno(@2.first_line);
$$ = tmp;
}
| expression K_RSS expression
{ PEBinary*tmp = new PEBinary('R', $1, $3);
{ PEBinary*tmp = new PEBShift('R', $1, $3);
tmp->set_file(@2.text);
tmp->set_lineno(@2.first_line);
$$ = tmp;
}
| expression K_EQ expression
{ PEBinary*tmp = new PEBinary('e', $1, $3);
{ PEBinary*tmp = new PEBComp('e', $1, $3);
tmp->set_file(@2.text);
tmp->set_lineno(@2.first_line);
$$ = tmp;
}
| expression K_CEQ expression
{ PEBinary*tmp = new PEBinary('E', $1, $3);
{ PEBinary*tmp = new PEBComp('E', $1, $3);
tmp->set_file(@2.text);
tmp->set_lineno(@2.first_line);
$$ = tmp;
}
| expression K_LE expression
{ PEBinary*tmp = new PEBinary('L', $1, $3);
{ PEBinary*tmp = new PEBComp('L', $1, $3);
tmp->set_file(@2.text);
tmp->set_lineno(@2.first_line);
$$ = tmp;
}
| expression K_GE expression
{ PEBinary*tmp = new PEBinary('G', $1, $3);
{ PEBinary*tmp = new PEBComp('G', $1, $3);
tmp->set_file(@2.text);
tmp->set_lineno(@2.first_line);
$$ = tmp;
}
| expression K_NE expression
{ PEBinary*tmp = new PEBinary('n', $1, $3);
{ PEBinary*tmp = new PEBComp('n', $1, $3);
tmp->set_file(@2.text);
tmp->set_lineno(@2.first_line);
$$ = tmp;
}
| expression K_CNE expression
{ PEBinary*tmp = new PEBinary('N', $1, $3);
{ PEBinary*tmp = new PEBComp('N', $1, $3);
tmp->set_file(@2.text);
tmp->set_lineno(@2.first_line);
$$ = tmp;
@@ -1102,7 +1144,7 @@ function_item
re = new PENumber(new verinum(INTEGER_WIDTH-1,
INTEGER_WIDTH));
(*range_stub)[0] = re;
re = new PENumber(new verinum(0UL, INTEGER_WIDTH));
re = new PENumber(new verinum((uint64_t)0, INTEGER_WIDTH));
(*range_stub)[1] = re;
svector<PWire*>*tmp
= pform_make_task_ports(NetNet::PINPUT,
@@ -1190,6 +1232,7 @@ gate_instance
svector<PExpr*>*rng = $2;
tmp->name = $1;
tmp->parms = 0;
tmp->parms_by_name = 0;
tmp->range[0] = (*rng)[0];
tmp->range[1] = (*rng)[1];
tmp->file = @1.text;
@@ -1204,12 +1247,28 @@ gate_instance
| IDENTIFIER '(' port_name_list ')'
{ lgate*tmp = new lgate;
tmp->name = $1;
tmp->parms = 0;
tmp->parms_by_name = $3;
tmp->file = @1.text;
tmp->lineno = @1.first_line;
delete $1;
$$ = tmp;
}
| IDENTIFIER range '(' port_name_list ')'
{ lgate*tmp = new lgate;
svector<PExpr*>*rng = $2;
tmp->name = $1;
tmp->parms = 0;
tmp->parms_by_name = $4;
tmp->range[0] = (*rng)[0];
tmp->range[1] = (*rng)[1];
tmp->file = @1.text;
tmp->lineno = @1.first_line;
delete $1;
delete rng;
$$ = tmp;
}
;
gate_instance_list
@@ -1287,6 +1346,7 @@ indexed_identifier
}
| indexed_identifier '[' expression ']'
{ PEIdent*tmp = $1;
tmp->sel_ = PEIdent::SEL_NONE;
tmp->idx_.push_back($3);
$$ = tmp;
}
@@ -1296,17 +1356,9 @@ indexed_identifier
non-hierarchical names separated by ',' characters. */
list_of_identifiers
: IDENTIFIER
{ list<perm_string>*tmp = new list<perm_string>;
tmp->push_back(lex_strings.make($1));
$$ = tmp;
delete[]$1;
}
{ $$ = list_from_identifier($1); }
| list_of_identifiers ',' IDENTIFIER
{ list<perm_string>*tmp = $1;
tmp->push_back(lex_strings.make($3));
$$ = tmp;
delete[]$3;
}
{ $$ = list_from_identifier($1, $3); }
;
@@ -1480,6 +1532,7 @@ lpvalue
{ PEIdent*tmp = $1;
tmp->msb_ = $3;
tmp->lsb_ = $5;
tmp->sel_ = PEIdent::SEL_PART;
$$ = tmp;
}
| indexed_identifier '[' expression K_PO_POS expression ']'
@@ -1576,7 +1629,7 @@ module_item
: attribute_list_opt net_type
primitive_type_opt signed_opt range_opt
delay3_opt
list_of_identifiers ';'
net_variable_list ';'
{ ivl_variable_type_t dtype = $3;
if (dtype == IVL_VT_NO_TYPE)
@@ -1774,7 +1827,8 @@ module_item
| K_task IDENTIFIER ';'
{ pform_push_scope($2); }
task_item_list_opt statement_opt
task_item_list_opt
statement_opt
K_endtask
{ PTask*tmp = new PTask;
perm_string tmp2 = lex_strings.make($2);
@@ -1787,6 +1841,23 @@ module_item
delete $2;
}
| K_task IDENTIFIER
{ pform_push_scope($2); }
'(' task_port_decl_list ')' ';'
task_item_list_opt
statement_opt
K_endtask
{ PTask*tmp = new PTask;
perm_string tmp2 = lex_strings.make($2);
tmp->set_file(@1.text);
tmp->set_lineno(@1.first_line);
tmp->set_ports($5);
tmp->set_statement($9);
pform_set_task(tmp2, tmp);
pform_pop_scope();
delete $2;
}
/* The function declaration rule matches the function declaration
header, then pushes the function scope. This causes the
definitions in the func_body to take on the scope of the function
@@ -2223,6 +2294,7 @@ port_reference
}
wtmp->msb_ = $3;
wtmp->lsb_ = $5;
wtmp->sel_ = PEIdent::SEL_PART;
Module::port_t*ptmp = new Module::port_t;
ptmp->name = perm_string();
ptmp->expr = svector<PEIdent*>(1);
@@ -2405,10 +2477,44 @@ register_variable_list
}
;
net_variable
: IDENTIFIER
{ pform_makewire(@1, $1, NetNet::IMPLICIT,
NetNet::NOT_A_PORT,
IVL_VT_NO_TYPE, 0);
$$ = $1;
}
| IDENTIFIER '[' expression ':' expression ']'
{ pform_makewire(@1, $1, NetNet::IMPLICIT,
NetNet::NOT_A_PORT,
IVL_VT_NO_TYPE, 0);
if (! pform_expression_is_constant($3))
yyerror(@3, "error: msb of net range must be constant.");
if (! pform_expression_is_constant($5))
yyerror(@3, "error: lsb of net range must be constant.");
pform_set_reg_idx($1, $3, $5);
$$ = $1;
}
;
net_variable_list
: net_variable
{ list<perm_string>*tmp = new list<perm_string>;
tmp->push_back(lex_strings.make($1));
$$ = tmp;
delete[]$1;
}
| net_variable_list ',' net_variable
{ list<perm_string>*tmp = $1;
tmp->push_back(lex_strings.make($3));
$$ = tmp;
delete[]$3;
}
;
specify_item
: K_specparam specparam_list ';'
| specify_simple_path_decl ';'
{
{ pform_module_specify_path($1);
}
| specify_edge_path_decl ';'
{
@@ -2419,6 +2525,9 @@ specify_item
| K_if '(' expression ')' specify_edge_path_decl ';'
{
}
| K_ifnone specify_simple_path_decl ';'
{
}
| K_Shold '(' spec_reference_event ',' spec_reference_event
',' delay_value spec_notifier_opt ')' ';'
{ delete $7;
@@ -2455,18 +2564,14 @@ specify_item
}
;
specify_delay_value_list
: delay_value { }
| specify_delay_value_list ',' delay_value { }
;
specify_item_list
: specify_item
| specify_item_list specify_item
;
specify_edge_path_decl
: specify_edge_path '=' '(' specify_delay_value_list ')'
: specify_edge_path '=' '(' delay_value_list ')'
{ delete $4; }
| specify_edge_path '=' delay_value_simple
;
@@ -2488,21 +2593,27 @@ polarity_operator
;
specify_simple_path_decl
: specify_simple_path '=' '(' specify_delay_value_list ')'
: specify_simple_path '=' '(' delay_value_list ')'
{ $$ = pform_assign_path_delay($1, $4); }
| specify_simple_path '=' delay_value_simple
{ svector<PExpr*>*tmp = new svector<PExpr*>(1);
(*tmp)[0] = $3;
$$ = pform_assign_path_delay($1, tmp);
}
| specify_simple_path '=' '(' error ')'
{ yyerror(@2, "Syntax error in delay value list.");
yyerrok;
$$ = 0;
}
;
specify_simple_path
: '(' specify_path_identifiers spec_polarity
K_EG specify_path_identifiers ')'
{ pform_make_specify_path($2, $3, false, $5); }
{ $$ = pform_make_specify_path(@1, $2, $3, false, $5); }
| '(' specify_path_identifiers spec_polarity
K_SG specify_path_identifiers ')'
{ pform_make_specify_path($2, $3, true, $5); }
{ $$ = pform_make_specify_path(@1, $2, $3, true, $5); }
| '(' error ')'
{ yyerror(@2, "Invalid simple path");
yyerrok;
@@ -2612,7 +2723,10 @@ spec_notifier
| spec_notifier ','
{ }
| spec_notifier ',' identifier
{ delete $3;
{ delete $3; }
| spec_notifier ',' identifier '[' expr_primary ']'
{ delete $3;
delete $5;
}
| IDENTIFIER
{ delete $1; }
@@ -3001,14 +3115,16 @@ statement_opt
| ';' { $$ = 0; }
;
/* Task items are, other then the statement, task port items and
other block items. */
task_item
: block_item_decl
{ $$ = new svector<PWire*>(0); }
: block_item_decl { $$ = new svector<PWire*>(0); }
| task_port_item { $$ = $1; }
;
/* The basic port concept. */
task_port_item
| K_input signed_opt range_opt list_of_identifiers ';'
: K_input signed_opt range_opt list_of_identifiers ';'
{ svector<PWire*>*tmp
= pform_make_task_ports(NetNet::PINPUT,
IVL_VT_LOGIC, $2,
@@ -3043,7 +3159,7 @@ task_item
re = new PENumber(new verinum(INTEGER_WIDTH-1,
INTEGER_WIDTH));
(*range_stub)[0] = re;
re = new PENumber(new verinum(0UL, INTEGER_WIDTH));
re = new PENumber(new verinum((uint64_t)0, INTEGER_WIDTH));
(*range_stub)[1] = re;
svector<PWire*>*tmp
= pform_make_task_ports(NetNet::PINPUT,
@@ -3059,7 +3175,7 @@ task_item
re = new PENumber(new verinum(INTEGER_WIDTH-1,
INTEGER_WIDTH));
(*range_stub)[0] = re;
re = new PENumber(new verinum(0UL, INTEGER_WIDTH));
re = new PENumber(new verinum((uint64_t)0, INTEGER_WIDTH));
(*range_stub)[1] = re;
svector<PWire*>*tmp
= pform_make_task_ports(NetNet::POUTPUT,
@@ -3075,7 +3191,7 @@ task_item
re = new PENumber(new verinum(INTEGER_WIDTH-1,
INTEGER_WIDTH));
(*range_stub)[0] = re;
re = new PENumber(new verinum(0UL, INTEGER_WIDTH));
re = new PENumber(new verinum((uint64_t)0, INTEGER_WIDTH));
(*range_stub)[1] = re;
svector<PWire*>*tmp
= pform_make_task_ports(NetNet::PINOUT,
@@ -3131,6 +3247,125 @@ task_item_list_opt
{ $$ = 0; }
;
task_port_decl
: K_input signed_opt range_opt IDENTIFIER
{ svector<PWire*>*tmp
= pform_make_task_ports(NetNet::PINPUT,
IVL_VT_LOGIC, $2,
$3, list_from_identifier($4),
@1.text, @1.first_line);
$$ = tmp;
}
| K_output signed_opt range_opt IDENTIFIER
{ svector<PWire*>*tmp
= pform_make_task_ports(NetNet::POUTPUT,
IVL_VT_LOGIC, $2,
$3, list_from_identifier($4),
@1.text, @1.first_line);
$$ = tmp;
}
| K_inout signed_opt range_opt IDENTIFIER
{ svector<PWire*>*tmp
= pform_make_task_ports(NetNet::PINOUT,
IVL_VT_LOGIC, $2,
$3, list_from_identifier($4),
@1.text, @1.first_line);
$$ = tmp;
}
| K_input K_integer IDENTIFIER
{ svector<PExpr*>*range_stub
= new svector<PExpr*>(2);
PExpr*re;
re = new PENumber(new verinum(INTEGER_WIDTH-1,
INTEGER_WIDTH));
(*range_stub)[0] = re;
re = new PENumber(new verinum((uint64_t)0, INTEGER_WIDTH));
(*range_stub)[1] = re;
svector<PWire*>*tmp
= pform_make_task_ports(NetNet::PINPUT,
IVL_VT_LOGIC, true,
range_stub,
list_from_identifier($3),
@1.text, @1.first_line);
$$ = tmp;
}
| K_output K_integer IDENTIFIER
{ svector<PExpr*>*range_stub
= new svector<PExpr*>(2);
PExpr*re;
re = new PENumber(new verinum(INTEGER_WIDTH-1,
INTEGER_WIDTH));
(*range_stub)[0] = re;
re = new PENumber(new verinum((uint64_t)0, INTEGER_WIDTH));
(*range_stub)[1] = re;
svector<PWire*>*tmp
= pform_make_task_ports(NetNet::POUTPUT,
IVL_VT_LOGIC, true,
range_stub,
list_from_identifier($3),
@1.text, @1.first_line);
$$ = tmp;
}
| K_inout K_integer IDENTIFIER
{ svector<PExpr*>*range_stub
= new svector<PExpr*>(2);
PExpr*re;
re = new PENumber(new verinum(INTEGER_WIDTH-1,
INTEGER_WIDTH));
(*range_stub)[0] = re;
re = new PENumber(new verinum((uint64_t)0, INTEGER_WIDTH));
(*range_stub)[1] = re;
svector<PWire*>*tmp
= pform_make_task_ports(NetNet::PINOUT,
IVL_VT_LOGIC, true,
range_stub,
list_from_identifier($3),
@1.text, @1.first_line);
$$ = tmp;
}
/* Ports can be real. */
| K_input K_real IDENTIFIER
{ svector<PWire*>*tmp
= pform_make_task_ports(NetNet::PINPUT,
IVL_VT_REAL, false,
0, list_from_identifier($3),
@1.text, @1.first_line);
$$ = tmp;
}
| K_output K_real IDENTIFIER
{ svector<PWire*>*tmp
= pform_make_task_ports(NetNet::POUTPUT,
IVL_VT_REAL, false,
0, list_from_identifier($3),
@1.text, @1.first_line);
$$ = tmp;
}
| K_inout K_real IDENTIFIER
{ svector<PWire*>*tmp
= pform_make_task_ports(NetNet::PINOUT,
IVL_VT_REAL, false,
0, list_from_identifier($3),
@1.text, @1.first_line);
$$ = tmp;
}
;
task_port_decl_list
: task_port_decl_list ',' task_port_decl
{ svector<PWire*>*tmp = new svector<PWire*>(*$1, *$3);
delete $1;
delete $3;
$$ = tmp;
}
| task_port_decl
{ $$ = $1; }
;
udp_body
: K_table { lex_start_table(); }
udp_entry_list
+69 -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: pform.cc,v 1.135 2006/04/10 00:37:42 steve Exp $"
#ident "$Id: pform.cc,v 1.138 2007/01/16 05:44:15 steve Exp $"
#endif
# include "config.h"
@@ -29,6 +29,7 @@
# include "PEvent.h"
# include "PUdp.h"
# include "PGenerate.h"
# include "PSpec.h"
# include <list>
# include <map>
# include <assert.h>
@@ -1196,24 +1197,21 @@ void pform_makewire(const vlltype&li, const char*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 << name << " 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;
@@ -1535,13 +1533,52 @@ void pform_set_defparam(const hname_t&name, PExpr*expr)
}
/*
* XXXX Not implemented yet.
* Specify paths.
*/
extern void pform_make_specify_path(list<perm_string>*src, char pol,
bool full_flag, list<perm_string>*dst)
extern PSpecPath* pform_make_specify_path(const struct vlltype&li,
list<perm_string>*src, char pol,
bool full_flag, list<perm_string>*dst)
{
PSpecPath*path = new PSpecPath(src->size(), dst->size());
path->set_file(li.text);
path->set_lineno(li.first_line);
unsigned idx;
list<perm_string>::const_iterator cur;
idx = 0;
for (idx = 0, cur = src->begin() ; cur != src->end() ; idx++, cur++) {
path->src[idx] = *cur;
}
assert(idx == path->src.size());
delete src;
for (idx = 0, cur = dst->begin() ; cur != dst->end() ; idx++, cur++) {
path->dst[idx] = *cur;
}
assert(idx == path->dst.size());
delete dst;
return path;
}
extern PSpecPath* pform_assign_path_delay(PSpecPath*path, svector<PExpr*>*del)
{
assert(path->delays.size() == 0);
path->delays.resize(del->count());
for (unsigned idx = 0 ; idx < path->delays.size() ; idx += 1)
path->delays[idx] = (*del)[idx];
delete del;
return path;
}
extern void pform_module_specify_path(PSpecPath*obj)
{
pform_cur_module->specify_paths.push_back(obj);
}
void pform_set_port_type(const struct vlltype&li,
@@ -1583,7 +1620,7 @@ 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(0UL, INTEGER_WIDTH)));
new PENumber(new verinum((uint64_t)0, INTEGER_WIDTH)));
cur->set_signed(true);
}
@@ -1614,7 +1651,7 @@ 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(0UL, INTEGER_WIDTH)));
new PENumber(new verinum((uint64_t)0, INTEGER_WIDTH)));
}
void pform_set_reg_time(list<perm_string>*names)
@@ -1707,6 +1744,18 @@ int pform_parse(const char*path, FILE*file)
/*
* $Log: pform.cc,v $
* 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.
*
* Revision 1.136 2006/08/08 05:11:37 steve
* Handle 64bit delay constants.
*
* Revision 1.135 2006/04/10 00:37:42 steve
* Add support for generate loops w/ wires and gates.
*
+11 -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: pform.h,v 1.86 2006/04/10 00:37:42 steve Exp $"
#ident "$Id: pform.h,v 1.87 2006/09/23 04:57:19 steve Exp $"
#endif
# include "netlist.h"
@@ -57,6 +57,7 @@
*/
class PGate;
class PExpr;
class PSpecPath;
struct vlltype;
/*
@@ -260,8 +261,12 @@ extern void pform_set_defparam(const hname_t&name, PExpr*expr);
* Functions related to specify blocks.
*/
extern void pform_set_specparam(perm_string name, PExpr*expr);
extern void pform_make_specify_path(list<perm_string>*src, char pol,
bool full_flag, list<perm_string>*dst);
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_assign_path_delay(PSpecPath*obj, svector<PExpr*>*delays);
extern void pform_module_specify_path(PSpecPath*obj);
/*
* pform_make_behavior creates processes that are declared with always
@@ -323,6 +328,9 @@ extern void pform_dump(ostream&out, Module*mod);
/*
* $Log: pform.h,v $
* Revision 1.87 2006/09/23 04:57:19 steve
* Basic support for specify timing.
*
* Revision 1.86 2006/04/10 00:37:42 steve
* Add support for generate loops w/ wires and gates.
*
+47 -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: pform_dump.cc,v 1.92 2006/04/10 00:37:42 steve Exp $"
#ident "$Id: pform_dump.cc,v 1.94 2006/09/23 04:57:19 steve Exp $"
#endif
# include "config.h"
@@ -31,6 +31,7 @@
# include "pform.h"
# include "PEvent.h"
# include "PGenerate.h"
# include "PSpec.h"
# include <iostream>
# include <iomanip>
# include <typeinfo>
@@ -162,6 +163,11 @@ void PEIdent::dump(ostream&out) const
}
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
@@ -734,6 +740,33 @@ void PProcess::dump(ostream&out, unsigned ind) const
statement_->dump(out, ind+2);
}
void PSpecPath::dump(std::ostream&out, unsigned ind) const
{
out << setw(ind) << "" << "specify path (";
for (unsigned idx = 0 ; idx < src.size() ; idx += 1) {
if (idx > 0) out << ", ";
assert(src[idx]);
out << src[idx];
}
out << " => ";
for (unsigned idx = 0 ; idx < dst.size() ; idx += 1) {
if (idx > 0) out << ", ";
assert(dst[idx]);
out << dst[idx];
}
out << ") = (";
for (unsigned idx = 0 ; idx < delays.size() ; idx += 1) {
if (idx > 0) out << ", ";
assert(delays[idx]);
out << *delays[idx];
}
out << ");" << endl;
}
void PGenerate::dump(ostream&out) const
{
out << " generate(" << id_number << ")";
@@ -915,6 +948,13 @@ void Module::dump(ostream&out) const
(*behav)->dump(out, 4);
}
for (list<PSpecPath*>::const_iterator spec = specify_paths.begin()
; spec != specify_paths.end()
; spec ++ ) {
(*spec)->dump(out, 4);
}
out << "endmodule" << endl;
}
@@ -967,6 +1007,12 @@ void PUdp::dump(ostream&out) const
/*
* $Log: pform_dump.cc,v $
* Revision 1.94 2006/09/23 04:57:19 steve
* Basic support for specify timing.
*
* Revision 1.93 2006/04/28 04:19:31 steve
* Dump indexes of ident expressions
*
* Revision 1.92 2006/04/10 00:37:42 steve
* Add support for generate loops w/ wires and gates.
*
+45 -8
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.37 2005/11/26 00:35:44 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>
@@ -185,6 +186,12 @@ bool NetEBMult::set_width(unsigned w, bool)
return w == expr_width();
}
bool NetEBPow::set_width(unsigned w, bool last_chance)
{
bool flag = left_->set_width(w, last_chance);
return flag;
}
/*
* The shift operator allows the shift amount to have its own
* natural width. The width of the operator result is the width of the
@@ -333,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())
@@ -342,7 +349,7 @@ bool NetEMemory::set_width(unsigned w, bool)
expr_width(w);
return true;
}
#endif
bool NetEParam::set_width(unsigned, bool)
{
return false;
@@ -367,17 +374,27 @@ 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;
}
bool NetETernary::set_width(unsigned w, bool)
bool NetETernary::set_width(unsigned w, bool last_chance)
{
bool flag = true;
flag = flag && true_val_->set_width(w);
flag = flag && false_val_->set_width(w);
flag = flag && true_val_->set_width(w, last_chance);
flag = flag && false_val_->set_width(w, last_chance);
/* The ternary really insists that the true and false clauses
have the same width. Even if we fail to make the width that
the user requests, at least pad the smaller width to suit
the larger. */
if (true_val_->expr_width() < false_val_->expr_width())
true_val_ = pad_to_width(true_val_, false_val_->expr_width());
if (false_val_->expr_width() < true_val_->expr_width())
false_val_ = pad_to_width(false_val_, true_val_->expr_width());
expr_width(true_val_->expr_width());
return flag;
}
@@ -424,6 +441,26 @@ 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.
*
* Revision 1.38 2006/05/02 04:29:42 steve
* Be more stubborn about widths.
*
* Revision 1.37 2005/11/26 00:35:44 steve
* More precise about r-value width of constants.
*
+7 -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: symbol_search.cc,v 1.3 2005/11/27 05:56:20 steve Exp $"
#ident "$Id: symbol_search.cc,v 1.4 2007/01/16 05:44:15 steve Exp $"
#endif
# include "netlist.h"
@@ -29,7 +29,6 @@
*/
NetScope*symbol_search(const Design*des, NetScope*scope, hname_t path,
NetNet*&net,
NetMemory*&mem,
const NetExpr*&par,
NetEvent*&eve,
const NetExpr*&ex1, const NetExpr*&ex2)
@@ -41,7 +40,6 @@ NetScope*symbol_search(const Design*des, NetScope*scope, hname_t path,
/* Initialize output argument to cleared. */
net = 0;
mem = 0;
par = 0;
eve = 0;
@@ -56,11 +54,6 @@ NetScope*symbol_search(const Design*des, NetScope*scope, hname_t path,
return scope;
}
if ( (mem = scope->find_memory(key)) ) {
delete key;
return scope;
}
if ( (eve = scope->find_event(key)) ) {
delete key;
return scope;
@@ -83,6 +76,12 @@ NetScope*symbol_search(const Design*des, NetScope*scope, hname_t path,
/*
* $Log: symbol_search.cc,v $
* 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()
+115 -190
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-api.cc,v 1.133 2006/02/02 02:43:59 steve Exp $"
#ident "$Id: t-dll-api.cc,v 1.140 2007/01/17 05:00:12 steve Exp $"
#endif
# include "config.h"
@@ -96,33 +96,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 +290,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 +419,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 +475,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 +678,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 +709,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 +721,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 +732,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 +755,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 +806,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;
@@ -852,6 +827,11 @@ extern "C" ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx)
assert(idx == 0);
return net->u_.repeat.a;
case IVL_LPM_SFUNC:
// Skip the return port.
assert(idx < (net->u_.sfunc.ports-1));
return net->u_.sfunc.pins[idx+1];
case IVL_LPM_UFUNC:
// Skip the return port.
assert(idx < (net->u_.ufunc.ports-1));
@@ -887,44 +867,6 @@ extern "C" ivl_nexus_t ivl_lpm_datab(ivl_lpm_t net, unsigned idx)
}
}
#if 0
extern "C" ivl_nexus_t ivl_lpm_data2(ivl_lpm_t net, unsigned sdx, unsigned idx)
{
cerr << "ANACHRONISM: Call to anachronistic ivl_lpm_data2." << endl;
assert(net);
switch (net->type) {
case IVL_LPM_UFUNC: {
sdx += 1; /* skip the output port. */
assert(sdx < net->u_.ufunc.ports);
assert(idx < net->u_.ufunc.port_wid[sdx]);
unsigned base = 0;
for (unsigned i = 0 ; i < sdx ; i += 1)
base += net->u_.ufunc.port_wid[i];
return net->u_.ufunc.pins[base+idx];
}
default:
assert(0);
return 0;
}
}
#endif
#if 0
extern "C" unsigned ivl_lpm_data2_width(ivl_lpm_t net, unsigned sdx)
{
assert(net);
switch (net->type) {
case IVL_LPM_UFUNC:
sdx += 1; /* skip the output port. */
assert(sdx < net->u_.ufunc.ports);
return net->u_.ufunc.port_wid[sdx];
default:
assert(0);
return 0;
}
}
#endif
/*
* This function returns the hierarchical name for the LPM device. The
@@ -978,10 +920,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;
@@ -1005,6 +943,10 @@ extern "C" ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx)
assert(idx == 0);
return net->u_.shift.q;
case IVL_LPM_SFUNC:
assert(idx == 0);
return net->u_.sfunc.pins[0];
case IVL_LPM_UFUNC:
assert(idx == 0);
return net->u_.ufunc.pins[0];
@@ -1022,6 +964,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;
@@ -1037,12 +983,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;
@@ -1052,10 +999,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:
@@ -1069,7 +1016,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:
@@ -1096,6 +1042,8 @@ extern "C" int ivl_lpm_signed(ivl_lpm_t net)
return net->u_.shift.signed_flag;
case IVL_LPM_SIGN_EXT: // Sign extend is always signed.
return 1;
case IVL_LPM_SFUNC:
return 0;
case IVL_LPM_UFUNC:
return 0;
case IVL_LPM_CONCAT: // Concatenations are always unsigned
@@ -1106,6 +1054,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;
@@ -1117,6 +1067,8 @@ extern "C" unsigned ivl_lpm_size(ivl_lpm_t net)
switch (net->type) {
case IVL_LPM_MUX:
return net->u_.mux.size;
case IVL_LPM_SFUNC:
return net->u_.sfunc.ports - 1;
case IVL_LPM_UFUNC:
return net->u_.ufunc.ports - 1;
case IVL_LPM_REPEAT:
@@ -1127,6 +1079,12 @@ extern "C" unsigned ivl_lpm_size(ivl_lpm_t net)
}
}
extern "C" const char* ivl_lpm_string(ivl_lpm_t net)
{
assert(net->type == IVL_LPM_SFUNC);
return net->u_.sfunc.fun_name;
}
extern "C" ivl_lpm_type_t ivl_lpm_type(ivl_lpm_t net)
{
return net->type;
@@ -1135,62 +1093,7 @@ extern "C" ivl_lpm_type_t ivl_lpm_type(ivl_lpm_t net)
extern "C" unsigned ivl_lpm_width(ivl_lpm_t net)
{
assert(net);
switch (net->type) {
case IVL_LPM_FF:
case IVL_LPM_RAM:
return net->u_.ff.width;
case IVL_LPM_MUX:
return net->u_.mux.width;
case IVL_LPM_ADD:
case IVL_LPM_CMP_EEQ:
case IVL_LPM_CMP_EQ:
case IVL_LPM_CMP_GE:
case IVL_LPM_CMP_GT:
case IVL_LPM_CMP_NE:
case IVL_LPM_CMP_NEE:
case IVL_LPM_DIVIDE:
case IVL_LPM_MOD:
case IVL_LPM_MULT:
case IVL_LPM_SUB:
return net->u_.arith.width;
case IVL_LPM_RE_AND:
case IVL_LPM_RE_OR:
case IVL_LPM_RE_XOR:
case IVL_LPM_RE_NAND:
case IVL_LPM_RE_NOR:
case IVL_LPM_RE_XNOR:
case IVL_LPM_SIGN_EXT:
return net->u_.reduce.width;
case IVL_LPM_SHIFTL:
case IVL_LPM_SHIFTR:
return net->u_.shift.width;
case IVL_LPM_UFUNC:
return net->u_.ufunc.width;
case IVL_LPM_CONCAT:
return net->u_.concat.width;
case IVL_LPM_PART_VP:
case IVL_LPM_PART_PV:
return net->u_.part.width;
case IVL_LPM_PART_BI:
return net->u_.part.width;
case IVL_LPM_REPEAT:
return net->u_.repeat.width;
default:
assert(0);
return 0;
}
}
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;
}
return net->width;
}
extern "C" ivl_expr_t ivl_lval_mux(ivl_lval_t net)
@@ -1204,16 +1107,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;
}
@@ -1229,23 +1125,6 @@ extern "C" unsigned ivl_lval_width(ivl_lval_t net)
return net->width_;
}
#if 0
extern "C" unsigned ivl_lval_pins(ivl_lval_t net)
{
assert(net);
return net->width_;
}
#endif
#if 0
extern "C" ivl_nexus_t ivl_lval_pin(ivl_lval_t net, unsigned idx)
{
assert(net);
assert(idx < net->width_);
assert(net->type_ != IVL_LVAL_MEM);
return ivl_signal_pin(net->n.sig, idx+net->loff_);
}
#endif
extern "C" ivl_signal_t ivl_lval_sig(ivl_lval_t net)
{
assert(net);
@@ -1253,6 +1132,7 @@ 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;
@@ -1362,6 +1242,17 @@ extern "C" ivl_scope_t ivl_parameter_scope(ivl_parameter_t net)
return net->scope;
}
extern uint64_t ivl_path_delay(ivl_delaypath_t obj, ivl_path_edge_t edg)
{
assert(obj);
return obj->delay[edg];
}
extern ivl_nexus_t ivl_path_source(ivl_delaypath_t net)
{
return net->src;
}
extern "C" ivl_process_type_t ivl_process_type(ivl_process_t net)
{
return net->type_;
@@ -1467,19 +1358,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;
@@ -1588,6 +1466,16 @@ 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" const char* ivl_signal_attr(ivl_signal_t net, const char*key)
{
if (net->nattr == 0)
@@ -1639,9 +1527,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)
@@ -1685,6 +1577,17 @@ extern "C" ivl_variable_type_t ivl_signal_data_type(ivl_signal_t net)
return net->data_type;
}
extern "C" unsigned ivl_signal_npath(ivl_signal_t net)
{
return net->npath;
}
extern "C" ivl_delaypath_t ivl_signal_path(ivl_signal_t net, unsigned idx)
{
assert(idx < net->npath);
return net->path + idx;
}
extern "C" ivl_signal_type_t ivl_signal_type(ivl_signal_t net)
{
return net->type_;
@@ -1848,7 +1751,7 @@ extern "C" ivl_expr_t ivl_stmt_delay_expr(ivl_statement_t net)
}
}
extern "C" unsigned long ivl_stmt_delay_val(ivl_statement_t net)
extern "C" uint64_t ivl_stmt_delay_val(ivl_statement_t net)
{
assert(net->type_ == IVL_ST_DELAY);
return net->u_.delay_.delay_;
@@ -1946,11 +1849,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);
}
@@ -2033,6 +1934,30 @@ extern "C" ivl_statement_t ivl_stmt_sub_stmt(ivl_statement_t net)
/*
* $Log: t-dll-api.cc,v $
* 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.
*
* Revision 1.136 2006/09/20 22:31:23 steve
* Remove dead code.
*
* Revision 1.135 2006/08/08 05:11:37 steve
* Handle 64bit delay constants.
*
* Revision 1.134 2006/06/18 04:15:50 steve
* Add support for system functions in continuous assignments.
*
* Revision 1.133 2006/02/02 02:43:59 steve
* Allow part selects of memory words in l-values.
*
+30 -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: t-dll-expr.cc,v 1.43 2005/09/14 02:53:15 steve Exp $"
#ident "$Id: t-dll-expr.cc,v 1.44 2007/01/16 05:44:15 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);
@@ -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 then 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.
}
}
@@ -473,6 +474,12 @@ void dll_target::expr_unary(const NetEUnary*net)
/*
* $Log: t-dll-expr.cc,v $
* 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.
*
+12 -15
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.69 2007/01/16 05:44:15 steve Exp $"
#endif
# include "config.h"
@@ -171,30 +171,21 @@ 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.
if (asn->word()) {
assert(expr_ == 0);
asn->bmux()->expr_scan(this);
asn->word()->expr_scan(this);
if (cur->n.sig->lsb_index != 0)
sub_off_from_expr_(asn->sig()->lsb());
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);
}
@@ -741,6 +732,12 @@ void dll_target::proc_while(const NetWhile*net)
/*
* $Log: t-dll-proc.cc,v $
* 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.
*
+184 -140
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.cc,v 1.156 2006/04/10 00:37:42 steve Exp $"
#ident "$Id: t-dll.cc,v 1.163 2007/01/17 05:00:12 steve Exp $"
#endif
# include "config.h"
@@ -242,27 +242,6 @@ ivl_signal_t dll_target::find_signal(ivl_design_s &des, const NetNet*net)
return 0;
}
/*
* This function locates an ivl_memory_t object that matches the
* NetMemory object. The search works by looking for the parent scope,
* then scanning the parent scope for the NetMemory object.
*/
ivl_memory_t dll_target::find_memory(ivl_design_s &des, const NetMemory*net)
{
ivl_scope_t scope = find_scope(des, net->scope());
assert(scope);
const char*nname = net->name();
for (unsigned idx = 0 ; idx < scope->nmem_ ; idx += 1) {
if (strcmp(scope->mem_[idx]->basename_, nname) == 0)
return scope->mem_[idx];
}
assert(0);
return 0;
}
static ivl_nexus_t nexus_sig_make(ivl_signal_t net, unsigned pin)
{
ivl_nexus_t tmp = new struct ivl_nexus_s;
@@ -417,14 +396,6 @@ static void scope_add_lpm(ivl_scope_t scope, ivl_lpm_t net)
}
}
static void scope_add_mem(ivl_scope_t scope, ivl_memory_t net)
{
scope->nmem_ += 1;
scope->mem_ = (ivl_memory_t*)
realloc(scope->mem_, scope->nmem_*sizeof(ivl_memory_t));
scope->mem_[scope->nmem_-1] = net;
}
ivl_parameter_t dll_target::scope_find_param(ivl_scope_t scope,
const char*name)
{
@@ -515,8 +486,6 @@ void dll_target::add_root(ivl_design_s &des_, const NetScope *s)
root_->event_ = 0;
root_->nlpm_ = 0;
root_->lpm_ = 0;
root_->nmem_ = 0;
root_->mem_ = 0;
make_scope_parameters(root_, s);
root_->type_ = IVL_SCT_MODULE;
root_->tname_ = root_->name_;
@@ -904,7 +873,7 @@ bool dll_target::sign_extend(const NetSignExtend*net)
{
struct ivl_lpm_s*obj = new struct ivl_lpm_s;
obj->type = IVL_LPM_SIGN_EXT;
obj->u_.reduce.width = net->width();
obj->width = net->width();
obj->name = net->name();
obj->scope = find_scope(des_, net->scope());
assert(obj->scope);
@@ -959,7 +928,7 @@ bool dll_target::ureduce(const NetUReduce*net)
obj->scope = find_scope(des_, net->scope());
assert(obj->scope);
obj->u_.reduce.width = net->width();
obj->width = net->width();
const Nexus*nex;
@@ -988,7 +957,7 @@ void dll_target::net_case_cmp(const NetCaseCmp*net)
obj->scope = find_scope(des_, net->scope());
assert(obj->scope);
obj->u_.arith.width = net->width();
obj->width = net->width();
obj->u_.arith.signed_flag = 0;
const Nexus*nex;
@@ -1014,6 +983,46 @@ void dll_target::net_case_cmp(const NetCaseCmp*net)
scope_add_lpm(obj->scope, obj);
}
bool dll_target::net_sysfunction(const NetSysFunc*net)
{
unsigned idx;
const Nexus*nex;
struct ivl_lpm_s*obj = new struct ivl_lpm_s;
obj->type = IVL_LPM_SFUNC;
obj->name = net->name();
obj->scope = find_scope(des_, net->scope());
assert(obj->scope);
obj->u_.sfunc.ports = net->pin_count();
assert(net->pin_count() >= 1);
obj->width = net->vector_width();
obj->u_.sfunc.fun_name = net->func_name();
obj->u_.sfunc.pins = new ivl_nexus_t[net->pin_count()];
nex = net->pin(0).nexus();
assert(nex->t_cookie());
obj->u_.sfunc.pins[0] = (ivl_nexus_t) nex->t_cookie();
nexus_lpm_add(obj->u_.sfunc.pins[0], obj, 0,
IVL_DR_STRONG, IVL_DR_STRONG);
for (idx = 1 ; idx < net->pin_count() ; idx += 1) {
nex = net->pin(idx).nexus();
assert(nex->t_cookie());
obj->u_.sfunc.pins[idx] = (ivl_nexus_t) nex->t_cookie();
nexus_lpm_add(obj->u_.sfunc.pins[idx], obj, 0,
IVL_DR_HiZ, IVL_DR_HiZ);
}
scope_add_lpm(obj->scope, obj);
return true;
}
/*
* An IVL_LPM_UFUNC represents a node in a combinational expression
* that calls a user defined function. I create an LPM object that has
@@ -1039,7 +1048,7 @@ bool dll_target::net_function(const NetUserFunc*net)
obj->u_.ufunc.ports = net->pin_count();
assert(net->pin_count() >= 1);
obj->u_.ufunc.width = net->port_width(0);
obj->width = net->port_width(0);
/* Now collect all the pins and connect them to the nexa of
the net. The output pins have strong drive, and the
@@ -1146,20 +1155,6 @@ void dll_target::udp(const NetUDP*net)
scope_add_logic(scope, obj);
}
void dll_target::memory(const NetMemory*net)
{
ivl_memory_t obj = new struct ivl_memory_s;
obj->scope_ = find_scope(des_, net->scope());
obj->basename_ = net->name();
obj->width_ = net->width();
obj->signed_ = 0;
obj->size_ = net->count();
obj->root_ = -net->index_to_address(0);
scope_add_mem(obj->scope_, obj);
}
void dll_target::lpm_add_sub(const NetAddSub*net)
{
ivl_lpm_t obj = new struct ivl_lpm_s;
@@ -1177,9 +1172,9 @@ void dll_target::lpm_add_sub(const NetAddSub*net)
/* Choose the width of the adder. If the carry bit is
connected, then widen the adder by one and plan on leaving
the fake inputs unconnected. */
obj->u_.arith.width = net->width();
obj->width = net->width();
if (net->pin_Cout().is_linked()) {
obj->u_.arith.width += 1;
obj->width += 1;
}
@@ -1212,6 +1207,35 @@ void dll_target::lpm_add_sub(const NetAddSub*net)
scope_add_lpm(obj->scope, obj);
}
bool dll_target::lpm_array_dq(const NetArrayDq*net)
{
ivl_lpm_t obj = new struct ivl_lpm_s;
obj->type = IVL_LPM_ARRAY;
obj->name = net->name();
obj->u_.array.sig = find_signal(des_, net->mem());
assert(obj->u_.array.sig);
obj->scope = find_scope(des_, net->scope());
assert(obj->scope);
obj->width = net->width();
obj->u_.array.swid = net->awidth();
scope_add_lpm(obj->scope, obj);
const Nexus*nex;
nex = net->pin_Address().nexus();
assert(nex->t_cookie());
obj->u_.array.a = (ivl_nexus_t) nex->t_cookie();
nexus_lpm_add(obj->u_.array.a, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
nex = net->pin_Result().nexus();
assert(nex->t_cookie());
obj->u_.array.q = (ivl_nexus_t) nex->t_cookie();
nexus_lpm_add(obj->u_.array.q, obj, 0, IVL_DR_STRONG, IVL_DR_STRONG);
return true;
}
/*
* The lpm_clshift device represents both left and right shifts,
* depending on what is connected to the Direction pin. We convert
@@ -1235,7 +1259,7 @@ void dll_target::lpm_clshift(const NetCLShift*net)
else
obj->u_.shift.signed_flag = 0;
obj->u_.shift.width = net->width();
obj->width = net->width();
obj->u_.shift.select = net->width_dist();
const Nexus*nex;
@@ -1276,7 +1300,7 @@ void dll_target::lpm_compare(const NetCompare*net)
bool swap_operands = false;
obj->u_.arith.width = net->width();
obj->width = net->width();
obj->u_.arith.signed_flag = net->get_signed()? 1 : 0;
const Nexus*nex;
@@ -1377,7 +1401,7 @@ void dll_target::lpm_divide(const NetDivide*net)
unsigned wid = net->width_r();
obj->u_.arith.width = wid;
obj->width = wid;
obj->u_.arith.signed_flag = net->get_signed()? 1 : 0;
const Nexus*nex;
@@ -1415,7 +1439,7 @@ void dll_target::lpm_modulo(const NetModulo*net)
unsigned wid = net->width_r();
obj->u_.arith.width = wid;
obj->width = wid;
obj->u_.arith.signed_flag = 0;
const Nexus*nex;
@@ -1449,7 +1473,7 @@ void dll_target::lpm_ff(const NetFF*net)
obj->scope = find_scope(des_, net->scope());
assert(obj->scope);
obj->u_.ff.width = net->width();
obj->width = net->width();
scope_add_lpm(obj->scope, obj);
@@ -1538,73 +1562,6 @@ void dll_target::lpm_ff(const NetFF*net)
}
void dll_target::lpm_ram_dq(const NetRamDq*net)
{
ivl_lpm_t obj = new struct ivl_lpm_s;
obj->type = IVL_LPM_RAM;
obj->name = net->name();
obj->u_.ff.mem = find_memory(des_, net->mem());
assert(obj->u_.ff.mem);
obj->scope = find_scope(des_, net->mem()->scope());
assert(obj->scope);
obj->u_.ff.width = net->width();
obj->u_.ff.swid = net->awidth();
scope_add_lpm(obj->scope, obj);
const Nexus*nex;
// A write port is present only if something is connected to
// the clock input.
bool has_write_port = net->pin_InClock().is_linked();
// Connect the write clock and write enable
if (has_write_port) {
nex = net->pin_InClock().nexus();
assert(nex->t_cookie());
obj->u_.ff.clk = (ivl_nexus_t) nex->t_cookie();
assert(obj->u_.ff.clk);
nexus_lpm_add(obj->u_.ff.clk, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
nex = net->pin_WE().nexus();
if (nex && nex->t_cookie()) {
obj->u_.ff.we = (ivl_nexus_t) nex->t_cookie();
assert(obj->u_.ff.we);
nexus_lpm_add(obj->u_.ff.we, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
}
else
obj->u_.ff.we = 0x0;
}
else {
obj->u_.ff.clk = 0x0;
obj->u_.ff.we = 0x0;
}
// Connect the address bus
nex = net->pin_Address().nexus();
assert(nex->t_cookie());
obj->u_.ff.s.pin = (ivl_nexus_t) nex->t_cookie();
nexus_lpm_add(obj->u_.ff.s.pin, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
// Connect the data busses
nex = net->pin_Q().nexus();
assert(nex->t_cookie());
obj->u_.ff.q.pin = (ivl_nexus_t) nex->t_cookie();
nexus_lpm_add(obj->u_.ff.q.pin, obj, 0, IVL_DR_STRONG, IVL_DR_STRONG);
if (has_write_port) {
nex = net->pin_Data().nexus();
assert(nex->t_cookie());
obj->u_.ff.d.pin = (ivl_nexus_t) nex->t_cookie();
nexus_lpm_add(obj->u_.ff.d.pin, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
}
}
/*
* Make the NetMult object into an IVL_LPM_MULT node.
*/
@@ -1619,7 +1576,7 @@ void dll_target::lpm_mult(const NetMult*net)
unsigned wid = net->width_r();
obj->u_.arith.width = wid;
obj->width = wid;
const Nexus*nex;
@@ -1657,7 +1614,7 @@ void dll_target::lpm_mux(const NetMux*net)
obj->scope = find_scope(des_, net->scope());
assert(obj->scope);
obj->u_.mux.width = net->width();
obj->width = net->width();
obj->u_.mux.size = net->size();
obj->u_.mux.swid = net->sel_width();
@@ -1701,7 +1658,7 @@ bool dll_target::concat(const NetConcat*net)
obj->scope = find_scope(des_, net->scope());
assert(obj->scope);
obj->u_.concat.width = net->width();
obj->width = net->width();
obj->u_.concat.inputs = net->pin_count() - 1;
obj->u_.concat.pins = new ivl_nexus_t[obj->u_.concat.inputs+1];
@@ -1743,7 +1700,7 @@ bool dll_target::part_select(const NetPartSelect*net)
obj->u_.part.signed_flag = 0;
/* Choose the width of the part select. */
obj->u_.part.width = net->width();
obj->width = net->width();
obj->u_.part.base = net->base();
obj->u_.part.s = 0;
@@ -1834,7 +1791,7 @@ bool dll_target::replicate(const NetReplicate*net)
obj->scope = find_scope(des_, net->scope());
assert(obj->scope);
obj->u_.repeat.width = net->width();
obj->width = net->width();
obj->u_.repeat.count = net->repeat();
ivl_drive_t dr = IVL_DR_STRONG;
@@ -1982,8 +1939,6 @@ void dll_target::scope(const NetScope*net)
scope->event_ = 0;
scope->nlpm_ = 0;
scope->lpm_ = 0;
scope->nmem_ = 0;
scope->mem_ = 0;
make_scope_parameters(scope, net);
scope->time_units = net->time_unit();
scope->nattr = net->attr_cnt();
@@ -2134,6 +2089,10 @@ void dll_target::signal(const NetNet*net)
break;
}
/* Initialize the path fields to be filled in later. */
obj->npath = 0;
obj->path = 0;
obj->data_type = net->data_type();
obj->nattr = net->attr_cnt();
obj->attr = fill_in_attributes(net);
@@ -2148,18 +2107,79 @@ void dll_target::signal(const NetNet*net)
t_cookie of the Nexus object so that I find it again when I
next encounter the nexus. */
const Nexus*nex = net->pin(0).nexus();
if (nex->t_cookie()) {
obj->pin_ = (ivl_nexus_t)nex->t_cookie();
nexus_sig_add(obj->pin_, obj, 0);
obj->array_base = net->array_first();
obj->array_words = net->array_count();
if (obj->array_words > 1)
obj->pins = new ivl_nexus_t[obj->array_words];
} else {
ivl_nexus_t tmp = nexus_sig_make(obj, 0);
tmp->name_ = strings_.add(nex->name());
nex->t_cookie(tmp);
obj->pin_ = tmp;
for (unsigned idx = 0 ; idx < obj->array_words ; idx += 1) {
const Nexus*nex = net->pin(idx).nexus();
if (nex->t_cookie()) {
if (obj->array_words > 1) {
obj->pins[idx] = (ivl_nexus_t)nex->t_cookie();
nexus_sig_add(obj->pins[idx], obj, idx);
} else {
obj->pin = (ivl_nexus_t)nex->t_cookie();
nexus_sig_add(obj->pin, obj, idx);
}
} else {
ivl_nexus_t tmp = nexus_sig_make(obj, idx);
tmp->name_ = strings_.add(nex->name());
nex->t_cookie(tmp);
if (obj->array_words > 1)
obj->pins[idx] = tmp;
else
obj->pin = tmp;
}
}
}
bool dll_target::signal_paths(const NetNet*net)
{
/* Nothing to do if there are no paths for this signal. */
if (net->delay_paths() == 0)
return true;
ivl_signal_t obj = find_signal(des_, net);
assert(obj);
/* We cannot have already set up the paths for this signal. */
assert(obj->npath == 0);
assert(obj->path == 0);
/* Figure out how many paths there really are. */
for (unsigned idx = 0 ; idx < net->delay_paths() ; idx += 1) {
const NetDelaySrc*src = net->delay_path(idx);
obj->npath += src->pin_count();
}
obj->path = new struct ivl_delaypath_s[obj->npath];
unsigned ptr = 0;
for (unsigned idx = 0 ; idx < net->delay_paths() ; idx += 1) {
const NetDelaySrc*src = net->delay_path(idx);
for (unsigned pin = 0; pin < src->pin_count(); pin += 1) {
const Nexus*nex = src->pin(pin).nexus();
if (! nex->t_cookie()) {
cerr << src->get_line() << ": internal error: "
<< "No signal connected to pin " << pin
<< " of delay path to " << net->name()
<< "." << endl;
}
assert(nex->t_cookie());
obj->path[ptr].src = (ivl_nexus_t) nex->t_cookie();
for (unsigned pe = 0 ; pe < 12 ; pe += 1) {
obj->path[ptr].delay[pe] = src->get_delay(pe);
}
ptr += 1;
}
}
return true;
}
extern const struct target tgt_dll = { "dll", &dll_target_obj };
@@ -2167,6 +2187,30 @@ extern const struct target tgt_dll = { "dll", &dll_target_obj };
/*
* $Log: t-dll.cc,v $
* Revision 1.163 2007/01/17 05:00:12 steve
* Dead code for memories in scopes.
*
* Revision 1.162 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.161 2006/11/10 05:44:45 steve
* Process delay paths in second path over signals.
*
* Revision 1.160 2006/10/15 03:25:58 steve
* More detailed internal error message.
*
* Revision 1.159 2006/09/28 00:29:49 steve
* Allow specparams as constants in expressions.
*
* Revision 1.158 2006/09/23 04:57:19 steve
* Basic support for specify timing.
*
* Revision 1.157 2006/06/18 04:15:50 steve
* Add support for system functions in continuous assignments.
*
* Revision 1.156 2006/04/10 00:37:42 steve
* Add support for generate loops w/ wires and gates.
*
+61 -42
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: t-dll.h,v 1.130 2006/02/02 02:43:59 steve Exp $"
#ident "$Id: t-dll.h,v 1.137 2007/01/17 05:00:12 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,11 +82,11 @@ 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*);
void net_assign(const NetAssign_*);
bool net_sysfunction(const NetSysFunc*);
bool net_function(const NetUserFunc*);
bool net_const(const NetConst*);
bool net_literal(const NetLiteral*);
@@ -95,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_;
@@ -132,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*);
@@ -155,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);
@@ -176,6 +173,11 @@ struct dll_target : public target_t, public expr_scan_t {
* These are various private declarations used by the t-dll target.
*/
struct ivl_delaypath_s {
ivl_nexus_t src;
uint64_t delay[12];
};
struct ivl_event_s {
perm_string name;
ivl_scope_t scope;
@@ -224,6 +226,7 @@ struct ivl_expr_s {
struct {
ivl_signal_t sig;
ivl_expr_t word;
} signal_;
struct {
@@ -282,11 +285,11 @@ struct ivl_lpm_s {
ivl_lpm_type_t type;
ivl_scope_t scope;
perm_string name;
// Value returned by ivl_lpm_width;
unsigned width;
union {
struct ivl_lpm_ff_s {
unsigned width;
unsigned swid; // ram only
ivl_nexus_t clk;
ivl_nexus_t we;
ivl_nexus_t aclr;
@@ -301,17 +304,11 @@ 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;
struct ivl_lpm_mux_s {
unsigned width;
unsigned size;
unsigned swid;
ivl_nexus_t*d;
@@ -319,26 +316,28 @@ struct ivl_lpm_s {
} mux;
struct ivl_lpm_shift_s {
unsigned width;
unsigned select;
unsigned signed_flag :1;
ivl_nexus_t q, d, s;
} shift;
struct ivl_lpm_arith_s {
unsigned width;
unsigned signed_flag :1;
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 width;
unsigned inputs;
ivl_nexus_t*pins;
} concat;
struct ivl_part_s {
unsigned width;
unsigned base;
unsigned signed_flag :1;
ivl_nexus_t q, a, s;
@@ -346,20 +345,23 @@ struct ivl_lpm_s {
// IVL_LPM_RE_* and IVL_LPM_SIGN_EXT use this.
struct ivl_lpm_reduce_s {
unsigned width;
ivl_nexus_t q, a;
} reduce;
struct ivl_lpm_repeat_s {
unsigned width;
unsigned count;
ivl_nexus_t q, a;
} repeat;
struct ivl_lpm_sfunc_s {
const char* fun_name;
unsigned ports;
ivl_nexus_t*pins;
} sfunc;
struct ivl_lpm_ufunc_s {
ivl_scope_t def;
unsigned ports;
unsigned width;
ivl_nexus_t*pins;
} ufunc;
} u_;
@@ -374,8 +376,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 {
@@ -478,19 +481,6 @@ struct ivl_nexus_s {
void*private_data;
};
/*
* Memory.
*/
struct ivl_memory_s {
perm_string basename_;
ivl_scope_t scope_;
unsigned width_;
unsigned signed_ : 1;
unsigned size_;
int root_;
};
/*
* This is the implementation of a parameter. Each scope has a list of
* these.
@@ -541,9 +531,6 @@ struct ivl_scope_s {
unsigned nlpm_;
ivl_lpm_t* lpm_;
unsigned nmem_;
ivl_memory_t* mem_;
unsigned nparam_;
ivl_parameter_t param_;
@@ -583,7 +570,15 @@ 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;
struct ivl_attribute_s*attr;
unsigned nattr;
@@ -626,7 +621,7 @@ struct ivl_statement_s {
} condit_;
struct { /* IVL_ST_DELAY */
unsigned long delay_;
uint64_t delay_;
ivl_statement_t stmt_;
} delay_;
@@ -671,6 +666,30 @@ struct ivl_statement_s {
/*
* $Log: t-dll.h,v $
* 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.
*
* Revision 1.132 2006/08/08 05:11:37 steve
* Handle 64bit delay constants.
*
* Revision 1.131 2006/06/18 04:15:50 steve
* Add support for system functions in continuous assignments.
*
* Revision 1.130 2006/02/02 02:43:59 steve
* Allow part selects of memory words in l-values.
*
+29 -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: target.cc,v 1.77 2005/07/11 16:56:51 steve Exp $"
#ident "$Id: target.cc,v 1.80 2007/01/16 05:44:16 steve Exp $"
#endif
# include "config.h"
@@ -41,12 +41,10 @@ void target_t::event(const NetEvent*ev)
<< "): Unhandled event <" << ev->full_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() << "): "
@@ -174,6 +172,13 @@ bool target_t::net_const(const NetConst*)
return false;
}
bool target_t::net_sysfunction(const NetSysFunc*net)
{
cerr << "target (" << typeid(*this).name() << "): "
"Unhandled NetSysFunc node." << endl;
return false;
}
bool target_t::net_function(const NetUserFunc*net)
{
cerr << "target (" << typeid(*this).name() << "): "
@@ -368,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() << "): "
@@ -431,6 +429,18 @@ void expr_scan_t::expr_binary(const NetEBinary*ex)
/*
* $Log: target.cc,v $
* 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.
*
* Revision 1.77 2005/07/11 16:56:51 steve
* Remove NetVariable and ivl_variable_t structures.
*
+16 -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.74 2005/07/11 16:56:51 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*);
@@ -94,6 +92,7 @@ struct target_t {
virtual void udp(const NetUDP*);
virtual void net_case_cmp(const NetCaseCmp*);
virtual bool net_const(const NetConst*);
virtual bool net_sysfunction(const NetSysFunc*);
virtual bool net_function(const NetUserFunc*);
virtual bool net_literal(const NetLiteral*);
virtual void net_probe(const NetEvProbe*);
@@ -137,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*);
@@ -170,6 +168,18 @@ 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.
*
* Revision 1.74 2005/07/11 16:56:51 steve
* Remove NetVariable and ivl_variable_t structures.
*
+4
View File
@@ -1,3 +1,7 @@
*.cache
stub.tgt
configure
config.log
config.status
Makefile
dep
+11 -4
View File
@@ -16,7 +16,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.15 2005/03/03 04:34:42 steve Exp $"
#ident "$Id: Makefile.in,v 1.19 2007/01/17 05:00:12 steve Exp $"
#
#
SHELL = /bin/sh
@@ -52,7 +52,7 @@ dep:
$(CC) $(CPPFLAGS) $(CFLAGS) -MD -c $< -o $*.o
mv $*.d dep
O = stub.o memory.o statement.o
O = stub.o expression.o statement.o
ifeq (@WIN32@,yes)
TGTLDFLAGS=-L.. -livl
@@ -70,20 +70,27 @@ clean:
rm -rf *.o dep stub.tgt
distclean: clean
rm -f Makefile
rm -f Makefile config.status config.log
install: all installdirs $(libdir)/ivl/stub.tgt \
$(includedir)/vpi_user.h
$(libdir)/ivl/stub.conf $(libdir)/ivl/stub-s.conf
$(libdir)/ivl/stub.tgt: ./stub.tgt
$(INSTALL_PROGRAM) ./stub.tgt $(libdir)/ivl/stub.tgt
$(libdir)/ivl/stub.conf: ./stub.conf
$(INSTALL_DATA) ./stub.conf $(libdir)/ivl/stub.conf
$(libdir)/ivl/stub-s.conf: ./stub-s.conf
$(INSTALL_DATA) ./stub-s.conf $(libdir)/ivl/stub-s.conf
installdirs: ../mkinstalldirs
$(srcdir)/../mkinstalldirs $(includedir) $(bindir) $(libdir)/ivl
uninstall:
rm -f $(libdir)/ivl/stub.tgt
rm -f $(libdir)/ivl/stub.conf
rm -f $(libdir)/ivl/stub-s.conf
-include $(patsubst %.o, dep/%.d, $O)
+26
View File
@@ -0,0 +1,26 @@
dnl Process this file with autoconf to produce a configure script.
AC_INIT(stub.c)
dnl Checks for programs.
AC_PROG_CC
AC_PROG_INSTALL
AC_CANONICAL_HOST
# $host
# Combined check for Microsoft-related bogosities; sets WIN32 if found
AX_WIN32
# may modify CPPFLAGS and CFLAGS
AX_CPP_PRECOMP
# Compiler option for position independent code, needed whan making shared objects.
AX_C_PICFLAG
# linker options when building a shared library
AX_LD_SHAREDLIB_OPTS
AX_CPP_IDENT
AC_OUTPUT(Makefile)
+273
View File
@@ -0,0 +1,273 @@
/*
* 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: expression.c,v 1.1 2007/01/16 05:44:16 steve Exp $"
#endif
# include "config.h"
# include "priv.h"
# include <stdlib.h>
# include <inttypes.h>
# include <assert.h>
static const char*vt_type_string(ivl_expr_t net)
{
return data_type_string(ivl_expr_value(net));
}
static void show_array_expression(ivl_expr_t net, unsigned ind)
{
ivl_signal_t sig = ivl_expr_signal(net);
const char*name = ivl_signal_basename(sig);
unsigned width = ivl_signal_width(sig);
const char*vt = vt_type_string(net);
fprintf(out, "%*sArray: %s, word_count=%u, width=%u, type=%s\n",
ind, "", name, ivl_signal_array_count(sig), width, vt);
}
static void show_binary_expression(ivl_expr_t net, unsigned ind)
{
unsigned width = ivl_expr_width(net);
const char*sign = ivl_expr_signed(net)? "signed" : "unsigned";
const char*vt = vt_type_string(net);
fprintf(out, "%*s<\"%c\" width=%u, %s, type=%s>\n", ind, "",
ivl_expr_opcode(net), width, sign, vt);
show_expression(ivl_expr_oper1(net), ind+3);
show_expression(ivl_expr_oper2(net), ind+3);
switch (ivl_expr_opcode(net)) {
case '*':
/* The width of multiply expressions is the sum of the
widths of the operands. This is slightly different
from the way the Verilog standard does it, but allows
us to keep operands smaller. */
width = ivl_expr_width(ivl_expr_oper1(net));
width += ivl_expr_width(ivl_expr_oper2(net));
if (ivl_expr_width(net) != width) {
fprintf(out, "%*sERROR: Result width incorrect\n",
ind+3, "");
stub_errors += 1;
}
break;
default:
break;
}
}
static void show_function_call(ivl_expr_t net, unsigned ind)
{
ivl_scope_t def = ivl_expr_def(net);
const char*vt = vt_type_string(net);
fprintf(out, "%*s<%s function %s>\n", ind, "",
vt, ivl_scope_name(def));
}
static void show_memory_expression(ivl_expr_t net, unsigned ind)
{
unsigned width = ivl_expr_width(net);
fprintf(out, "%*s<memory width=%u>\n", ind, "",
width);
}
static void show_signal_expression(ivl_expr_t net, unsigned ind)
{
unsigned width = ivl_expr_width(net);
const char*sign = ivl_expr_signed(net)? "signed" : "unsigned";
const char*vt = vt_type_string(net);
ivl_expr_t word = ivl_expr_oper1(net);
ivl_signal_t sig = ivl_expr_signal(net);
unsigned word_count = ivl_signal_array_count(sig);
fprintf(out, "%*s<signal=%s, words=%u, width=%u, %s type=%s>\n", ind, "",
ivl_expr_name(net), word_count, width, sign, vt);
/* If the expression refers to a signal array, then there must
also be a word select expression, and if the signal is not an
array, there must NOT be a word expression. */
if (word_count == 1 && word != 0) {
fprintf(out, "%*sERROR: Unexpected word expression\n", ind+2, "");
stub_errors += 1;
}
if (word_count > 1 && word == 0) {
fprintf(out, "%*sERROR: Missing word expression\n", ind+2, "");
stub_errors += 1;
}
if (word != 0) {
fprintf(out, "%*sAddress-0 word address:\n", ind+2, "");
show_expression(word, ind+2);
}
}
static void show_ternary_expression(ivl_expr_t net, unsigned ind)
{
unsigned width = ivl_expr_width(net);
const char*sign = ivl_expr_signed(net)? "signed" : "unsigned";
fprintf(out, "%*s<ternary width=%u, %s>\n", ind, "", width, sign);
show_expression(ivl_expr_oper1(net), ind+4);
show_expression(ivl_expr_oper2(net), ind+4);
show_expression(ivl_expr_oper3(net), ind+4);
if (ivl_expr_width(ivl_expr_oper2(net)) != width) {
fprintf(out, "ERROR: Width of TRUE expressions is %u, not %u\n",
ivl_expr_width(ivl_expr_oper2(net)), width);
stub_errors += 1;
}
if (ivl_expr_width(ivl_expr_oper3(net)) != width) {
fprintf(out, "ERROR: Width of FALSE expressions is %u, not %u\n",
ivl_expr_width(ivl_expr_oper3(net)), width);
stub_errors += 1;
}
}
void show_expression(ivl_expr_t net, unsigned ind)
{
unsigned idx;
const ivl_expr_type_t code = ivl_expr_type(net);
ivl_parameter_t par = ivl_expr_parameter(net);
unsigned width = ivl_expr_width(net);
const char*sign = ivl_expr_signed(net)? "signed" : "unsigned";
const char*vt = vt_type_string(net);
switch (code) {
case IVL_EX_ARRAY:
show_array_expression(net, ind);
break;
case IVL_EX_BINARY:
show_binary_expression(net, ind);
break;
case IVL_EX_CONCAT:
fprintf(out, "%*s<concat repeat=%u, width=%u, %s, type=%s>\n",
ind, "", ivl_expr_repeat(net), width, sign, vt);
for (idx = 0 ; idx < ivl_expr_parms(net) ; idx += 1)
show_expression(ivl_expr_parm(net, idx), ind+3);
break;
case IVL_EX_MEMORY:
show_memory_expression(net, ind);
break;
case IVL_EX_NUMBER: {
const char*bits = ivl_expr_bits(net);
fprintf(out, "%*s<number=%u'b", ind, "", width);
for (idx = width ; idx > 0 ; idx -= 1)
fprintf(out, "%c", bits[idx-1]);
fprintf(out, ", %s %s", sign, vt);
if (par != 0)
fprintf(out, ", parameter=%s",
ivl_parameter_basename(par));
fprintf(out, ">\n");
break;
}
case IVL_EX_SELECT:
/* The SELECT expression can be used to express part
select, or if the base is null vector extension. */
if (ivl_expr_oper2(net)) {
fprintf(out, "%*s<select: width=%u, %s>\n", ind, "",
width, sign);
show_expression(ivl_expr_oper1(net), ind+3);
show_expression(ivl_expr_oper2(net), ind+3);
} else {
fprintf(out, "%*s<expr pad: width=%u, %s>\n", ind, "",
width, sign);
show_expression(ivl_expr_oper1(net), ind+3);
}
break;
case IVL_EX_STRING:
fprintf(out, "%*s<string=\"%s\", width=%u", ind, "",
ivl_expr_string(net), ivl_expr_width(net));
if (par != 0)
fprintf(out, ", parameter=%s",
ivl_parameter_basename(par));
fprintf(out, ">\n");
break;
case IVL_EX_SFUNC:
fprintf(out, "%*s<function=\"%s\", width=%u, %s, type=%s>\n",
ind, "", ivl_expr_name(net), width, sign, vt);
{ unsigned cnt = ivl_expr_parms(net);
unsigned idx;
for (idx = 0 ; idx < cnt ; idx += 1)
show_expression(ivl_expr_parm(net, idx), ind+3);
}
break;
case IVL_EX_SIGNAL:
show_signal_expression(net, ind);
break;
case IVL_EX_TERNARY:
show_ternary_expression(net, ind);
break;
case IVL_EX_UNARY:
fprintf(out, "%*s<unary \"%c\" width=%u, %s>\n", ind, "",
ivl_expr_opcode(net), width, sign);
show_expression(ivl_expr_oper1(net), ind+4);
break;
case IVL_EX_UFUNC:
show_function_call(net, ind);
break;
case IVL_EX_REALNUM:
{
int idx;
union foo {
double rv;
unsigned char bv[sizeof(double)];
} tmp;
tmp.rv = ivl_expr_dvalue(net);
fprintf(out, "%*s<realnum=%f (", ind, "", tmp.rv);
for (idx = sizeof(double) ; idx > 0 ; idx -= 1)
fprintf(out, "%02x", tmp.bv[idx-1]);
fprintf(out, ")");
if (par != 0)
fprintf(out, ", parameter=%s",
ivl_parameter_basename(par));
fprintf(out, ">\n");
}
break;
default:
fprintf(out, "%*s<expr_type=%u>\n", ind, "", code);
break;
}
}
+4 -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: priv.h,v 1.3 2005/03/05 05:47:42 steve Exp $"
#ident "$Id: priv.h,v 1.5 2007/01/17 05:00:12 steve Exp $"
#endif
# include <ivl_target.h>
@@ -40,10 +40,11 @@ extern int stub_errors;
*/
extern void show_expression(ivl_expr_t net, unsigned ind);
extern void show_memory(ivl_memory_t mem);
/*
* Show the statement.
*/
extern void show_statement(ivl_statement_t net, unsigned ind);
/*
*/
extern const char*data_type_string(ivl_variable_type_t vtype);
+32 -42
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.c,v 1.9 2006/02/02 02:43:59 steve Exp $"
#ident "$Id: statement.c,v 1.12 2007/01/17 05:00:12 steve Exp $"
#endif
# include "config.h"
@@ -26,54 +26,44 @@
static unsigned show_assign_lval(ivl_lval_t lval, unsigned ind)
{
ivl_memory_t mem;
unsigned wid = 0;
if ( (mem = ivl_lval_mem(lval)) ) {
ivl_signal_t sig = ivl_lval_sig(lval);
assert(sig);
ivl_scope_t scope = ivl_memory_scope(mem);
fprintf(out, "%*s{ %s.%s width=%u }\n", ind, "",
ivl_scope_name(scope),
ivl_memory_basename(mem),
ivl_lval_width(lval));
fprintf(out, "%*s{name=%s width=%u lvwidth=%u}\n",
ind, "",
ivl_signal_name(sig),
ivl_signal_width(sig),
ivl_lval_width(lval));
fprintf(out, "%*sAddress-0 expression:\n", ind+4, "");
show_expression(ivl_lval_idx(lval), ind+8);
if (ivl_lval_part_off(lval)) {
fprintf(out, "%*sPart select base:\n", ind+4, "");
show_expression(ivl_lval_part_off(lval), ind+8);
}
/* When the l-value is a memory word, the lval_width
must exactly match the word width. */
if (ivl_lval_width(lval) != ivl_memory_width(mem)) {
fprintf(out, "%*sERROR: l-value width mismatch with "
" memory word width=%u\n", ind, "",
ivl_memory_width(mem));
if (ivl_lval_idx(lval)) {
fprintf(out, "%*sAddress-0 select expression:\n", ind+4, "");
show_expression(ivl_lval_idx(lval), ind+6);
if (ivl_signal_array_count(sig) <= 1) {
fprintf(out, "%*sERROR: Address on signal with "
"word count=%u\n", ind+4, "",
ivl_signal_array_count(sig));
stub_errors += 1;
}
} else {
ivl_signal_t sig = ivl_lval_sig(lval);
fprintf(out, "%*s{name=%s width=%u lvwidth=%u}\n",
ind, "",
ivl_signal_name(sig),
ivl_signal_width(sig),
ivl_lval_width(lval));
if (ivl_lval_mux(lval)) {
fprintf(out, "%*sBit select expression:\n", ind+4, "");
show_expression(ivl_lval_mux(lval), ind+8);
}
if (ivl_lval_part_off(lval)) {
fprintf(out, "%*sPart select base:\n", ind+4, "");
show_expression(ivl_lval_part_off(lval), ind+8);
}
wid = ivl_lval_width(lval);
} else if (ivl_signal_array_count(sig) > 1) {
fprintf(out, "%*sERROR: Address missing on signal with "
"word count=%u\n", ind+4, "",
ivl_signal_array_count(sig));
stub_errors += 1;
}
if (ivl_lval_mux(lval)) {
fprintf(out, "%*sBit select expression:\n", ind+4, "");
show_expression(ivl_lval_mux(lval), ind+8);
}
if (ivl_lval_part_off(lval)) {
fprintf(out, "%*sPart select base:\n", ind+4, "");
show_expression(ivl_lval_part_off(lval), ind+8);
}
wid = ivl_lval_width(lval);
return wid;
}
@@ -301,7 +291,7 @@ void show_statement(ivl_statement_t net, unsigned ind)
break;
case IVL_ST_DELAY:
fprintf(out, "%*s#%lu\n", ind, "", ivl_stmt_delay_val(net));
fprintf(out, "%*s#%llu\n", ind, "", ivl_stmt_delay_val(net));
show_statement(ivl_stmt_sub_stmt(net), ind+2);
break;
+1
View File
@@ -4,3 +4,4 @@ functor:syn-rules
functor:cprop
functor:nodangle
-t:dll
flag:DLL=stub.tgt
+228 -312
View File
@@ -17,12 +17,20 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: stub.c,v 1.136 2006/01/02 05:33:20 steve Exp $"
#ident "$Id: stub.c,v 1.144 2007/01/17 05:00:12 steve Exp $"
#endif
/*
* This is a sample target module. All this does is write to the
* output file some information about each object handle when each of
* the various object functions is called. This can be used to
* understand the behavior of the core as it uses a target module.
*/
# include "config.h"
# include "priv.h"
# include <stdlib.h>
# include <inttypes.h>
# include <assert.h>
FILE*out;
@@ -83,11 +91,29 @@ unsigned width_of_nexus(ivl_nexus_t nex)
return 0;
}
const char*vt_type_string(ivl_expr_t net)
ivl_variable_type_t type_of_nexus(ivl_nexus_t net)
{
unsigned idx;
for (idx = 0 ; idx < ivl_nexus_ptrs(net); idx += 1) {
ivl_nexus_ptr_t ptr = ivl_nexus_ptr(net, idx);
ivl_signal_t sig = ivl_nexus_ptr_sig(ptr);
if (sig != 0) {
return ivl_signal_data_type(sig);
}
}
/* ERROR: A nexus should have at least one signal to carry
properties like the data type. */
return IVL_VT_NO_TYPE;
}
const char*data_type_string(ivl_variable_type_t vtype)
{
const char*vt = "??";
switch (ivl_expr_value(net)) {
switch (vtype) {
case IVL_VT_NO_TYPE:
vt = "NO_TYPE";
break;
@@ -108,209 +134,6 @@ const char*vt_type_string(ivl_expr_t net)
return vt;
}
void show_binary_expression(ivl_expr_t net, unsigned ind)
{
unsigned width = ivl_expr_width(net);
const char*sign = ivl_expr_signed(net)? "signed" : "unsigned";
const char*vt = vt_type_string(net);
fprintf(out, "%*s<\"%c\" width=%u, %s, type=%s>\n", ind, "",
ivl_expr_opcode(net), width, sign, vt);
show_expression(ivl_expr_oper1(net), ind+3);
show_expression(ivl_expr_oper2(net), ind+3);
switch (ivl_expr_opcode(net)) {
case '*':
/* The width of multiply expressions is the sum of the
widths of the operands. This is slightly different
from the way the Verilog standard does it, but allows
us to keep operands smaller. */
width = ivl_expr_width(ivl_expr_oper1(net));
width += ivl_expr_width(ivl_expr_oper2(net));
if (ivl_expr_width(net) != width) {
fprintf(out, "%*sERROR: Result width incorrect\n",
ind+3, "");
stub_errors += 1;
}
break;
default:
break;
}
}
void show_function_call(ivl_expr_t net, unsigned ind)
{
ivl_scope_t def = ivl_expr_def(net);
const char*vt = vt_type_string(net);
fprintf(out, "%*s<%s function %s>\n", ind, "",
vt, ivl_scope_name(def));
}
void show_memory_expression(ivl_expr_t net, unsigned ind)
{
unsigned width = ivl_expr_width(net);
fprintf(out, "%*s<memory width=%u>\n", ind, "",
width);
}
/*
* This is a sample target module. All this does is write to the
* output file some information about each object handle when each of
* the various object functions is called. This can be used to
* understand the behavior of the core as it uses a target module.
*/
void show_ternary_expression(ivl_expr_t net, unsigned ind)
{
unsigned width = ivl_expr_width(net);
const char*sign = ivl_expr_signed(net)? "signed" : "unsigned";
fprintf(out, "%*s<ternary width=%u, %s>\n", ind, "", width, sign);
show_expression(ivl_expr_oper1(net), ind+4);
show_expression(ivl_expr_oper2(net), ind+4);
show_expression(ivl_expr_oper3(net), ind+4);
if (ivl_expr_width(ivl_expr_oper2(net)) != width) {
fprintf(out, "ERROR: Width of TRUE expressions is %u, not %u\n",
ivl_expr_width(ivl_expr_oper2(net)), width);
stub_errors += 1;
}
if (ivl_expr_width(ivl_expr_oper3(net)) != width) {
fprintf(out, "ERROR: Width of FALSE expressions is %u, not %u\n",
ivl_expr_width(ivl_expr_oper3(net)), width);
stub_errors += 1;
}
}
void show_expression(ivl_expr_t net, unsigned ind)
{
unsigned idx;
const ivl_expr_type_t code = ivl_expr_type(net);
ivl_parameter_t par = ivl_expr_parameter(net);
unsigned width = ivl_expr_width(net);
const char*sign = ivl_expr_signed(net)? "signed" : "unsigned";
const char*vt = vt_type_string(net);
switch (code) {
case IVL_EX_BINARY:
show_binary_expression(net, ind);
break;
case IVL_EX_CONCAT:
fprintf(out, "%*s<concat repeat=%u, width=%u, %s, type=%s>\n",
ind, "", ivl_expr_repeat(net), width, sign, vt);
for (idx = 0 ; idx < ivl_expr_parms(net) ; idx += 1)
show_expression(ivl_expr_parm(net, idx), ind+3);
break;
case IVL_EX_MEMORY:
show_memory_expression(net, ind);
break;
case IVL_EX_NUMBER: {
const char*bits = ivl_expr_bits(net);
fprintf(out, "%*s<number=%u'b", ind, "", width);
for (idx = width ; idx > 0 ; idx -= 1)
fprintf(out, "%c", bits[idx-1]);
fprintf(out, ", %s %s", sign, vt);
if (par != 0)
fprintf(out, ", parameter=%s",
ivl_parameter_basename(par));
fprintf(out, ">\n");
break;
}
case IVL_EX_SELECT:
/* The SELECT expression can be used to express part
select, or if the base is null vector extension. */
if (ivl_expr_oper2(net)) {
fprintf(out, "%*s<select: width=%u, %s>\n", ind, "",
width, sign);
show_expression(ivl_expr_oper1(net), ind+3);
show_expression(ivl_expr_oper2(net), ind+3);
} else {
fprintf(out, "%*s<expr pad: width=%u, %s>\n", ind, "",
width, sign);
show_expression(ivl_expr_oper1(net), ind+3);
}
break;
case IVL_EX_STRING:
fprintf(out, "%*s<string=\"%s\", width=%u", ind, "",
ivl_expr_string(net), ivl_expr_width(net));
if (par != 0)
fprintf(out, ", parameter=%s",
ivl_parameter_basename(par));
fprintf(out, ">\n");
break;
case IVL_EX_SFUNC:
fprintf(out, "%*s<function=\"%s\", width=%u, %s, vt=%d>\n",
ind, "", ivl_expr_name(net), ivl_expr_width(net),
sign, ivl_expr_value(net));
{ unsigned cnt = ivl_expr_parms(net);
unsigned idx;
for (idx = 0 ; idx < cnt ; idx += 1)
show_expression(ivl_expr_parm(net, idx), ind+3);
}
break;
case IVL_EX_SIGNAL:
fprintf(out, "%*s<signal=%s, width=%u, %s type=%s>\n", ind, "",
ivl_expr_name(net), width, sign, vt);
break;
case IVL_EX_TERNARY:
show_ternary_expression(net, ind);
break;
case IVL_EX_UNARY:
fprintf(out, "%*s<unary \"%c\" width=%u, %s>\n", ind, "",
ivl_expr_opcode(net), width, sign);
show_expression(ivl_expr_oper1(net), ind+4);
break;
case IVL_EX_UFUNC:
show_function_call(net, ind);
break;
case IVL_EX_REALNUM:
{
int idx;
union foo {
double rv;
unsigned char bv[sizeof(double)];
} tmp;
tmp.rv = ivl_expr_dvalue(net);
fprintf(out, "%*s<realnum=%f (", ind, "", tmp.rv);
for (idx = sizeof(double) ; idx > 0 ; idx -= 1)
fprintf(out, "%02x", tmp.bv[idx-1]);
fprintf(out, ")");
if (par != 0)
fprintf(out, ", parameter=%s",
ivl_parameter_basename(par));
fprintf(out, ">\n");
}
break;
default:
fprintf(out, "%*s<expr_type=%u>\n", ind, "", code);
break;
}
}
/*
* The compare-like LPM nodes have input widths that match the
* ivl_lpm_width() value, and an output width of 1. This function
@@ -365,6 +188,35 @@ static void show_lpm_add(ivl_lpm_t net)
show_lpm_arithmetic_pins(net);
}
static void show_lpm_array(ivl_lpm_t net)
{
ivl_nexus_t nex;
unsigned width = ivl_lpm_width(net);
ivl_signal_t array = ivl_lpm_array(net);
fprintf(out, " LPM_ARRAY: <width=%u, signal=%s>\n",
width, ivl_signal_basename(array));
nex = ivl_lpm_q(net, 0);
assert(nex);
fprintf(out, " Q: %s\n", ivl_nexus_name(nex));
nex = ivl_lpm_select(net);
assert(nex);
fprintf(out, " Address: %s (address width=%u)\n",
ivl_nexus_name(nex), ivl_lpm_selects(net));
if (width_of_nexus(ivl_lpm_q(net,0)) != width) {
fprintf(out, " ERROR: Data Q width doesn't match "
"nexus width=%u\n", width_of_nexus(ivl_lpm_q(net,0)));
stub_errors += 1;
}
if (ivl_signal_width(array) != width) {
fprintf(out, " ERROR: Data width doesn't match "
"word width=%u\n", ivl_signal_width(array));
stub_errors += 1;
}
}
static void show_lpm_divide(ivl_lpm_t net)
{
unsigned width = ivl_lpm_width(net);
@@ -712,42 +564,6 @@ static void show_lpm_part_bi(ivl_lpm_t net)
}
static void show_lpm_ram(ivl_lpm_t net)
{
ivl_nexus_t nex;
unsigned width = ivl_lpm_width(net);
ivl_memory_t mem = ivl_lpm_memory(net);
fprintf(out, " LPM_RAM: <width=%u>\n", width);
nex = ivl_lpm_q(net, 0);
assert(nex);
fprintf(out, " Q: %s\n", ivl_nexus_name(nex));
nex = ivl_lpm_select(net);
fprintf(out, " Address: %s (address width=%u)\n",
ivl_nexus_name(nex), ivl_lpm_selects(net));
if (width_of_nexus(ivl_lpm_q(net,0)) != width) {
fprintf(out, " ERROR: Data width doesn't match "
"nexus width=%u\n", width_of_nexus(ivl_lpm_q(net,0)));
stub_errors += 1;
}
if (width_of_nexus(ivl_lpm_select(net)) != ivl_lpm_selects(net)) {
fprintf(out, " ERROR: Width of address doesn't match "
"nexus width=%u\n", width_of_nexus(ivl_lpm_select(net)));
stub_errors += 1;
}
/* The width of the port must match the width of the memory
word. the compile assures that for us. */
if (width != ivl_memory_width(mem)) {
fprintf(out, " ERROR: Width doesn't match"
" memory word width=%u\n", ivl_memory_width(mem));
stub_errors += 1;
}
}
/*
* The reduction operators have similar characteristics and are
* displayed here.
@@ -762,14 +578,25 @@ static void show_lpm_re(ivl_lpm_t net)
case IVL_LPM_RE_AND:
type = "AND";
break;
case IVL_LPM_RE_NAND:
type = "NAND";
break;
case IVL_LPM_RE_OR:
type = "OR";
break;
case IVL_LPM_RE_NOR:
type = "NOR";
case IVL_LPM_RE_XOR:
type = "XOR";
break;
case IVL_LPM_RE_XNOR:
type = "XNOR";
default:
break;
}
fprintf(out, " LPM_RE_%s: <width=%u>\n", type, width);
fprintf(out, " LPM_RE_%s: %s <width=%u>\n",
type, ivl_lpm_name(net),width);
nex = ivl_lpm_q(net, 0);
fprintf(out, " Q: %s\n", ivl_nexus_name(nex));
@@ -828,8 +655,9 @@ static void show_lpm_shift(ivl_lpm_t net, const char*shift_dir)
ivl_nexus_t nex;
unsigned width = ivl_lpm_width(net);
fprintf(out, " LPM_SHIFT%s %s: <width=%u>\n", shift_dir,
ivl_lpm_basename(net), width);
fprintf(out, " LPM_SHIFT%s %s: <width=%u, %ssigned>\n", shift_dir,
ivl_lpm_basename(net), width,
ivl_lpm_signed(net)? "" : "un");
nex = ivl_lpm_q(net, 0);
fprintf(out, " Q: %s\n", ivl_nexus_name(nex));
@@ -884,6 +712,34 @@ static void show_lpm_sub(ivl_lpm_t net)
show_lpm_arithmetic_pins(net);
}
static void show_lpm_sfunc(ivl_lpm_t net)
{
unsigned width = ivl_lpm_width(net);
unsigned ports = ivl_lpm_size(net);
ivl_variable_type_t data_type = type_of_nexus(ivl_lpm_q(net,0));
ivl_nexus_t nex;
unsigned idx;
fprintf(out, " LPM_SFUNC %s: <call=%s, width=%u, type=%s, ports=%u>\n",
ivl_lpm_basename(net), ivl_lpm_string(net),
width, data_type_string(data_type), ports);
nex = ivl_lpm_q(net, 0);
if (width != width_of_nexus(nex)) {
fprintf(out, " ERROR: Q output nexus width=%u "
" does not match part width\n", width_of_nexus(nex));
stub_errors += 1;
}
fprintf(out, " Q: %s\n", ivl_nexus_name(nex));
for (idx = 0 ; idx < ports ; idx += 1) {
nex = ivl_lpm_data(net, idx);
fprintf(out, " D%u: %s <width=%u, type=%s>\n", idx,
ivl_nexus_name(nex), width_of_nexus(nex),
data_type_string(type_of_nexus(nex)));
}
}
static void show_lpm_ufunc(ivl_lpm_t net)
{
unsigned width = ivl_lpm_width(net);
@@ -920,6 +776,10 @@ static void show_lpm(ivl_lpm_t net)
show_lpm_add(net);
break;
case IVL_LPM_ARRAY:
show_lpm_array(net);
break;
case IVL_LPM_DIVIDE:
show_lpm_divide(net);
break;
@@ -949,15 +809,12 @@ static void show_lpm(ivl_lpm_t net)
show_lpm_concat(net);
break;
case IVL_LPM_RAM:
show_lpm_ram(net);
break;
case IVL_LPM_RE_AND:
show_lpm_re(net);
break;
case IVL_LPM_RE_NAND:
case IVL_LPM_RE_NOR:
case IVL_LPM_RE_OR:
case IVL_LPM_RE_XOR:
case IVL_LPM_RE_XNOR:
show_lpm_re(net);
break;
@@ -1003,6 +860,10 @@ static void show_lpm(ivl_lpm_t net)
show_lpm_repeat(net);
break;
case IVL_LPM_SFUNC:
show_lpm_sfunc(net);
break;
case IVL_LPM_UFUNC:
show_lpm_ufunc(net);
break;
@@ -1135,6 +996,57 @@ static void signal_nexus_const(ivl_signal_t sig,
}
}
static void show_nexus_details(ivl_signal_t net, ivl_nexus_t nex)
{
unsigned idx;
for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) {
ivl_net_const_t con;
ivl_net_logic_t log;
ivl_lpm_t lpm;
ivl_signal_t sig;
ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex, idx);
const char*dr0 = str_tab[ivl_nexus_ptr_drive0(ptr)];
const char*dr1 = str_tab[ivl_nexus_ptr_drive1(ptr)];
if ((sig = ivl_nexus_ptr_sig(ptr))) {
fprintf(out, " SIG %s word=%u (%s0, %s1)",
ivl_signal_name(sig), ivl_nexus_ptr_pin(ptr), dr0, dr1);
if (ivl_signal_width(sig) != ivl_signal_width(net)) {
fprintf(out, " (ERROR: Width=%u)",
ivl_signal_width(sig));
stub_errors += 1;
}
if (ivl_signal_data_type(sig) != ivl_signal_data_type(net)) {
fprintf(out, " (ERROR: data type mismatch)");
stub_errors += 1;
}
fprintf(out, "\n");
} else if ((log = ivl_nexus_ptr_log(ptr))) {
fprintf(out, " LOG %s.%s[%u] (%s0, %s1)\n",
ivl_scope_name(ivl_logic_scope(log)),
ivl_logic_basename(log),
ivl_nexus_ptr_pin(ptr), dr0, dr1);
} else if ((lpm = ivl_nexus_ptr_lpm(ptr))) {
fprintf(out, " LPM %s.%s (%s0, %s1)\n",
ivl_scope_name(ivl_lpm_scope(lpm)),
ivl_lpm_basename(lpm), dr0, dr1);
} else if ((con = ivl_nexus_ptr_con(ptr))) {
signal_nexus_const(net, ptr, con);
} else {
fprintf(out, " ?[%u] (%s0, %s1)\n",
ivl_nexus_ptr_pin(ptr), dr0, dr1);
}
}
}
static void show_signal(ivl_signal_t net)
{
@@ -1200,68 +1112,42 @@ static void show_signal(ivl_signal_t net)
break;
}
nex = ivl_signal_nex(net);
for (idx = 0 ; idx < ivl_signal_array_count(net) ; idx += 1) {
fprintf(out, " %s %s %s%s[%d:%d] %s <width=%u> nexus=%s\n",
type, sign, port, data_type,
ivl_signal_msb(net), ivl_signal_lsb(net),
ivl_signal_basename(net), ivl_signal_width(net),
ivl_nexus_name(nex));
nex = ivl_signal_nex(net, idx);
fprintf(out, " %s %s %s%s[%d:%d] %s[word=%u, adr=%d] <width=%u> nexus=%s\n",
type, sign, port, data_type,
ivl_signal_msb(net), ivl_signal_lsb(net),
ivl_signal_basename(net),
idx, ivl_signal_array_base(net)+idx,
ivl_signal_width(net),
ivl_nexus_name(nex));
for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) {
ivl_net_const_t con;
ivl_net_logic_t log;
ivl_lpm_t lpm;
ivl_signal_t sig;
ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex, idx);
show_nexus_details(net, nex);
}
const char*dr0 = str_tab[ivl_nexus_ptr_drive0(ptr)];
const char*dr1 = str_tab[ivl_nexus_ptr_drive1(ptr)];
for (idx = 0 ; idx < ivl_signal_npath(net) ; idx += 1) {
ivl_delaypath_t path = ivl_signal_path(net,idx);
ivl_nexus_t nex = ivl_path_source(path);
if ((sig = ivl_nexus_ptr_sig(ptr))) {
fprintf(out, " SIG %s (%s0, %s1)",
ivl_signal_name(sig), dr0, dr1);
/* Only pin-0 of signals is used. If this is
something other then pin-0, report an error. */
if (ivl_nexus_ptr_pin(ptr) != 0) {
fprintf(out, " (pin=%u, should be 0)",
ivl_nexus_ptr_pin(ptr));
stub_errors += 1;
}
if (ivl_signal_width(sig) != ivl_signal_width(net)) {
fprintf(out, " (ERROR: Width=%u)",
ivl_signal_width(sig));
stub_errors += 1;
}
if (ivl_signal_data_type(sig) != ivl_signal_data_type(net)) {
fprintf(out, " (ERROR: data type mismatch)");
stub_errors += 1;
}
fprintf(out, "\n");
} else if ((log = ivl_nexus_ptr_log(ptr))) {
fprintf(out, " LOG %s.%s[%u] (%s0, %s1)\n",
ivl_scope_name(ivl_logic_scope(log)),
ivl_logic_basename(log),
ivl_nexus_ptr_pin(ptr), dr0, dr1);
} else if ((lpm = ivl_nexus_ptr_lpm(ptr))) {
fprintf(out, " LPM %s.%s (%s0, %s1)\n",
ivl_scope_name(ivl_lpm_scope(lpm)),
ivl_lpm_basename(lpm), dr0, dr1);
} else if ((con = ivl_nexus_ptr_con(ptr))) {
signal_nexus_const(net, ptr, con);
} else {
fprintf(out, " ?[%u] (%s0, %s1)\n",
ivl_nexus_ptr_pin(ptr), dr0, dr1);
}
fprintf(out, " path %s", ivl_nexus_name(nex));
fprintf(out, " %" PRIu64 ",%" PRIu64 ",%" PRIu64
" %" PRIu64 ",%" PRIu64 ",%" PRIu64
" %" PRIu64 ",%" PRIu64 ",%" PRIu64
" %" PRIu64 ",%" PRIu64 ",%" PRIu64 "\n",
ivl_path_delay(path, IVL_PE_01),
ivl_path_delay(path, IVL_PE_10),
ivl_path_delay(path, IVL_PE_0z),
ivl_path_delay(path, IVL_PE_z1),
ivl_path_delay(path, IVL_PE_1z),
ivl_path_delay(path, IVL_PE_z0),
ivl_path_delay(path, IVL_PE_0x),
ivl_path_delay(path, IVL_PE_x1),
ivl_path_delay(path, IVL_PE_1x),
ivl_path_delay(path, IVL_PE_x0),
ivl_path_delay(path, IVL_PE_xz),
ivl_path_delay(path, IVL_PE_zx));
}
for (idx = 0 ; idx < ivl_signal_attr_cnt(net) ; idx += 1) {
@@ -1327,6 +1213,12 @@ static void show_logic(ivl_net_logic_t net)
case IVL_LO_BUFZ:
fprintf(out, " bufz %s", name);
break;
case IVL_LO_NAND:
fprintf(out, " nand %s", name);
break;
case IVL_LO_NOR:
fprintf(out, " nor %s", name);
break;
case IVL_LO_NOT:
fprintf(out, " not %s", name);
break;
@@ -1486,9 +1378,6 @@ static int show_scope(ivl_scope_t net, void*x)
for (idx = 0 ; idx < ivl_scope_sigs(net) ; idx += 1)
show_signal(ivl_scope_sig(net, idx));
for (idx = 0 ; idx < ivl_scope_mems(net) ; idx += 1)
show_memory(ivl_scope_mem(net, idx));
for (idx = 0 ; idx < ivl_scope_events(net) ; idx += 1)
show_event(ivl_scope_event(net, idx));
@@ -1580,6 +1469,33 @@ int target_design(ivl_design_t des)
/*
* $Log: stub.c,v $
* Revision 1.144 2007/01/17 05:00:12 steve
* Dead code for memories in scopes.
*
* Revision 1.143 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.142 2006/11/28 05:56:41 steve
* Dump nand logic.
*
* Revision 1.141 2006/09/23 04:57:19 steve
* Basic support for specify timing.
*
* Revision 1.140 2006/07/30 02:51:36 steve
* Fix/implement signed right shift.
*
* Revision 1.139 2006/06/18 04:15:50 steve
* Add support for system functions in continuous assignments.
*
* Revision 1.138 2006/04/30 05:16:53 steve
* Dump *all* the reduction operator gates.
*
* Revision 1.137 2006/04/27 04:26:38 steve
* Dump function type as string.
*
* Revision 1.136 2006/01/02 05:33:20 steve
* Node delays can be more general expressions in structural contexts.
*
+1
View File
@@ -1,3 +1,4 @@
functor:cprop
functor:nodangle
-t:dll
flag:DLL=stub.tgt
+3 -3
View File
@@ -16,7 +16,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.24 2005/09/14 02:53:15 steve Exp $"
#ident "$Id: Makefile.in,v 1.25 2006/10/30 22:45:37 steve Exp $"
#
#
SHELL = /bin/sh
@@ -77,10 +77,10 @@ Makefile: Makefile.in config.status
./config.status
clean:
rm -rf *.o dep vvp.tgt
rm -rf *.o dep vvp.tgt vvp.conf vvp-s.conf
distclean: clean
rm -f Makefile config.status config.log config.cache
rm -f Makefile config.status config.log config.cache vvp_config.h
check: all
+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: draw_mux.c,v 1.13 2005/10/12 17:26:17 steve Exp $"
#ident "$Id: draw_mux.c,v 1.14 2007/01/16 05:44:16 steve Exp $"
#endif
# include "vvp_priv.h"
@@ -76,9 +76,9 @@ static void draw_lpm_mux_nest(ivl_lpm_t net, const char*muxz)
for (idx = 0 ; idx < (ivl_lpm_size(net) >> level); idx += 2) {
fprintf(vvp_out, "L_%p/%d/%d .functor %s %u",
net, width, level, muxz, idx);
fprintf(vvp_out, ", L_%p/%d/%d", net, level-1, idx/2+0);
fprintf(vvp_out, ", L_%p/%d/%d", net, level-1, idx/2+1);
net, level, idx/2, muxz, width);
fprintf(vvp_out, ", L_%p/%d/%d", net, level-1, idx+0);
fprintf(vvp_out, ", L_%p/%d/%d", net, level-1, idx+1);
fprintf(vvp_out, ", L_%p/%ds", net, level);
fprintf(vvp_out, ", C4<>;\n");
}
@@ -127,6 +127,12 @@ void draw_lpm_mux(ivl_lpm_t net)
/*
* $Log: draw_mux.c,v $
* Revision 1.14 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.13 2005/10/12 17:26:17 steve
* MUX nodes get inputs from nets, not from net inputs,
* Detect and draw alias nodes to reduce net size and
+16 -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: draw_ufunc.c,v 1.1 2005/07/13 04:52:31 steve Exp $"
#ident "$Id: draw_ufunc.c,v 1.2 2007/01/16 05:44:16 steve Exp $"
#endif
# include "vvp_priv.h"
@@ -32,10 +32,12 @@ static void function_argument_logic(ivl_signal_t port, ivl_expr_t exp)
{
struct vector_info res;
/* ports cannot be arrays. */
assert(ivl_signal_array_count(port) == 1);
res = draw_eval_expr_wid(exp, ivl_signal_width(port), 0);
assert(res.wid <= ivl_signal_width(port));
fprintf(vvp_out, " %%set/v V_%s, %u, %u;\n",
vvp_signal_label(port), res.base, res.wid);
fprintf(vvp_out, " %%set/v v%p_0, %u, %u;\n", port, res.base, res.wid);
clr_vector(res);
}
@@ -44,8 +46,10 @@ static void function_argument_real(ivl_signal_t port, ivl_expr_t exp)
{
int res = draw_eval_real(exp);
fprintf(vvp_out, " %%set/wr V_%s, %d;\n",
vvp_signal_label(port), res);
/* ports cannot be arrays. */
assert(ivl_signal_array_count(port) == 1);
fprintf(vvp_out, " %%set/wr v%p_0, %d;\n", port, res);
}
static void draw_function_argument(ivl_signal_t port, ivl_expr_t exp)
@@ -113,8 +117,9 @@ struct vector_info draw_ufunc_expr(ivl_expr_t exp, unsigned wid)
if (load_wid > ivl_signal_width(retval))
load_wid = ivl_signal_width(retval);
fprintf(vvp_out, " %%load/v %u, V_%s, %u;\n",
res.base, vvp_signal_label(retval), load_wid);
assert(ivl_signal_array_count(retval) == 1);
fprintf(vvp_out, " %%load/v %u, v%p_0, %u;\n",
res.base, retval, load_wid);
if (load_wid < swid)
fprintf(vvp_out, " %%mov %u, 0, %u;\n",
@@ -148,10 +153,12 @@ int draw_ufunc_real(ivl_expr_t exp)
fprintf(vvp_out, ", S_%p;\n", def);
fprintf(vvp_out, " %%join;\n");
/* Return value signal cannot be an array. */
assert(ivl_signal_array_count(retval) == 1);
/* Load the result into a word. */
res = allocate_word();
fprintf(vvp_out, " %%load/wr %d, V_%s;\n",
res, vvp_signal_label(retval));
fprintf(vvp_out, " %%load/wr %d, v%p_0;\n", res, retval);
return res;
}
+24 -13
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: draw_vpi.c,v 1.13 2005/10/11 18:30:50 steve Exp $"
#ident "$Id: draw_vpi.c,v 1.15 2007/01/17 04:39:18 steve Exp $"
#endif
# include "vvp_priv.h"
@@ -75,6 +75,7 @@ static void draw_vpi_taskfunc_args(const char*call_string,
with VPI handles of their own. Therefore, skip
them in the process of evaluating expressions. */
case IVL_EX_NONE:
case IVL_EX_ARRAY:
case IVL_EX_NUMBER:
case IVL_EX_STRING:
case IVL_EX_EVENT:
@@ -107,7 +108,8 @@ static void draw_vpi_taskfunc_args(const char*call_string,
} else if (ivl_expr_signed(expr) !=
ivl_signal_signed(ivl_expr_signal(expr))) {
break;
} else if (ivl_signal_array_count(ivl_expr_signal(expr))>1){
break;
} else {
continue;
}
@@ -153,6 +155,10 @@ static void draw_vpi_taskfunc_args(const char*call_string,
fprintf(vvp_out, ", \" \"");
continue;
case IVL_EX_ARRAY:
fprintf(vvp_out, ", v%p", ivl_expr_signal(expr));
continue;
case IVL_EX_NUMBER: {
unsigned bit, wid = ivl_expr_width(expr);
const char*bits = ivl_expr_bits(expr);
@@ -176,13 +182,16 @@ static void draw_vpi_taskfunc_args(const char*call_string,
ivl_signal_signed(ivl_expr_signal(expr))) {
break;
} else if (ivl_signal_array_count(ivl_expr_signal(expr))>1){
break;
} else {
fprintf(vvp_out, ", V_%s",
vvp_signal_label(ivl_expr_signal(expr)));
ivl_signal_t sig = ivl_expr_signal(expr);
assert(ivl_signal_array_count(sig) == 1);
fprintf(vvp_out, ", v%p_0", sig);
continue;
}
fprintf(vvp_out, ", V_%s",
vvp_signal_label(ivl_expr_signal(expr)));
assert(0);
continue;
case IVL_EX_STRING:
@@ -210,13 +219,6 @@ static void draw_vpi_taskfunc_args(const char*call_string,
}
break;
case IVL_EX_MEMORY:
if (!ivl_expr_oper1(expr)) {
fprintf(vvp_out, ", M_%p", ivl_expr_memory(expr)) ;
continue;
}
break;
default:
break;
}
@@ -291,6 +293,15 @@ int draw_vpi_rfunc_call(ivl_expr_t fnet)
/*
* $Log: draw_vpi.c,v $
* Revision 1.15 2007/01/17 04:39:18 steve
* Remove dead code related to memories.
*
* Revision 1.14 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.13 2005/10/11 18:30:50 steve
* Remove obsolete vvp_memory_label function.
*
+88 -96
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_expr.c,v 1.130 2006/02/02 02:43:59 steve Exp $"
#ident "$Id: eval_expr.c,v 1.133 2007/01/19 05:24:53 steve Exp $"
#endif
# include "vvp_priv.h"
@@ -1464,11 +1464,39 @@ static struct vector_info draw_realnum_expr(ivl_expr_t exp, unsigned wid)
{
struct vector_info res;
double val = ivl_expr_dvalue(exp);
long ival = val;
unsigned addr, run, idx;
int bit;
fprintf(vvp_out, "; draw_realnum_expr(%f, %u) as %ld\n",
val, wid, ival);
res.base = allocate_vector(wid);
res.wid = wid;
fprintf(vvp_out, " ; XXXX draw_realnum_expr(%f, %u)\n", val, wid);
addr = res.base;
run = 1;
bit = ival & 1;
ival >>= 1LL;
for (idx = 1 ; idx < wid ; idx += 1) {
int next_bit = ival & 1;
ival >>= 1LL;
if (next_bit == bit) {
run += 1;
continue;
}
fprintf(vvp_out, " %%mov %u, %d, %u;\n", addr, bit, run);
addr += run;
run = 1;
bit = next_bit;
}
fprintf(vvp_out, " %%mov %u, %d, %u;\n", addr, bit, run);
return res;
}
@@ -1531,21 +1559,39 @@ static struct vector_info draw_string_expr(ivl_expr_t exp, unsigned wid)
*/
static void draw_signal_dest(ivl_expr_t exp, struct vector_info res)
{
unsigned idx;
unsigned swid = ivl_expr_width(exp);
ivl_signal_t sig = ivl_expr_signal(exp);
unsigned word = 0;
if (swid > res.wid)
swid = res.wid;
/* If this is an access to an array, handle that by emiting a
load/av instruction. */
if (ivl_signal_array_count(sig) > 1) {
ivl_expr_t ix = ivl_expr_oper1(exp);
if (!number_is_immediate(ix, 8*sizeof(unsigned long))) {
draw_eval_expr_into_integer(ix, 3);
fprintf(vvp_out, " %%load/av %u, v%p, %u;\n",
res.base, sig, swid);
return;
}
/* The index is constant, so we can return to direct
readout with the specific word selected. */
word = get_number_immediate(ix);
}
/* If this is a REG (a variable) then I can do a vector read. */
fprintf(vvp_out, " %%load/v %u, V_%s, %u;\n",
res.base, vvp_signal_label(sig), swid);
fprintf(vvp_out, " %%load/v %u, v%p_%u, %u;\n",
res.base, sig, word, swid);
/* Pad the signal value with zeros. */
if (swid < res.wid) {
if (ivl_expr_signed(exp)) {
unsigned idx;
for (idx = swid ; idx < res.wid ; idx += 1)
fprintf(vvp_out, " %%mov %u, %u, 1;\n",
res.base+idx, res.base+swid-1);
@@ -1581,86 +1627,6 @@ static struct vector_info draw_signal_expr(ivl_expr_t exp, unsigned wid,
return res;
}
/*
* Draw code to evaluate a memory word index expression and write the
* value into index register 3. This expression converts the run-time
* calculated value to canonical form that the %load/mv takes.
*/
void draw_memory_index_expr(ivl_memory_t mem, ivl_expr_t ae)
{
int root = ivl_memory_root(mem);
switch (ivl_expr_type(ae)) {
case IVL_EX_NUMBER: {
unsigned nbits = ivl_expr_width(ae);
const char*bits = ivl_expr_bits(ae);
unsigned long v = 0;
int unknown_flag = 0;
unsigned idx;
for (idx = 0 ; idx < nbits ; idx += 1)
switch (bits[idx]) {
case '0':
break;
case '1':
assert(idx < (8*sizeof v));
v |= 1 << idx;
break;
default:
v = ~0UL;
unknown_flag = 1;
break;
}
fprintf(vvp_out, " %%ix/load 3, %lu;\n", v-root);
fprintf(vvp_out, " %%mov 4, %c, 1;\n",
unknown_flag?'1':'0');
break;
}
case IVL_EX_ULONG: {
unsigned v = ivl_expr_uvalue(ae);
fprintf(vvp_out, " %%ix/load 3, %u;\n", v-root);
fprintf(vvp_out, " %%mov 4, 0, 1;\n");
break;
}
default: {
struct vector_info addr = draw_eval_expr(ae, 0);
fprintf(vvp_out, " %%ix/get 3, %u, %u;\n",
addr.base, addr.wid);
clr_vector(addr);
if (root>0)
fprintf(vvp_out, " %%ix/sub 3, %u;\n", root);
break;
}
}
}
static struct vector_info draw_memory_expr(ivl_expr_t exp, unsigned wid)
{
unsigned swid = ivl_expr_width(exp);
ivl_memory_t mem = ivl_expr_memory(exp);
struct vector_info res;
draw_memory_index_expr(mem, ivl_expr_oper1(exp));
if (swid > wid)
swid = wid;
res.base = allocate_vector(wid);
res.wid = wid;
fprintf(vvp_out, " %%load/mv %u, M_%p, %u;\n",
res.base, mem, swid);
/* Pad the signal value with zeros. */
if (swid < wid)
fprintf(vvp_out, " %%mov %u, 0, %u;\n",
res.base+swid, wid-swid);
if (res.base >= 8)
save_expression_lookaside(res.base, exp, wid);
return res;
}
static struct vector_info draw_select_signal(ivl_expr_t sube,
ivl_expr_t bit_idx,
unsigned bit_wid,
@@ -1671,6 +1637,24 @@ static struct vector_info draw_select_signal(ivl_expr_t sube,
struct vector_info res;
unsigned idx;
/* Use this word of the signal. */
unsigned use_word = 0;
/* If this is an access to an array, handle that by emiting a
load/av instruction. */
if (ivl_signal_array_count(sig) > 1) {
ivl_expr_t ix = ivl_expr_oper1(sube);
if (!number_is_immediate(ix, 8*sizeof(unsigned long))) {
draw_eval_expr_into_integer(ix, 3);
assert(0); /* XXXX Don't know how to load part
select! */
return res;
}
/* The index is constant, so we can return to direct
readout with the specific word selected. */
use_word = get_number_immediate(ix);
}
shiv = draw_eval_expr(bit_idx, STUFF_OK_XZ|STUFF_OK_RO);
fprintf(vvp_out, " %%ix/get 0, %u, %u;\n", shiv.base, shiv.wid);
@@ -1683,8 +1667,8 @@ static struct vector_info draw_select_signal(ivl_expr_t sube,
if (shiv.base == 0 && ivl_expr_width(sube) == wid) {
res.base = allocate_vector(wid);
res.wid = wid;
fprintf(vvp_out, " %%load/v %u, V_%p, %u;\n",
res.base, sig, ivl_expr_width(sube));
fprintf(vvp_out, " %%load/v %u, v%p_%u, %u;\n",
res.base, sig, use_word, ivl_expr_width(sube));
return res;
}
@@ -1698,10 +1682,10 @@ static struct vector_info draw_select_signal(ivl_expr_t sube,
res.base = allocate_vector(ivl_expr_width(sube));
res.wid = ivl_expr_width(sube);
fprintf(vvp_out, " %%load/v %u, V_%p, %u; Only need %u bits\n",
res.base, sig, ivl_expr_width(sube), wid);
fprintf(vvp_out, " %%load/v %u, v%p_%u, %u; Only need %u bits\n",
res.base, sig, use_word, ivl_expr_width(sube), wid);
save_signal_lookaside(res.base, sig, res.wid);
save_signal_lookaside(res.base, sig, use_word, res.wid);
{
struct vector_info tmp;
@@ -1724,8 +1708,8 @@ static struct vector_info draw_select_signal(ivl_expr_t sube,
ivl_expr_width(sube), wid);
break;
}
fprintf(vvp_out, " %%load/x.p %u, V_%p, 0;\n",
res.base+idx, sig);
fprintf(vvp_out, " %%load/x.p %u, v%p_%u, 0;\n",
res.base+idx, sig, use_word);
}
return res;
@@ -2182,10 +2166,6 @@ struct vector_info draw_eval_expr_wid(ivl_expr_t exp, unsigned wid,
res = draw_ternary_expr(exp, wid);
break;
case IVL_EX_MEMORY:
res = draw_memory_expr(exp, wid);
break;
case IVL_EX_SFUNC:
res = draw_sfunc_expr(exp, wid);
break;
@@ -2209,6 +2189,18 @@ struct vector_info draw_eval_expr(ivl_expr_t exp, int stuff_ok_flag)
/*
* $Log: eval_expr.c,v $
* Revision 1.133 2007/01/19 05:24:53 steve
* Handle real constants in vector expressions.
*
* Revision 1.132 2007/01/17 04:39:18 steve
* Remove dead code related to memories.
*
* Revision 1.131 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.130 2006/02/02 02:43:59 steve
* Allow part selects of memory words in l-values.
*
+44 -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: eval_real.c,v 1.14 2005/07/13 04:52:31 steve Exp $"
#ident "$Id: eval_real.c,v 1.17 2007/01/16 05:44:16 steve Exp $"
#endif
/*
@@ -80,6 +80,10 @@ static int draw_binary_real(ivl_expr_t exp)
fprintf(vvp_out, " %%div/wr %d, %d;\n", l, r);
break;
case '%':
fprintf(vvp_out, " %%mod/wr %d, %d;\n", l, r);
break;
#if 0
case '%':
{ struct vector_info res = draw_eval_expr(exp, STUFF_OK_XZ);
l = allocate_word();
@@ -89,7 +93,7 @@ static int draw_binary_real(ivl_expr_t exp)
clr_vector(res);
}
break;
#endif
default:
fprintf(stderr, "XXXX draw_binary_real(%c)\n",
ivl_expr_opcode(exp));
@@ -108,13 +112,23 @@ static int draw_number_real(ivl_expr_t exp)
const char*bits = ivl_expr_bits(exp);
unsigned wid = ivl_expr_width(exp);
unsigned long mant = 0;
int vexp = 0x1000;
for (idx = 0 ; idx < wid ; idx += 1) {
if (bits[idx] == '1')
mant |= 1 << idx;
}
fprintf(vvp_out, " %%loadi/wr %d, %lu, 4096;\n", res, mant);
/* If this is actually a negative number, then get the
positive equivilent, and set the sign bit in the exponent
field. */
if (ivl_expr_signed(exp) && (bits[wid-1] == '1')) {
mant = (0-mant) & ((1UL<<wid) - 1UL);
vexp |= 0x4000;
}
fprintf(vvp_out, " %%loadi/wr %d, %lu, %d; load(num)= %c%lu\n",
res, mant, vexp, (vexp&0x4000)? '-' : '+', mant);
return res;
}
@@ -231,9 +245,22 @@ static int draw_signal_real_real(ivl_expr_t exp)
{
ivl_signal_t sig = ivl_expr_signal(exp);
int res = allocate_word();
unsigned long word = 0;
fprintf(vvp_out, " %%load/wr %d, V_%s;\n",
res, vvp_signal_label(sig));
if (ivl_signal_array_count(sig) > 1) {
ivl_expr_t ix = ivl_expr_oper1(exp);
if (!number_is_immediate(ix, 8*sizeof(word))) {
/* XXXX Need to generate a %load/ar instruction. */
assert(0);
return res;
}
/* The index is constant, so we can return to direct
readout with the specific word selected. */
word = get_number_immediate(ix);
}
fprintf(vvp_out, " %%load/wr %d, v%p_%lu;\n", res, sig, word);
return res;
}
@@ -312,6 +339,18 @@ int draw_eval_real(ivl_expr_t exp)
/*
* $Log: eval_real.c,v $
* Revision 1.17 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.16 2006/10/10 23:54:28 steve
* Fix rendering of signed numbers in real expressions.
*
* Revision 1.15 2006/08/09 05:19:08 steve
* Add support for real valued modulus.
*
* Revision 1.14 2005/07/13 04:52:31 steve
* Handle functions with real values.
*
+51 -6
View File
@@ -16,7 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vector.c,v 1.7 2005/09/17 01:01:00 steve Exp $"
#ident "$Id: vector.c,v 1.10 2007/01/19 02:30:19 steve Exp $"
#endif
# include "vvp_priv.h"
@@ -32,6 +32,7 @@
static struct allocation_score_s {
ivl_expr_t exp;
ivl_signal_t sig;
unsigned sig_word;
unsigned exp_bit : 24;
unsigned sig_bit : 24;
unsigned alloc : 8;
@@ -56,9 +57,10 @@ static inline void set_exp(unsigned addr, ivl_expr_t exp, unsigned ebit)
allocation_map[addr].exp_bit = ebit;
}
static inline void set_sig(unsigned addr, ivl_signal_t exp, unsigned ebit)
static inline void set_sig(unsigned addr, ivl_signal_t exp, unsigned sig_word, unsigned ebit)
{
allocation_map[addr].sig = exp;
allocation_map[addr].sig_word = sig_word;
allocation_map[addr].sig_bit = ebit;
}
@@ -139,7 +141,7 @@ void clear_expression_lookaside(void)
for (idx = 0 ; idx < lookaside_top ; idx += 1) {
set_exp(idx, 0, 0);
set_sig(idx, 0, 0);
set_sig(idx, 0, 0, 0);
}
lookaside_top = 0;
@@ -157,14 +159,26 @@ void save_expression_lookaside(unsigned addr, ivl_expr_t exp, unsigned wid)
bits. */
for (idx = 0 ; idx < wid ; idx += 1) {
set_exp(addr+idx, exp, idx);
set_sig(addr+idx, 0, 0);
set_sig(addr+idx, 0, 0, 0);
}
if ((addr+wid) > lookaside_top)
lookaside_top = addr+wid;
}
void save_signal_lookaside(unsigned addr, ivl_signal_t sig, unsigned wid)
static void clear_signal_lookaside_bit(unsigned idx, ivl_signal_t sig, unsigned sig_word)
{
if (allocation_map[idx].alloc > 0)
return;
if (allocation_map[idx].sig != sig)
return;
if (allocation_map[idx].sig_word != sig_word)
return;
set_sig(idx, 0, 0, 0);
}
void save_signal_lookaside(unsigned addr, ivl_signal_t sig, unsigned sig_word, unsigned wid)
{
unsigned idx;
/* Don't bind any of hte low bits to a signal. */
@@ -173,11 +187,17 @@ void save_signal_lookaside(unsigned addr, ivl_signal_t sig, unsigned wid)
assert((addr+wid) <= MAX_VEC);
for (idx = 8 ; idx < addr ; idx += 1)
clear_signal_lookaside_bit(idx, sig, sig_word);
for (idx = 0 ; idx < wid ; idx += 1)
set_sig(addr+idx, sig, idx);
set_sig(addr+idx, sig, sig_word, idx);
if ((addr+wid) > lookaside_top)
lookaside_top = addr+wid;
for (idx = addr+wid ; idx < lookaside_top ; idx += 1)
clear_signal_lookaside_bit(idx, sig, sig_word);
}
static int compare_exp(ivl_expr_t l, ivl_expr_t r)
@@ -224,6 +244,10 @@ static int compare_exp(ivl_expr_t l, ivl_expr_t r)
if (ivl_expr_width(l) != ivl_expr_width(r))
return 0;
/* Don't match array words. */
if (ivl_expr_oper1(l) || ivl_expr_oper1(r))
return 0;
return 1;
default:
@@ -263,6 +287,9 @@ static unsigned find_expression_lookaside(ivl_expr_t exp, unsigned wid)
return idx-match+1;
}
/* The general expression lookup failed. If this is an
IVL_EX_SIGNAL, then look again in the variable lookaside
(which is saved l-values) for the expression. */
if (ivl_expr_type(exp) != IVL_EX_SIGNAL)
return 0;
@@ -290,6 +317,7 @@ static unsigned find_expression_lookaside(ivl_expr_t exp, unsigned wid)
match += 1;
if (match == wid)
return idx-match+1;
}
return 0;
@@ -306,8 +334,13 @@ unsigned allocate_vector_exp(ivl_expr_t exp, unsigned wid,
{
unsigned idx;
unsigned la = find_expression_lookaside(exp, wid);
if (la == 0)
return 0;
if (exclusive_flag) {
/* If the caller is requesting exclusive allocation of
the expression, then return not-found if a lookup
already matched the expression. */
for (idx = 0 ; idx < wid ; idx += 1)
if (allocation_map[la+idx].alloc)
return 0;
@@ -321,6 +354,18 @@ unsigned allocate_vector_exp(ivl_expr_t exp, unsigned wid,
/*
* $Log: vector.c,v $
* Revision 1.10 2007/01/19 02:30:19 steve
* Fix bad lookaside references in vvp thread code generator.
*
* Revision 1.9 2007/01/18 00:59:48 steve
* Do not match array words in expression lookaside.
*
* Revision 1.8 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.7 2005/09/17 01:01:00 steve
* More robust use of precalculated expressions, and
* Separate lookaside for written variables that can
+11 -10
View File
@@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvp_priv.h,v 1.40 2006/02/02 02:43:59 steve Exp $"
#ident "$Id: vvp_priv.h,v 1.42 2007/01/17 04:39:18 steve Exp $"
#endif
# include "vvp_config.h"
@@ -142,14 +142,6 @@ extern struct vector_info draw_eval_expr_wid(ivl_expr_t exp, unsigned w,
#define STUFF_OK_47 0x0002
#define STUFF_OK_RO 0x0004
/*
* This function draws code to evaluate the index expression exp for
* the memory mem. The result is loaded into index register i3, and
* the flag bit 4 is set to 0 if the numerical value is defined, or 1
* if not.
*/
extern void draw_memory_index_expr(ivl_memory_t mem, ivl_expr_t exp);
/*
* This evaluates an expression and leaves the result in the numbered
* integer index register. It also will set bit-4 to 1 if the value is
@@ -212,7 +204,7 @@ extern void save_expression_lookaside(unsigned addr,
ivl_expr_t exp,
unsigned wid);
extern void save_signal_lookaside(unsigned addr,
ivl_signal_t sig,
ivl_signal_t sig, unsigned use_word,
unsigned wid);
extern unsigned allocate_vector_exp(ivl_expr_t exp, unsigned wid,
@@ -252,6 +244,15 @@ extern unsigned thread_count;
/*
* $Log: vvp_priv.h,v $
* Revision 1.42 2007/01/17 04:39:18 steve
* Remove dead code related to memories.
*
* Revision 1.41 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.40 2006/02/02 02:43:59 steve
* Allow part selects of memory words in l-values.
*
+225 -134
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2005 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-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: vvp_process.c,v 1.122 2006/02/02 02:43:59 steve Exp $"
#ident "$Id: vvp_process.c,v 1.129 2007/01/19 02:30:19 steve Exp $"
#endif
# include "vvp_priv.h"
@@ -76,74 +76,115 @@ static void set_to_lvariable(ivl_lval_t lval,
{
ivl_signal_t sig = ivl_lval_sig(lval);
ivl_expr_t part_off_ex = ivl_lval_part_off(lval);
unsigned part_off;
unsigned part_off = 0;
/* Although Verilog doesn't support it, we'll handle
here the case of an l-value part select of an array
word if the address is constant. */
ivl_expr_t word_ix = ivl_lval_idx(lval);
unsigned long use_word = 0;
if (part_off_ex == 0) {
part_off = 0;
} else {
assert(number_is_immediate(part_off_ex, 64));
} else if (number_is_immediate(part_off_ex, 64)) {
part_off = get_number_immediate(part_off_ex);
part_off_ex = 0;
}
if (ivl_lval_mux(lval)) {
/* If the word index is a constand expression, then evaluate
it to select the word, and pay no further heed to the
expression itself. */
if (word_ix && number_is_immediate(word_ix, 8*sizeof(use_word))) {
use_word = get_number_immediate(word_ix);
word_ix = 0;
}
if (ivl_lval_mux(lval))
part_off_ex = ivl_lval_mux(lval);
if (part_off_ex) {
unsigned skip_set = transient_id++;
/* There is a mux expression, so this must be a write to
a bit-select leval. Presumably, the x0 index register
a bit-select l-val. Presumably, the x0 index register
has been loaded wit the result of the evaluated
ivl_lval_mux expression. */
part select base expression. */
assert(!word_ix);
draw_eval_expr_into_integer(ivl_lval_mux(lval), 0);
draw_eval_expr_into_integer(part_off_ex, 0);
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_set);
fprintf(vvp_out, " %%set/x0 V_%s, %u, %u;\n",
vvp_signal_label(sig), bit, wid);
fprintf(vvp_out, " %%set/x0 v%p_%lu, %u, %u;\n",
sig, use_word, bit, wid);
fprintf(vvp_out, "t_%u ;\n", skip_set);
/* save_signal width of 0 CLEARS the signal from the
lookaside. */
save_signal_lookaside(bit, sig, use_word, 0);
} else if (part_off>0 || ivl_lval_width(lval)!=ivl_signal_width(sig)) {
/* There is no mux expression, but a constant part
offset. Load that into index x0 and generate a
single-bit set instruction. */
vector set instruction. */
assert(ivl_lval_width(lval) == wid);
assert(!word_ix);
fprintf(vvp_out, " %%ix/load 0, %u;\n", part_off);
fprintf(vvp_out, " %%set/x0 V_%s, %u, %u;\n",
vvp_signal_label(sig), bit, wid);
fprintf(vvp_out, " %%set/x0 v%p_%lu, %u, %u;\n",
sig, use_word, bit, wid);
/* save_signal width of 0 CLEARS the signal from the
lookaside. */
save_signal_lookaside(bit, sig, use_word, 0);
} else if (ivl_signal_array_count(sig) > 1) {
/* If the word index is a constant, then we can write
directly to the word and save the index calculation. */
if (word_ix == 0) {
fprintf(vvp_out, " %%set/v v%p_%lu, %u, %u;\n",
sig, use_word, bit, wid);
} else {
unsigned skip_set = transient_id++;
unsigned index_reg = 3;
draw_eval_expr_into_integer(word_ix, index_reg);
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_set);
fprintf(vvp_out, " %%ix/load 1, 0;\n");
fprintf(vvp_out, " %%set/av v%p, %u, %u;\n",
sig, bit, wid);
fprintf(vvp_out, "t_%u ;\n", skip_set);
}
/* save_signal width of 0 CLEARS the signal from the
lookaside. */
save_signal_lookaside(bit, sig, use_word, 0);
} else {
save_signal_lookaside(bit, sig, wid);
fprintf(vvp_out, " %%set/v V_%s, %u, %u;\n",
vvp_signal_label(sig), bit, wid);
save_signal_lookaside(bit, sig, use_word, wid);
fprintf(vvp_out, " %%set/v v%p_%lu, %u, %u;\n",
sig, use_word, bit, wid);
}
}
/*
* This function writes the code to set a vector to a memory word. The
* idx is the thread register that contains the address of the word in
* the memory, and bit is the base of the thread vector. The wid is
* the width of the vector to be written to the word.
*/
static void set_to_memory_word(ivl_lval_t lval, unsigned idx,
unsigned bit, unsigned wid)
static void assign_to_array_word(ivl_signal_t lsig, ivl_expr_t word_ix,
unsigned bit, unsigned delay, unsigned width)
{
unsigned skip_set = transient_id++;
ivl_memory_t mem = ivl_lval_mem(lval);
unsigned skip_assign = transient_id++;
/* Calculate the word part select into index-1 */
if (ivl_lval_part_off(lval)) {
draw_eval_expr_into_integer(ivl_lval_part_off(lval), 1);
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_set);
} else {
fprintf(vvp_out, " %%ix/load 1, 0;\n");
}
/* Store expression width into index word 0 */
fprintf(vvp_out, " %%ix/load 0, %u;\n", width);
/* Store constant (0) word part select into index 1 */
fprintf(vvp_out, " %%ix/load 1, 0;\n");
/* Calculate array word index into index register 3 */
draw_eval_expr_into_integer(word_ix, 3);
/* Skip assignment if word expression is not defined. */
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_assign);
/* Calculate the memory address into index-3 */
draw_memory_index_expr(mem, ivl_lval_idx(lval));
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_set);
fprintf(vvp_out, " %%assign/av v%p, %u, %u;\n", lsig, delay, bit);
fprintf(vvp_out, "t_%u ;\n", skip_assign);
fprintf(vvp_out, " %%set/mv M_%p, %u, %u;\n", mem, bit, wid);
fprintf(vvp_out, "t_%u ;\n", skip_set);
clear_expression_lookaside();
}
static void assign_to_lvector(ivl_lval_t lval, unsigned bit,
@@ -152,25 +193,41 @@ static void assign_to_lvector(ivl_lval_t lval, unsigned bit,
{
ivl_signal_t sig = ivl_lval_sig(lval);
ivl_expr_t part_off_ex = ivl_lval_part_off(lval);
ivl_expr_t mux = ivl_lval_mux(lval);
unsigned part_off;
unsigned part_off = 0;
ivl_expr_t word_ix = ivl_lval_idx(lval);
unsigned long use_word = 0;
if (ivl_signal_array_count(sig) > 1) {
assert(word_ix);
if (! number_is_immediate(word_ix, 8*sizeof(use_word))) {
assert(!dexp);
assign_to_array_word(sig, word_ix, bit, delay, width);
return;
}
use_word = get_number_immediate(word_ix);
}
if (part_off_ex == 0) {
part_off = 0;
} else {
assert(number_is_immediate(part_off_ex, 64));
} else if (number_is_immediate(part_off_ex, 64)) {
part_off = get_number_immediate(part_off_ex);
part_off_ex = 0;
}
if (mux != 0) {
if (ivl_lval_mux(lval))
part_off_ex = ivl_lval_mux(lval);
if (part_off_ex) {
unsigned skip_assign = transient_id++;
assert(dexp == 0);
draw_eval_expr_into_integer(mux, 1);
draw_eval_expr_into_integer(part_off_ex, 1);
/* If the index expression has XZ bits, skip the assign. */
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_assign);
fprintf(vvp_out, " %%ix/load 0, %u;\n", width);
fprintf(vvp_out, " %%assign/v0/x1 V_%s, %u, %u;\n",
vvp_signal_label(sig), delay, bit);
fprintf(vvp_out, " %%assign/v0/x1 v%p_%lu, %u, %u;\n",
sig, use_word, delay, bit);
fprintf(vvp_out, "t_%u ;\n", skip_assign);
} else if (part_off>0 || ivl_lval_width(lval)!=ivl_signal_width(sig)) {
@@ -178,56 +235,37 @@ static void assign_to_lvector(ivl_lval_t lval, unsigned bit,
offset. Load that into index x1 and generate a
single-bit set instruction. */
assert(ivl_lval_width(lval) == width);
assert(dexp == 0);
fprintf(vvp_out, " %%ix/load 0, %u;\n", width);
fprintf(vvp_out, " %%ix/load 1, %u;\n", part_off);
fprintf(vvp_out, " %%assign/v0/x1 V_%s, %u, %u;\n",
vvp_signal_label(sig), delay, bit);
if (dexp == 0) {
/* Constant delay... */
fprintf(vvp_out, " %%ix/load 0, %u;\n", width);
fprintf(vvp_out, " %%ix/load 1, %u;\n", part_off);
fprintf(vvp_out, " %%assign/v0/x1 v%p_%lu, %u, %u;\n",
sig, use_word, delay, bit);
} else {
/* Calculated delay... */
int delay_index = allocate_word();
draw_eval_expr_into_integer(dexp, delay_index);
fprintf(vvp_out, " %%ix/load 0, %u;\n", width);
fprintf(vvp_out, " %%ix/load 1, %u;\n", part_off);
fprintf(vvp_out, " %%assign/v0/x1/d v%p_%lu, %u, %u;\n",
sig, use_word, delay_index, bit);
clr_word(delay_index);
}
} else if (dexp != 0) {
draw_eval_expr_into_integer(dexp, 1);
fprintf(vvp_out, " %%ix/load 0, %u;\n", width);
fprintf(vvp_out, " %%assign/v0/d V_%s, 1, %u;\n",
vvp_signal_label(sig), bit);
fprintf(vvp_out, " %%assign/v0/d v%p_%lu, 1, %u;\n",
sig, use_word, bit);
} else {
fprintf(vvp_out, " %%ix/load 0, %u;\n", width);
fprintf(vvp_out, " %%assign/v0 V_%s, %u, %u;\n",
vvp_signal_label(sig), delay, bit);
fprintf(vvp_out, " %%assign/v0 v%p_%lu, %u, %u;\n",
sig, use_word, delay, bit);
}
}
static void assign_to_memory_word(ivl_lval_t lval, unsigned bit,
unsigned delay, unsigned wid)
{
unsigned skip_set = transient_id++;
ivl_memory_t mem = ivl_lval_mem(lval);
//assert(wid == ivl_memory_width(mem));
/* Calculate the word part select into index-1 */
if (ivl_lval_part_off(lval)) {
draw_eval_expr_into_integer(ivl_lval_part_off(lval), 1);
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_set);
} else {
fprintf(vvp_out, " %%ix/load 1, 0;\n");
}
/* Calculate the memory address into index-3 */
draw_memory_index_expr(mem, ivl_lval_idx(lval));
fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_set);
/* Load the word/part-select width into index-0 */
fprintf(vvp_out, " %%ix/load 0, %u;\n", wid);
fprintf(vvp_out, " %%assign/mv M_%p, %u, %u;\n", mem, delay, bit);
fprintf(vvp_out, "t_%u ;\n", skip_set);
clear_expression_lookaside();
}
static void calculate_into_x1(ivl_expr_t expr)
{
draw_eval_expr_into_integer(expr, 1);
}
/*
* This is a private function to generate %set code for the
@@ -238,7 +276,6 @@ static void calculate_into_x1(ivl_expr_t expr)
static void set_vec_to_lval(ivl_statement_t net, struct vector_info res)
{
ivl_lval_t lval;
ivl_memory_t mem;
unsigned wid = res.wid;
unsigned lidx;
@@ -250,8 +287,6 @@ static void set_vec_to_lval(ivl_statement_t net, struct vector_info res)
lval = ivl_stmt_lval(net, lidx);
mem = ivl_lval_mem(lval);
/* Reduce bit_limit to the width of this l-value. */
if (bit_limit > ivl_lval_width(lval))
bit_limit = ivl_lval_width(lval);
@@ -260,12 +295,7 @@ static void set_vec_to_lval(ivl_statement_t net, struct vector_info res)
bit that this l-value takes. */
bidx = res.base < 4? res.base : (res.base+cur_rbit);
if (mem) {
set_to_memory_word(lval, 3, bidx, bit_limit);
} else {
set_to_lvariable(lval, bidx, bit_limit);
}
set_to_lvariable(lval, bidx, bit_limit);
/* Now we've consumed this many r-value bits for the
current l-value. */
@@ -333,8 +363,9 @@ static int show_stmt_assign_sig_real(ivl_statement_t net)
var = ivl_lval_sig(lval);
assert(var != 0);
fprintf(vvp_out, " %%set/wr V_%s, %d;\n",
vvp_signal_label(var), res);
assert(ivl_signal_array_count(var) == 1);
fprintf(vvp_out, " %%set/wr v%p_0, %d;\n", var, res);
return 0;
}
@@ -378,13 +409,27 @@ static int show_stmt_assign_nb_real(ivl_statement_t net)
ivl_signal_t sig;
ivl_expr_t rval = ivl_stmt_rval(net);
ivl_expr_t del = ivl_stmt_delay_expr(net);
/* variables for the selection of word from an array. */
ivl_expr_t word_ix;
unsigned long use_word = 0;
/* thread address for a word value. */
int word;
unsigned long delay;
/* Must be exactly 1 l-value. */
assert(ivl_stmt_lvals(net) == 1);
lval = ivl_stmt_lval(net, 0);
sig = ivl_lval_sig(lval);
assert(sig);
if (ivl_signal_array_count(sig) > 1) {
word_ix = ivl_lval_idx(lval);
assert(word_ix);
assert(number_is_immediate(word_ix, 8*sizeof(use_word)));
use_word = get_number_immediate(word_ix);
}
delay = 0;
if (del && (ivl_expr_type(del) == IVL_EX_ULONG)) {
delay = ivl_expr_uvalue(del);
@@ -397,11 +442,8 @@ static int show_stmt_assign_nb_real(ivl_statement_t net)
/* Evaluate the r-value */
word = draw_eval_real(rval);
lval = ivl_stmt_lval(net, 0);
sig = ivl_lval_sig(lval);
assert(sig);
fprintf(vvp_out, " %%assign/wr V_%s, %lu, %u;\n",
vvp_signal_label(sig), delay, word);
fprintf(vvp_out, " %%assign/wr v%p_%lu, %lu, %u;\n",
sig, use_word, delay, word);
clr_word(word);
@@ -413,7 +455,6 @@ static int show_stmt_assign_nb(ivl_statement_t net)
ivl_lval_t lval;
ivl_expr_t rval = ivl_stmt_rval(net);
ivl_expr_t del = ivl_stmt_delay_expr(net);
ivl_memory_t mem;
ivl_signal_t sig;
unsigned long delay = 0;
@@ -440,34 +481,17 @@ static int show_stmt_assign_nb(ivl_statement_t net)
unsigned lidx;
unsigned cur_rbit = 0;
if (del != 0)
calculate_into_x1(del);
for (lidx = 0 ; lidx < ivl_stmt_lvals(net) ; lidx += 1) {
unsigned bit_limit = wid - cur_rbit;
lval = ivl_stmt_lval(net, lidx);
mem = ivl_lval_mem(lval);
if (bit_limit > ivl_lval_width(lval))
bit_limit = ivl_lval_width(lval);
if (mem == 0) {
unsigned bidx;
unsigned bidx;
bidx = res.base < 4? res.base : (res.base+cur_rbit);
assign_to_lvector(lval, bidx, delay, del, bit_limit);
} else {
unsigned bidx;
/* XXXX don't yet know what to do with a
non-constant delay exprssion. */
assert(del == 0);
bidx = res.base < 4? res.base : (res.base+cur_rbit);
assign_to_memory_word(lval, bidx, delay, bit_limit);
}
bidx = res.base < 4? res.base : (res.base+cur_rbit);
assign_to_lvector(lval, bidx, delay, del, bit_limit);
cur_rbit += bit_limit;
@@ -741,6 +765,8 @@ static void force_vector_to_lval(ivl_statement_t net, struct vector_info rvec)
unsigned use_wid = ivl_lval_width(lval);
ivl_expr_t part_off_ex = ivl_lval_part_off(lval);
unsigned part_off;
ivl_expr_t word_idx = ivl_lval_idx(lval);
unsigned long use_word = 0;
if (part_off_ex == 0) {
part_off = 0;
@@ -749,6 +775,11 @@ static void force_vector_to_lval(ivl_statement_t net, struct vector_info rvec)
part_off = get_number_immediate(part_off_ex);
}
if (word_idx != 0) {
assert(number_is_immediate(word_idx, 8*sizeof(unsigned long)));
use_word = get_number_immediate(word_idx);
}
/* L-Value must be a signal: reg or wire */
assert(lsig != 0);
@@ -766,8 +797,8 @@ static void force_vector_to_lval(ivl_statement_t net, struct vector_info rvec)
assert((roff + use_wid) <= rvec.wid);
}
fprintf(vvp_out, " %s V_%s, %u, %u;\n", command_name,
vvp_signal_label(lsig), rvec.base+roff, use_wid);
fprintf(vvp_out, " %s v%p_%lu, %u, %u;\n", command_name,
lsig, use_word, rvec.base+roff, use_wid);
if (rvec.base >= 4)
roff += use_wid;
@@ -781,6 +812,9 @@ static void force_link_rval(ivl_statement_t net, ivl_expr_t rval)
ivl_signal_t lsig;
const char*command_name;
ivl_expr_t lword_idx, rword_idx;
unsigned long use_lword = 0, use_rword = 0;
if (ivl_expr_type(rval) != IVL_EX_SIGNAL)
return;
@@ -802,9 +836,23 @@ static void force_link_rval(ivl_statement_t net, ivl_expr_t rval)
lval = ivl_stmt_lval(net, 0);
lsig = ivl_lval_sig(lval);
/* At least for now, only handle force to fixed words of an array. */
if ((lword_idx = ivl_lval_idx(lval)) != 0) {
assert(number_is_immediate(lword_idx, 8*sizeof(unsigned long)));
use_lword = get_number_immediate(lword_idx);
}
if ((rword_idx = ivl_expr_oper1(rval)) != 0) {
assert(number_is_immediate(rword_idx, 8*sizeof(unsigned long)));
use_rword = get_number_immediate(rword_idx);
}
assert(ivl_signal_array_count(rsig) == 1);
use_rword = 0;
fprintf(vvp_out, " %s/link", command_name);
fprintf(vvp_out, " V_%s", vvp_signal_label(lsig));
fprintf(vvp_out, ", V_%s;\n", vvp_signal_label(rsig));
fprintf(vvp_out, " v%p_%lu", lsig, use_lword);
fprintf(vvp_out, ", v%p_%lu;\n", rsig, use_rword);
}
static int show_stmt_cassign(ivl_statement_t net)
@@ -839,11 +887,20 @@ static int show_stmt_deassign(ivl_statement_t net)
ivl_lval_t lval = ivl_stmt_lval(net, lidx);
ivl_signal_t lsig = ivl_lval_sig(lval);
ivl_expr_t word_idx = ivl_lval_idx(lval);
unsigned long use_word = 0;
assert(lsig != 0);
assert(ivl_lval_mux(lval) == 0);
assert(ivl_lval_part_off(lval) == 0);
fprintf(vvp_out, " %%deassign V_%s;\n", vvp_signal_label(lsig));
if (word_idx != 0) {
assert(number_is_immediate(word_idx, 8*sizeof(use_word)));
use_word = get_number_immediate(word_idx);
}
fprintf(vvp_out, " %%deassign v%p_%lu;\n", lsig, use_word);
}
return 0;
@@ -902,10 +959,13 @@ static int show_stmt_condit(ivl_statement_t net, ivl_scope_t sscope)
static int show_stmt_delay(ivl_statement_t net, ivl_scope_t sscope)
{
int rc = 0;
unsigned long delay = ivl_stmt_delay_val(net);
uint64_t delay = ivl_stmt_delay_val(net);
ivl_statement_t stmt = ivl_stmt_sub_stmt(net);
fprintf(vvp_out, " %%delay %lu;\n", delay);
unsigned long low = delay % UINT64_C(0x100000000);
unsigned long hig = delay / UINT64_C(0x100000000);
fprintf(vvp_out, " %%delay %lu, %lu;\n", low, hig);
/* Lots of things can happen during a delay. */
clear_expression_lookaside();
@@ -1074,6 +1134,8 @@ static int show_stmt_release(ivl_statement_t net)
ivl_signal_t lsig = ivl_lval_sig(lval);
const char*opcode = 0;
ivl_expr_t word_idx = ivl_lval_idx(lval);
unsigned long use_word = 0;
assert(lsig != 0);
assert(ivl_lval_mux(lval) == 0);
assert(ivl_lval_part_off(lval) == 0);
@@ -1087,10 +1149,15 @@ static int show_stmt_release(ivl_statement_t net)
break;
}
if (word_idx != 0) {
assert(number_is_immediate(word_idx, 8*sizeof(use_word)));
use_word = get_number_immediate(word_idx);
}
/* Generate the appropriate release statement for this
l-value. */
fprintf(vvp_out, " %%release/%s V_%s;\n",
opcode, vvp_signal_label(lsig));
fprintf(vvp_out, " %%release/%s v%p_%lu;\n",
opcode, lsig, use_word);
}
return 0;
@@ -1479,6 +1546,30 @@ int draw_func_definition(ivl_scope_t scope)
/*
* $Log: vvp_process.c,v $
* Revision 1.129 2007/01/19 02:30:19 steve
* Fix bad lookaside references in vvp thread code generator.
*
* Revision 1.128 2007/01/17 04:39:18 steve
* Remove dead code related to memories.
*
* Revision 1.127 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.126 2006/10/05 01:37:34 steve
* Remove dead code.
*
* Revision 1.125 2006/10/05 01:23:53 steve
* Handle non-constant delays on indexed non-blocking assignments.
*
* Revision 1.124 2006/08/08 05:11:37 steve
* Handle 64bit delay constants.
*
* Revision 1.123 2006/04/16 00:15:43 steve
* Fix part selects in l-values.
*
* Revision 1.122 2006/02/02 02:43:59 steve
* Allow part selects of memory words in l-values.
*
+302 -125
View File
@@ -17,16 +17,17 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: vvp_scope.c,v 1.143 2006/04/10 00:37:42 steve Exp $"
#ident "$Id: vvp_scope.c,v 1.152 2007/01/17 04:39:18 steve Exp $"
#endif
# include "vvp_priv.h"
# include <assert.h>
#ifdef HAVE_MALLOC_H
# include <malloc.h>
#endif
# include <stdlib.h>
# include <string.h>
# include <inttypes.h>
# include <assert.h>
struct vvp_nexus_data {
/* draw_net_input uses this */
@@ -38,6 +39,7 @@ struct vvp_nexus_data {
};
#define VVP_NEXUS_DATA_STR 0x0001
static struct vvp_nexus_data*new_nexus_data()
{
struct vvp_nexus_data*data = calloc(1, sizeof(struct vvp_nexus_data));
@@ -176,7 +178,7 @@ const char* vvp_signal_label(ivl_signal_t sig)
return buf;
}
ivl_signal_t signal_of_nexus(ivl_nexus_t nex)
ivl_signal_t signal_of_nexus(ivl_nexus_t nex, unsigned*word)
{
unsigned idx;
for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) {
@@ -186,9 +188,8 @@ ivl_signal_t signal_of_nexus(ivl_nexus_t nex)
continue;
if (ivl_signal_local(sig))
continue;
*word = ivl_nexus_ptr_pin(ptr);
return sig;
}
return 0;
@@ -376,6 +377,28 @@ static int can_elide_bufz(ivl_net_logic_t net, ivl_nexus_ptr_t nptr)
return 1;
}
/*
* Given a nexus, look for a signal that has module delay
* paths. Return that signal. (There should be no more then 1.) If we
* don't find any, then return nil.
*/
static ivl_signal_t find_modpath(ivl_nexus_t nex)
{
unsigned idx;
for (idx = 0 ; idx < ivl_nexus_ptrs(nex) ; idx += 1) {
ivl_nexus_ptr_t ptr = ivl_nexus_ptr(nex,idx);
ivl_signal_t sig = ivl_nexus_ptr_sig(ptr);
if (sig == 0)
continue;
if (ivl_signal_npath(sig) == 0)
continue;
return sig;
}
return 0;
}
static void draw_C4_to_string(char*result, size_t nresult,
ivl_net_const_t cptr)
{
@@ -551,11 +574,9 @@ static const char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
sptr = ivl_nexus_ptr_sig(nptr);
if (sptr && (ivl_signal_type(sptr) == IVL_SIT_REG)) {
/* Input is a .var. Note that these devices have only
exactly one pin (that carries a vector) so nptr_pin
must be 0. */
assert(nptr_pin == 0);
sprintf(result, "V_%s", vvp_signal_label(sptr));
/* Input is a .var. This device may be a non-zero pin
because it may be an array of reg vectors. */
snprintf(result, sizeof result, "v%p_%u", sptr, nptr_pin);
return result;
}
@@ -596,8 +617,8 @@ static const char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
if (lpm) switch (ivl_lpm_type(lpm)) {
case IVL_LPM_FF:
case IVL_LPM_RAM:
case IVL_LPM_ADD:
case IVL_LPM_ARRAY:
case IVL_LPM_CONCAT:
case IVL_LPM_CMP_EEQ:
case IVL_LPM_CMP_EQ:
@@ -611,6 +632,7 @@ static const char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
case IVL_LPM_RE_NAND:
case IVL_LPM_RE_NOR:
case IVL_LPM_RE_XNOR:
case IVL_LPM_SFUNC:
case IVL_LPM_SHIFTL:
case IVL_LPM_SHIFTR:
case IVL_LPM_SIGN_EXT:
@@ -646,6 +668,49 @@ static const char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr)
return "C<z>";
}
static void draw_modpath(const char*label, const char*driver,
ivl_signal_t path_sig)
{
unsigned idx;
typedef const char*ccharp;
ccharp*src_drivers;
src_drivers = calloc(ivl_signal_npath(path_sig), sizeof(ccharp));
for (idx = 0 ; idx < ivl_signal_npath(path_sig) ; idx += 1) {
ivl_delaypath_t path = ivl_signal_path(path_sig, idx);
ivl_nexus_t src = ivl_path_source(path);
src_drivers[idx] = draw_net_input(src);
}
fprintf(vvp_out, "%s .modpath %s", label, driver);
for (idx = 0 ; idx < ivl_signal_npath(path_sig); idx += 1) {
ivl_delaypath_t path = ivl_signal_path(path_sig, idx);
fprintf(vvp_out, ",\n %s", src_drivers[idx]);
fprintf(vvp_out,
" (%"PRIu64",%"PRIu64",%"PRIu64
", %"PRIu64",%"PRIu64",%"PRIu64
", %"PRIu64",%"PRIu64",%"PRIu64
", %"PRIu64",%"PRIu64",%"PRIu64")",
ivl_path_delay(path, IVL_PE_01),
ivl_path_delay(path, IVL_PE_10),
ivl_path_delay(path, IVL_PE_0z),
ivl_path_delay(path, IVL_PE_z1),
ivl_path_delay(path, IVL_PE_1z),
ivl_path_delay(path, IVL_PE_z0),
ivl_path_delay(path, IVL_PE_0x),
ivl_path_delay(path, IVL_PE_x1),
ivl_path_delay(path, IVL_PE_1x),
ivl_path_delay(path, IVL_PE_x0),
ivl_path_delay(path, IVL_PE_xz),
ivl_path_delay(path, IVL_PE_zx));
}
fprintf(vvp_out, ";\n");
free(src_drivers);
}
/*
* This function draws the input to a net into a string. What that
* means is that it returns a static string that can be used to
@@ -785,7 +850,18 @@ static char* draw_net_input_x(ivl_nexus_t nex,
it. Note that this will *not* work if the nexus is not a
TRI type nexus. */
if (ndrivers == 1 && res == IVL_SIT_TRI) {
nex_private = strdup(draw_net_input_drive(nex, drivers[0]));
ivl_signal_t path_sig = find_modpath(nex);
if (path_sig) {
char*nex_str = strdup(draw_net_input_drive(nex, drivers[0]));
char modpath_label[64];
snprintf(modpath_label, sizeof modpath_label,
"V_%p/m", path_sig);
draw_modpath(modpath_label, nex_str, path_sig);
nex_private = strdup(modpath_label);
free(nex_str);
} else {
nex_private = strdup(draw_net_input_drive(nex, drivers[0]));
}
return nex_private;
}
@@ -857,12 +933,13 @@ const char*draw_net_input(ivl_nexus_t nex)
const char*draw_input_from_net(ivl_nexus_t nex)
{
static char result[32];
unsigned word;
ivl_signal_t sig = signal_of_nexus(nex);
ivl_signal_t sig = signal_of_nexus(nex, &word);
if (sig == 0)
return draw_net_input(nex);
snprintf(result, sizeof result, "V_%p", sig);
snprintf(result, sizeof result, "v%p_%u", sig, word);
return result;
}
@@ -870,7 +947,8 @@ const char*draw_input_from_net(ivl_nexus_t nex)
/*
* This function draws a reg/int/variable in the scope. This is a very
* simple device to draw as there are no inputs to connect so no need
* to scan the nexus.
* to scan the nexus. We do have to account for the possibility that
* the device is arrayed, though, by making a node for each array element.
*/
static void draw_reg_in_scope(ivl_signal_t sig)
{
@@ -888,11 +966,32 @@ static void draw_reg_in_scope(ivl_signal_t sig)
break;
}
fprintf(vvp_out, "V_%s .var%s \"%s\", %d, %d;\n",
vvp_signal_label(sig), datatype_flag,
vvp_mangle_name(ivl_signal_basename(sig)), msb, lsb);
/* If the reg objects are collected into an array, then first
write out the .array record to declare the array indices. */
if (ivl_signal_array_count(sig) > 1) {
unsigned word_count = ivl_signal_array_count(sig);
unsigned iword;
int last = ivl_signal_array_base(sig)+ivl_signal_array_count(sig)-1;
int first = ivl_signal_array_base(sig);
fprintf(vvp_out, "v%p .array \"%s\", %d %d;\n",
sig, vvp_mangle_name(ivl_signal_basename(sig)),
last, first);
/* Scan the words of the array... */
for (iword = 0 ; iword < word_count ; iword += 1) {
fprintf(vvp_out, "v%p_%u .var%s v%p, %d %d;\n",
sig, iword, datatype_flag, sig, msb, lsb);
}
} else {
fprintf(vvp_out, "v%p_0 .var%s \"%s\", %d %d;\n",
sig, datatype_flag,
vvp_mangle_name(ivl_signal_basename(sig)), msb, lsb);
}
}
/*
* This function draws a net. This is a bit more complicated as we
* have to find an appropriate functor to connect to the input.
@@ -901,26 +1000,14 @@ static void draw_net_in_scope(ivl_signal_t sig)
{
int msb = ivl_signal_msb(sig);
int lsb = ivl_signal_lsb(sig);
typedef const char*const_charp;
const char* arg;
const char*datatype_flag = ivl_signal_signed(sig)? "/s" : "";
struct vvp_nexus_data*nex_data;
unsigned iword;
/* Skip the local signal. */
if (ivl_signal_local(sig))
return;
/* Connect the pin of the signal to something. */
{
ivl_nexus_t nex = ivl_signal_nex(sig);
arg = draw_net_input(nex);
nex_data = (struct vvp_nexus_data*)ivl_nexus_get_private(nex);
assert(nex_data);
}
switch (ivl_signal_data_type(sig)) {
case IVL_VT_REAL:
datatype_flag = "/real";
@@ -929,29 +1016,70 @@ static void draw_net_in_scope(ivl_signal_t sig)
break;
}
if (nex_data->net == 0) {
const char*vec8 = "";
if (nex_data->drivers_count > 1)
vec8 = "8";
if (nex_data->flags & VVP_NEXUS_DATA_STR)
vec8 = "8";
for (iword = 0 ; iword < ivl_signal_array_count(sig); iword += 1) {
fprintf(vvp_out, "V_%p .net%s%s \"%s\", %d, %d, %s;"
" %u drivers%s\n",
sig, vec8, datatype_flag,
vvp_mangle_name(ivl_signal_basename(sig)),
msb, lsb, arg,
nex_data->drivers_count,
nex_data->flags&VVP_NEXUS_DATA_STR?", strength-aware":"");
nex_data->net = sig;
} else {
/* Detect that this is an alias of nex_data->net. Create
a different kind of node that refers to the alias
source data instead of holding our own data. */
fprintf(vvp_out, "V_%p .alias%s \"%s\", %d, %d, V_%p;\n",
sig, datatype_flag,
vvp_mangle_name(ivl_signal_basename(sig)),
msb, lsb, nex_data->net);
unsigned word_count = ivl_signal_array_count(sig);
struct vvp_nexus_data*nex_data;
/* Connect the pin of the signal to something. */
ivl_nexus_t nex = ivl_signal_nex(sig, iword);
const char*driver = draw_net_input(nex);
nex_data = (struct vvp_nexus_data*)ivl_nexus_get_private(nex);
assert(nex_data);
if (nex_data->net == 0) {
int strength_aware_flag = 0;
const char*vec8 = "";
if (nex_data->flags&VVP_NEXUS_DATA_STR)
strength_aware_flag = 1;
if (nex_data->drivers_count > 1)
vec8 = "8";
if (strength_aware_flag)
vec8 = "8";
if (iword == 0 && word_count > 1) {
int last = ivl_signal_array_base(sig) + word_count-1;
int first = ivl_signal_array_base(sig);
fprintf(vvp_out, "v%p .array \"%s\", %d %d;\n",
sig, vvp_mangle_name(ivl_signal_basename(sig)),
last, first);
}
if (word_count > 1) {
/* If this is a word of an array, then use an
array reference in place of the net name. */
fprintf(vvp_out, "v%p_%u .net%s%s v%p, %d %d, %s;"
" %u drivers%s\n",
sig, iword, vec8, datatype_flag, sig,
msb, lsb, driver,
nex_data->drivers_count,
strength_aware_flag?", strength-aware":"");
} else {
/* If this is an isolated word, it uses its
own name. */
fprintf(vvp_out, "v%p_%u .net%s%s \"%s\", %d %d, %s;"
" %u drivers%s\n",
sig, iword, vec8, datatype_flag,
vvp_mangle_name(ivl_signal_basename(sig)),
msb, lsb, driver,
nex_data->drivers_count,
strength_aware_flag?", strength-aware":"");
}
nex_data->net = sig;
} else {
assert(word_count == 1);
assert(ivl_signal_array_count(nex_data->net) == 1);
/* Detect that this is an alias of nex_data->net. Create
a different kind of node that refers to the alias
source data instead of holding our own data. */
fprintf(vvp_out, "v%p_0 .alias%s \"%s\", %d %d, v%p_0;\n",
sig, datatype_flag,
vvp_mangle_name(ivl_signal_basename(sig)),
msb, lsb, nex_data->net);
}
}
}
@@ -1290,13 +1418,16 @@ static void draw_logic_in_scope(ivl_net_logic_t lptr)
fprintf(vvp_out, "L_%p .delay L_%p/d", lptr, lptr);
sig = ivl_expr_signal(rise_exp);
fprintf(vvp_out, ", V_%p", sig);
assert(ivl_signal_array_count(sig) == 1);
fprintf(vvp_out, ", v%p_0", sig);
sig = ivl_expr_signal(fall_exp);
fprintf(vvp_out, ", V_%p", sig);
assert(ivl_signal_array_count(sig) == 1);
fprintf(vvp_out, ", v%p_0", sig);
sig = ivl_expr_signal(decay_exp);
fprintf(vvp_out, ", V_%p;\n", sig);
assert(ivl_signal_array_count(sig) == 1);
fprintf(vvp_out, ", v%p_0;\n", sig);
}
}
}
@@ -1341,7 +1472,7 @@ static void draw_event_in_scope(ivl_event_t obj)
top = nany;
for (sub = idx ; sub < top ; sub += 1) {
ivl_nexus_t nex = ivl_event_any(obj, sub);
fprintf(vvp_out, ", %s", draw_net_input(nex));
fprintf(vvp_out, ", %s", draw_input_from_net(nex));
}
fprintf(vvp_out, ";\n");
}
@@ -1356,7 +1487,7 @@ static void draw_event_in_scope(ivl_event_t obj)
top = nneg;
for (sub = idx ; sub < top ; sub += 1) {
ivl_nexus_t nex = ivl_event_neg(obj, sub);
fprintf(vvp_out, ", %s", draw_net_input(nex));
fprintf(vvp_out, ", %s", draw_input_from_net(nex));
}
fprintf(vvp_out, ";\n");
}
@@ -1371,7 +1502,7 @@ static void draw_event_in_scope(ivl_event_t obj)
top = npos;
for (sub = idx ; sub < top ; sub += 1) {
ivl_nexus_t nex = ivl_event_pos(obj, sub);
fprintf(vvp_out, ", %s", draw_net_input(nex));
fprintf(vvp_out, ", %s", draw_input_from_net(nex));
}
fprintf(vvp_out, ";\n");
}
@@ -1389,9 +1520,11 @@ static void draw_event_in_scope(ivl_event_t obj)
} else {
unsigned num_input_strings = nany + nneg + npos;
unsigned idx;
const char* input_strings[4];
ivl_nexus_t input_nexa[4];
const char*edge = 0;
assert(num_input_strings <= 4);
if (nany > 0) {
assert((nneg + npos) == 0);
assert(nany <= 4);
@@ -1400,7 +1533,7 @@ static void draw_event_in_scope(ivl_event_t obj)
for (idx = 0 ; idx < nany ; idx += 1) {
ivl_nexus_t nex = ivl_event_any(obj, idx);
input_strings[idx] = draw_net_input(nex);
input_nexa[idx] = nex;
}
} else if (nneg > 0) {
@@ -1409,7 +1542,7 @@ static void draw_event_in_scope(ivl_event_t obj)
for (idx = 0 ; idx < nneg ; idx += 1) {
ivl_nexus_t nex = ivl_event_neg(obj, idx);
input_strings[idx] = draw_net_input(nex);
input_nexa[idx] = nex;
}
} else {
@@ -1418,50 +1551,18 @@ static void draw_event_in_scope(ivl_event_t obj)
for (idx = 0 ; idx < npos ; idx += 1) {
ivl_nexus_t nex = ivl_event_pos(obj, idx);
input_strings[idx] = draw_net_input(nex);
input_nexa[idx] = nex;
}
}
fprintf(vvp_out, "E_%p .event %s", obj, edge);
for (idx = 0 ; idx < num_input_strings ; idx += 1)
fprintf(vvp_out, ", %s", input_strings[idx]);
fprintf(vvp_out, ", %s", draw_input_from_net(input_nexa[idx]));
fprintf(vvp_out, ";\n");
}
}
static void draw_lpm_ram(ivl_lpm_t net)
{
ivl_memory_t mem = ivl_lpm_memory(net);
ivl_nexus_t clk = ivl_lpm_clk(net);
ivl_nexus_t pin;
if (clk) {
fprintf(vvp_out, "CLK_%p .event posedge, %s;\n",
net, draw_net_input(clk));
}
fprintf(vvp_out, "L_%p .mem/port M_%p, ", net, mem);
pin = ivl_lpm_select(net);
fprintf(vvp_out, "%s", draw_net_input(pin));
if (clk) {
fprintf(vvp_out, ", CLK_%p, ", net);
pin = ivl_lpm_enable(net);
if (pin)
fprintf(vvp_out, "%s", draw_net_input(pin));
else
fprintf(vvp_out, "C4<1>");
pin = ivl_lpm_data(net, 0);
fprintf(vvp_out, ", %s", draw_net_input(pin));
}
fprintf(vvp_out, ";\n");
}
/*
* This function draws any functors needed to calculate the input to
* this nexus, and leaves in the data array strings that can be used
@@ -1526,6 +1627,23 @@ static void draw_lpm_add(ivl_lpm_t net)
net, type, width, src_table[0], src_table[1]);
}
/*
* The read port to an array is generated as a single record that takes
* the address as an input.
*/
static void draw_lpm_array(ivl_lpm_t net)
{
ivl_nexus_t nex;
ivl_signal_t mem = ivl_lpm_array(net);
fprintf(vvp_out, "L_%p .array/port v%p, ", net, mem);
nex = ivl_lpm_select(net);
fprintf(vvp_out, "%s", draw_net_input(nex));
fprintf(vvp_out, ";\n");
}
static void draw_lpm_cmp(ivl_lpm_t net)
{
const char*src_table[2];
@@ -1621,7 +1739,7 @@ static void draw_lpm_concat(ivl_lpm_t net)
unsigned icnt = ivl_lpm_selects(net);
if (icnt <= 4) {
/* This is the easies case. There are 4 or fewer input
/* This is the easiest case. There are 4 or fewer input
vectors, so the entire IVL_LPM_CONCAT can be
implemented with a single .concat node. */
draw_lpm_data_inputs(net, 0, icnt, src_table);
@@ -1660,6 +1778,10 @@ static void draw_lpm_concat(ivl_lpm_t net)
tree[idx/4].wid = wid;
}
/* icnt is the input count for the level. It is the
number of .concats of the previous level that have to
be concatenated at the current level. (This is not
the same as the bit width.) */
icnt = (icnt + 3)/4;
/* Tree now has icnt nodes that are depth=0 concat nodes
@@ -1682,8 +1804,8 @@ static void draw_lpm_concat(ivl_lpm_t net)
net, depth, idx);
for (tdx = 0 ; tdx < trans ; tdx += 1) {
fprintf(vvp_out, " %u", tree[idx].wid);
wid += tree[idx].wid;
fprintf(vvp_out, " %u", tree[idx+tdx].wid);
wid += tree[idx+tdx].wid;
}
for ( ; tdx < 4 ; tdx += 1)
@@ -1783,10 +1905,10 @@ static void draw_lpm_ff(ivl_lpm_t net)
static void draw_lpm_shiftl(ivl_lpm_t net)
{
unsigned width = ivl_lpm_width(net);
const char* signed_flag = ivl_lpm_signed(net)? "s" : "";
if (ivl_lpm_type(net) == IVL_LPM_SHIFTR)
fprintf(vvp_out, "L_%p .shift/r %u", net, width);
fprintf(vvp_out, "L_%p .shift/r%s %u", net, signed_flag, width);
else
fprintf(vvp_out, "L_%p .shift/l %u", net, width);
@@ -1797,6 +1919,43 @@ static void draw_lpm_shiftl(ivl_lpm_t net)
fprintf(vvp_out, ";\n");
}
static void draw_type_string_of_nex(ivl_nexus_t nex)
{
switch (data_type_of_nexus(nex)) {
case IVL_VT_REAL:
fprintf(vvp_out, "r");
break;
case IVL_VT_LOGIC:
fprintf(vvp_out, "v%d", width_of_nexus(nex));
break;
default:
assert(0);
break;
}
}
static void draw_lpm_sfunc(ivl_lpm_t net)
{
unsigned idx;
fprintf(vvp_out, "L_%p .sfunc \"%s\"", net, ivl_lpm_string(net));
/* Print the function type descriptor string. */
fprintf(vvp_out, ", \"");
draw_type_string_of_nex(ivl_lpm_q(net,0));
for (idx = 0 ; idx < ivl_lpm_size(net) ; idx += 1)
draw_type_string_of_nex(ivl_lpm_data(net,idx));
fprintf(vvp_out, "\"");
for (idx = 0 ; idx < ivl_lpm_size(net) ; idx += 1) {
fprintf(vvp_out, ", %s", draw_net_input(ivl_lpm_data(net,idx)));
}
fprintf(vvp_out, ";\n");
}
static void draw_lpm_ufunc(ivl_lpm_t net)
{
unsigned idx;
@@ -1825,7 +1984,8 @@ static void draw_lpm_ufunc(ivl_lpm_t net)
else
fprintf(vvp_out, ", ");
fprintf(vvp_out, "V_%s", vvp_signal_label(psig));
assert(ivl_signal_array_count(psig) == 1);
fprintf(vvp_out, "v%p_0", psig);
}
fprintf(vvp_out, ")");
@@ -1834,8 +1994,9 @@ static void draw_lpm_ufunc(ivl_lpm_t net)
result is collected. */
{ ivl_signal_t psig = ivl_scope_port(def, 0);
assert(ivl_lpm_width(net) == ivl_signal_width(psig));
assert(ivl_signal_array_count(psig) == 1);
fprintf(vvp_out, " V_%s", vvp_signal_label(psig));
fprintf(vvp_out, " v%p_0", psig);
}
fprintf(vvp_out, ";\n");
@@ -1997,10 +2158,6 @@ static void draw_lpm_in_scope(ivl_lpm_t net)
{
switch (ivl_lpm_type(net)) {
case IVL_LPM_RAM:
draw_lpm_ram(net);
return;
case IVL_LPM_ADD:
case IVL_LPM_SUB:
case IVL_LPM_MULT:
@@ -2009,6 +2166,10 @@ static void draw_lpm_in_scope(ivl_lpm_t net)
draw_lpm_add(net);
return;
case IVL_LPM_ARRAY:
draw_lpm_array(net);
return;
case IVL_LPM_PART_BI:
draw_lpm_part_bi(net);
return;
@@ -2074,6 +2235,10 @@ static void draw_lpm_in_scope(ivl_lpm_t net)
draw_lpm_sign_ext(net);
return;
case IVL_LPM_SFUNC:
draw_lpm_sfunc(net);
return;
case IVL_LPM_UFUNC:
draw_lpm_ufunc(net);
return;
@@ -2084,19 +2249,6 @@ static void draw_lpm_in_scope(ivl_lpm_t net)
}
}
static void draw_mem_in_scope(ivl_memory_t net)
{
int root = ivl_memory_root(net);
int last = root + ivl_memory_size(net) - 1;
int msb = ivl_memory_width(net) - 1;
int lsb = 0;
fprintf(vvp_out, "M_%p .mem \"%s\", %u,%u, %u,%u;\n", net,
vvp_mangle_name(ivl_memory_basename(net)),
msb, lsb, root, last);
}
int draw_scope(ivl_scope_t net, ivl_scope_t parent)
{
unsigned idx;
@@ -2183,11 +2335,6 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent)
draw_event_in_scope(event);
}
for (idx = 0 ; idx < ivl_scope_mems(net) ; idx += 1) {
ivl_memory_t mem = ivl_scope_mem(net, idx);
draw_mem_in_scope(mem);
}
for (idx = 0 ; idx < ivl_scope_lpms(net) ; idx += 1) {
ivl_lpm_t lpm = ivl_scope_lpm(net, idx);
draw_lpm_in_scope(lpm);
@@ -2205,6 +2352,36 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent)
/*
* $Log: vvp_scope.c,v $
* Revision 1.152 2007/01/17 04:39:18 steve
* Remove dead code related to memories.
*
* Revision 1.151 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.150 2006/11/23 22:42:48 steve
* Do not intertangle modpaths due to references to input nets.
*
* Revision 1.149 2006/11/22 06:09:08 steve
* Get the .event input from the signal instead of the signal input.
*
* Revision 1.148 2006/10/01 23:51:15 steve
* Modpath is input to net, draw .modpath to account.
*
* Revision 1.147 2006/09/23 04:57:19 steve
* Basic support for specify timing.
*
* Revision 1.146 2006/07/30 02:51:36 steve
* Fix/implement signed right shift.
*
* Revision 1.145 2006/06/18 04:15:50 steve
* Add support for system functions in continuous assignments.
*
* Revision 1.144 2006/04/22 04:27:36 steve
* Get tail counts right in nested concatenations.
*
* Revision 1.143 2006/04/10 00:37:42 steve
* Add support for generate loops w/ wires and gates.
*
+10 -10
View File
@@ -1,10 +1,10 @@
Summary: Icarus Verilog
Name: verilog
Version: 0.9.0.20060409
Version: 0.9.0.20070123
Release: 0
Copyright: GPL
License: GPL
Group: Applications/Engineering
Source: ftp://icarus.com/pub/eda/verilog//verilog-20060409.tar.gz
Source: ftp://icarus.com/pub/eda/verilog//verilog-20070123.tar.gz
URL: http://www.icarus.com/eda/verilog/index.html
Packager: Stephen Williams <[email protected]>
@@ -22,13 +22,13 @@ engineering formats, including simulation. It strives to be true
to the IEEE-1364 standard.
%prep
%setup -n verilog-20060409
%setup -n verilog-20070123
%build
%ifarch x86_64
./configure --prefix=/usr libdir64='$(prefix)/lib64' vpidir1=vpi64 vpidir2=. --enable-vvp32
./configure --prefix=/usr --mandir='$(prefix)/share/man' libdir64='$(prefix)/lib64' vpidir1=vpi64 vpidir2=. --enable-vvp32
%else
./configure --prefix=/usr
./configure --prefix=/usr --mandir='$(prefix)/share/man'
%endif
make CXXFLAGS=-O
@@ -40,10 +40,10 @@ make prefix=$RPM_BUILD_ROOT/usr install
%attr(-,root,root) %doc COPYING README.txt BUGS.txt QUICK_START.txt ieee1364-notes.txt mingw.txt swift.txt netlist.txt t-dll.txt vpi.txt xnf.txt tgt-fpga/fpga.txt cadpli/cadpli.txt xilinx-hint.txt
%attr(-,root,root) %doc examples/*
%attr(-,root,root) /usr/man/man1/iverilog.1.gz
%attr(-,root,root) /usr/man/man1/iverilog-fpga.1.gz
%attr(-,root,root) /usr/man/man1/iverilog-vpi.1.gz
%attr(-,root,root) /usr/man/man1/vvp.1.gz
%attr(-,root,root) /usr/share/man/man1/iverilog.1.gz
#%attr(-,root,root) /usr/man/man1/iverilog-fpga.1.gz
%attr(-,root,root) /usr/share/man/man1/iverilog-vpi.1.gz
%attr(-,root,root) /usr/share/man/man1/vvp.1.gz
%attr(-,root,root) /usr/bin/iverilog
%attr(-,root,root) /usr/bin/iverilog-vpi
+151 -35
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: verinum.cc,v 1.44 2005/12/07 04:04:24 steve Exp $"
#ident "$Id: verinum.cc,v 1.50 2007/01/19 05:42:04 steve Exp $"
#endif
# include "config.h"
@@ -87,14 +87,14 @@ verinum::verinum(verinum::V val, unsigned n, bool h)
bits_[idx] = val;
}
verinum::verinum(unsigned long val, unsigned n)
verinum::verinum(uint64_t val, unsigned n)
: has_len_(true), has_sign_(false), string_flag_(false)
{
nbits_ = n;
bits_ = new V[nbits_];
for (unsigned idx = 0 ; idx < nbits_ ; idx += 1) {
bits_[idx] = (val&1) ? V1 : V0;
val >>= 1;
val >>= (uint64_t)1;
}
}
@@ -134,10 +134,10 @@ verinum::verinum(const verinum&that, unsigned nbits)
}
}
verinum::verinum(long that)
verinum::verinum(int64_t that)
: has_len_(false), has_sign_(true), string_flag_(false)
{
long tmp;
int64_t tmp;
tmp = that/2;
nbits_ = 1;
@@ -208,6 +208,27 @@ unsigned long verinum::as_ulong() const
return val;
}
uint64_t verinum::as_ulong64() const
{
if (nbits_ == 0)
return 0;
if (!is_defined())
return 0;
unsigned top = nbits_;
if (top >= (8 * sizeof(uint64_t)))
top = 8 * sizeof(uint64_t);
uint64_t val = 0;
uint64_t mask = 1;
for (unsigned idx = 0 ; idx < top ; idx += 1, mask <<= 1)
if (bits_[idx] == V1)
val |= mask;
return val;
}
/*
* This function returns the native long integer that represents the
* value of this object. It accounts for sign extension if the value
@@ -317,6 +338,30 @@ bool verinum::is_zero() const
return true;
}
verinum pad_to_width(const verinum&that, unsigned width)
{
if (that.len() >= width)
return that;
if (that.len() == 0) {
verinum val (verinum::V0, width, that.has_len());
val.has_sign(that.has_sign());
return val;
}
verinum::V pad = that[that.len()-1];
if (pad==verinum::V1 && !that.has_sign())
pad = verinum::V0;
verinum val(pad, width, that.has_len());
for (unsigned idx = 0 ; idx < that.len() ; idx += 1)
val.set(idx, that[idx]);
val.has_sign(that.has_sign());
return val;
}
/*
* This function returns a version of the verinum that has only as
* many bits as are needed to accurately represent the value. It takes
@@ -423,7 +468,7 @@ ostream& operator<< (ostream&o, const verinum&v)
/* If the number is fully defined (no x or z) then print it
out as a decimal number. */
if (v.is_defined()) {
if (v.is_defined() && v.len() < sizeof(long)) {
if (v.has_sign())
o << "'sd" << v.as_long();
else
@@ -612,7 +657,7 @@ verinum operator + (const verinum&left, const verinum&right)
val_bits[idx] = add_with_carry(left[idx], right[idx], carry);
verinum::V rpad = signed_flag? right[right.len()-1] : verinum::V0;
verinum::V lpad = signed_flag? left[left.len()-1] : verinum::V0;
verinum::V lpad = signed_flag? left[left.len()-1] : verinum::V0;
if (left.len() > right.len()) {
@@ -639,35 +684,46 @@ verinum operator + (const verinum&left, const verinum&right)
return val;
}
verinum operator - (const verinum&left, const verinum&r)
verinum operator - (const verinum&left, const verinum&right)
{
verinum right;
unsigned min = left.len();
if (r.len() < min) {
right = verinum(verinum::V0, min);
for (unsigned idx = 0 ; idx < r.len() ; idx += 1)
right.set(idx, r[idx]);
} else {
right = r;
}
right = v_not(right);
if (right.len() < min) min = right.len();
unsigned max = left.len();
if (right.len() > max) max = right.len();
verinum val (verinum::V0, max);
bool signed_flag = left.has_sign() && right.has_sign();
verinum::V*val_bits = new verinum::V[max+1];
verinum::V carry = verinum::V1;
for (unsigned idx = 0 ; idx < min ; idx += 1)
val.set(idx, add_with_carry(left[idx], right[idx], carry));
val_bits[idx] = add_with_carry(left[idx], ~right[idx], carry);
assert(left.len() <= right.len());
for (unsigned idx = min ; idx < max ; idx += 1)
val.set(idx, add_with_carry(verinum::V0, right[idx], carry));
verinum::V rpad = signed_flag? ~right[right.len()-1] : verinum::V1;
verinum::V lpad = signed_flag? left[left.len()-1] : verinum::V0;
if (left.len() > right.len()) {
for (unsigned idx = min ; idx < left.len() ; idx += 1)
val_bits[idx] = add_with_carry(left[idx], rpad, carry);
} else {
for (unsigned idx = min ; idx < right.len() ; idx += 1)
val_bits[idx] = add_with_carry(lpad, ~right[idx], carry);
}
if (signed_flag) {
val_bits[max] = add_with_carry(lpad, rpad, carry);
if (val_bits[max] != val_bits[max-1])
max += 1;
}
verinum val (val_bits, max, false);
val.has_sign(signed_flag);
delete[]val_bits;
val.has_sign(left.has_sign() && r.has_sign());
return val;
}
@@ -714,6 +770,17 @@ verinum operator * (const verinum&left, const verinum&right)
return trim_vnum(result);
}
verinum pow(const verinum&left, const verinum&right)
{
verinum result = left;
unsigned pow_count = right.as_ulong();
for (unsigned idx = 1 ; idx < pow_count ; idx += 1)
result = result * left;
return result;
}
verinum operator << (const verinum&that, unsigned shift)
{
verinum result(verinum::V0, that.len() + shift, that.has_len());
@@ -811,16 +878,33 @@ verinum operator / (const verinum&left, const verinum&right)
result is signed or not. */
if (result.has_sign()) {
/* XXXX FIXME XXXX Use native unsigned division to do
the work. This does not work if the result is too
large for the native integer. */
assert(use_len <= 8*sizeof(long));
long l = left.as_long();
long r = right.as_long();
long v = l / r;
for (unsigned idx = 0 ; idx < use_len ; idx += 1) {
result.set(idx, (v & 1)? verinum::V1 : verinum::V0);
v >>= 1;
if (use_len <= 8*sizeof(long)) {
long l = left.as_long();
long r = right.as_long();
long v = l / r;
for (unsigned idx = 0 ; idx < use_len ; idx += 1) {
result.set(idx, (v & 1)? verinum::V1 : verinum::V0);
v >>= 1;
}
} else {
verinum use_left, use_right;
verinum zero(verinum::V0, 1, false);
bool negative = false;
if (left < zero) {
use_left = zero - left;
negative ^= negative;
} else {
use_left = left;
}
if (right < zero) {
use_right = zero - right;
negative ^= negative;
} else {
use_right = right;
}
result = unsigned_divide(use_left, use_right);
if (negative) result = zero - result;
}
} else {
@@ -920,6 +1004,18 @@ verinum concat(const verinum&left, const verinum&right)
return res;
}
verinum::V operator ~ (verinum::V l)
{
switch (l) {
case verinum::V0:
return verinum::V1;
case verinum::V1:
return verinum::V0;
default:
return verinum::Vx;
}
}
verinum::V operator | (verinum::V l, verinum::V r)
{
if (l == verinum::V1)
@@ -960,6 +1056,26 @@ verinum::V operator ^ (verinum::V l, verinum::V r)
/*
* $Log: verinum.cc,v $
* Revision 1.50 2007/01/19 05:42:04 steve
* Fix calculation of verinum pow operation.
*
* Revision 1.49 2006/12/08 19:56:09 steve
* Handle very wide signed divide.
*
* Revision 1.48 2006/08/08 05:11:37 steve
* Handle 64bit delay constants.
*
* Revision 1.47 2006/07/31 03:50:17 steve
* Add support for power in constant expressions.
*
* Revision 1.46 2006/06/02 04:48:50 steve
* Make elaborate_expr methods aware of the width that the context
* requires of it. In the process, fix sizing of the width of unary
* minus is context determined sizes.
*
* Revision 1.45 2006/06/01 03:54:51 steve
* Fix broken subtraction of small constants.
*
* Revision 1.44 2005/12/07 04:04:24 steve
* Allow constant concat expressions.
*
+27 -3
View File
@@ -19,10 +19,11 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: verinum.h,v 1.28 2005/12/07 04:04:24 steve Exp $"
#ident "$Id: verinum.h,v 1.32 2006/08/08 05:11:37 steve Exp $"
#endif
# include <string>
# include <stdint.h>
# include "config.h"
#ifdef HAVE_IOSFWD
@@ -48,11 +49,11 @@ class verinum {
verinum(const string&str);
verinum(const V*v, unsigned nbits, bool has_len =true);
verinum(V, unsigned nbits =1, bool has_len =true);
verinum(unsigned long val, unsigned bits);
verinum(uint64_t val, unsigned bits);
verinum(const verinum&);
// Create a signed number, with an unspecified number of bits.
explicit verinum(long val);
explicit verinum(int64_t val);
// Copy only the specified number of bits from the
// source. Also mark this number as has_len.
@@ -90,6 +91,7 @@ class verinum {
V operator[] (unsigned idx) const { return get(idx); }
uint64_t as_ulong64() const;
unsigned long as_ulong() const;
signed long as_long() const;
string as_string() const;
@@ -105,6 +107,11 @@ class verinum {
bool string_flag_;
};
/* Return a verinum that has the same value as the input, but is at
least as wide as the requested width. This may involve sign
extension, if the value is signed. */
extern verinum pad_to_width(const verinum&, unsigned width);
/* Return a verinum that is minimal. That is, it has only the length
needed to accurately represent the contained value, signed or not. */
extern verinum trim_vnum(const verinum&);
@@ -112,6 +119,7 @@ extern verinum trim_vnum(const verinum&);
extern ostream& operator<< (ostream&, const verinum&);
extern ostream& operator<< (ostream&, verinum::V);
extern verinum::V operator ~ (verinum::V l);
extern verinum::V operator | (verinum::V l, verinum::V r);
extern verinum::V operator & (verinum::V l, verinum::V r);
extern verinum::V operator ^ (verinum::V l, verinum::V r);
@@ -141,6 +149,8 @@ extern verinum operator * (const verinum&left, const verinum&right);
extern verinum operator / (const verinum&left, const verinum&right);
extern verinum operator % (const verinum&left, const verinum&right);
extern verinum pow(const verinum&left, const verinum&right);
extern verinum operator<< (const verinum&left, unsigned shift);
extern verinum operator>> (const verinum&left, unsigned shift);
@@ -151,6 +161,20 @@ extern verinum v_not(const verinum&left);
/*
* $Log: verinum.h,v $
* Revision 1.32 2006/08/08 05:11:37 steve
* Handle 64bit delay constants.
*
* Revision 1.31 2006/07/31 03:50:17 steve
* Add support for power in constant expressions.
*
* Revision 1.30 2006/06/02 04:48:50 steve
* Make elaborate_expr methods aware of the width that the context
* requires of it. In the process, fix sizing of the width of unary
* minus is context determined sizes.
*
* Revision 1.29 2006/06/01 03:54:51 steve
* Fix broken subtraction of small constants.
*
* Revision 1.28 2005/12/07 04:04:24 steve
* Allow constant concat expressions.
*
+39 -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: verireal.cc,v 1.15 2004/06/04 23:33:51 steve Exp $"
#ident "$Id: verireal.cc,v 1.18 2006/10/03 05:06:00 steve Exp $"
#endif
# include "config.h"
@@ -56,6 +56,11 @@ verireal::verireal(long val)
value_ = (double)val;
}
verireal::verireal(double val)
{
value_ = val;
}
verireal::~verireal()
{
}
@@ -77,6 +82,23 @@ long verireal::as_long(int shift) const
return (long) outf;
}
int64_t verireal::as_long64(int shift) const
{
double out = value_ * pow(10.0,shift);
double outf;
if (out >= 0.0) {
outf = floor(out);
if (out >= (outf + 0.5))
outf += 1.0;
} else {
outf = ceil(out);
if (out <= (outf - 0.5))
outf -= 1.0;
}
return (int64_t) outf;
}
double verireal::as_double() const
{
return value_;
@@ -117,6 +139,13 @@ verireal operator% (const verireal&l, const verinum&r)
return res;
}
verireal pow (const verireal&l, const verireal&r)
{
verireal res;
res.value_ = pow(l.value_, r.value_);
return res;
}
verireal operator- (const verireal&l)
{
verireal res;
@@ -132,6 +161,15 @@ ostream& operator<< (ostream&out, const verireal&v)
/*
* $Log: verireal.cc,v $
* Revision 1.18 2006/10/03 05:06:00 steve
* Support real valued specify delays, properly scaled.
*
* Revision 1.17 2006/08/08 05:11:37 steve
* Handle 64bit delay constants.
*
* Revision 1.16 2006/07/31 03:50:18 steve
* Add support for power in constant expressions.
*
* Revision 1.15 2004/06/04 23:33:51 steve
* Add unary minus as operator supported by verireal.
*
+16 -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: verireal.h,v 1.11 2005/06/14 19:13:43 steve Exp $"
#ident "$Id: verireal.h,v 1.14 2006/10/03 05:06:00 steve Exp $"
#endif
#ifdef HAVE_IOSFWD
@@ -28,6 +28,8 @@
class ostream;
#endif
# include <stdint.h>
using namespace std;
class verinum;
@@ -47,6 +49,7 @@ class verireal {
friend verireal operator/ (const verireal&, const verinum&);
friend verireal operator% (const verireal&, const verireal&);
friend verireal operator% (const verireal&, const verinum&);
friend verireal pow(const verireal&, const verireal&);
// Unary minus.
friend verireal operator- (const verireal&);
@@ -55,6 +58,7 @@ class verireal {
explicit verireal();
explicit verireal(const char*text);
explicit verireal(long val);
explicit verireal(double val);
~verireal();
/* Return the value of the floating point number as an
@@ -63,6 +67,7 @@ class verireal {
example if the value is 2.5 and shift == 1, the result
is 25. */
long as_long(int shift =0) const;
int64_t as_long64(int shift =0) const;
double as_double() const;
@@ -76,10 +81,20 @@ extern verireal operator/ (const verireal&, const verireal&);
extern verireal operator/ (const verireal&, const verinum&);
extern verireal operator% (const verireal&, const verireal&);
extern verireal operator% (const verireal&, const verinum&);
extern verireal pow(const verireal&, const verireal&);
extern verireal operator- (const verireal&);
/*
* $Log: verireal.h,v $
* Revision 1.14 2006/10/03 05:06:00 steve
* Support real valued specify delays, properly scaled.
*
* Revision 1.13 2006/08/08 05:11:37 steve
* Handle 64bit delay constants.
*
* Revision 1.12 2006/07/31 03:50:18 steve
* Add support for power in constant expressions.
*
* Revision 1.11 2005/06/14 19:13:43 steve
* gcc3/4 compile errors.
*
+3 -3
View File
@@ -16,7 +16,7 @@
# 59 Temple Place - Suite 330
# Boston, MA 02111-1307, USA
#
#ident "$Id: Makefile.in,v 1.58 2004/10/04 01:09:22 steve Exp $"
#ident "$Id: Makefile.in,v 1.60 2006/10/30 22:45:37 steve Exp $"
#
#
SHELL = /bin/sh
@@ -65,7 +65,7 @@ dep:
O = sys_table.o sys_convert.o sys_deposit.o sys_display.o sys_fileio.o \
sys_finish.o sys_plusargs.o sys_random.o sys_random_mti.o \
sys_readmem.o sys_readmem_lex.o \
sys_readmem.o sys_readmem_lex.o sys_scanf.o \
sys_time.o sys_vcd.o sys_vcdoff.o vcd_priv.o mt19937int.o priv.o stringheap.o
ifeq (@HAVE_LIBZ@,yes)
@@ -111,7 +111,7 @@ clean:
rm -rf *.o sys_readmem_lex.c dep system.vpi bin32
distclean: clean
rm -f Makefile
rm -f Makefile config.status config.log vpi_config.h
install: all installdirs $(vpidir)/system.vpi $(libdir)/ivl/system.sft $(INSTALL32)
+12 -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: sys_convert.c,v 1.5 2004/02/15 18:03:30 steve Exp $"
#ident "$Id: sys_convert.c,v 1.6 2006/10/30 22:45:37 steve Exp $"
#endif
# include "vpi_config.h"
@@ -86,13 +86,13 @@ static void double2bits(double real, PLI_UINT32 bits[2])
#endif
}
static int sizetf_32 (char*x) { return 32; }
static int sizetf_64 (char*x) { return 64; }
static PLI_INT32 sizetf_32 (char*x) { return 32; }
static PLI_INT32 sizetf_64 (char*x) { return 64; }
static int sys_convert_compiletf(char *name)
static PLI_INT32 sys_convert_compiletf(char *name)
{
vpiHandle call_hand, argv, arg;
int rtn = 0;
PLI_INT32 rtn = 0;
call_hand = vpi_handle(vpiSysTfCall, 0);
argv = vpi_iterate(vpiArgument, call_hand);
@@ -116,7 +116,7 @@ static int sys_convert_compiletf(char *name)
return rtn;
}
static int sys_bitstoreal_calltf(char *user)
static PLI_INT32 sys_bitstoreal_calltf(char *user)
{
vpiHandle sys, argv, arg;
s_vpi_value value;
@@ -147,7 +147,7 @@ static int sys_bitstoreal_calltf(char *user)
return 0;
}
static int sys_itor_calltf(char *user)
static PLI_INT32 sys_itor_calltf(char *user)
{
vpiHandle sys, argv, arg;
s_vpi_value value;
@@ -174,7 +174,7 @@ static int sys_itor_calltf(char *user)
return 0;
}
static int sys_realtobits_calltf(char *user)
static PLI_INT32 sys_realtobits_calltf(char *user)
{
vpiHandle sys, argv, arg;
s_vpi_value value;
@@ -211,7 +211,7 @@ static int sys_realtobits_calltf(char *user)
return 0;
}
static int sys_rtoi_calltf(char *user)
static PLI_INT32 sys_rtoi_calltf(char *user)
{
vpiHandle sys, argv, arg;
s_vpi_value value;
@@ -281,6 +281,9 @@ void sys_convert_register()
/*
* $Log: sys_convert.c,v $
* Revision 1.6 2006/10/30 22:45:37 steve
* Updates for Cygwin portability (pr1585922)
*
* Revision 1.5 2004/02/15 18:03:30 steve
* Cleanup of warnings.
*
+5 -2
View File
@@ -18,7 +18,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: sys_deposit.c,v 1.5 2004/10/04 01:10:58 steve Exp $"
#ident "$Id: sys_deposit.c,v 1.6 2006/10/30 22:45:37 steve Exp $"
#endif
# include "vpi_config.h"
@@ -26,7 +26,7 @@
# include "vpi_user.h"
# include <assert.h>
static int sys_deposit_calltf(char *name)
static PLI_INT32 sys_deposit_calltf(char *name)
{
vpiHandle sys, argv, target, value;
s_vpi_value val;
@@ -79,6 +79,9 @@ void sys_deposit_register()
/*
* $Log: sys_deposit.c,v $
* Revision 1.6 2006/10/30 22:45:37 steve
* Updates for Cygwin portability (pr1585922)
*
* Revision 1.5 2004/10/04 01:10:58 steve
* Clean up spurious trailing white space.
*
+20 -20
View File
@@ -17,12 +17,13 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: sys_display.c,v 1.71 2004/10/04 01:10:58 steve Exp $"
#ident "$Id: sys_display.c,v 1.73 2006/10/30 22:45:37 steve Exp $"
#endif
# include "vpi_config.h"
# include "vpi_user.h"
# include "sys_priv.h"
# include <assert.h>
# include <string.h>
# include <ctype.h>
@@ -51,13 +52,6 @@ static PLI_INT32 my_mcd_printf(PLI_UINT32 mcd, const char *fmt, ...)
return r;
}
struct timeformat_info_s {
int units;
unsigned prec;
char*suff;
unsigned width;
};
struct timeformat_info_s timeformat_info = { 0, 0, 0, 20 };
struct strobe_cb_info {
@@ -931,7 +925,7 @@ static int get_default_format(char *name)
return default_format;
}
static int sys_display_calltf(char *name)
static PLI_INT32 sys_display_calltf(char *name)
{
struct strobe_cb_info*info;
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
@@ -966,7 +960,7 @@ static int sys_display_calltf(char *name)
* where it is use to perform the actual formatting and printing.
*/
static int strobe_cb(p_cb_data cb)
static PLI_INT32 strobe_cb(p_cb_data cb)
{
struct strobe_cb_info*info = (struct strobe_cb_info*)cb->user_data;
@@ -980,7 +974,7 @@ static int strobe_cb(p_cb_data cb)
return 0;
}
static int sys_strobe_calltf(char*name)
static PLI_INT32 sys_strobe_calltf(char*name)
{
struct t_cb_data cb;
struct t_vpi_time time;
@@ -1070,7 +1064,7 @@ static vpiHandle *monitor_callbacks = 0;
static int monitor_scheduled = 0;
static int monitor_enabled = 1;
static int monitor_cb_2(p_cb_data cb)
static PLI_INT32 monitor_cb_2(p_cb_data cb)
{
do_display(1, &monitor_info);
vpi_printf("\n");
@@ -1084,7 +1078,7 @@ static int monitor_cb_2(p_cb_data cb)
* display to occur in a ReadOnlySync callback. The monitor_scheduled
* flag is used to allow only one monitor strobe to be scheduled.
*/
static int monitor_cb_1(p_cb_data cause)
static PLI_INT32 monitor_cb_1(p_cb_data cause)
{
struct t_cb_data cb;
struct t_vpi_time time;
@@ -1110,7 +1104,7 @@ static int monitor_cb_1(p_cb_data cause)
return 0;
}
static int sys_monitor_calltf(char*name)
static PLI_INT32 sys_monitor_calltf(char*name)
{
unsigned idx;
struct t_cb_data cb;
@@ -1177,14 +1171,14 @@ static int sys_monitor_calltf(char*name)
return 0;
}
static int sys_monitoron_calltf(char*name)
static PLI_INT32 sys_monitoron_calltf(char*name)
{
monitor_enabled = 1;
monitor_cb_1(0);
return 0;
}
static int sys_monitoroff_calltf(char*name)
static PLI_INT32 sys_monitoroff_calltf(char*name)
{
monitor_enabled = 0;
return 0;
@@ -1193,7 +1187,7 @@ static int sys_monitoroff_calltf(char*name)
/* Implement $fdisplay and $fwrite.
* Perhaps this could be merged into sys_display_calltf.
*/
static int sys_fdisplay_calltf(char *name)
static PLI_INT32 sys_fdisplay_calltf(char *name)
{
struct strobe_cb_info info;
unsigned int mcd;
@@ -1257,7 +1251,7 @@ static int sys_fdisplay_calltf(char *name)
return 0;
}
static int sys_timeformat_compiletf(char *xx)
static PLI_INT32 sys_timeformat_compiletf(char *xx)
{
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, sys);
@@ -1279,7 +1273,7 @@ static int sys_timeformat_compiletf(char *xx)
return 0;
}
static int sys_timeformat_calltf(char *xx)
static PLI_INT32 sys_timeformat_calltf(char *xx)
{
s_vpi_value value;
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
@@ -1310,7 +1304,7 @@ static int sys_timeformat_calltf(char *xx)
return 0;
}
static int sys_end_of_compile(p_cb_data cb_data)
static PLI_INT32 sys_end_of_compile(p_cb_data cb_data)
{
/* The default timeformat prints times in unit of simulation
precision. */
@@ -1566,6 +1560,12 @@ void sys_display_register()
/*
* $Log: sys_display.c,v $
* Revision 1.73 2006/10/30 22:45:37 steve
* Updates for Cygwin portability (pr1585922)
*
* Revision 1.72 2006/08/12 03:38:12 steve
* scanf support for real values.
*
* Revision 1.71 2004/10/04 01:10:58 steve
* Clean up spurious trailing white space.
*
+73 -36
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: sys_fileio.c,v 1.7 2005/09/20 18:34:01 steve Exp $"
#ident "$Id: sys_fileio.c,v 1.9 2006/10/30 22:45:37 steve Exp $"
#endif
# include "vpi_user.h"
@@ -33,40 +33,72 @@
/*
* Implement the $fopen system function.
*/
static int sys_fopen_calltf(char *name)
static PLI_INT32 sys_fopen_compiletf(char *name)
{
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, sys);
vpiHandle item;
if (argv == 0) {
vpi_printf("%s: file name argument missing.\n", name);
vpi_sim_control(vpiFinish, -1);
return -1;
}
item = vpi_scan(argv);
if (item == 0) {
vpi_printf("%s: file name argument missing.\n", name);
vpi_sim_control(vpiFinish, -1);
return -1;
}
item = vpi_scan(argv);
if (item == 0) {
/* The mode argument is optional. It is OK for it
to be missing. In this case, there are no more
arguments, and we're done. */
return 0;
}
if (! is_constant(item)) {
vpi_printf("ERROR: %s mode argument must be a constant\n", name);
vpi_sim_control(vpiFinish, -1);
}
if (vpi_get(vpiConstType, item) != vpiStringConst) {
vpi_printf("ERROR: %s mode argument must be a string.\n", name);
vpi_sim_control(vpiFinish, -1);
}
item = vpi_scan(argv);
if (item == 0) {
/* There should be no more arguments. */
return 0;
}
vpi_free_object(argv);
vpi_printf("%s: Too many arguments to system function.\n", name);
return 0;
}
static PLI_INT32 sys_fopen_calltf(char *name)
{
s_vpi_value value;
char *mode_string = 0;
vpiHandle call_handle = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, call_handle);
vpiHandle item = argv ? vpi_scan(argv) : 0;
vpiHandle mode = item ? vpi_scan(argv) : 0;
vpiHandle item = vpi_scan(argv);
vpiHandle mode = vpi_scan(argv);
if (item == 0) {
vpi_printf("%s: file name parameter missing.\n", name);
return 0;
}
if (mode == 0) {
argv = 0;
}
assert(item);
if (mode) {
if (! is_constant(mode)) {
vpi_printf("ERROR: %s parameter must be a constant\n", name);
if (argv) vpi_free_object(argv);
return 0;
}
if (vpi_get(vpiConstType, mode) != vpiStringConst) {
vpi_printf("ERROR: %s parameter must be a string.\n", name);
if (argv) vpi_free_object(argv);
return 0;
}
value.format = vpiStringVal;
vpi_get_value(mode, &value);
mode_string = strdup(value.value.str);
vpi_free_object(argv);
}
/* Get the string form of the file name from the file name
@@ -79,7 +111,6 @@ static int sys_fopen_calltf(char *name)
" does not have a string value\n",
name, vpi_get(vpiType, item));
if (mode) free(mode_string);
if (argv) vpi_free_object(argv);
return 0;
}
@@ -95,7 +126,7 @@ static int sys_fopen_calltf(char *name)
return 0;
}
static int sys_fopen_sizetf(char*x)
static PLI_INT32 sys_fopen_sizetf(char*x)
{
return 32;
}
@@ -103,7 +134,7 @@ static int sys_fopen_sizetf(char*x)
/*
* Implement $fclose system function
*/
static int sys_fclose_calltf(char *name)
static PLI_INT32 sys_fclose_calltf(char *name)
{
unsigned int mcd;
int type;
@@ -139,14 +170,14 @@ static int sys_fclose_calltf(char *name)
return 0;
}
static int sys_fflush_calltf(char *name)
static PLI_INT32 sys_fflush_calltf(char *name)
{
fflush(0);
return 0;
}
static int sys_fputc_calltf(char *name)
static PLI_INT32 sys_fputc_calltf(char *name)
{
unsigned int mcd;
int type;
@@ -193,7 +224,7 @@ static int sys_fputc_calltf(char *name)
return fputc(x, fp);
}
static int sys_fgetc_calltf(char *name)
static PLI_INT32 sys_fgetc_calltf(char *name)
{
unsigned int mcd;
int type;
@@ -238,12 +269,12 @@ static int sys_fgetc_calltf(char *name)
return 0;
}
static int sys_fgetc_sizetf(char*x)
static PLI_INT32 sys_fgetc_sizetf(char*x)
{
return 32;
}
static int sys_fgets_compiletf(char*name)
static PLI_INT32 sys_fgets_compiletf(char*name)
{
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
vpiHandle argv = vpi_iterate(vpiArgument, sys);
@@ -276,7 +307,7 @@ static int sys_fgets_compiletf(char*name)
return 0;
}
static int sys_fgets_calltf(char *name)
static PLI_INT32 sys_fgets_calltf(char *name)
{
unsigned int mcd;
FILE*fd;
@@ -326,7 +357,7 @@ static int sys_fgets_calltf(char *name)
return 0;
}
static int sys_ungetc_compiletf(char*name)
static PLI_INT32 sys_ungetc_compiletf(char*name)
{
int type;
vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
@@ -354,7 +385,7 @@ static int sys_ungetc_compiletf(char*name)
return 0;
}
static int sys_ungetc_calltf(char *name)
static PLI_INT32 sys_ungetc_calltf(char *name)
{
unsigned int mcd;
unsigned char x;
@@ -398,7 +429,7 @@ static int sys_ungetc_calltf(char *name)
return 0;
}
static int sys_ungetc_sizetf(char*x)
static PLI_INT32 sys_ungetc_sizetf(char*x)
{
return 32;
}
@@ -413,7 +444,7 @@ void sys_fileio_register()
tf_data.type = vpiSysFunc;
tf_data.tfname = "$fopen";
tf_data.calltf = sys_fopen_calltf;
tf_data.compiletf = 0;
tf_data.compiletf = sys_fopen_compiletf;
tf_data.sizetf = sys_fopen_sizetf;
tf_data.user_data = "$fopen";
vpi_register_systf(&tf_data);
@@ -479,6 +510,12 @@ void sys_fileio_register()
/*
* $Log: sys_fileio.c,v $
* Revision 1.9 2006/10/30 22:45:37 steve
* Updates for Cygwin portability (pr1585922)
*
* Revision 1.8 2006/08/03 05:02:46 steve
* Use compiletf to check arguments.
*
* Revision 1.7 2005/09/20 18:34:01 steve
* Clean up compiler warnings.
*
+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: sys_finish.c,v 1.9 2004/01/21 01:22:53 steve Exp $"
#ident "$Id: sys_finish.c,v 1.10 2006/10/30 22:45:37 steve Exp $"
#endif
# include "vpi_config.h"
@@ -25,7 +25,7 @@
# include "vpi_user.h"
# include <string.h>
static int sys_finish_calltf(char *name)
static PLI_INT32 sys_finish_calltf(char *name)
{
if (strcmp(name,"$stop") == 0) {
vpi_sim_control(vpiStop, 0);
@@ -59,6 +59,9 @@ void sys_finish_register()
/*
* $Log: sys_finish.c,v $
* Revision 1.10 2006/10/30 22:45:37 steve
* Updates for Cygwin portability (pr1585922)
*
* Revision 1.9 2004/01/21 01:22:53 steve
* Give the vip directory its own configure and vpi_config.h
*
+13 -10
View File
@@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CVS_IDENT
#ident "$Id: sys_lxt.c,v 1.26 2004/10/04 01:10:58 steve Exp $"
#ident "$Id: sys_lxt.c,v 1.27 2006/10/30 22:45:37 steve Exp $"
#endif
# include "sys_priv.h"
@@ -220,7 +220,7 @@ static void vcd_checkpoint_x()
show_this_item_x(cur);
}
static int variable_cb_2(p_cb_data cause)
static PLI_INT32 variable_cb_2(p_cb_data cause)
{
struct vcd_info* info = vcd_dmp_list;
PLI_UINT64 now = timerec_to_time64(cause->time);
@@ -240,7 +240,7 @@ static int variable_cb_2(p_cb_data cause)
return 0;
}
static int variable_cb_1(p_cb_data cause)
static PLI_INT32 variable_cb_1(p_cb_data cause)
{
struct t_cb_data cb;
struct vcd_info*info = (struct vcd_info*)cause->user_data;
@@ -263,7 +263,7 @@ static int variable_cb_1(p_cb_data cause)
return 0;
}
static int dumpvars_cb(p_cb_data cause)
static PLI_INT32 dumpvars_cb(p_cb_data cause)
{
if (dumpvars_status != 1)
return 0;
@@ -310,7 +310,7 @@ inline static int install_dumpvars_callback(void)
return 0;
}
static int sys_dumpoff_calltf(char*name)
static PLI_INT32 sys_dumpoff_calltf(char*name)
{
s_vpi_time now;
PLI_UINT64 now64;
@@ -340,7 +340,7 @@ static int sys_dumpoff_calltf(char*name)
return 0;
}
static int sys_dumpon_calltf(char*name)
static PLI_INT32 sys_dumpon_calltf(char*name)
{
s_vpi_time now;
PLI_UINT64 now64;
@@ -370,7 +370,7 @@ static int sys_dumpon_calltf(char*name)
return 0;
}
static int sys_dumpall_calltf(char*name)
static PLI_INT32 sys_dumpall_calltf(char*name)
{
s_vpi_time now;
PLI_UINT64 now64;
@@ -426,7 +426,7 @@ static void open_dumpfile(const char*path)
}
}
static int sys_dumpfile_calltf(char*name)
static PLI_INT32 sys_dumpfile_calltf(char*name)
{
char*path;
@@ -470,7 +470,7 @@ static int sys_dumpfile_calltf(char*name)
/*
* The LXT1 format has no concept of file flushing.
*/
static int sys_dumpflush_calltf(char*name)
static PLI_INT32 sys_dumpflush_calltf(char*name)
{
return 0;
}
@@ -674,7 +674,7 @@ static int draw_scope(vpiHandle item)
return depth;
}
static int sys_dumpvars_calltf(char*name)
static PLI_INT32 sys_dumpvars_calltf(char*name)
{
unsigned depth;
s_vpi_value value;
@@ -819,6 +819,9 @@ void sys_lxt_register()
/*
* $Log: sys_lxt.c,v $
* Revision 1.27 2006/10/30 22:45:37 steve
* Updates for Cygwin portability (pr1585922)
*
* Revision 1.26 2004/10/04 01:10:58 steve
* Clean up spurious trailing white space.
*

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