diff --git a/net_expr.cc b/net_expr.cc index b568835b4..5beb05efb 100644 --- a/net_expr.cc +++ b/net_expr.cc @@ -17,13 +17,79 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: net_expr.cc,v 1.8 2002/10/19 22:59:49 steve Exp $" +#ident "$Id: net_expr.cc,v 1.9 2002/11/06 02:25:13 steve Exp $" #endif # include "config.h" # include "netlist.h" # include +/* + * Create an add/sub node from the two operands. Make a best guess of + * the + */ +NetEBAdd::NetEBAdd(char op, NetExpr*l, NetExpr*r) +: NetEBinary(op, l, r) +{ + NetEConst* tmp; + + /* Catch the special case that one of the operands is an + unsized constant number. If so, then we should set the + width of that number to the size of the other operand, plus + one. This expands the expression to account for the largest + possible result. + + The set_width applied to a constant value will only + truncate the constant so far as it can still hold its + logical value, so this is safe to do. */ + if ( (tmp = dynamic_cast(r)) + && (! tmp->has_width()) + && (tmp->expr_width() > l->expr_width()) ) { + + unsigned target_width = l->expr_width() + 1; + r->set_width(target_width); + + /* Note: This constant value will not gain a defined + with from this. Make sure. */ + assert(! r->has_width() ); + + } else if ( (tmp = dynamic_cast(l)) + && (! tmp->has_width()) + && (tmp->expr_width() > r->expr_width()) ) { + + unsigned target_width = r->expr_width() + 1; + l->set_width(target_width); + + /* Note: This constant value will not gain a defined + with from this. Make sure. */ + assert(! l->has_width() ); + + } + + /* Now that we have the operand sizes the way we like, or as + good as we are going to get them, set the size of myself. */ + if (r->expr_width() > l->expr_width()) { + + expr_width(r->expr_width()); + + } else { + expr_width(l->expr_width()); + } + + cast_signed(l->has_sign() && r->has_sign()); +} + +NetEBAdd::~NetEBAdd() +{ +} + +NetEBAdd* NetEBAdd::dup_expr() const +{ + NetEBAdd*result = new NetEBAdd(op_, left_->dup_expr(), + right_->dup_expr()); + return result; +} + NetEConcat::NetEConcat(unsigned cnt, NetExpr* r) : parms_(cnt), repeat_(r) { @@ -171,6 +237,11 @@ bool NetESelect::set_width(unsigned w) /* * $Log: net_expr.cc,v $ + * Revision 1.9 2002/11/06 02:25:13 steve + * No need to keep excess width from an + * unsigned constant value, if it can + * be trimmed safely. + * * Revision 1.8 2002/10/19 22:59:49 steve * Redo the parameter vector support to allow * parameter names in range expressions. diff --git a/netlist.cc b/netlist.cc index 6e3539b78..2a12c1780 100644 --- a/netlist.cc +++ b/netlist.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #ifdef HAVE_CVS_IDENT -#ident "$Id: netlist.cc,v 1.201 2002/10/23 01:47:17 steve Exp $" +#ident "$Id: netlist.cc,v 1.202 2002/11/06 02:25:13 steve Exp $" #endif # include "config.h" @@ -1756,34 +1756,6 @@ 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 (r->expr_width() > l->expr_width()) - expr_width(r->expr_width()); - else - expr_width(l->expr_width()); - - cast_signed(l->has_sign() && r->has_sign()); -} - -NetEBAdd::~NetEBAdd() -{ -} - -NetEBAdd* NetEBAdd::dup_expr() const -{ - NetEBAdd*result = new NetEBAdd(op_, left_->dup_expr(), - right_->dup_expr()); - 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 @@ -2320,6 +2292,11 @@ const NetProc*NetTaskDef::proc() const /* * $Log: netlist.cc,v $ + * Revision 1.202 2002/11/06 02:25:13 steve + * No need to keep excess width from an + * unsigned constant value, if it can + * be trimmed safely. + * * Revision 1.201 2002/10/23 01:47:17 steve * Fix synth2 handling of aset/aclr signals where * flip-flops are split by begin-end blocks. diff --git a/set_width.cc b/set_width.cc index 818b7eb02..ab8bf99ed 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.23 2002/08/12 01:35:00 steve Exp $" +#ident "$Id: set_width.cc,v 1.24 2002/11/06 02:25:13 steve Exp $" #endif # include "config.h" @@ -238,7 +238,7 @@ bool NetEConst::set_width(unsigned w) if (value_.has_sign()) pad = value_.get(value_.len()-1); - verinum tmp (verinum::V0, w); + verinum tmp (verinum::V0, w, has_width()); for (unsigned idx = 0 ; idx < value_.len() ; idx += 1) tmp.set(idx, value_[idx]); for (unsigned idx = value_.len() ; idx < w ; idx += 1) @@ -259,7 +259,7 @@ bool NetEConst::set_width(unsigned w) if (value_[idx] != verinum::V0) use_w = idx+1; - verinum tmp (verinum::V0, use_w); + verinum tmp (verinum::V0, use_w, has_width()); for (unsigned idx = 0 ; idx < use_w ; idx += 1) tmp.set(idx, value_[idx]); @@ -357,6 +357,11 @@ bool NetEUReduce::set_width(unsigned w) /* * $Log: set_width.cc,v $ + * Revision 1.24 2002/11/06 02:25:13 steve + * No need to keep excess width from an + * unsigned constant value, if it can + * be trimmed safely. + * * Revision 1.23 2002/08/12 01:35:00 steve * conditional ident string using autoconfig. *