Remove last bits of relax_width methods, and use test_width

to calculate the width of an r-value expression that may
 contain unsized numbers.
This commit is contained in:
steve 2006-11-04 06:19:24 +00:00
parent ed5d3188b3
commit c339dc4bbc
7 changed files with 247 additions and 187 deletions

52
PExpr.h
View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: PExpr.h,v 1.84 2006/10/30 05:44:49 steve Exp $" #ident "$Id: PExpr.h,v 1.85 2006/11/04 06:19:24 steve Exp $"
#endif #endif
# include <string> # include <string>
@ -72,7 +72,9 @@ class PExpr : public LineInfo {
// unsized and therefore expandable. This happens if a // unsized and therefore expandable. This happens if a
// sub-expression is an unsized literal. Some expressions make // sub-expression is an unsized literal. Some expressions make
// special use of that. // special use of that.
virtual unsigned test_width(unsigned min, unsigned lval, bool&unsized_flag) const; virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
bool&unsized_flag) const;
// Procedural elaboration of the expression. The expr_width is // Procedural elaboration of the expression. The expr_width is
// the width of the context of the expression (i.e. the // the width of the context of the expression (i.e. the
@ -151,8 +153,6 @@ class PEConcat : public PExpr {
virtual verinum* eval_const(const Design*des, NetScope*sc) const; virtual verinum* eval_const(const Design*des, NetScope*sc) const;
virtual void dump(ostream&) const; virtual void dump(ostream&) const;
//virtual int test_width(bool) const;
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope, virtual NetNet* elaborate_lnet(Design*des, NetScope*scope,
bool implicit_net_ok =false) const; bool implicit_net_ok =false) const;
virtual NetNet* elaborate_bi_net(Design*des, NetScope*scope) const; virtual NetNet* elaborate_bi_net(Design*des, NetScope*scope) const;
@ -202,8 +202,6 @@ class PEEvent : public PExpr {
virtual void dump(ostream&) const; virtual void dump(ostream&) const;
//virtual int test_width(bool) const;
private: private:
edge_t type_; edge_t type_;
PExpr *expr_; PExpr *expr_;
@ -220,8 +218,6 @@ class PEFNumber : public PExpr {
const verireal& value() const; const verireal& value() const;
//virtual int test_width(bool) const;
/* The eval_const method as applied to a floating point number /* The eval_const method as applied to a floating point number
gets the *integer* value of the number. This accounts for gets the *integer* value of the number. This accounts for
any rounding that is needed to get the value. */ any rounding that is needed to get the value. */
@ -255,9 +251,9 @@ class PEIdent : public PExpr {
~PEIdent(); ~PEIdent();
virtual void dump(ostream&) const; virtual void dump(ostream&) const;
virtual unsigned test_width(unsigned min, unsigned lval, bool&unsized_flag) const; virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
//virtual int test_width(bool) const; bool&unsized_flag) const;
// Identifiers are allowed (with restrictions) is assign l-values. // Identifiers are allowed (with restrictions) is assign l-values.
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope, virtual NetNet* elaborate_lnet(Design*des, NetScope*scope,
@ -292,6 +288,11 @@ class PEIdent : public PExpr {
const hname_t& path() const; const hname_t& path() const;
private:
// Common functions to calculate parts of part/bit selects.
bool calculate_parts_(Design*, NetScope*, long&msb, long&lsb) const;
bool calculate_up_do_width_(Design*, NetScope*, unsigned long&wid) const;
private: private:
NetAssign_*elaborate_lval_net_part_(Design*, NetScope*, NetNet*) const; NetAssign_*elaborate_lval_net_part_(Design*, NetScope*, NetNet*) const;
NetAssign_*elaborate_lval_net_idx_up_(Design*, NetScope*, NetNet*) const; NetAssign_*elaborate_lval_net_idx_up_(Design*, NetScope*, NetNet*) const;
@ -376,7 +377,9 @@ class PENumber : public PExpr {
const verinum& value() const; const verinum& value() const;
virtual void dump(ostream&) const; virtual void dump(ostream&) const;
virtual unsigned test_width(unsigned min, unsigned lval, bool&unsized_flag) const; virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
bool&unsized_flag) const;
virtual NetNet* elaborate_net(Design*des, NetScope*scope, virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned lwidth, unsigned lwidth,
@ -416,7 +419,6 @@ class PEString : public PExpr {
string value() const; string value() const;
virtual void dump(ostream&) const; virtual void dump(ostream&) const;
//virtual int test_width(bool) const;
virtual NetNet* elaborate_net(Design*des, NetScope*scope, virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned width, unsigned width,
@ -443,7 +445,6 @@ class PEUnary : public PExpr {
~PEUnary(); ~PEUnary();
virtual void dump(ostream&out) const; virtual void dump(ostream&out) const;
//virtual int test_width(bool) const;
virtual NetNet* elaborate_net(Design*des, NetScope*scope, virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned width, unsigned width,
@ -471,11 +472,12 @@ class PEBinary : public PExpr {
~PEBinary(); ~PEBinary();
virtual bool is_constant(Module*) const; virtual bool is_constant(Module*) const;
//virtual int test_width(bool) const;
virtual void dump(ostream&out) const; virtual void dump(ostream&out) const;
virtual unsigned test_width(unsigned min, unsigned lval, bool&unsized_flag) const; virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
bool&unsized_flag) const;
virtual NetNet* elaborate_net(Design*des, NetScope*scope, virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned width, unsigned width,
@ -494,8 +496,8 @@ class PEBinary : public PExpr {
PExpr*left_; PExpr*left_;
PExpr*right_; PExpr*right_;
NetEBinary*elaborate_expr_base_(Design*, NetExpr*lp, NetExpr*rp) const; NetEBinary*elaborate_expr_base_(Design*, NetExpr*lp, NetExpr*rp, int use_wid) const;
NetEBinary*elaborate_eval_expr_base_(Design*, NetExpr*lp, NetExpr*rp) const; NetEBinary*elaborate_eval_expr_base_(Design*, NetExpr*lp, NetExpr*rp, int use_wid) const;
private: private:
NetNet* elaborate_net_add_(Design*des, NetScope*scope, NetNet* elaborate_net_add_(Design*des, NetScope*scope,
@ -550,7 +552,9 @@ class PEBComp : public PEBinary {
explicit PEBComp(char op, PExpr*l, PExpr*r); explicit PEBComp(char op, PExpr*l, PExpr*r);
~PEBComp(); ~PEBComp();
virtual unsigned test_width(unsigned min, unsigned lval, bool&flag) const; virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
bool&flag) const;
NetEBinary* elaborate_expr(Design*des, NetScope*scope, NetEBinary* elaborate_expr(Design*des, NetScope*scope,
int expr_width, bool sys_task_arg) const; int expr_width, bool sys_task_arg) const;
@ -562,7 +566,8 @@ class PEBShift : public PEBinary {
explicit PEBShift(char op, PExpr*l, PExpr*r); explicit PEBShift(char op, PExpr*l, PExpr*r);
~PEBShift(); ~PEBShift();
virtual unsigned test_width(unsigned min, unsigned lval, bool&flag) const; virtual unsigned test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval, bool&flag) const;
}; };
/* /*
@ -576,7 +581,6 @@ class PETernary : public PExpr {
~PETernary(); ~PETernary();
virtual bool is_constant(Module*) const; virtual bool is_constant(Module*) const;
//virtual int test_width(bool) const;
virtual void dump(ostream&out) const; virtual void dump(ostream&out) const;
virtual NetNet* elaborate_net(Design*des, NetScope*scope, virtual NetNet* elaborate_net(Design*des, NetScope*scope,
@ -609,7 +613,6 @@ class PECallFunction : public PExpr {
~PECallFunction(); ~PECallFunction();
virtual void dump(ostream &) const; virtual void dump(ostream &) const;
//virtual int test_width(bool) const;
virtual NetNet* elaborate_net(Design*des, NetScope*scope, virtual NetNet* elaborate_net(Design*des, NetScope*scope,
unsigned width, unsigned width,
@ -639,6 +642,11 @@ class PECallFunction : public PExpr {
/* /*
* $Log: PExpr.h,v $ * $Log: PExpr.h,v $
* Revision 1.85 2006/11/04 06:19:24 steve
* Remove last bits of relax_width methods, and use test_width
* to calculate the width of an r-value expression that may
* contain unsized numbers.
*
* Revision 1.84 2006/10/30 05:44:49 steve * Revision 1.84 2006/10/30 05:44:49 steve
* Expression widths with unsized literals are pseudo-infinite width. * Expression widths with unsized literals are pseudo-infinite width.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: elab_expr.cc,v 1.114 2006/10/30 05:44:49 steve Exp $" #ident "$Id: elab_expr.cc,v 1.115 2006/11/04 06:19:24 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -32,7 +32,8 @@
* The default behavor for the test_width method is to just return the * The default behavor for the test_width method is to just return the
* minimum width that is passed in. * minimum width that is passed in.
*/ */
unsigned PExpr::test_width(unsigned min, unsigned lval, bool&) const unsigned PExpr::test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval, bool&) const
{ {
if (debug_elaborate) { if (debug_elaborate) {
cerr << get_line() << ": debug: test_width defaults to " cerr << get_line() << ": debug: test_width defaults to "
@ -51,12 +52,13 @@ NetExpr* PExpr::elaborate_expr(Design*des, NetScope*, int, bool) const
return 0; return 0;
} }
unsigned PEBinary::test_width(unsigned min, unsigned lval, bool&unsized_flag) const unsigned PEBinary::test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval, bool&unsized_flag) const
{ {
bool flag_left = false; bool flag_left = false;
bool flag_right = false; bool flag_right = false;
unsigned wid_left = left_->test_width(min, lval, flag_left); unsigned wid_left = left_->test_width(des,scope, min, lval, flag_left);
unsigned wid_right = right_->test_width(min, lval, flag_right); unsigned wid_right = right_->test_width(des,scope, min, lval, flag_right);
if (flag_left || flag_right) if (flag_left || flag_right)
unsized_flag = true; unsized_flag = true;
@ -106,13 +108,14 @@ NetEBinary* PEBinary::elaborate_expr(Design*des, NetScope*scope,
return 0; return 0;
} }
NetEBinary*tmp = elaborate_eval_expr_base_(des, lp, rp); NetEBinary*tmp = elaborate_eval_expr_base_(des, lp, rp, expr_wid);
return tmp; return tmp;
} }
NetEBinary* PEBinary::elaborate_eval_expr_base_(Design*des, NetEBinary* PEBinary::elaborate_eval_expr_base_(Design*des,
NetExpr*lp, NetExpr*lp,
NetExpr*rp) const NetExpr*rp,
int expr_wid) const
{ {
/* If either expression can be evaluated ahead of time, then /* If either expression can be evaluated ahead of time, then
do so. This can prove helpful later. */ do so. This can prove helpful later. */
@ -130,7 +133,7 @@ NetEBinary* PEBinary::elaborate_eval_expr_base_(Design*des,
} }
} }
return elaborate_expr_base_(des, lp, rp); return elaborate_expr_base_(des, lp, rp, expr_wid);
} }
/* /*
@ -139,7 +142,8 @@ NetEBinary* PEBinary::elaborate_eval_expr_base_(Design*des,
* the correct NetEBinary object and connect the parameters. * the correct NetEBinary object and connect the parameters.
*/ */
NetEBinary* PEBinary::elaborate_expr_base_(Design*des, NetEBinary* PEBinary::elaborate_expr_base_(Design*des,
NetExpr*lp, NetExpr*rp) const NetExpr*lp, NetExpr*rp,
int expr_wid) const
{ {
bool flag; bool flag;
@ -204,6 +208,9 @@ NetEBinary* PEBinary::elaborate_expr_base_(Design*des,
case '+': case '+':
case '-': case '-':
tmp = new NetEBAdd(op_, lp, rp); tmp = new NetEBAdd(op_, lp, rp);
if (expr_wid > 0 && (tmp->expr_type() == IVL_VT_BOOL
|| tmp->expr_type() == IVL_VT_LOGIC))
tmp->set_width(expr_wid);
tmp->set_line(*this); tmp->set_line(*this);
break; break;
@ -245,7 +252,7 @@ NetEBinary* PEBinary::elaborate_expr_base_(Design*des,
return tmp; return tmp;
} }
unsigned PEBComp::test_width(unsigned, unsigned, bool&) const unsigned PEBComp::test_width(Design*, NetScope*,unsigned, unsigned, bool&) const
{ {
return 1; return 1;
} }
@ -256,8 +263,26 @@ NetEBinary* PEBComp::elaborate_expr(Design*des, NetScope*scope,
assert(left_); assert(left_);
assert(right_); assert(right_);
bool unsized_flag = false;
unsigned left_width = left_->test_width(des, scope, 0, 0, unsized_flag);
bool save_flag = unsized_flag;
unsigned right_width = right_->test_width(des, scope, 0, 0, unsized_flag);
if (save_flag != unsized_flag)
left_width = left_->test_width(des, scope, 0, 0, unsized_flag);
/* Width of operands is self-determined. */ /* Width of operands is self-determined. */
int use_wid = -1; int use_wid = left_width;
if (right_width > left_width)
use_wid = right_width;
if (debug_elaborate) {
cerr << get_line() << ": debug: "
<< "Comparison expression operands are "
<< left_width << " bits and "
<< right_width << " bits. Resorting to "
<< use_wid << " bits." << endl;
}
NetExpr*lp = left_->elaborate_expr(des, scope, use_wid, false); NetExpr*lp = left_->elaborate_expr(des, scope, use_wid, false);
NetExpr*rp = right_->elaborate_expr(des, scope, use_wid, false); NetExpr*rp = right_->elaborate_expr(des, scope, use_wid, false);
@ -267,20 +292,13 @@ NetEBinary* PEBComp::elaborate_expr(Design*des, NetScope*scope,
return 0; return 0;
} }
/* If we find that one of the operands are indefinitely wide, return elaborate_eval_expr_base_(des, lp, rp, use_wid);
then go ahead and relax the width of the operand to
eliminate loss. */
if (! lp->has_width())
rp->relax_width();
if (! rp->has_width())
lp->relax_width();
return elaborate_eval_expr_base_(des, lp, rp);
} }
unsigned PEBShift::test_width(unsigned min, unsigned lval, bool&unsized_flag) const unsigned PEBShift::test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval, bool&unsized_flag) const
{ {
unsigned wid_left = left_->test_width(min, 0, unsized_flag); unsigned wid_left = left_->test_width(des,scope,min, 0, unsized_flag);
// The right expression is self-determined and has no impact // The right expression is self-determined and has no impact
// on the expression size that is generated. // on the expression size that is generated.
@ -591,9 +609,118 @@ NetExpr* PEFNumber::elaborate_expr(Design*des, NetScope*scope, int, bool) const
return tmp; return tmp;
} }
/*
unsigned PEIdent::test_width(unsigned min, unsigned lval, bool&unsized_flag) const * Given that the msb_ and lsb_ are part select expressions, this
* function calculates their values. Note that this method does *not*
* convert the values to canonical form.
*/
bool PEIdent::calculate_parts_(Design*des, NetScope*scope,
long&msb, long&lsb) const
{ {
assert(lsb_ != 0);
assert(msb_ != 0);
/* This handles part selects. In this case, there are
two bit select expressions, and both must be
constant. Evaluate them and pass the results back to
the caller. */
NetExpr*lsb_ex = elab_and_eval(des, scope, lsb_, -1);
NetEConst*lsb_c = dynamic_cast<NetEConst*>(lsb_ex);
if (lsb_c == 0) {
cerr << lsb_->get_line() << ": error: "
"Part select expressions must be constant."
<< endl;
cerr << lsb_->get_line() << ": : This lsb expression "
"violates the rule: " << *lsb_ << endl;
des->errors += 1;
return false;
}
NetExpr*msb_ex = elab_and_eval(des, scope, msb_, -1);
NetEConst*msb_c = dynamic_cast<NetEConst*>(msb_ex);
if (msb_c == 0) {
cerr << msb_->get_line() << ": error: "
"Part select expressions must be constant."
<< endl;
cerr << msb_->get_line() << ": : This msb expression "
"violates the rule: " << *msb_ << endl;
des->errors += 1;
return false;
}
msb = msb_c->value().as_long();
lsb = lsb_c->value().as_long();
delete msb_ex;
delete lsb_ex;
return true;
}
bool PEIdent::calculate_up_do_width_(Design*des, NetScope*scope,
unsigned long&wid) const
{
assert(lsb_);
bool flag = true;
/* Calculate the width expression (in the lsb_ position)
first. If the expression is not constant, error but guess 1
so we can keep going and find more errors. */
NetExpr*wid_ex = elab_and_eval(des, scope, lsb_, -1);
NetEConst*wid_c = dynamic_cast<NetEConst*>(wid_ex);
if (wid_c == 0) {
cerr << get_line() << ": error: Indexed part width must be "
<< "constant. Expression in question is..." << endl;
cerr << get_line() << ": : " << *wid_ex << endl;
des->errors += 1;
flag = false;
}
wid = wid_c? wid_c->value().as_ulong() : 1;
delete wid_ex;
return flag;
}
unsigned PEIdent::test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval,
bool&unsized_flag) const
{
NetNet* net = 0;
NetMemory* mem = 0;
const NetExpr*par = 0;
NetEvent* eve = 0;
const NetExpr*ex1, *ex2;
NetScope*found_in = symbol_search(des, scope, path_,
net, mem, par, eve,
ex1, ex2);
if (net != 0) {
unsigned use_width = net->vector_width();
switch (sel_) {
case SEL_NONE:
break;
case SEL_PART:
{ long msb, lsb;
bool flag = calculate_parts_(des, scope, msb, lsb);
use_width = 1 + ((msb>lsb)? (msb-lsb) : (lsb-msb));
break;
}
case SEL_IDX_UP:
case SEL_IDX_DO:
{ unsigned long tmp = 0;
calculate_up_do_width_(des, scope, tmp);
use_width = tmp;
break;
}
default:
assert(0);
}
return use_width;
}
return min; return min;
} }
@ -1055,37 +1182,23 @@ NetExpr* PEIdent::elaborate_expr_param(Design*des,
NetExpr* PEIdent::elaborate_expr_net_part_(Design*des, NetScope*scope, NetExpr* PEIdent::elaborate_expr_net_part_(Design*des, NetScope*scope,
NetNet*net, NetScope*found_in)const NetNet*net, NetScope*found_in)const
{ {
assert(lsb_ != 0); long msv, lsv;
assert(msb_ != 0);
assert(idx_.empty()); assert(idx_.empty());
bool flag = calculate_parts_(des, scope, msv, lsv);
verinum*lsn = lsb_->eval_const(des, scope); if (!flag)
verinum*msn = msb_->eval_const(des, scope);
if ((lsn == 0) || (msn == 0)) {
cerr << get_line() << ": error: "
"Part select expressions must be "
"constant expressions." << endl;
des->errors += 1;
return 0; return 0;
}
assert(lsn);
assert(msn);
/* The indices of part selects are signed integers, so allow /* The indices of part selects are signed integers, so allow
negative values. However, the width that they represent is negative values. However, the width that they represent is
unsigned. Remember that any order is possible, unsigned. Remember that any order is possible,
i.e., [1:0], [-4:6], etc. */ i.e., [1:0], [-4:6], etc. */
long lsv = lsn->as_long();
long msv = msn->as_long();
unsigned long wid = 1 + ((msv>lsv)? (msv-lsv) : (lsv-msv)); unsigned long wid = 1 + ((msv>lsv)? (msv-lsv) : (lsv-msv));
if (wid > net->vector_width()) { if (wid > net->vector_width()) {
cerr << get_line() << ": error: part select [" cerr << get_line() << ": error: part select ["
<< msv << ":" << lsv << "] out of range." << endl; << msv << ":" << lsv << "] out of range." << endl;
des->errors += 1; des->errors += 1;
delete lsn; //delete lsn;
delete msn; //delete msn;
return 0; return 0;
} }
assert(wid <= net->vector_width()); assert(wid <= net->vector_width());
@ -1094,8 +1207,8 @@ NetExpr* PEIdent::elaborate_expr_net_part_(Design*des, NetScope*scope,
cerr << get_line() << ": error: part select [" cerr << get_line() << ": error: part select ["
<< msv << ":" << lsv << "] out of order." << endl; << msv << ":" << lsv << "] out of order." << endl;
des->errors += 1; des->errors += 1;
delete lsn; //delete lsn;
delete msn; //delete msn;
return 0; return 0;
} }
@ -1104,8 +1217,8 @@ NetExpr* PEIdent::elaborate_expr_net_part_(Design*des, NetScope*scope,
cerr << get_line() << ": error: part select [" cerr << get_line() << ": error: part select ["
<< msv << ":" << lsv << "] out of range." << endl; << msv << ":" << lsv << "] out of range." << endl;
des->errors += 1; des->errors += 1;
delete lsn; //delete lsn;
delete msn; //delete msn;
return 0; return 0;
} }
@ -1140,19 +1253,9 @@ NetExpr* PEIdent::elaborate_expr_net_idx_up_(Design*des, NetScope*scope,
NetExpr*base = elab_and_eval(des, scope, msb_, -1); NetExpr*base = elab_and_eval(des, scope, msb_, -1);
NetExpr*wid_e = elab_and_eval(des, scope, lsb_, -1); unsigned long wid = 0;
NetEConst*wid_c = dynamic_cast<NetEConst*> (wid_e); calculate_up_do_width_(des, scope, wid);
if (wid_c == 0) {
cerr << get_line() << ": error: Width of indexed part select "
<< "must be constant." << endl;
cerr << get_line() << ": : Width expression is: "
<< *wid_e << endl;
des->errors += 1;
return 0;
}
assert(wid_c != 0);
unsigned long wid = wid_c->value().as_ulong();
// Handle the special case that the base is constant as // Handle the special case that the base is constant as
// well. In this case it can be converted to a conventional // well. In this case it can be converted to a conventional
@ -1193,19 +1296,8 @@ NetExpr* PEIdent::elaborate_expr_net_idx_do_(Design*des, NetScope*scope,
NetExpr*base = elab_and_eval(des, scope, msb_, -1); NetExpr*base = elab_and_eval(des, scope, msb_, -1);
NetExpr*wid_e = elab_and_eval(des, scope, lsb_, -1); unsigned long wid = 0;
NetEConst*wid_c = dynamic_cast<NetEConst*> (wid_e); calculate_up_do_width_(des, scope, wid);
if (wid_c == 0) {
cerr << get_line() << ": error: Width of indexed part select "
<< "must be constant." << endl;
cerr << get_line() << ": : Width expression is: "
<< *wid_e << endl;
des->errors += 1;
return 0;
}
assert(wid_c != 0);
long wid = wid_c->value().as_long();
// Handle the special case that the base is constant as // Handle the special case that the base is constant as
// well. In this case it can be converted to a conventional // well. In this case it can be converted to a conventional
@ -1335,7 +1427,8 @@ NetExpr* PEIdent::elaborate_expr_net(Design*des, NetScope*scope,
return node; return node;
} }
unsigned PENumber::test_width(unsigned min, unsigned lval, bool&unsized_flag) const unsigned PENumber::test_width(Design*, NetScope*,
unsigned min, unsigned lval, bool&unsized_flag) const
{ {
unsigned use_wid = value_->len(); unsigned use_wid = value_->len();
if (min > use_wid) if (min > use_wid)
@ -1545,6 +1638,11 @@ NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope,
/* /*
* $Log: elab_expr.cc,v $ * $Log: elab_expr.cc,v $
* Revision 1.115 2006/11/04 06:19:24 steve
* Remove last bits of relax_width methods, and use test_width
* to calculate the width of an r-value expression that may
* contain unsized numbers.
*
* Revision 1.114 2006/10/30 05:44:49 steve * Revision 1.114 2006/10/30 05:44:49 steve
* Expression widths with unsized literals are pseudo-infinite width. * Expression widths with unsized literals are pseudo-infinite width.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: elab_lval.cc,v 1.36 2006/06/02 04:48:50 steve Exp $" #ident "$Id: elab_lval.cc,v 1.37 2006/11/04 06:19:25 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -304,41 +304,10 @@ NetAssign_* PEIdent::elaborate_lval_net_part_(Design*des,
NetScope*scope, NetScope*scope,
NetNet*reg) const NetNet*reg) const
{ {
assert(msb_ && lsb_); long msb, lsb;
bool flag = calculate_parts_(des, scope, msb, lsb);
/* This handles part selects. In this case, there are if (!flag)
two bit select expressions, and both must be
constant. Evaluate them and pass the results back to
the caller. */
NetExpr*lsb_ex = elab_and_eval(des, scope, lsb_, -1);
NetEConst*lsb_c = dynamic_cast<NetEConst*>(lsb_ex);
if (lsb_c == 0) {
cerr << lsb_->get_line() << ": error: "
"Part select expressions must be constant."
<< endl;
cerr << lsb_->get_line() << ": : This lsb expression "
"violates the rule: " << *lsb_ << endl;
des->errors += 1;
return 0; return 0;
}
NetExpr*msb_ex = elab_and_eval(des, scope, msb_, -1);
NetEConst*msb_c = dynamic_cast<NetEConst*>(msb_ex);
if (msb_c == 0) {
cerr << msb_->get_line() << ": error: "
"Part select expressions must be constant."
<< endl;
cerr << msb_->get_line() << ": : This msb expression "
"violates the rule: " << *msb_ << endl;
des->errors += 1;
return 0;
}
long msb = msb_c->value().as_long();
long lsb = lsb_c->value().as_long();
delete msb_ex;
delete lsb_ex;
NetAssign_*lv = 0; NetAssign_*lv = 0;
@ -402,21 +371,8 @@ NetAssign_* PEIdent::elaborate_lval_net_idx_up_(Design*des,
return 0; return 0;
} }
/* Calculate the width expression (in the lsb_ position) unsigned long wid;
first. If the expression is not constant, error but guess 1 calculate_up_do_width_(des, scope, wid);
so we can keep going and find more errors. */
NetExpr*wid_ex = elab_and_eval(des, scope, lsb_, -1);
NetEConst*wid_c = dynamic_cast<NetEConst*>(wid_ex);
if (wid_c == 0) {
cerr << get_line() << ": error: Indexed part width must be "
<< "constant. Expression in question is..." << endl;
cerr << get_line() << ": : " << *wid_ex << endl;
des->errors += 1;
}
unsigned wid = wid_c? wid_c->value().as_ulong() : 1;
delete wid_ex;
NetExpr*base = elab_and_eval(des, scope, msb_, -1); NetExpr*base = elab_and_eval(des, scope, msb_, -1);
@ -544,6 +500,11 @@ NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*, bool) const
/* /*
* $Log: elab_lval.cc,v $ * $Log: elab_lval.cc,v $
* Revision 1.37 2006/11/04 06:19:25 steve
* Remove last bits of relax_width methods, and use test_width
* to calculate the width of an r-value expression that may
* contain unsized numbers.
*
* Revision 1.36 2006/06/02 04:48:50 steve * Revision 1.36 2006/06/02 04:48:50 steve
* Make elaborate_expr methods aware of the width that the context * Make elaborate_expr methods aware of the width that the context
* requires of it. In the process, fix sizing of the width of unary * requires of it. In the process, fix sizing of the width of unary

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: elab_pexpr.cc,v 1.24 2006/06/02 04:48:50 steve Exp $" #ident "$Id: elab_pexpr.cc,v 1.25 2006/11/04 06:19:25 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -53,7 +53,7 @@ NetExpr*PEBinary::elaborate_pexpr (Design*des, NetScope*scope) const
return 0; return 0;
} }
NetEBinary*tmp = elaborate_expr_base_(des, lp, rp); NetEBinary*tmp = elaborate_expr_base_(des, lp, rp, -1);
return tmp; return tmp;
} }
@ -236,6 +236,11 @@ NetExpr*PEUnary::elaborate_pexpr (Design*des, NetScope*scope) const
/* /*
* $Log: elab_pexpr.cc,v $ * $Log: elab_pexpr.cc,v $
* Revision 1.25 2006/11/04 06:19:25 steve
* Remove last bits of relax_width methods, and use test_width
* to calculate the width of an r-value expression that may
* contain unsized numbers.
*
* Revision 1.24 2006/06/02 04:48:50 steve * Revision 1.24 2006/06/02 04:48:50 steve
* Make elaborate_expr methods aware of the width that the context * Make elaborate_expr methods aware of the width that the context
* requires of it. In the process, fix sizing of the width of unary * requires of it. In the process, fix sizing of the width of unary

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: elaborate.cc,v 1.348 2006/10/30 05:44:49 steve Exp $" #ident "$Id: elaborate.cc,v 1.349 2006/11/04 06:19:25 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -1428,7 +1428,7 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
something else based on self-determined widths inside. */ something else based on self-determined widths inside. */
unsigned use_width = lv->lwidth(); unsigned use_width = lv->lwidth();
bool unsized_flag = false; bool unsized_flag = false;
use_width = rval()->test_width(use_width, use_width, unsized_flag); use_width = rval()->test_width(des, scope, use_width, use_width, unsized_flag);
/* Now elaborate to the expected width. */ /* Now elaborate to the expected width. */
NetExpr*rv = elab_and_eval(des, scope, rval(), use_width); NetExpr*rv = elab_and_eval(des, scope, rval(), use_width);
@ -2619,11 +2619,17 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const
assert(sig); assert(sig);
NetAssign_*lv = new NetAssign_(sig); NetAssign_*lv = new NetAssign_(sig);
/* Calculate the width of the initialization as if this were
any other assignment statement. */
unsigned use_width = lv->lwidth();
bool unsized_flag = false;
use_width = expr1_->test_width(des, scope, use_width, use_width, unsized_flag);
/* Make the r-value of the initial assignment, and size it /* Make the r-value of the initial assignment, and size it
properly. Then use it to build the assignment statement. */ properly. Then use it to build the assignment statement. */
etmp = elab_and_eval(des, scope, expr1_, lv->lwidth()); etmp = elab_and_eval(des, scope, expr1_, use_width);
etmp->set_width(lv->lwidth()); etmp->set_width(use_width);
etmp = pad_to_width(etmp, lv->lwidth()); etmp = pad_to_width(etmp, use_width);
if (debug_elaborate) { if (debug_elaborate) {
cerr << get_line() << ": debug: FOR initial assign: " cerr << get_line() << ": debug: FOR initial assign: "
@ -3320,6 +3326,11 @@ Design* elaborate(list<perm_string>roots)
/* /*
* $Log: elaborate.cc,v $ * $Log: elaborate.cc,v $
* Revision 1.349 2006/11/04 06:19:25 steve
* Remove last bits of relax_width methods, and use test_width
* to calculate the width of an r-value expression that may
* contain unsized numbers.
*
* Revision 1.348 2006/10/30 05:44:49 steve * Revision 1.348 2006/10/30 05:44:49 steve
* Expression widths with unsized literals are pseudo-infinite width. * Expression widths with unsized literals are pseudo-infinite width.
* *

View File

@ -19,7 +19,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: netlist.h,v 1.364 2006/10/30 05:44:49 steve Exp $" #ident "$Id: netlist.h,v 1.365 2006/11/04 06:19:25 steve Exp $"
#endif #endif
/* /*
@ -1134,12 +1134,6 @@ class NetExpr : public LineInfo {
// width to the l-value width, if possible. // width to the l-value width, if possible.
virtual bool set_width(unsigned wid, bool last_chance =false); virtual bool set_width(unsigned wid, bool last_chance =false);
// This is similar to set_width, but allows the expression to
// set the width for itself, it a way that eliminates
// loss. This is used by elaboration in expressions where the
// expression width is determined to be "indefinitely large".
virtual void relax_width(void);
// This method returns true if the expression is // This method returns true if the expression is
// signed. Unsigned expressions return false. // signed. Unsigned expressions return false.
bool has_sign() const; bool has_sign() const;
@ -2682,7 +2676,6 @@ class NetEBAdd : public NetEBinary {
virtual ivl_variable_type_t expr_type() const; virtual ivl_variable_type_t expr_type() const;
virtual bool set_width(unsigned w, bool last_chance); virtual bool set_width(unsigned w, bool last_chance);
virtual void relax_width(void);
virtual NetEBAdd* dup_expr() const; virtual NetEBAdd* dup_expr() const;
virtual NetEConst* eval_tree(); virtual NetEConst* eval_tree();
virtual NetNet* synthesize(Design*); virtual NetNet* synthesize(Design*);
@ -3574,6 +3567,11 @@ extern ostream& operator << (ostream&, NetNet::Type);
/* /*
* $Log: netlist.h,v $ * $Log: netlist.h,v $
* Revision 1.365 2006/11/04 06:19:25 steve
* Remove last bits of relax_width methods, and use test_width
* to calculate the width of an r-value expression that may
* contain unsized numbers.
*
* Revision 1.364 2006/10/30 05:44:49 steve * Revision 1.364 2006/10/30 05:44:49 steve
* Expression widths with unsized literals are pseudo-infinite width. * Expression widths with unsized literals are pseudo-infinite width.
* *

View File

@ -17,7 +17,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/ */
#ifdef HAVE_CVS_IDENT #ifdef HAVE_CVS_IDENT
#ident "$Id: set_width.cc,v 1.40 2006/10/30 05:44:49 steve Exp $" #ident "$Id: set_width.cc,v 1.41 2006/11/04 06:19:25 steve Exp $"
#endif #endif
# include "config.h" # include "config.h"
@ -46,14 +46,6 @@ bool NetExpr::set_width(unsigned w, bool)
return false; return false;
} }
/*
* The default relax_width method does nothing, and leaves the
* previously elaborated width.
*/
void NetExpr::relax_width(void)
{
}
bool NetEBinary::set_width(unsigned w, bool) bool NetEBinary::set_width(unsigned w, bool)
{ {
bool flag = true; bool flag = true;
@ -117,24 +109,6 @@ bool NetEBAdd::set_width(unsigned w, bool)
return wid == w; return wid == w;
} }
void NetEBAdd::relax_width(void)
{
unsigned wid = left_->expr_width();
if (right_->expr_width() > wid)
wid = right_->expr_width();
// Allow space for the carry.
wid += 1;
if (debug_elaborate)
cerr << get_line() << ": debug: "
<< "Relax addition width to " << wid << endl;
left_->set_width(wid);
right_->set_width(wid);
expr_width(wid);
}
/* /*
* The bitwise logical operators have operands the same size as the * The bitwise logical operators have operands the same size as the
* result. Anything else is a mess. I first try to get the operands to * result. Anything else is a mess. I first try to get the operands to
@ -467,6 +441,11 @@ bool NetEUReduce::set_width(unsigned w, bool)
/* /*
* $Log: set_width.cc,v $ * $Log: set_width.cc,v $
* Revision 1.41 2006/11/04 06:19:25 steve
* Remove last bits of relax_width methods, and use test_width
* to calculate the width of an r-value expression that may
* contain unsized numbers.
*
* Revision 1.40 2006/10/30 05:44:49 steve * Revision 1.40 2006/10/30 05:44:49 steve
* Expression widths with unsized literals are pseudo-infinite width. * Expression widths with unsized literals are pseudo-infinite width.
* *