diff --git a/elaborate.cc b/elaborate.cc index c37e28c30..7e4449dd8 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -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.363 2007/03/05 05:59:10 steve Exp $" +#ident "$Id: elaborate.cc,v 1.364 2007/03/08 05:30:02 steve Exp $" #endif # include "config.h" @@ -1442,8 +1442,9 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const 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); + /* Now elaborate to the expected width. Pass the lwidth to + prune any constant result to fit with the lvalue at hand. */ + NetExpr*rv = elab_and_eval(des, scope, rval(), use_width, lv->lwidth()); if (rv == 0) return 0; assert(rv); @@ -3400,6 +3401,9 @@ Design* elaborate(listroots) /* * $Log: elaborate.cc,v $ + * Revision 1.364 2007/03/08 05:30:02 steve + * Limit the calculated widths of constants. + * * Revision 1.363 2007/03/05 05:59:10 steve * Handle processes within generate loops. * diff --git a/eval_tree.cc b/eval_tree.cc index d2f74fc16..69a336555 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 */ #ifdef HAVE_CVS_IDENT -#ident "$Id: eval_tree.cc,v 1.73 2007/01/16 05:44:15 steve Exp $" +#ident "$Id: eval_tree.cc,v 1.74 2007/03/08 05:30:02 steve Exp $" #endif # include "config.h" @@ -27,7 +27,7 @@ # include "netlist.h" -NetExpr* NetExpr::eval_tree() +NetExpr* NetExpr::eval_tree(int prune_to_width) { return 0; } @@ -51,7 +51,7 @@ void NetEBinary::eval_sub_tree_() } } -NetEConst* NetEBAdd::eval_tree() +NetEConst* NetEBAdd::eval_tree(int prune_to_width) { eval_sub_tree_(); NetEConst*lc = dynamic_cast(left_); @@ -115,7 +115,7 @@ NetEConst* NetEBAdd::eval_tree() return 0; } -NetEConst* NetEBBits::eval_tree() +NetEConst* NetEBBits::eval_tree(int prune_to_width) { eval_sub_tree_(); @@ -690,7 +690,7 @@ NetEConst* NetEBComp::eval_neeqeq_() return res; } -NetEConst* NetEBComp::eval_tree() +NetEConst* NetEBComp::eval_tree(int prune_to_width) { eval_sub_tree_(); @@ -728,7 +728,7 @@ NetEConst* NetEBComp::eval_tree() * The NetEBDiv operator includes the / and % operators. First evaluate * the sub-expressions, then perform the required operation. */ -NetExpr* NetEBDiv::eval_tree() +NetExpr* NetEBDiv::eval_tree(int prune_to_width) { eval_sub_tree_(); @@ -798,7 +798,7 @@ NetExpr* NetEBDiv::eval_tree() return 0; } -NetEConst* NetEBLogic::eval_tree() +NetEConst* NetEBLogic::eval_tree(int prune_to_width) { eval_sub_tree_(); NetEConst*lc = dynamic_cast(left_); @@ -917,7 +917,7 @@ NetExpr* NetEBMult::eval_tree_real_() return res; } -NetExpr* NetEBMult::eval_tree() +NetExpr* NetEBMult::eval_tree(int prune_to_width) { eval_sub_tree_(); @@ -990,7 +990,7 @@ NetExpr* NetEBPow::eval_tree_real_() return res; } -NetExpr* NetEBPow::eval_tree() +NetExpr* NetEBPow::eval_tree(int prune_to_width) { eval_sub_tree_(); @@ -1015,7 +1015,7 @@ NetExpr* NetEBPow::eval_tree() * Evaluate the shift operator if possible. For this to work, both * operands must be constant. */ -NetEConst* NetEBShift::eval_tree() +NetEConst* NetEBShift::eval_tree(int prune_to_width) { eval_sub_tree_(); NetEConst*re = dynamic_cast(right_); @@ -1042,7 +1042,7 @@ NetEConst* NetEBShift::eval_tree() cerr << get_line() << ": debug: " << "Evaluate " << lv << "<<" << op() << ">> " << rv << ", wid=" << wid << ", shift=" << shift - << ", lv.las_len()=" << lv.has_len() << endl; + << ", lv.has_len()=" << lv.has_len() << endl; } if ((wid == 0) || ! lv.has_len()) { @@ -1056,6 +1056,9 @@ NetEConst* NetEBShift::eval_tree() wid = lv.len() + shift; } + if (prune_to_width > 0 && wid > prune_to_width) + wid = prune_to_width; + assert(wid); verinum nv (verinum::V0, wid, lv.has_len()); @@ -1096,7 +1099,7 @@ NetEConst* NetEBShift::eval_tree() return res; } -NetEConst* NetEConcat::eval_tree() +NetEConst* NetEConcat::eval_tree(int prune_to_width) { unsigned repeat_val = repeat(); unsigned local_errors = 0; @@ -1190,7 +1193,7 @@ NetEConst* NetEConcat::eval_tree() return res; } -NetExpr* NetEParam::eval_tree() +NetExpr* NetEParam::eval_tree(int prune_to_width) { if (des_ == 0) { assert(scope_ == 0); @@ -1297,7 +1300,7 @@ NetExpr* NetEParam::eval_tree() } } -NetEConst* NetESelect::eval_tree() +NetEConst* NetESelect::eval_tree(int prune_to_width) { NetEConst*expr = dynamic_cast(expr_); if (expr == 0) { @@ -1370,7 +1373,7 @@ NetEConst* NetESelect::eval_tree() * evaluates to x or z, then merge the constant bits of the true and * false expressions. */ -NetExpr* NetETernary::eval_tree() +NetExpr* NetETernary::eval_tree(int prune_to_width) { NetExpr*tmp; @@ -1507,7 +1510,7 @@ void NetEUnary::eval_expr_() expr_ = oper; } -NetEConst* NetEUnary::eval_tree() +NetEConst* NetEUnary::eval_tree(int prune_to_width) { eval_expr_(); NetEConst*rval = dynamic_cast(expr_); @@ -1564,12 +1567,12 @@ NetEConst* NetEUnary::eval_tree() } -NetEConst* NetEUBits::eval_tree() +NetEConst* NetEUBits::eval_tree(int prune_to_width) { - return NetEUnary::eval_tree(); + return NetEUnary::eval_tree(prune_to_width); } -NetEConst* NetEUReduce::eval_tree() +NetEConst* NetEUReduce::eval_tree(int prune_to_width) { eval_expr_(); NetEConst*rval = dynamic_cast(expr_); @@ -1652,6 +1655,9 @@ NetEConst* NetEUReduce::eval_tree() /* * $Log: eval_tree.cc,v $ + * Revision 1.74 2007/03/08 05:30:02 steve + * Limit the calculated widths of constants. + * * 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 diff --git a/netlist.h b/netlist.h index 9726f8bdd..4285b8755 100644 --- a/netlist.h +++ b/netlist.h @@ -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.371 2007/03/02 06:13:22 steve Exp $" +#ident "$Id: netlist.h,v 1.372 2007/03/08 05:30:03 steve Exp $" #endif /* @@ -1116,7 +1116,10 @@ class NetExpr : public LineInfo { // equivalent expression that is reduced as far as compile // time knows how. Essentially, this is designed to fold // constants. - virtual NetExpr*eval_tree(); + // + // The prune_to_width is the maximum width that the result + // should be. If it is -1, then do not prune the result. + virtual NetExpr*eval_tree(int prune_to_width = -1); // Make a duplicate of myself, and subexpressions if I have // any. This is a deep copy operation. @@ -2635,7 +2638,7 @@ class NetEBAdd : public NetEBinary { virtual bool set_width(unsigned w, bool last_chance); virtual NetEBAdd* dup_expr() const; - virtual NetEConst* eval_tree(); + virtual NetEConst* eval_tree(int prune_to_width = -1); virtual NetNet* synthesize(Design*); }; @@ -2654,7 +2657,7 @@ class NetEBDiv : public NetEBinary { virtual bool set_width(unsigned w, bool last_chance); virtual NetEBDiv* dup_expr() const; - virtual NetExpr* eval_tree(); + virtual NetExpr* eval_tree(int prune_to_width = -1); virtual NetNet* synthesize(Design*); }; @@ -2680,7 +2683,7 @@ class NetEBBits : public NetEBinary { virtual bool set_width(unsigned w, bool last_chance); virtual NetEBBits* dup_expr() const; - virtual NetEConst* eval_tree(); + virtual NetEConst* eval_tree(int prune_to_width = -1); virtual NetNet* synthesize(Design*); }; @@ -2711,7 +2714,7 @@ class NetEBComp : public NetEBinary { virtual bool has_width() const; virtual ivl_variable_type_t expr_type() const; virtual NetEBComp* dup_expr() const; - virtual NetEConst* eval_tree(); + virtual NetEConst* eval_tree(int prune_to_width = -1); virtual NetNet* synthesize(Design*); @@ -2741,7 +2744,7 @@ class NetEBLogic : public NetEBinary { virtual bool set_width(unsigned w, bool last_chance); virtual NetEBLogic* dup_expr() const; - virtual NetEConst* eval_tree(); + virtual NetEConst* eval_tree(int prune_to_width = -1); virtual NetNet* synthesize(Design*); private: @@ -2761,7 +2764,7 @@ class NetEBMult : public NetEBinary { virtual bool set_width(unsigned w, bool last_chance); virtual NetEBMult* dup_expr() const; - virtual NetExpr* eval_tree(); + virtual NetExpr* eval_tree(int prune_to_width = -1); virtual NetNet* synthesize(Design*); private: @@ -2783,7 +2786,7 @@ class NetEBPow : public NetEBinary { virtual bool set_width(unsigned w, bool last_chance); virtual NetEBPow* dup_expr() const; - virtual NetExpr* eval_tree(); + virtual NetExpr* eval_tree(int prune_to_width = -1); virtual NetNet* synthesize(Design*); private: @@ -2814,7 +2817,7 @@ class NetEBShift : public NetEBinary { virtual bool has_width() const; virtual NetEBShift* dup_expr() const; - virtual NetEConst* eval_tree(); + virtual NetEConst* eval_tree(int prune_to_width = -1); virtual NetNet* synthesize(Design*); @@ -2849,7 +2852,7 @@ class NetEConcat : public NetExpr { virtual bool has_width() const; virtual bool set_width(unsigned w, bool last_chance =false); virtual NetEConcat* dup_expr() const; - virtual NetEConst* eval_tree(); + virtual NetEConst* eval_tree(int prune_to_width = -1); virtual NetNet*synthesize(Design*); virtual void expr_scan(struct expr_scan_t*) const; virtual void dump(ostream&) const; @@ -2881,7 +2884,7 @@ class NetEParam : public NetExpr { virtual bool set_width(unsigned w, bool last_chance); virtual bool has_width() const; virtual void expr_scan(struct expr_scan_t*) const; - virtual NetExpr* eval_tree(); + virtual NetExpr* eval_tree(int prune_to_width = -1); virtual NetEParam* dup_expr() const; virtual void dump(ostream&) const; @@ -2920,7 +2923,7 @@ class NetESelect : public NetExpr { virtual bool set_width(unsigned w, bool last_chance =false); virtual bool has_width() const; virtual void expr_scan(struct expr_scan_t*) const; - virtual NetEConst* eval_tree(); + virtual NetEConst* eval_tree(int prune_to_width = -1); virtual NetESelect* dup_expr() const; virtual NetNet*synthesize(Design*des); virtual void dump(ostream&) const; @@ -3030,7 +3033,7 @@ class NetETernary : public NetExpr { const NetExpr*false_expr() const; virtual NetETernary* dup_expr() const; - virtual NetExpr* eval_tree(); + virtual NetExpr* eval_tree(int prune_to_width = -1); virtual ivl_variable_type_t expr_type() const; virtual NexusSet* nex_input(); @@ -3071,7 +3074,7 @@ class NetEUnary : public NetExpr { virtual bool set_width(unsigned w, bool last_chance); virtual NetEUnary* dup_expr() const; - virtual NetEConst* eval_tree(); + virtual NetEConst* eval_tree(int prune_to_width = -1); virtual ivl_variable_type_t expr_type() const; virtual NexusSet* nex_input(); @@ -3093,7 +3096,7 @@ class NetEUBits : public NetEUnary { virtual NetNet* synthesize(Design*); - virtual NetEConst* eval_tree(); + virtual NetEConst* eval_tree(int prune_to_width = -1); virtual ivl_variable_type_t expr_type() const; }; @@ -3106,7 +3109,7 @@ class NetEUReduce : public NetEUnary { virtual bool set_width(unsigned w, bool last_chance); virtual NetNet* synthesize(Design*); virtual NetEUReduce* dup_expr() const; - virtual NetEConst* eval_tree(); + virtual NetEConst* eval_tree(int prune_to_width = -1); virtual ivl_variable_type_t expr_type() const; }; @@ -3492,6 +3495,9 @@ extern ostream& operator << (ostream&, NetNet::Type); /* * $Log: netlist.h,v $ + * Revision 1.372 2007/03/08 05:30:03 steve + * Limit the calculated widths of constants. + * * Revision 1.371 2007/03/02 06:13:22 steve * Add support for edge sensitive spec paths. * diff --git a/netmisc.cc b/netmisc.cc index df99fa5d7..fc9083fda 100644 --- a/netmisc.cc +++ b/netmisc.cc @@ -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.12 2006/06/02 04:48:50 steve Exp $" +#ident "$Id: netmisc.cc,v 1.13 2007/03/08 05:30:03 steve Exp $" #endif # include "config.h" @@ -124,13 +124,13 @@ NetExpr* make_sub_expr(long val, NetExpr*expr) } NetExpr* elab_and_eval(Design*des, NetScope*scope, - const PExpr*pe, int expr_wid) + const PExpr*pe, int expr_wid, int prune_width) { NetExpr*tmp = pe->elaborate_expr(des, scope, expr_wid, false); if (tmp == 0) return 0; - if (NetExpr*tmp2 = tmp->eval_tree()) { + if (NetExpr*tmp2 = tmp->eval_tree(prune_width)) { delete tmp; tmp = tmp2; } @@ -141,6 +141,9 @@ NetExpr* elab_and_eval(Design*des, NetScope*scope, /* * $Log: netmisc.cc,v $ + * Revision 1.13 2007/03/08 05:30:03 steve + * Limit the calculated widths of constants. + * * 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 diff --git a/netmisc.h b/netmisc.h index 21e8978d7..b20e1f822 100644 --- a/netmisc.h +++ b/netmisc.h @@ -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.28 2007/02/26 19:49:49 steve Exp $" +#ident "$Id: netmisc.h,v 1.29 2007/03/08 05:30:03 steve Exp $" #endif # include "netlist.h" @@ -112,14 +112,22 @@ extern unsigned count_lval_width(const class NetAssign_*first); * 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. + * being elaborated, or -1 if the expression is self-determined width. + * + * Also, the prune_width is the maximum width of the result, and it + * passed to the eval_tree method of the expression to limit constant + * results if possible. */ class PExpr; extern NetExpr* elab_and_eval(Design*des, NetScope*scope, - const PExpr*pe, int expr_wid); + const PExpr*pe, int expr_wid, + int prune_width =-1); /* * $Log: netmisc.h,v $ + * Revision 1.29 2007/03/08 05:30:03 steve + * Limit the calculated widths of constants. + * * Revision 1.28 2007/02/26 19:49:49 steve * Spelling fixes (larry doolittle) *