mirror of
https://github.com/steveicarus/iverilog.git
synced 2026-08-24 06:46:52 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8ae6240947 | ||
|
|
f77d803aeb | ||
|
|
4b829bf04f | ||
|
|
17a508047b | ||
|
|
b350b14f93 | ||
|
|
ca9da51a79 | ||
|
|
98417cb03a | ||
|
|
f07257067a | ||
|
|
e4d7eda02a | ||
|
|
4d8164945e | ||
|
|
c0954349e4 | ||
|
|
e89b9fc25e | ||
|
|
11a83c352d | ||
|
|
d8d7673d27 | ||
|
|
6f3ddce7c4 | ||
|
|
f5a7ee0736 | ||
|
|
91d84e7dc7 | ||
|
|
5c3b2f4193 | ||
|
|
0ae45e5644 | ||
|
|
296c2a575a | ||
|
|
316422d93b | ||
|
|
2c7d2effd1 | ||
|
|
4fb5556d1c | ||
|
|
2eeea7003e | ||
|
|
d7de70bdeb | ||
|
|
078019ddec | ||
|
|
b4c3e8208f | ||
|
|
2f9a3e90ae | ||
|
|
4f8a7ea84a | ||
|
|
a3da90aa4a | ||
|
|
48029ed8e5 | ||
|
|
94f07d16e3 | ||
|
|
041091cfac | ||
|
|
0af4ea7cbe | ||
|
|
d6f98599f8 | ||
|
|
2ac30824ac | ||
|
|
64b4e2fa01 | ||
|
|
f5a204720d | ||
|
|
21522c90bc | ||
|
|
34b5a31ff4 | ||
|
|
c339dc4bbc | ||
|
|
ed5d3188b3 | ||
|
|
8e379bd634 | ||
|
|
841378426f | ||
|
|
2302693201 | ||
|
|
2a8b960b06 | ||
|
|
0e102a94b2 | ||
|
|
168b3f2743 | ||
|
|
0d71b1cc18 | ||
|
|
ec23bb0367 | ||
|
|
26e2e85ffa | ||
|
|
4af28e2b77 | ||
|
|
69cd007a71 | ||
|
|
cbe1a6a3ca | ||
|
|
1a0d48c346 | ||
|
|
549f226c6e | ||
|
|
e1f712356f | ||
|
|
6593b603ad | ||
|
|
852d10500d | ||
|
|
44ca0fe798 | ||
|
|
35ce5f3e2a | ||
|
|
d6be82f748 | ||
|
|
7e3ea2ffe8 | ||
|
|
b658a3b41f | ||
|
|
d3ceae7ee0 | ||
|
|
0edb5a7547 | ||
|
|
ceb6bf4afd | ||
|
|
0e2c6544b9 | ||
|
|
b4893dc16f | ||
|
|
f49039a3d6 | ||
|
|
3617f0346e | ||
|
|
f20191e6f5 | ||
|
|
182734fd4d | ||
|
|
431eee16e4 | ||
|
|
92cb1d4e2d | ||
|
|
6f34dfc8e5 | ||
|
|
2c7e96caec | ||
|
|
54c7ef72cb | ||
|
|
50800fd3a1 | ||
|
|
fc0695beb6 | ||
|
|
00891db0d2 | ||
|
|
898b0e0365 | ||
|
|
382c4d74fd | ||
|
|
5bcf083662 | ||
|
|
1bd530c144 | ||
|
|
82a85131a8 | ||
|
|
49b65e86fe | ||
|
|
06d6ac4b33 | ||
|
|
2037650080 | ||
|
|
61f3a84557 | ||
|
|
ed70db84ce | ||
|
|
5348ac14a5 | ||
|
|
aab6fefd8a | ||
|
|
1b8e2a17c7 | ||
|
|
33a391cb71 | ||
|
|
bcc08112aa | ||
|
|
80f30be9d0 | ||
|
|
71faebd6df | ||
|
|
53ae1f29c9 | ||
|
|
857b3e15b6 | ||
|
|
019d61f633 | ||
|
|
d37b6599f4 | ||
|
|
68e52ce6b7 | ||
|
|
4c885f65e1 | ||
|
|
f0e114d59f | ||
|
|
aaaa042f73 | ||
|
|
044da54b41 | ||
|
|
a8b86ea3bb | ||
|
|
e98aad1e9b | ||
|
|
1ef91f800f | ||
|
|
a19efe181b | ||
|
|
81bfbd1549 | ||
|
|
dc2898cc73 | ||
|
|
0c9fb766b6 | ||
|
|
10f8c66f4a | ||
|
|
56f70ec702 | ||
|
|
949054e000 | ||
|
|
47b72c3b74 | ||
|
|
a2c036d5ab | ||
|
|
0d17e57656 | ||
|
|
fd94268315 | ||
|
|
36039e13ec | ||
|
|
a702f99c04 | ||
|
|
4493e3f928 | ||
|
|
3727052000 | ||
|
|
39ff233cf1 | ||
|
|
58118bddc5 | ||
|
|
c2ff3d501c | ||
|
|
46d86ad276 | ||
|
|
4dd1308eb0 | ||
|
|
a978bb1e14 | ||
|
|
707af782b3 | ||
|
|
fc5cf55400 | ||
|
|
6a74a090f0 | ||
|
|
c448b75f2c |
+9
-8
@@ -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
|
||||
|
||||
@@ -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
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
@@ -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
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
+176
-123
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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
@@ -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
@@ -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`
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: a_next.c,v 1.3 2003/06/17 16:55:07 steve Exp $"
|
||||
#ident "$Id: a_next.c,v 1.4 2006/10/30 22:45:37 steve Exp $"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
@@ -34,7 +34,7 @@ handle acc_next(PLI_INT32 *type, handle scope, handle prev)
|
||||
|
||||
/* trace */
|
||||
if (pli_trace) {
|
||||
int *ip;
|
||||
PLI_INT32 *ip;
|
||||
fprintf(pli_trace, "acc_next(%p <", type);
|
||||
for (ip = type; *ip; ip++) {
|
||||
fprintf(pli_trace, "%s%d", ip != type ? "," : "", *ip);
|
||||
@@ -94,6 +94,9 @@ handle acc_next_scope(handle scope, handle prev)
|
||||
|
||||
/*
|
||||
* $Log: a_next.c,v $
|
||||
* Revision 1.4 2006/10/30 22:45:37 steve
|
||||
* Updates for Cygwin portability (pr1585922)
|
||||
*
|
||||
* Revision 1.3 2003/06/17 16:55:07 steve
|
||||
* 1) setlinebuf() for vpi_trace
|
||||
* 2) Addes error checks for trace file opens
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
AC_INIT(Makefile.in)
|
||||
AC_CONFIG_HEADER(config.h)
|
||||
|
||||
AC_CANONICAL_HOST
|
||||
|
||||
AC_PROG_CC
|
||||
AC_PROG_INSTALL
|
||||
AC_PROG_RANLIB
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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
|
||||
*
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
*.cache
|
||||
stub.tgt
|
||||
configure
|
||||
config.log
|
||||
config.status
|
||||
Makefile
|
||||
dep
|
||||
|
||||
+11
-4
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
|
||||
@@ -4,3 +4,4 @@ functor:syn-rules
|
||||
functor:cprop
|
||||
functor:nodangle
|
||||
-t:dll
|
||||
flag:DLL=stub.tgt
|
||||
|
||||
+228
-312
@@ -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,3 +1,4 @@
|
||||
functor:cprop
|
||||
functor:nodangle
|
||||
-t:dll
|
||||
flag:DLL=stub.tgt
|
||||
|
||||
+3
-3
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
Reference in New Issue
Block a user