diff --git a/README.txt b/README.txt index 3c80b4a79..0ddfb5f7f 100644 --- a/README.txt +++ b/README.txt @@ -405,6 +405,35 @@ constructs. - force to nets are not supported. Force to variables, and assign/deassign, are supported. +5.0 Nonstandard Constructs + +Icarus Verilog includes some features that are not part of the +IEEE1364 standard, but have well defined meaning. These are extensions +to the language. + + $sizeof() + This system function returns the size in bits of the + expression that is its argument. The result of this + function is undefined if the argument doesn't have a + self-determined size. + + Builtin system functions + + Certain of the system functions have well defined meanings, so + can theoretically be evaluated at compile time, instead of + using runtime VPI code. Doing so means that VPI cannot + override the definitions of functions handled in this + manner. On the other hand, this makes them synthesizeable, and + also allows for more agressive constant propagation. The + functions handled in this manner are: + + $signed + $sizeof + $unsigned + + Implementations of these system functions in VPI modules will + be ignored. + 6.0 CREDITS Except where otherwise noted, Icarus Verilog, ivl and ivlpp are diff --git a/design_dump.cc b/design_dump.cc index c568d8cb6..56f75d4f0 100644 --- a/design_dump.cc +++ b/design_dump.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: design_dump.cc,v 1.122 2002/03/09 02:10:22 steve Exp $" +#ident "$Id: design_dump.cc,v 1.123 2002/05/05 21:11:49 steve Exp $" #endif # include "config.h" @@ -850,8 +850,8 @@ void NetEBinary::dump(ostream&o) const void NetEConcat::dump(ostream&o) const { - if (repeat_ != 1) - o << repeat_; + if (repeat_) + o << *repeat_; if (parms_[0]) o << "{" << *parms_[0]; @@ -980,6 +980,13 @@ void Design::dump(ostream&o) const /* * $Log: design_dump.cc,v $ + * Revision 1.123 2002/05/05 21:11:49 steve + * Put off evaluation of concatenation repeat expresions + * until after parameters are defined. This allows parms + * to be used in repeat expresions. + * + * Add the builtin $signed system function. + * * Revision 1.122 2002/03/09 02:10:22 steve * Add the NetUserFunc netlist node. * diff --git a/elab_expr.cc b/elab_expr.cc index 840db97d1..08e09977f 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: elab_expr.cc,v 1.57 2002/04/27 05:03:46 steve Exp $" +#ident "$Id: elab_expr.cc,v 1.58 2002/05/05 21:11:49 steve Exp $" #endif # include "config.h" @@ -182,6 +182,29 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope) const return sub; } + /* Interpret the internal $sizeof system function to return + the bit width of the sub-expression. The value of the + sub-expression is not used, so the expression itself can be + deleted. */ + if (strcmp(path_.peek_name(0), "$sizeof") == 0) { + if ((parms_.count() != 1) || (parms_[0] == 0)) { + cerr << get_line() << ": error: The $sizeof() function " + << "takes exactly one(1) argument." << endl; + des->errors += 1; + return 0; + } + + PExpr*expr = parms_[0]; + NetExpr*sub = expr->elaborate_expr(des, scope, true); + verinum val (sub->expr_width(), sizeof(unsigned)); + delete sub; + + sub = new NetEConst(val); + sub->set_line(*this); + + return sub; + } + unsigned wid = 32; if (strcmp(path_.peek_name(0), "$time") == 0) @@ -322,7 +345,7 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope, bool) const NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope, bool) const { - unsigned repeat = 1; + NetExpr* repeat = 0; /* If there is a repeat expression, then evaluate the constant value and set the repeat count. */ @@ -338,10 +361,9 @@ NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope, bool) const cerr << get_line() << ": : The expression is: " << *tmp << endl; des->errors += 1; - return 0; } - repeat = rep->value().as_ulong(); + repeat = rep; } /* Make the empty concat expression. */ @@ -842,6 +864,13 @@ NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope, bool) const /* * $Log: elab_expr.cc,v $ + * Revision 1.58 2002/05/05 21:11:49 steve + * Put off evaluation of concatenation repeat expresions + * until after parameters are defined. This allows parms + * to be used in repeat expresions. + * + * Add the builtin $signed system function. + * * Revision 1.57 2002/04/27 05:03:46 steve * Preserve stringiness string part select and concatenation. * diff --git a/elab_pexpr.cc b/elab_pexpr.cc index 220d9a17a..0c41b1ff4 100644 --- a/elab_pexpr.cc +++ b/elab_pexpr.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: elab_pexpr.cc,v 1.13 2002/01/28 00:52:41 steve Exp $" +#ident "$Id: elab_pexpr.cc,v 1.14 2002/05/05 21:11:50 steve Exp $" #endif # include "config.h" @@ -66,28 +66,21 @@ NetExpr*PEBinary::elaborate_pexpr (Design*des, NetScope*scope) const */ NetEConcat* PEConcat::elaborate_pexpr(Design*des, NetScope*scope) const { - unsigned repeat = 1; + NetExpr* repeat = 0; /* If there is a repeat expression, then evaluate the constant - value and set the repeat count. - - XXXX Potential bug XXX In principle, the repeat expression - can have a parameter name in it. Since where are in the - working of parameters now, we will not be able to - accurately evaluate such expressions. So eventually, I will - need to be able to defer the evaluation of the expression. */ + value and set the repeat count. */ if (repeat_) { - verinum*vrep = repeat_->eval_const(des, scope); - if (vrep == 0) { + repeat = repeat_->elaborate_pexpr(des, scope); + if (repeat == 0) { cerr << get_line() << ": error: " "concatenation repeat expression cannot be evaluated." << endl; des->errors += 1; - return 0; } - repeat = vrep->as_ulong(); - delete vrep; + /* continue on even if the repeat expression doesn't + work, as we can find more errors. */ } /* Make the empty concat expression. */ @@ -224,6 +217,13 @@ NetExpr*PEUnary::elaborate_pexpr (Design*des, NetScope*scope) const /* * $Log: elab_pexpr.cc,v $ + * Revision 1.14 2002/05/05 21:11:50 steve + * Put off evaluation of concatenation repeat expresions + * until after parameters are defined. This allows parms + * to be used in repeat expresions. + * + * Add the builtin $signed system function. + * * Revision 1.13 2002/01/28 00:52:41 steve * Add support for bit select of parameters. * This leads to a NetESelect node and the diff --git a/eval_tree.cc b/eval_tree.cc index d3e856f7e..eaed243e7 100644 --- a/eval_tree.cc +++ b/eval_tree.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: eval_tree.cc,v 1.37 2002/04/27 05:03:46 steve Exp $" +#ident "$Id: eval_tree.cc,v 1.38 2002/05/05 21:11:50 steve Exp $" #endif # include "config.h" @@ -705,6 +705,9 @@ NetEConst* NetEBShift::eval_tree() NetEConst* NetEConcat::eval_tree() { + unsigned repeat_val = repeat(); + + unsigned gap = 0; for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) { // Parameter not here? This is an error, but presumably @@ -712,10 +715,13 @@ NetEConst* NetEConcat::eval_tree() if (parms_[idx] == 0) continue; + // If this parameter is already a constant, all is well // so go on. - if (dynamic_cast(parms_[idx])) + if (dynamic_cast(parms_[idx])) { + gap += parms_[idx]->expr_width(); continue; + } // Finally, try to evaluate the parameter expression // that is here. If I succeed, reset the parameter to @@ -725,23 +731,24 @@ NetEConst* NetEConcat::eval_tree() if (expr) { delete parms_[idx]; parms_[idx] = expr; + gap += expr->expr_width(); } } // Handle the special case that the repeat expression is // zero. In this case, just return a 0 value with the expected // width. - if (repeat_ == 0) { + if (repeat_val == 0) { verinum val (verinum::V0, expr_width()); NetEConst*res = new NetEConst(val); res->set_width(val.len()); return res; } - // Figure out the width of the repeated expression, and make a - // verinum to hold the result. - unsigned gap = expr_width() / repeat_; - verinum val (verinum::Vx, repeat_ * gap); + // At this point, the "gap" is the width of a single repeat of + // the concatenation. The total width of the result is the gap + // times the repeat count. + verinum val (verinum::Vx, repeat_val * gap); // build up the result from least significant to most. @@ -754,7 +761,7 @@ NetEConst* NetEConcat::eval_tree() verinum tmp = expr->value(); for (unsigned bit = 0; bit < tmp.len(); bit += 1, cur += 1) - for (unsigned rep = 0 ; rep < repeat_ ; rep += 1) + for (unsigned rep = 0 ; rep < repeat_val ; rep += 1) val.set(rep*gap+cur, tmp[bit]); is_string_flag = is_string_flag && tmp.is_string(); @@ -1079,6 +1086,13 @@ NetEConst* NetEUReduce::eval_tree() /* * $Log: eval_tree.cc,v $ + * Revision 1.38 2002/05/05 21:11:50 steve + * Put off evaluation of concatenation repeat expresions + * until after parameters are defined. This allows parms + * to be used in repeat expresions. + * + * Add the builtin $signed system function. + * * Revision 1.37 2002/04/27 05:03:46 steve * Preserve stringiness string part select and concatenation. * diff --git a/net_expr.cc b/net_expr.cc index 6481fdb68..b128c3e0f 100644 --- a/net_expr.cc +++ b/net_expr.cc @@ -17,12 +17,98 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: net_expr.cc,v 1.2 2002/01/29 22:36:31 steve Exp $" +#ident "$Id: net_expr.cc,v 1.3 2002/05/05 21:11:50 steve Exp $" #endif # include "config.h" # include "netlist.h" +NetEConcat::NetEConcat(unsigned cnt, NetExpr* r) +: parms_(cnt), repeat_(r) +{ + if (repeat_ == 0) { + repeat_calculated_ = true; + repeat_value_ = 1; + } else { + repeat_calculated_ = false; + } + + expr_width(0); +} + +NetEConcat::~NetEConcat() +{ + for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) + delete parms_[idx]; +} + +void NetEConcat::set(unsigned idx, NetExpr*e) +{ + assert(idx < parms_.count()); + assert(parms_[idx] == 0); + parms_[idx] = e; + expr_width( expr_width() + e->expr_width() ); +} + +NetEConcat* NetEConcat::dup_expr() const +{ + NetEConcat*dup = new NetEConcat(parms_.count(), repeat_); + for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) + if (parms_[idx]) { + NetExpr*tmp = parms_[idx]->dup_expr(); + assert(tmp); + dup->parms_[idx] = tmp; + } + + + dup->expr_width(expr_width()); + return dup; +} + +unsigned NetEConcat::repeat() +{ + if (repeat_calculated_) + return repeat_value_; + + assert(repeat_); + + if (! dynamic_cast(repeat_)) { + NetExpr*tmp = repeat_->eval_tree(); + if (tmp != 0) { + delete repeat_; + repeat_ = tmp; + } + } + + NetEConst*repeat_const = dynamic_cast(repeat_); + + /* This should not be possible, as it was checked earlier to + assure that this is a constant expression. */ + if (repeat_const == 0) { + cerr << get_line() << ": internal error: repeat expression " + << "is not a compile time constant." << endl; + cerr << get_line() << ": : Expression is: " + << *repeat_ << endl; + repeat_calculated_ = true; + repeat_value_ = 1; + return 1; + } + + repeat_calculated_ = true; + repeat_value_ = repeat_const->value().as_ulong(); + + delete repeat_; + repeat_ = 0; + + return repeat_value_; +} + +unsigned NetEConcat::repeat() const +{ + assert(repeat_calculated_); + return repeat_value_; +} + NetESelect::NetESelect(NetExpr*exp, NetExpr*base, unsigned wid) : expr_(exp), base_(base) { @@ -60,6 +146,13 @@ bool NetESelect::set_width(unsigned w) /* * $Log: net_expr.cc,v $ + * Revision 1.3 2002/05/05 21:11:50 steve + * Put off evaluation of concatenation repeat expresions + * until after parameters are defined. This allows parms + * to be used in repeat expresions. + * + * Add the builtin $signed system function. + * * Revision 1.2 2002/01/29 22:36:31 steve * include config.h to eliminate warnings. * diff --git a/netlist.cc b/netlist.cc index 02f621947..bd158a9ab 100644 --- a/netlist.cc +++ b/netlist.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: netlist.cc,v 1.184 2002/04/21 04:59:08 steve Exp $" +#ident "$Id: netlist.cc,v 1.185 2002/05/05 21:11:50 steve Exp $" #endif # include "config.h" @@ -1983,41 +1983,6 @@ NetEBShift* NetEBShift::dup_expr() const return result; } -NetEConcat::NetEConcat(unsigned cnt, unsigned r) -: parms_(cnt), repeat_(r) -{ - expr_width(0); -} - -NetEConcat::~NetEConcat() -{ - for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) - delete parms_[idx]; -} - -void NetEConcat::set(unsigned idx, NetExpr*e) -{ - assert(idx < parms_.count()); - assert(parms_[idx] == 0); - parms_[idx] = e; - expr_width( expr_width() + repeat_*e->expr_width() ); -} - -NetEConcat* NetEConcat::dup_expr() const -{ - NetEConcat*dup = new NetEConcat(parms_.count(), repeat_); - for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) - if (parms_[idx]) { - NetExpr*tmp = parms_[idx]->dup_expr(); - assert(tmp); - dup->parms_[idx] = tmp; - } - - - dup->expr_width(expr_width()); - return dup; -} - NetEConst::NetEConst(const verinum&val) : NetExpr(val.len()), value_(val) { @@ -2394,6 +2359,13 @@ const NetProc*NetTaskDef::proc() const /* * $Log: netlist.cc,v $ + * Revision 1.185 2002/05/05 21:11:50 steve + * Put off evaluation of concatenation repeat expresions + * until after parameters are defined. This allows parms + * to be used in repeat expresions. + * + * Add the builtin $signed system function. + * * Revision 1.184 2002/04/21 04:59:08 steve * Add support for conbinational events by finding * the inputs to expressions and some statements. diff --git a/netlist.h b/netlist.h index ce8824b7f..633d1cfc6 100644 --- a/netlist.h +++ b/netlist.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: netlist.h,v 1.235 2002/04/21 22:31:02 steve Exp $" +#ident "$Id: netlist.h,v 1.236 2002/05/05 21:11:50 steve Exp $" #endif /* @@ -2332,13 +2332,14 @@ class NetEBShift : public NetEBinary { class NetEConcat : public NetExpr { public: - NetEConcat(unsigned cnt, unsigned repeat =1); + NetEConcat(unsigned cnt, NetExpr* repeat =0); ~NetEConcat(); // Manipulate the parameters. void set(unsigned idx, NetExpr*e); - unsigned repeat() const { return repeat_; } + unsigned repeat(); + unsigned repeat() const; unsigned nparms() const { return parms_.count() ; } NetExpr* parm(unsigned idx) const { return parms_[idx]; } @@ -2352,7 +2353,9 @@ class NetEConcat : public NetExpr { private: svectorparms_; - unsigned repeat_; + NetExpr* repeat_; + unsigned repeat_value_; + bool repeat_calculated_; }; /* @@ -2977,6 +2980,13 @@ extern ostream& operator << (ostream&, NetNet::Type); /* * $Log: netlist.h,v $ + * Revision 1.236 2002/05/05 21:11:50 steve + * Put off evaluation of concatenation repeat expresions + * until after parameters are defined. This allows parms + * to be used in repeat expresions. + * + * Add the builtin $signed system function. + * * Revision 1.235 2002/04/21 22:31:02 steve * Redo handling of assignment internal delays. * Leave it possible for them to be calculated diff --git a/set_width.cc b/set_width.cc index ecbf5b39c..e3d76a099 100644 --- a/set_width.cc +++ b/set_width.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: set_width.cc,v 1.21 2002/04/27 04:49:27 steve Exp $" +#ident "$Id: set_width.cc,v 1.22 2002/05/05 21:11:50 steve Exp $" #endif # include "config.h" @@ -220,7 +220,7 @@ bool NetEConcat::set_width(unsigned w) if (parms_[idx] != 0) sum += parms_[idx]->expr_width(); - sum *= repeat_; + sum *= repeat(); expr_width(sum); if (sum != w) return false; return true; @@ -357,6 +357,13 @@ bool NetEUReduce::set_width(unsigned w) /* * $Log: set_width.cc,v $ + * Revision 1.22 2002/05/05 21:11:50 steve + * Put off evaluation of concatenation repeat expresions + * until after parameters are defined. This allows parms + * to be used in repeat expresions. + * + * Add the builtin $signed system function. + * * Revision 1.21 2002/04/27 04:49:27 steve * If the verinum is already right, no need to reset it. *