diff --git a/elaborate.cc b/elaborate.cc index eb844147b..ac39ed207 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.205 2001/01/14 23:04:56 steve Exp $" +#ident "$Id: elaborate.cc,v 1.206 2001/02/07 21:47:13 steve Exp $" #endif /* @@ -1280,7 +1280,7 @@ NetProc* PCondit::elaborate(Design*des, const string&path) const return 0; } - if (! expr->set_width(1)) { + if (expr->expr_width() > 1) { assert(expr->expr_width() > 1); verinum zero (verinum::V0, expr->expr_width()); NetEConst*ezero = new NetEConst(zero); @@ -1955,6 +1955,7 @@ NetProc* PForce::elaborate(Design*des, const string&path) const */ NetProc* PForStatement::elaborate(Design*des, const string&path) const { + NetExpr*etmp; NetScope*scope = des->find_scope(path); assert(scope); @@ -1980,7 +1981,13 @@ NetProc* PForStatement::elaborate(Design*des, const string&path) const for (unsigned idx = 0 ; idx < lv->pin_count() ; idx += 1) connect(lv->pin(idx), sig->pin(idx)); des->add_node(lv); - NetAssign*init = new NetAssign(lv, expr1_->elaborate_expr(des, scope)); + + /* Make the r-value of the initial assignment, and size it + properly. Then use it to build the assignment statement. */ + etmp = expr1_->elaborate_expr(des, scope); + etmp->set_width(lv->lwidth()); + + NetAssign*init = new NetAssign(lv, etmp); top->append(init); @@ -2004,7 +2011,12 @@ NetProc* PForStatement::elaborate(Design*des, const string&path) const for (unsigned idx = 0 ; idx < lv->pin_count() ; idx += 1) connect(lv->pin(idx), sig->pin(idx)); des->add_node(lv); - NetAssign*step = new NetAssign(lv, expr2_->elaborate_expr(des, scope)); + + /* Make the rvalue of the increment expression, and size it + for the lvalue. */ + etmp = expr2_->elaborate_expr(des, scope); + etmp->set_width(lv->lwidth()); + NetAssign*step = new NetAssign(lv, etmp); body->append(step); @@ -2355,6 +2367,9 @@ Design* elaborate(const map&modules, /* * $Log: elaborate.cc,v $ + * Revision 1.206 2001/02/07 21:47:13 steve + * Fix expression widths for rvalues and parameters (PR#131,132) + * * Revision 1.205 2001/01/14 23:04:56 steve * Generalize the evaluation of floating point delays, and * get it working with delay assignment statements. diff --git a/netlist.cc b/netlist.cc index 3bbdfc877..3abbaca8d 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.154 2001/01/18 03:16:35 steve Exp $" +#ident "$Id: netlist.cc,v 1.155 2001/02/07 21:47:13 steve Exp $" #endif # include @@ -1780,9 +1780,16 @@ bool NetExpr::has_width() const return true; } +/* + * Create a bitwise operator node from the opcode and the left and + * right expressions. Don't worry about the width of the expression + * yet, we'll get that from the l-value, whatever that turns out to + * be. + */ NetEBAdd::NetEBAdd(char op, NetExpr*l, NetExpr*r) : NetEBinary(op, l, r) { +#if 0 if (l->expr_width() > r->expr_width()) r->set_width(l->expr_width()); @@ -1794,7 +1801,7 @@ NetEBAdd::NetEBAdd(char op, NetExpr*l, NetExpr*r) if (r->expr_width() < l->expr_width()) l->set_width(r->expr_width()); - +#endif if (r->expr_width() > l->expr_width()) expr_width(r->expr_width()); else @@ -1812,9 +1819,17 @@ NetEBAdd* NetEBAdd::dup_expr() const return result; } +/* + * Create a bitwise operator node from the opcode and the left and + * right expressions. Don't worry about the width of the expression + * yet, we'll get that from the l-value, whatever that turns out to + * be. However, if we don't, our default will be the width of the + * largest operand. + */ NetEBBits::NetEBBits(char op, NetExpr*l, NetExpr*r) : NetEBinary(op, l, r) { +#if 0 /* First try to naturally adjust the size of the expressions to match. */ if (l->expr_width() > r->expr_width()) @@ -1838,6 +1853,11 @@ NetEBBits::NetEBBits(char op, NetExpr*l, NetExpr*r) assert(left_->expr_width() == right_->expr_width()); expr_width(left_->expr_width()); +#endif + if (r->expr_width() > l->expr_width()) + expr_width(r->expr_width()); + else + expr_width(l->expr_width()); } NetEBBits::~NetEBBits() @@ -2473,6 +2493,9 @@ bool NetUDP::sequ_glob_(string input, char output) /* * $Log: netlist.cc,v $ + * Revision 1.155 2001/02/07 21:47:13 steve + * Fix expression widths for rvalues and parameters (PR#131,132) + * * Revision 1.154 2001/01/18 03:16:35 steve * NetMux needs a scope. (PR#115) * diff --git a/set_width.cc b/set_width.cc index 5a7a44a9c..ef28e6989 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.15 2001/01/27 05:41:48 steve Exp $" +#ident "$Id: set_width.cc,v 1.16 2001/02/07 21:47:13 steve Exp $" #endif /* @@ -105,18 +105,48 @@ bool NetEBAdd::set_width(unsigned w) /* * The bitwise logical operators have operands the same size as the - * result. Anything else is a mess. + * result. Anything else is a mess. I first try to get the operands to + * shrink to the desired size. I then expand operands that are too small. */ bool NetEBBits::set_width(unsigned w) { - bool flag = true; + /* First, give the operands a chance to adjust themselves to + the requested width. */ + left_->set_width(w); + right_->set_width(w); - flag = left_->set_width(w) && flag; - flag = right_->set_width(w) && flag; - if (flag) - expr_width(w); + /* Now increase me up to the size of the largest operand. This + accounts for operands that can't shrink. */ - return flag; + unsigned use_width = w; +#if 0 + if (use_width < left_->expr_width()) + use_width = left_->expr_width(); + + if (use_width < right_->expr_width()) + use_width = right_->expr_width(); +#endif + + /* If the operands end up too small, then pad them to suit. */ + + if (left_->expr_width() < use_width) { + NetExpr*tmp = pad_to_width(left_, use_width); + assert(tmp); + left_ = tmp; + } + + if (right_->expr_width() < w) { + NetExpr*tmp = pad_to_width(right_, use_width); + assert(tmp); + right_ = tmp; + } + + + /* And here is the final width. If this is not the size the + caller requested, then return false. Otherwise, return + true. */ + expr_width(use_width); + return w == use_width; } /* @@ -313,6 +343,9 @@ bool NetEUnary::set_width(unsigned w) /* * $Log: set_width.cc,v $ + * Revision 1.16 2001/02/07 21:47:13 steve + * Fix expression widths for rvalues and parameters (PR#131,132) + * * Revision 1.15 2001/01/27 05:41:48 steve * Fix sign extension of evaluated constants. (PR#91) * diff --git a/verinum.cc b/verinum.cc index e498a04fe..34b95ab6f 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.23 2001/02/07 02:46:31 steve Exp $" +#ident "$Id: verinum.cc,v 1.24 2001/02/07 21:47:13 steve Exp $" #endif # include "verinum.h" @@ -144,11 +144,13 @@ verinum& verinum::operator= (const verinum&that) verinum::V verinum::get(unsigned idx) const { + assert(idx < nbits_); return bits_[idx]; } verinum::V verinum::set(unsigned idx, verinum::V val) { + assert(idx < nbits_); return bits_[idx] = val; } @@ -688,6 +690,9 @@ verinum::V operator & (verinum::V l, verinum::V r) /* * $Log: verinum.cc,v $ + * Revision 1.24 2001/02/07 21:47:13 steve + * Fix expression widths for rvalues and parameters (PR#131,132) + * * Revision 1.23 2001/02/07 02:46:31 steve * Support constant evaluation of / and % (PR#124) * diff --git a/vvm/vvm_func.cc b/vvm/vvm_func.cc index 7bd46d146..3defea686 100644 --- a/vvm/vvm_func.cc +++ b/vvm/vvm_func.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: vvm_func.cc,v 1.13 2000/12/11 00:31:44 steve Exp $" +#ident "$Id: vvm_func.cc,v 1.14 2001/02/07 21:47:13 steve Exp $" #endif # include "vvm_func.h" @@ -122,16 +122,16 @@ void vvm_binop_minus(vvm_bitset_t&v, const vvm_bitset_t&l, void vvm_binop_nor(vvm_bitset_t&v, const vvm_bitset_t&l, const vvm_bitset_t&r) { - assert(v.nbits == l.nbits); - assert(v.nbits == r.nbits); + assert(v.nbits <= l.nbits); + assert(v.nbits <= r.nbits); for (unsigned idx = 0 ; idx < v.nbits ; idx += 1) v[idx] = B_NOT(B_OR(l[idx], r[idx])); } void vvm_binop_or(vvm_bitset_t&v, const vvm_bitset_t&l, const vvm_bitset_t&r) { - assert(v.nbits == l.nbits); - assert(v.nbits == r.nbits); + assert(v.nbits <= l.nbits); + assert(v.nbits <= r.nbits); for (unsigned idx = 0 ; idx < v.nbits ; idx += 1) v[idx] = B_OR(l[idx], r[idx]); } @@ -167,16 +167,16 @@ void vvm_binop_shiftr(vvm_bitset_t&v, void vvm_binop_xnor(vvm_bitset_t&v, const vvm_bitset_t&l, const vvm_bitset_t&r) { - assert(v.nbits == l.nbits); - assert(v.nbits == r.nbits); + assert(v.nbits <= l.nbits); + assert(v.nbits <= r.nbits); for (unsigned idx = 0 ; idx < v.nbits ; idx += 1) v[idx] = B_NOT(B_XOR(l[idx], r[idx])); } void vvm_binop_xor(vvm_bitset_t&v, const vvm_bitset_t&l, const vvm_bitset_t&r) { - assert(v.nbits == l.nbits); - assert(v.nbits == r.nbits); + assert(v.nbits <= l.nbits); + assert(v.nbits <= r.nbits); for (unsigned idx = 0 ; idx < v.nbits ; idx += 1) v[idx] = B_XOR(l[idx], r[idx]); } @@ -607,6 +607,9 @@ void vvm_ternary(vvm_bitset_t&v, vpip_bit_t c, /* * $Log: vvm_func.cc,v $ + * Revision 1.14 2001/02/07 21:47:13 steve + * Fix expression widths for rvalues and parameters (PR#131,132) + * * Revision 1.13 2000/12/11 00:31:44 steve * Add support for signed reg variables, * simulate in t-vvm signed comparisons.