From 7ef3b44ab1b1770cba55ab3cc91c072e2cab9b79 Mon Sep 17 00:00:00 2001 From: steve Date: Fri, 9 Feb 2001 05:44:23 +0000 Subject: [PATCH] support evaluation of constant < in expressions. --- elab_expr.cc | 69 ++++++++++++++++++++++++++++++++++++++++++++++------ elaborate.cc | 11 ++++++--- eval_tree.cc | 52 ++++++++++++++++++++++++++++++++++++++- netlist.h | 6 ++++- verinum.cc | 30 +++++++++++++++++++++-- verinum.h | 6 ++++- 6 files changed, 158 insertions(+), 16 deletions(-) diff --git a/elab_expr.cc b/elab_expr.cc index 5904e1074..356db14c9 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.34 2001/01/14 23:04:55 steve Exp $" +#ident "$Id: elab_expr.cc,v 1.35 2001/02/09 05:44:23 steve Exp $" #endif @@ -145,6 +145,12 @@ NetEBinary* PEBinary::elaborate_expr_base_(Design*des, return tmp; } +/* + * Given a call to a system function, generate the proper expression + * nodes to represent the call in the netlist. Since we don't support + * size_tf functions, make assumptions about widths based on some + * known function names. + */ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope) const { unsigned wid = 32; @@ -152,11 +158,43 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope) const if (name_ == "$time") wid = 64; - NetESFunc*fun = new NetESFunc(name_, wid, parms_.count()); - for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) { + + /* How many parameters are there? The Verilog language allows + empty parameters in certain contexts, so the parser will + allow things like func(1,,3). It will also cause func() to + be interpreted as a single empty parameter. + + Functions cannot really take empty parameters, but the + case ``func()'' is the same as no parmaters at all. So + catch that special case here. */ + unsigned nparms = parms_.count(); + if ((nparms == 1) && (parms_[0] == 0)) + nparms = 0; + + NetESFunc*fun = new NetESFunc(name_, wid, nparms); + + /* Now run through the expected parameters. If we find that + there are missing parameters, print an error message. */ + + unsigned missing_parms = 0; + for (unsigned idx = 0 ; idx < nparms ; idx += 1) { PExpr*expr = parms_[idx]; - NetExpr*tmp = expr->elaborate_expr(des, scope); - fun->parm(idx, tmp); + if (expr) { + NetExpr*tmp = expr->elaborate_expr(des, scope); + fun->parm(idx, tmp); + + } else { + missing_parms += 1; + fun->parm(idx, 0); + } + } + + if (missing_parms > 0) { + cerr << get_line() << ": error: The function " << name_ + << " has been called with empty parameters." << endl; + cerr << get_line() << ": : Verilog doesn't allow " + << "passing empty parameters to functions." << endl; + des->errors += 1; } return fun; @@ -195,10 +233,24 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope) const of the function being called. The scope of the called function is elaborated when the definition is elaborated. */ + unsigned missing_parms = 0; for (unsigned idx = 0 ; idx < parms.count() ; idx += 1) { PExpr*tmp = parms_[idx]; - assert(tmp); - parms[idx] = tmp->elaborate_expr(des, scope); + if (tmp) { + parms[idx] = tmp->elaborate_expr(des, scope); + + } else { + missing_parms += 1; + parms[idx] = 0; + } + } + + if (missing_parms > 0) { + cerr << get_line() << ": error: The function " << name_ + << " has been called with empty parameters." << endl; + cerr << get_line() << ": : Verilog doesn't allow " + << "passing empty parameters to functions." << endl; + des->errors += 1; } @@ -545,6 +597,9 @@ NetEUnary* PEUnary::elaborate_expr(Design*des, NetScope*scope) const /* * $Log: elab_expr.cc,v $ + * Revision 1.35 2001/02/09 05:44:23 steve + * support evaluation of constant < in expressions. + * * Revision 1.34 2001/01/14 23:04:55 steve * Generalize the evaluation of floating point delays, and * get it working with delay assignment statements. diff --git a/elaborate.cc b/elaborate.cc index ac39ed207..153291c48 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: elaborate.cc,v 1.206 2001/02/07 21:47:13 steve Exp $" +#ident "$Id: elaborate.cc,v 1.207 2001/02/09 05:44:23 steve Exp $" #endif /* @@ -2031,10 +2031,10 @@ NetProc* PForStatement::elaborate(Design*des, const string&path) const } if (NetExpr*tmp = ce->eval_tree()) { - if (dynamic_cast(tmp)) + if (dynamic_cast(tmp)) { cerr << get_line() << ": warning: condition expression " - "is constant." << endl; - + "of for-loop is constant." << endl; + } ce = tmp; } @@ -2367,6 +2367,9 @@ Design* elaborate(const map&modules, /* * $Log: elaborate.cc,v $ + * Revision 1.207 2001/02/09 05:44:23 steve + * support evaluation of constant < in expressions. + * * Revision 1.206 2001/02/07 21:47:13 steve * Fix expression widths for rvalues and parameters (PR#131,132) * diff --git a/eval_tree.cc b/eval_tree.cc index 62a2ffbe6..d8bc9e80b 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.22 2001/02/07 02:46:31 steve Exp $" +#ident "$Id: eval_tree.cc,v 1.23 2001/02/09 05:44:23 steve Exp $" #endif # include "netlist.h" @@ -161,6 +161,50 @@ NetEConst* NetEBComp::eval_eqeq_() } +NetEConst* NetEBComp::eval_less_() +{ + NetEConst*r = dynamic_cast(right_); + if (r == 0) return 0; + + verinum rv = r->value(); + if (! rv.is_defined()) { + verinum result(verinum::Vx, 1); + return new NetEConst(result); + } + + /* Detect the case where the right side is greater that or + equal to the largest value the left side can possibly + have. */ + assert(left_->expr_width() > 0); + verinum lv (verinum::V1, left_->expr_width()); + if (lv < rv) { + verinum result(verinum::V1, 1); + return new NetEConst(result); + } + + /* Now go on to the normal test of the values. */ + NetEConst*l = dynamic_cast(left_); + if (l == 0) return 0; + lv = l->value(); + if (! lv.is_defined()) { + verinum result(verinum::Vx, 1); + return new NetEConst(result); + } + + if (lv.has_sign() && rv.has_sign() && (lv.as_long() < rv.as_long())) { + verinum result(verinum::V1, 1); + return new NetEConst(result); + } + + if (lv.as_ulong() < rv.as_ulong()) { + verinum result(verinum::V1, 1); + return new NetEConst(result); + } + + verinum result(verinum::V0, 1); + return new NetEConst(result); +} + NetEConst* NetEBComp::eval_leeq_() { NetEConst*r = dynamic_cast(right_); @@ -358,6 +402,9 @@ NetEConst* NetEBComp::eval_tree() case 'n': // not-equal (!=) return eval_neeq_(); + case '<': // Less than + return eval_less_(); + default: return 0; } @@ -843,6 +890,9 @@ NetEConst* NetEUReduce::eval_tree() /* * $Log: eval_tree.cc,v $ + * Revision 1.23 2001/02/09 05:44:23 steve + * support evaluation of constant < in expressions. + * * Revision 1.22 2001/02/07 02:46:31 steve * Support constant evaluation of / and % (PR#124) * diff --git a/netlist.h b/netlist.h index a6a5bece5..51ef45cf9 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.195 2001/01/18 03:16:35 steve Exp $" +#ident "$Id: netlist.h,v 1.196 2001/02/09 05:44:23 steve Exp $" #endif /* @@ -2182,6 +2182,7 @@ class NetEBComp : public NetEBinary { private: NetEConst*eval_eqeq_(); + NetEConst*eval_less_(); NetEConst*eval_leeq_(); NetEConst*eval_neeq_(); NetEConst*eval_eqeqeq_(); @@ -2852,6 +2853,9 @@ extern ostream& operator << (ostream&, NetNet::Type); /* * $Log: netlist.h,v $ + * Revision 1.196 2001/02/09 05:44:23 steve + * support evaluation of constant < in expressions. + * * Revision 1.195 2001/01/18 03:16:35 steve * NetMux needs a scope. (PR#115) * diff --git a/verinum.cc b/verinum.cc index af11c7fe5..6ff3e65fd 100644 --- a/verinum.cc +++ b/verinum.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: verinum.cc,v 1.25 2001/02/08 05:38:18 steve Exp $" +#ident "$Id: verinum.cc,v 1.26 2001/02/09 05:44:23 steve Exp $" #endif # include "verinum.h" @@ -420,7 +420,7 @@ verinum::V operator <= (const verinum&left, const verinum&right) } for (idx = right.len() ; idx > left.len() ; idx -= 1) { - if (right[idx-1] != verinum::V0) return verinum::V0; + if (right[idx-1] != verinum::V0) return verinum::V1; } while (idx > 0) { @@ -435,6 +435,29 @@ verinum::V operator <= (const verinum&left, const verinum&right) return verinum::V1; } +verinum::V operator < (const verinum&left, const verinum&right) +{ + unsigned idx; + for (idx = left.len() ; idx > right.len() ; idx -= 1) { + if (left[idx-1] != verinum::V0) return verinum::V0; + } + + for (idx = right.len() ; idx > left.len() ; idx -= 1) { + if (right[idx-1] != verinum::V0) return verinum::V1; + } + + while (idx > 0) { + if (left[idx-1] == verinum::Vx) return verinum::Vx; + if (left[idx-1] == verinum::Vz) return verinum::Vx; + if (right[idx-1] == verinum::Vx) return verinum::Vx; + if (right[idx-1] == verinum::Vz) return verinum::Vx; + if (left[idx-1] > right[idx-1]) return verinum::V0; + idx -= 1; + } + + return verinum::V0; +} + static verinum::V add_with_carry(verinum::V l, verinum::V r, verinum::V&c) { unsigned sum = 0; @@ -743,6 +766,9 @@ verinum::V operator & (verinum::V l, verinum::V r) /* * $Log: verinum.cc,v $ + * Revision 1.26 2001/02/09 05:44:23 steve + * support evaluation of constant < in expressions. + * * Revision 1.25 2001/02/08 05:38:18 steve * trim the length of unsized numbers. * diff --git a/verinum.h b/verinum.h index 9e792e9d6..b238305c5 100644 --- a/verinum.h +++ b/verinum.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: verinum.h,v 1.16 2001/02/07 02:46:31 steve Exp $" +#ident "$Id: verinum.h,v 1.17 2001/02/09 05:44:23 steve Exp $" #endif # include @@ -110,6 +110,7 @@ extern verinum::V operator & (verinum::V l, verinum::V r); extern verinum::V operator == (const verinum&left, const verinum&right); extern verinum::V operator <= (const verinum&left, const verinum&right); +extern verinum::V 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 operator * (const verinum&left, const verinum&right); @@ -120,6 +121,9 @@ extern verinum v_not(const verinum&left); /* * $Log: verinum.h,v $ + * Revision 1.17 2001/02/09 05:44:23 steve + * support evaluation of constant < in expressions. + * * Revision 1.16 2001/02/07 02:46:31 steve * Support constant evaluation of / and % (PR#124) *