diff --git a/Makefile.in b/Makefile.in index e060649a6..7c077ae0d 100644 --- a/Makefile.in +++ b/Makefile.in @@ -16,7 +16,7 @@ # 59 Temple Place - Suite 330 # Boston, MA 02111-1307, USA # -#ident "$Id: Makefile.in,v 1.90 2001/01/14 23:04:55 steve Exp $" +#ident "$Id: Makefile.in,v 1.91 2001/02/10 20:29:39 steve Exp $" # # SHELL = /bin/sh @@ -98,7 +98,7 @@ O = main.o cprop.o design_dump.o dup_expr.o elaborate.o elab_expr.o \ elab_lval.o elab_net.o elab_anet.o elab_pexpr.o elab_scope.o \ elab_sig.o emit.o eval.o eval_rconst.o \ eval_tree.o expr_synth.o functor.o lexor.o lexor_keyword.o link_const.o \ -mangle.o netlist.o net_assign.o \ +mangle.o netlist.o netmisc.o net_assign.o \ net_design.o net_event.o net_force.o net_link.o net_modulo.o net_proc.o \ net_scope.o net_udp.o pad_to_width.o \ parse.o parse_misc.o pform.o pform_dump.o \ diff --git a/elab_expr.cc b/elab_expr.cc index 356db14c9..b83cea640 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -17,12 +17,13 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: elab_expr.cc,v 1.35 2001/02/09 05:44:23 steve Exp $" +#ident "$Id: elab_expr.cc,v 1.36 2001/02/10 20:29:39 steve Exp $" #endif # include "pform.h" # include "netlist.h" +# include "netmisc.h" NetExpr* PExpr::elaborate_expr(Design*des, NetScope*) const { @@ -174,14 +175,23 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope) const 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. */ + there are missing parameters, print an error message. + + While we're at it, try to evaluate the function parameter + expression as much as possible, and use the reduced + expression if one is created. */ unsigned missing_parms = 0; for (unsigned idx = 0 ; idx < nparms ; idx += 1) { PExpr*expr = parms_[idx]; if (expr) { - NetExpr*tmp = expr->elaborate_expr(des, scope); - fun->parm(idx, tmp); + NetExpr*tmp1 = expr->elaborate_expr(des, scope); + if (NetExpr*tmp2 = tmp1->eval_tree()) { + delete tmp1; + fun->parm(idx, tmp2); + } else { + fun->parm(idx, tmp1); + } } else { missing_parms += 1; @@ -283,17 +293,21 @@ NetExpr* PEConcat::elaborate_expr(Design*des, NetScope*scope) const /* If there is a repeat expression, then evaluate the constant value and set the repeat count. */ if (repeat_) { - verinum*vrep = repeat_->eval_const(des, scope->name()); - if (vrep == 0) { + NetExpr*tmp = elab_and_eval(des, scope, repeat_); + assert(tmp); + NetEConst*rep = dynamic_cast(tmp); + + if (rep == 0) { cerr << get_line() << ": error: " "concatenation repeat expression cannot be evaluated." << endl; + cerr << get_line() << ": : The expression is: " + << *tmp << endl; des->errors += 1; return 0; } - repeat = vrep->as_ulong(); - delete vrep; + repeat = rep->value().as_ulong(); } /* Make the empty concat expression. */ @@ -597,6 +611,10 @@ NetEUnary* PEUnary::elaborate_expr(Design*des, NetScope*scope) const /* * $Log: elab_expr.cc,v $ + * Revision 1.36 2001/02/10 20:29:39 steve + * In the context of range declarations, use elab_and_eval instead + * of the less robust eval_const methods. + * * Revision 1.35 2001/02/09 05:44:23 steve * support evaluation of constant < in expressions. * diff --git a/elab_sig.cc b/elab_sig.cc index 3edf46122..0da41d735 100644 --- a/elab_sig.cc +++ b/elab_sig.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_sig.cc,v 1.10 2001/01/13 22:20:08 steve Exp $" +#ident "$Id: elab_sig.cc,v 1.11 2001/02/10 20:29:39 steve Exp $" #endif # include "Module.h" @@ -26,6 +26,7 @@ # include "PTask.h" # include "PWire.h" # include "netlist.h" +# include "netmisc.h" # include "util.h" /* @@ -320,27 +321,35 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const here. I will resolve the values later. */ for (unsigned idx = 0 ; idx < msb_.count() ; idx += 1) { - verinum*mval = msb_[idx]->eval_const(des,path); - if (mval == 0) { + + NetEConst*tmp; + NetExpr*texpr = elab_and_eval(des, scope, msb_[idx]); + + tmp = dynamic_cast(texpr); + if (tmp == 0) { cerr << msb_[idx]->get_line() << ": error: " "Unable to evaluate constant expression ``" << *msb_[idx] << "''." << endl; des->errors += 1; return; } - verinum*lval = lsb_[idx]->eval_const(des, path); - if (lval == 0) { - cerr << lsb_[idx]->get_line() << ": error: " + + mnum[idx] = tmp->value().as_long(); + delete texpr; + + texpr = elab_and_eval(des, scope, lsb_[idx]); + tmp = dynamic_cast(texpr); + if (tmp == 0) { + cerr << msb_[idx]->get_line() << ": error: " "Unable to evaluate constant expression ``" << *lsb_[idx] << "''." << endl; des->errors += 1; return; } - mnum[idx] = mval->as_long(); - lnum[idx] = lval->as_long(); - delete mval; - delete lval; + lnum[idx] = tmp->value().as_long(); + delete texpr; + } /* Make sure all the values for msb and lsb match by @@ -404,6 +413,10 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const /* * $Log: elab_sig.cc,v $ + * Revision 1.11 2001/02/10 20:29:39 steve + * In the context of range declarations, use elab_and_eval instead + * of the less robust eval_const methods. + * * Revision 1.10 2001/01/13 22:20:08 steve * Parse parameters within nested scopes. * diff --git a/eval_tree.cc b/eval_tree.cc index d8bc9e80b..c9eff44a0 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.23 2001/02/09 05:44:23 steve Exp $" +#ident "$Id: eval_tree.cc,v 1.24 2001/02/10 20:29:39 steve Exp $" #endif # include "netlist.h" @@ -249,6 +249,92 @@ NetEConst* NetEBComp::eval_leeq_() return new NetEConst(result); } +NetEConst* NetEBComp::eval_gt_() +{ + NetEConst*l = dynamic_cast(left_); + if (l == 0) return 0; + + verinum lv = l->value(); + if (! lv.is_defined()) { + verinum result(verinum::Vx, 1); + return new NetEConst(result); + } + + /* Detect the case where the left side is greater than the + largest value the right side can possibly have. */ + assert(right_->expr_width() > 0); + verinum rv (verinum::V1, right_->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*r = dynamic_cast(right_); + if (r == 0) return 0; + rv = r->value(); + if (! rv.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_gteq_() +{ + NetEConst*l = dynamic_cast(left_); + if (l == 0) return 0; + + verinum lv = l->value(); + if (! lv.is_defined()) { + verinum result(verinum::Vx, 1); + return new NetEConst(result); + } + + /* Detect the case where the left side is greater than the + largest value the right side can possibly have. */ + assert(right_->expr_width() > 0); + verinum rv (verinum::V1, right_->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*r = dynamic_cast(right_); + if (r == 0) return 0; + rv = r->value(); + if (! rv.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_neeq_() { NetEConst*l = dynamic_cast(left_); @@ -393,6 +479,9 @@ NetEConst* NetEBComp::eval_tree() case 'e': // Equality (==) return eval_eqeq_(); + case 'G': // >= + return eval_gteq_(); + case 'L': // <= return eval_leeq_(); @@ -405,6 +494,9 @@ NetEConst* NetEBComp::eval_tree() case '<': // Less than return eval_less_(); + case '>': // Greater then + return eval_gt_(); + default: return 0; } @@ -890,6 +982,10 @@ NetEConst* NetEUReduce::eval_tree() /* * $Log: eval_tree.cc,v $ + * Revision 1.24 2001/02/10 20:29:39 steve + * In the context of range declarations, use elab_and_eval instead + * of the less robust eval_const methods. + * * Revision 1.23 2001/02/09 05:44:23 steve * support evaluation of constant < in expressions. * diff --git a/netlist.h b/netlist.h index 51ef45cf9..14c023722 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.196 2001/02/09 05:44:23 steve Exp $" +#ident "$Id: netlist.h,v 1.197 2001/02/10 20:29:39 steve Exp $" #endif /* @@ -2184,6 +2184,8 @@ class NetEBComp : public NetEBinary { NetEConst*eval_eqeq_(); NetEConst*eval_less_(); NetEConst*eval_leeq_(); + NetEConst*eval_gt_(); + NetEConst*eval_gteq_(); NetEConst*eval_neeq_(); NetEConst*eval_eqeqeq_(); NetEConst*eval_neeqeq_(); @@ -2853,6 +2855,10 @@ extern ostream& operator << (ostream&, NetNet::Type); /* * $Log: netlist.h,v $ + * Revision 1.197 2001/02/10 20:29:39 steve + * In the context of range declarations, use elab_and_eval instead + * of the less robust eval_const methods. + * * Revision 1.196 2001/02/09 05:44:23 steve * support evaluation of constant < in expressions. * diff --git a/netmisc.h b/netmisc.h index f6b1da5db..413951b5c 100644 --- a/netmisc.h +++ b/netmisc.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: netmisc.h,v 1.10 2000/11/20 00:58:40 steve Exp $" +#ident "$Id: netmisc.h,v 1.11 2001/02/10 20:29:39 steve Exp $" #endif # include "netlist.h" @@ -54,9 +54,20 @@ extern verinum::V driven_value(const Link&lnk); */ extern unsigned count_lval_width(const class NetAssign_*first); +/* + * This function elaborates an expression, and tries to evaluate it + * right away. It is useful for those places where the user is + * supposed to supply a constant expression. + */ +class PExpr; +extern NetExpr* elab_and_eval(Design*des, NetScope*scope, const PExpr*pe); /* * $Log: netmisc.h,v $ + * Revision 1.11 2001/02/10 20:29:39 steve + * In the context of range declarations, use elab_and_eval instead + * of the less robust eval_const methods. + * * Revision 1.10 2000/11/20 00:58:40 steve * Add support for supply nets (PR#17) * @@ -69,32 +80,5 @@ extern unsigned count_lval_width(const class NetAssign_*first); * * Revision 1.7 2000/05/14 17:55:04 steve * Support initialization of FF Q value. - * - * Revision 1.6 2000/05/07 04:37:56 steve - * Carry strength values from Verilog source to the - * pform and netlist for gates. - * - * Change vvm constants to use the driver_t to drive - * a constant value. This works better if there are - * multiple drivers on a signal. - * - * Revision 1.5 2000/04/20 00:28:03 steve - * Catch some simple identity compareoptimizations. - * - * Revision 1.4 2000/03/16 19:03:03 steve - * Revise the VVM backend to use nexus objects so that - * drivers and resolution functions can be used, and - * the t-vvm module doesn't need to write a zillion - * output functions. - * - * Revision 1.3 2000/02/23 02:56:55 steve - * Macintosh compilers do not support ident. - * - * Revision 1.2 2000/02/16 03:58:27 steve - * Fix up width matching in structural bitwise operators. - * - * Revision 1.1 1999/09/29 00:42:51 steve - * Allow expanding of additive operators. - * */ #endif diff --git a/verinum.h b/verinum.h index b238305c5..87082c955 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.17 2001/02/09 05:44:23 steve Exp $" +#ident "$Id: verinum.h,v 1.18 2001/02/10 20:29:39 steve Exp $" #endif # include @@ -117,10 +117,20 @@ 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); +inline verinum::V operator > (const verinum&left, const verinum&right) +{ return right < left; } + +inline verinum::V operator >= (const verinum&left, const verinum&right) +{ return right <= left; } + extern verinum v_not(const verinum&left); /* * $Log: verinum.h,v $ + * Revision 1.18 2001/02/10 20:29:39 steve + * In the context of range declarations, use elab_and_eval instead + * of the less robust eval_const methods. + * * Revision 1.17 2001/02/09 05:44:23 steve * support evaluation of constant < in expressions. *