diff --git a/elaborate.cc b/elaborate.cc index 3fb7249ff..7a2e2f10c 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.331 2005/11/10 13:28:11 steve Exp $" +#ident "$Id: elaborate.cc,v 1.332 2005/11/26 00:35:42 steve Exp $" #endif # include "config.h" @@ -2479,7 +2479,7 @@ NetForce* PForce::elaborate(Design*des, NetScope*scope) const unsigned lwid = count_lval_width(lval); - rexp->set_width(lwid); + rexp->set_width(lwid, true); rexp = pad_to_width(rexp, lwid); dev = new NetForce(lval, rexp); @@ -3028,6 +3028,9 @@ Design* elaborate(listroots) /* * $Log: elaborate.cc,v $ + * Revision 1.332 2005/11/26 00:35:42 steve + * More precise about r-value width of constants. + * * Revision 1.331 2005/11/10 13:28:11 steve * Reorganize signal part select handling, and add support for * indexed part selects. diff --git a/net_expr.cc b/net_expr.cc index e162fcc39..e994ff85e 100644 --- a/net_expr.cc +++ b/net_expr.cc @@ -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.25 2005/09/14 02:53:14 steve Exp $" +#ident "$Id: net_expr.cc,v 1.26 2005/11/26 00:35:43 steve Exp $" #endif # include "config.h" @@ -468,14 +468,6 @@ bool NetESelect::has_width() const return true; } -bool NetESelect::set_width(unsigned w) -{ - if (expr_width() == 1) - return true; - else - return false; -} - NetESFunc::NetESFunc(const char*n, ivl_variable_type_t t, unsigned width, unsigned np) : name_(0), type_(t) @@ -534,6 +526,9 @@ ivl_variable_type_t NetESFunc::expr_type() const /* * $Log: net_expr.cc,v $ + * Revision 1.26 2005/11/26 00:35:43 steve + * More precise about r-value width of constants. + * * Revision 1.25 2005/09/14 02:53:14 steve * Support bool expressions and compares handle them optimally. * diff --git a/netlist.h b/netlist.h index f23af616d..80d1a50b1 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.351 2005/09/19 21:45:36 steve Exp $" +#ident "$Id: netlist.h,v 1.352 2005/11/26 00:35:43 steve Exp $" #endif /* @@ -1043,7 +1043,21 @@ class NetExpr : public LineInfo { // Coerce the expression to have a specific width. If the // coercion works, then return true. Otherwise, return false. - virtual bool set_width(unsigned); + // A coercion will work or not depending on the implementation + // in the derived class. Normally, the width will be set if + // the expression is: + // - already the requested size, OR + // - otherwise unsized. + // Normally, the resize will not allow a width size that loses + // data. For example, it will not reduce a constant expression + // to the point where significant bits are lost. But if the + // last_chance flag is true, then the method assumes that high + // bits will be lost anyhow, so try harder. Loss will be + // allowed, but it still won't resize fixed size expressions + // such as vector signals. This flag is meant to be used by + // elaboration of procedural assignment to set the expression + // width to the l-value width, if possible. + virtual bool set_width(unsigned wid, bool last_chance =false); // This method returns true if the expression is // signed. Unsigned expressions return false. @@ -1106,7 +1120,7 @@ class NetEConst : public NetExpr { const verinum&value() const; - virtual bool set_width(unsigned w); + virtual bool set_width(unsigned w, bool last_chance =false); virtual bool has_width() const; virtual ivl_variable_type_t expr_type() const; @@ -1132,7 +1146,7 @@ class NetEConstParam : public NetEConst { perm_string name() const; const NetScope*scope() const; - virtual bool set_width(unsigned w); + virtual bool set_width(unsigned w, bool last_chance); virtual void expr_scan(struct expr_scan_t*) const; virtual void dump(ostream&) const; @@ -1156,7 +1170,7 @@ class NetECReal : public NetExpr { // Reals can be used in vector expressions. Conversions will // be done at the right time. - virtual bool set_width(unsigned w); + virtual bool set_width(unsigned w, bool last_chance); // This type has no self-determined width. This is false. virtual bool has_width() const; @@ -2391,7 +2405,7 @@ class NetEUFunc : public NetExpr { const NetScope* func() const; - virtual bool set_width(unsigned); + virtual bool set_width(unsigned, bool last_chance); virtual ivl_variable_type_t expr_type() const; virtual void dump(ostream&) const; @@ -2545,7 +2559,7 @@ class NetEBinary : public NetExpr { char op() const { return op_; } - virtual bool set_width(unsigned w); + virtual bool set_width(unsigned w, bool last_chance =false); // A binary expression node only has a definite // self-determinable width if the operands both have definite @@ -2581,7 +2595,7 @@ class NetEBAdd : public NetEBinary { virtual ivl_variable_type_t expr_type() const; - virtual bool set_width(unsigned w); + virtual bool set_width(unsigned w, bool last_chance); virtual NetEBAdd* dup_expr() const; virtual NetEConst* eval_tree(); virtual NetNet* synthesize(Design*); @@ -2600,7 +2614,7 @@ class NetEBDiv : public NetEBinary { virtual ivl_variable_type_t expr_type() const; - virtual bool set_width(unsigned w); + virtual bool set_width(unsigned w, bool last_chance); virtual NetEBDiv* dup_expr() const; virtual NetExpr* eval_tree(); virtual NetNet* synthesize(Design*); @@ -2626,7 +2640,7 @@ class NetEBBits : public NetEBinary { NetEBBits(char op, NetExpr*l, NetExpr*r); ~NetEBBits(); - virtual bool set_width(unsigned w); + virtual bool set_width(unsigned w, bool last_chance); virtual NetEBBits* dup_expr() const; virtual NetEConst* eval_tree(); @@ -2653,7 +2667,7 @@ class NetEBComp : public NetEBinary { NetEBComp(char op, NetExpr*l, NetExpr*r); ~NetEBComp(); - virtual bool set_width(unsigned w); + virtual bool set_width(unsigned w, bool last_chance); /* A compare expression has a definite width. */ virtual bool has_width() const; @@ -2688,7 +2702,7 @@ class NetEBLogic : public NetEBinary { NetEBLogic(char op, NetExpr*l, NetExpr*r); ~NetEBLogic(); - virtual bool set_width(unsigned w); + virtual bool set_width(unsigned w, bool last_chance); virtual NetEBLogic* dup_expr() const; virtual NetEConst* eval_tree(); virtual NetNet* synthesize(Design*); @@ -2708,7 +2722,7 @@ class NetEBMult : public NetEBinary { virtual ivl_variable_type_t expr_type() const; - virtual bool set_width(unsigned w); + virtual bool set_width(unsigned w, bool last_chance); virtual NetEBMult* dup_expr() const; virtual NetExpr* eval_tree(); virtual NetNet* synthesize(Design*); @@ -2734,7 +2748,7 @@ class NetEBShift : public NetEBinary { NetEBShift(char op, NetExpr*l, NetExpr*r); ~NetEBShift(); - virtual bool set_width(unsigned w); + virtual bool set_width(unsigned w, bool last_chance); // A shift expression only needs the left expression to have a // definite width to give the expression a definite width. @@ -2774,7 +2788,7 @@ class NetEConcat : public NetExpr { virtual NexusSet* nex_input(); virtual bool has_width() const; - virtual bool set_width(unsigned w); + virtual bool set_width(unsigned w, bool last_chance =false); virtual NetEConcat* dup_expr() const; virtual NetEConst* eval_tree(); virtual NetNet*synthesize(Design*); @@ -2805,7 +2819,7 @@ class NetEParam : public NetExpr { ~NetEParam(); virtual NexusSet* nex_input(); - virtual bool set_width(unsigned w); + 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(); @@ -2844,7 +2858,7 @@ class NetESelect : public NetExpr { const NetExpr*select() const; virtual NexusSet* nex_input(); - virtual bool set_width(unsigned w); + 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(); @@ -2922,7 +2936,7 @@ class NetESFunc : public NetExpr { virtual ivl_variable_type_t expr_type() const; virtual NexusSet* nex_input(); - virtual bool set_width(unsigned); + virtual bool set_width(unsigned, bool last_chance); virtual void dump(ostream&) const; virtual void expr_scan(struct expr_scan_t*) const; @@ -2950,7 +2964,7 @@ class NetETernary : public NetExpr { NetETernary(NetExpr*c, NetExpr*t, NetExpr*f); ~NetETernary(); - virtual bool set_width(unsigned w); + virtual bool set_width(unsigned w, bool last_chance); const NetExpr*cond_expr() const; const NetExpr*true_expr() const; @@ -2994,7 +3008,7 @@ class NetEUnary : public NetExpr { char op() const { return op_; } const NetExpr* expr() const { return expr_; } - virtual bool set_width(unsigned w); + virtual bool set_width(unsigned w, bool last_chance); virtual NetEUnary* dup_expr() const; virtual NetEConst* eval_tree(); @@ -3027,7 +3041,7 @@ class NetEUReduce : public NetEUnary { NetEUReduce(char op, NetExpr*ex); ~NetEUReduce(); - virtual bool set_width(unsigned w); + virtual bool set_width(unsigned w, bool last_chance); virtual NetNet* synthesize(Design*); virtual NetEUReduce* dup_expr() const; virtual NetEConst* eval_tree(); @@ -3048,7 +3062,7 @@ class NetEMemory : public NetExpr { perm_string name () const; const NetExpr* index() const; - virtual bool set_width(unsigned); + virtual bool set_width(unsigned, bool last_chance); virtual NetNet* synthesize(Design*des); NetExpr* eval_tree(); @@ -3083,7 +3097,7 @@ class NetESignal : public NetExpr { ~NetESignal(); perm_string name() const; - virtual bool set_width(unsigned); + virtual bool set_width(unsigned, bool last_chance); virtual NetESignal* dup_expr() const; NetNet* synthesize(Design*des); @@ -3444,6 +3458,9 @@ extern ostream& operator << (ostream&, NetNet::Type); /* * $Log: netlist.h,v $ + * Revision 1.352 2005/11/26 00:35:43 steve + * More precise about r-value width of constants. + * * Revision 1.351 2005/09/19 21:45:36 steve * Spelling patches from Larry. * diff --git a/set_width.cc b/set_width.cc index db8915e96..4bbde7d24 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 */ #ifdef HAVE_CVS_IDENT -#ident "$Id: set_width.cc,v 1.36 2005/05/17 20:56:55 steve Exp $" +#ident "$Id: set_width.cc,v 1.37 2005/11/26 00:35:44 steve Exp $" #endif # include "config.h" @@ -36,7 +36,7 @@ # include -bool NetExpr::set_width(unsigned w) +bool NetExpr::set_width(unsigned w, bool) { cerr << get_line() << ": internal warning: " <set_width(right_->expr_width()); @@ -180,7 +180,7 @@ bool NetEBLogic::set_width(unsigned w) * There is nothing we can do to the operands of a multiply to make it * confirm to the requested width. Force the context to pad or truncate. */ -bool NetEBMult::set_width(unsigned w) +bool NetEBMult::set_width(unsigned w, bool) { return w == expr_width(); } @@ -190,7 +190,7 @@ bool NetEBMult::set_width(unsigned w) * natural width. The width of the operator result is the width of the * left operand, the value that is to be shifted. */ -bool NetEBShift::set_width(unsigned w) +bool NetEBShift::set_width(unsigned w, bool) { bool flag = true; @@ -228,7 +228,7 @@ bool NetEBShift::set_width(unsigned w) * matter because the null expression is indication of an error and * the compiler will not go beyond elaboration. */ -bool NetEConcat::set_width(unsigned w) +bool NetEConcat::set_width(unsigned w, bool) { unsigned sum = 0; for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1) @@ -241,7 +241,7 @@ bool NetEConcat::set_width(unsigned w) return true; } -bool NetEConst::set_width(unsigned w) +bool NetEConst::set_width(unsigned w, bool last_chance) { if (w == value_.len()) { expr_width(w); @@ -289,17 +289,19 @@ bool NetEConst::set_width(unsigned w) ? value_[value_.len() - 1] : verinum::V0; - // Don't reduce a number too small to hold all the - // significant bits. - for (unsigned idx = w ; idx < value_.len() ; idx += 1) - if (value_[idx] != pad_bit) - use_w = idx+1; + if (! last_chance) { + // Don't reduce a number too small to hold all the + // significant bits. + for (unsigned idx = w ; idx < value_.len() ; idx += 1) + if (value_[idx] != pad_bit) + use_w = idx+1; - // Correct for the special case of signed value. We - // cannot have the result change sign on us. - if (value_.has_sign() && (use_w < value_.len()) - && (value_[use_w-1] != pad_bit)) - use_w += 1; + // Correct for the special case of signed value. We + // cannot have the result change sign on us. + if (value_.has_sign() && (use_w < value_.len()) + && (value_[use_w-1] != pad_bit)) + use_w += 1; + } verinum tmp (verinum::V0, use_w, has_width()); for (unsigned idx = 0 ; idx < use_w ; idx += 1) @@ -316,7 +318,7 @@ bool NetEConst::set_width(unsigned w) * Parameter vectors cannot be resized because they refer to a common * value. */ -bool NetEConstParam::set_width(unsigned w) +bool NetEConstParam::set_width(unsigned w, bool) { return w == expr_width(); } @@ -326,13 +328,13 @@ bool NetEConstParam::set_width(unsigned w) * because it isn't really a vector. The environment will convert this * to a vector at the right time. */ -bool NetECReal::set_width(unsigned w) +bool NetECReal::set_width(unsigned w, bool) { expr_width(w); return true; } -bool NetEMemory::set_width(unsigned w) +bool NetEMemory::set_width(unsigned w, bool) { if (w != mem_->width()) return false; @@ -341,12 +343,20 @@ bool NetEMemory::set_width(unsigned w) return true; } -bool NetEParam::set_width(unsigned) +bool NetEParam::set_width(unsigned, bool) { return false; } -bool NetESFunc::set_width(unsigned w) +bool NetESelect::set_width(unsigned w, bool) +{ + if (expr_width() == 1) + return true; + else + return false; +} + +bool NetESFunc::set_width(unsigned w, bool) { return w == expr_width(); } @@ -355,7 +365,7 @@ bool NetESFunc::set_width(unsigned w) * The signal should automatically pad with zeros to get to the desired * width. Do not allow signal bits to be truncated, however. */ -bool NetESignal::set_width(unsigned w) +bool NetESignal::set_width(unsigned w, bool) { if (w != bit_count()) return false; @@ -363,7 +373,7 @@ bool NetESignal::set_width(unsigned w) return true; } -bool NetETernary::set_width(unsigned w) +bool NetETernary::set_width(unsigned w, bool) { bool flag = true; flag = flag && true_val_->set_width(w); @@ -377,13 +387,13 @@ bool NetETernary::set_width(unsigned w) * width. What I really need to do is note the width of the output * parameter of the function definition and take that into account. */ -bool NetEUFunc::set_width(unsigned wid) +bool NetEUFunc::set_width(unsigned wid, bool) { expr_width(wid); return true; } -bool NetEUnary::set_width(unsigned w) +bool NetEUnary::set_width(unsigned w, bool) { bool flag = true; switch (op_) { @@ -406,7 +416,7 @@ bool NetEUnary::set_width(unsigned w) * Unary reduction operators allow its operand to have any width. The * result is defined to be 1. */ -bool NetEUReduce::set_width(unsigned w) +bool NetEUReduce::set_width(unsigned w, bool) { return w == 1; } @@ -414,6 +424,9 @@ bool NetEUReduce::set_width(unsigned w) /* * $Log: set_width.cc,v $ + * Revision 1.37 2005/11/26 00:35:44 steve + * More precise about r-value width of constants. + * * Revision 1.36 2005/05/17 20:56:55 steve * Parameters cannot have their width changed. * diff --git a/tgt-vvp/vvp_process.c b/tgt-vvp/vvp_process.c index 4d63e40bd..aa5efbfa2 100644 --- a/tgt-vvp/vvp_process.c +++ b/tgt-vvp/vvp_process.c @@ -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.119 2005/10/12 17:26:01 steve Exp $" +#ident "$Id: vvp_process.c,v 1.120 2005/11/26 00:35:44 steve Exp $" #endif # include "vvp_priv.h" @@ -750,9 +750,9 @@ static void force_vector_to_lval(ivl_statement_t net, struct vector_info rvec) /* Do not support bit or part selects of l-values yet. */ assert(ivl_lval_mux(lval) == 0); assert(ivl_lval_part_off(lval) == 0); - assert(ivl_lval_width(lval) == ivl_signal_width(lsig)); + //assert(ivl_lval_width(lval) == ivl_signal_width(lsig)); - use_wid = ivl_signal_width(lsig); + use_wid = ivl_lval_width(lval); assert((roff + use_wid) <= rvec.wid); fprintf(vvp_out, " %s V_%s, %u, %u;\n", command_name, @@ -1468,6 +1468,9 @@ int draw_func_definition(ivl_scope_t scope) /* * $Log: vvp_process.c,v $ + * Revision 1.120 2005/11/26 00:35:44 steve + * More precise about r-value width of constants. + * * Revision 1.119 2005/10/12 17:26:01 steve * force l-values do not support bit/part select. *