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:
parent
ed5d3188b3
commit
c339dc4bbc
52
PExpr.h
52
PExpr.h
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#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
|
||||
|
||||
# include <string>
|
||||
|
|
@ -72,7 +72,9 @@ class PExpr : public LineInfo {
|
|||
// unsized and therefore expandable. This happens if a
|
||||
// sub-expression is an unsized literal. Some expressions make
|
||||
// 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
|
||||
// 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 void dump(ostream&) const;
|
||||
|
||||
//virtual int test_width(bool) const;
|
||||
|
||||
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope,
|
||||
bool implicit_net_ok =false) 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 int test_width(bool) const;
|
||||
|
||||
private:
|
||||
edge_t type_;
|
||||
PExpr *expr_;
|
||||
|
|
@ -220,8 +218,6 @@ class PEFNumber : public PExpr {
|
|||
|
||||
const verireal& value() const;
|
||||
|
||||
//virtual int test_width(bool) const;
|
||||
|
||||
/* The eval_const method as applied to a floating point number
|
||||
gets the *integer* value of the number. This accounts for
|
||||
any rounding that is needed to get the value. */
|
||||
|
|
@ -255,9 +251,9 @@ class PEIdent : public PExpr {
|
|||
~PEIdent();
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
virtual unsigned test_width(unsigned min, unsigned lval, bool&unsized_flag) const;
|
||||
|
||||
//virtual int test_width(bool) const;
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
unsigned min, unsigned lval,
|
||||
bool&unsized_flag) const;
|
||||
|
||||
// Identifiers are allowed (with restrictions) is assign l-values.
|
||||
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope,
|
||||
|
|
@ -292,6 +288,11 @@ class PEIdent : public PExpr {
|
|||
|
||||
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:
|
||||
NetAssign_*elaborate_lval_net_part_(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;
|
||||
|
||||
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,
|
||||
unsigned lwidth,
|
||||
|
|
@ -416,7 +419,6 @@ class PEString : public PExpr {
|
|||
|
||||
string value() const;
|
||||
virtual void dump(ostream&) const;
|
||||
//virtual int test_width(bool) const;
|
||||
|
||||
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
|
||||
unsigned width,
|
||||
|
|
@ -443,7 +445,6 @@ class PEUnary : public PExpr {
|
|||
~PEUnary();
|
||||
|
||||
virtual void dump(ostream&out) const;
|
||||
//virtual int test_width(bool) const;
|
||||
|
||||
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
|
||||
unsigned width,
|
||||
|
|
@ -471,11 +472,12 @@ class PEBinary : public PExpr {
|
|||
~PEBinary();
|
||||
|
||||
virtual bool is_constant(Module*) const;
|
||||
//virtual int test_width(bool) 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,
|
||||
unsigned width,
|
||||
|
|
@ -494,8 +496,8 @@ class PEBinary : public PExpr {
|
|||
PExpr*left_;
|
||||
PExpr*right_;
|
||||
|
||||
NetEBinary*elaborate_expr_base_(Design*, NetExpr*lp, NetExpr*rp) const;
|
||||
NetEBinary*elaborate_eval_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, int use_wid) const;
|
||||
|
||||
private:
|
||||
NetNet* elaborate_net_add_(Design*des, NetScope*scope,
|
||||
|
|
@ -550,7 +552,9 @@ class PEBComp : public PEBinary {
|
|||
explicit PEBComp(char op, PExpr*l, PExpr*r);
|
||||
~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,
|
||||
int expr_width, bool sys_task_arg) const;
|
||||
|
|
@ -562,7 +566,8 @@ class PEBShift : public PEBinary {
|
|||
explicit PEBShift(char op, PExpr*l, PExpr*r);
|
||||
~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();
|
||||
|
||||
virtual bool is_constant(Module*) const;
|
||||
//virtual int test_width(bool) const;
|
||||
|
||||
virtual void dump(ostream&out) const;
|
||||
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
|
||||
|
|
@ -609,7 +613,6 @@ class PECallFunction : public PExpr {
|
|||
~PECallFunction();
|
||||
|
||||
virtual void dump(ostream &) const;
|
||||
//virtual int test_width(bool) const;
|
||||
|
||||
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
|
||||
unsigned width,
|
||||
|
|
@ -639,6 +642,11 @@ class PECallFunction : public PExpr {
|
|||
|
||||
/*
|
||||
* $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
|
||||
* Expression widths with unsized literals are pseudo-infinite width.
|
||||
*
|
||||
|
|
|
|||
244
elab_expr.cc
244
elab_expr.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#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
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -32,7 +32,8 @@
|
|||
* The default behavor for the test_width method is to just return the
|
||||
* 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) {
|
||||
cerr << get_line() << ": debug: test_width defaults to "
|
||||
|
|
@ -51,12 +52,13 @@ NetExpr* PExpr::elaborate_expr(Design*des, NetScope*, int, bool) const
|
|||
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_right = false;
|
||||
unsigned wid_left = left_->test_width(min, lval, flag_left);
|
||||
unsigned wid_right = right_->test_width(min, lval, flag_right);
|
||||
unsigned wid_left = left_->test_width(des,scope, min, lval, flag_left);
|
||||
unsigned wid_right = right_->test_width(des,scope, min, lval, flag_right);
|
||||
|
||||
if (flag_left || flag_right)
|
||||
unsized_flag = true;
|
||||
|
|
@ -106,13 +108,14 @@ NetEBinary* PEBinary::elaborate_expr(Design*des, NetScope*scope,
|
|||
return 0;
|
||||
}
|
||||
|
||||
NetEBinary*tmp = elaborate_eval_expr_base_(des, lp, rp);
|
||||
NetEBinary*tmp = elaborate_eval_expr_base_(des, lp, rp, expr_wid);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetEBinary* PEBinary::elaborate_eval_expr_base_(Design*des,
|
||||
NetExpr*lp,
|
||||
NetExpr*rp) const
|
||||
NetExpr*rp,
|
||||
int expr_wid) const
|
||||
{
|
||||
/* If either expression can be evaluated ahead of time, then
|
||||
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.
|
||||
*/
|
||||
NetEBinary* PEBinary::elaborate_expr_base_(Design*des,
|
||||
NetExpr*lp, NetExpr*rp) const
|
||||
NetExpr*lp, NetExpr*rp,
|
||||
int expr_wid) const
|
||||
{
|
||||
bool flag;
|
||||
|
||||
|
|
@ -204,6 +208,9 @@ NetEBinary* PEBinary::elaborate_expr_base_(Design*des,
|
|||
case '+':
|
||||
case '-':
|
||||
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);
|
||||
break;
|
||||
|
||||
|
|
@ -245,7 +252,7 @@ NetEBinary* PEBinary::elaborate_expr_base_(Design*des,
|
|||
return tmp;
|
||||
}
|
||||
|
||||
unsigned PEBComp::test_width(unsigned, unsigned, bool&) const
|
||||
unsigned PEBComp::test_width(Design*, NetScope*,unsigned, unsigned, bool&) const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -256,8 +263,26 @@ NetEBinary* PEBComp::elaborate_expr(Design*des, NetScope*scope,
|
|||
assert(left_);
|
||||
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. */
|
||||
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*rp = right_->elaborate_expr(des, scope, use_wid, false);
|
||||
|
|
@ -267,20 +292,13 @@ NetEBinary* PEBComp::elaborate_expr(Design*des, NetScope*scope,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* If we find that one of the operands are indefinitely wide,
|
||||
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);
|
||||
return elaborate_eval_expr_base_(des, lp, rp, use_wid);
|
||||
}
|
||||
|
||||
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
|
||||
// on the expression size that is generated.
|
||||
|
|
@ -591,9 +609,118 @@ NetExpr* PEFNumber::elaborate_expr(Design*des, NetScope*scope, int, bool) const
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
@ -1055,37 +1182,23 @@ NetExpr* PEIdent::elaborate_expr_param(Design*des,
|
|||
NetExpr* PEIdent::elaborate_expr_net_part_(Design*des, NetScope*scope,
|
||||
NetNet*net, NetScope*found_in)const
|
||||
{
|
||||
assert(lsb_ != 0);
|
||||
assert(msb_ != 0);
|
||||
long msv, lsv;
|
||||
assert(idx_.empty());
|
||||
|
||||
verinum*lsn = lsb_->eval_const(des, scope);
|
||||
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;
|
||||
bool flag = calculate_parts_(des, scope, msv, lsv);
|
||||
if (!flag)
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(lsn);
|
||||
assert(msn);
|
||||
|
||||
/* The indices of part selects are signed integers, so allow
|
||||
negative values. However, the width that they represent is
|
||||
unsigned. Remember that any order is possible,
|
||||
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));
|
||||
if (wid > net->vector_width()) {
|
||||
cerr << get_line() << ": error: part select ["
|
||||
<< msv << ":" << lsv << "] out of range." << endl;
|
||||
des->errors += 1;
|
||||
delete lsn;
|
||||
delete msn;
|
||||
//delete lsn;
|
||||
//delete msn;
|
||||
return 0;
|
||||
}
|
||||
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 ["
|
||||
<< msv << ":" << lsv << "] out of order." << endl;
|
||||
des->errors += 1;
|
||||
delete lsn;
|
||||
delete msn;
|
||||
//delete lsn;
|
||||
//delete msn;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1104,8 +1217,8 @@ NetExpr* PEIdent::elaborate_expr_net_part_(Design*des, NetScope*scope,
|
|||
cerr << get_line() << ": error: part select ["
|
||||
<< msv << ":" << lsv << "] out of range." << endl;
|
||||
des->errors += 1;
|
||||
delete lsn;
|
||||
delete msn;
|
||||
//delete lsn;
|
||||
//delete msn;
|
||||
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*wid_e = elab_and_eval(des, scope, lsb_, -1);
|
||||
NetEConst*wid_c = dynamic_cast<NetEConst*> (wid_e);
|
||||
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;
|
||||
}
|
||||
unsigned long wid = 0;
|
||||
calculate_up_do_width_(des, scope, wid);
|
||||
|
||||
assert(wid_c != 0);
|
||||
unsigned long wid = wid_c->value().as_ulong();
|
||||
|
||||
// Handle the special case that the base is constant as
|
||||
// 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*wid_e = elab_and_eval(des, scope, lsb_, -1);
|
||||
NetEConst*wid_c = dynamic_cast<NetEConst*> (wid_e);
|
||||
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();
|
||||
unsigned long wid = 0;
|
||||
calculate_up_do_width_(des, scope, wid);
|
||||
|
||||
// Handle the special case that the base is constant as
|
||||
// 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;
|
||||
}
|
||||
|
||||
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();
|
||||
if (min > use_wid)
|
||||
|
|
@ -1545,6 +1638,11 @@ NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope,
|
|||
|
||||
/*
|
||||
* $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
|
||||
* Expression widths with unsized literals are pseudo-infinite width.
|
||||
*
|
||||
|
|
|
|||
61
elab_lval.cc
61
elab_lval.cc
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#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
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -304,41 +304,10 @@ NetAssign_* PEIdent::elaborate_lval_net_part_(Design*des,
|
|||
NetScope*scope,
|
||||
NetNet*reg) const
|
||||
{
|
||||
assert(msb_ && lsb_);
|
||||
|
||||
/* 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;
|
||||
long msb, lsb;
|
||||
bool flag = calculate_parts_(des, scope, msb, lsb);
|
||||
if (!flag)
|
||||
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;
|
||||
|
||||
|
|
@ -402,21 +371,8 @@ NetAssign_* PEIdent::elaborate_lval_net_idx_up_(Design*des,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
unsigned wid = wid_c? wid_c->value().as_ulong() : 1;
|
||||
delete wid_ex;
|
||||
unsigned long wid;
|
||||
calculate_up_do_width_(des, scope, wid);
|
||||
|
||||
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 $
|
||||
* 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
|
||||
* Make elaborate_expr methods aware of the width that the context
|
||||
* requires of it. In the process, fix sizing of the width of unary
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#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
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -53,7 +53,7 @@ NetExpr*PEBinary::elaborate_pexpr (Design*des, NetScope*scope) const
|
|||
return 0;
|
||||
}
|
||||
|
||||
NetEBinary*tmp = elaborate_expr_base_(des, lp, rp);
|
||||
NetEBinary*tmp = elaborate_expr_base_(des, lp, rp, -1);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
|
@ -236,6 +236,11 @@ NetExpr*PEUnary::elaborate_pexpr (Design*des, NetScope*scope) const
|
|||
|
||||
/*
|
||||
* $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
|
||||
* Make elaborate_expr methods aware of the width that the context
|
||||
* requires of it. In the process, fix sizing of the width of unary
|
||||
|
|
|
|||
21
elaborate.cc
21
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.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
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -1428,7 +1428,7 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
|
|||
something else based on self-determined widths inside. */
|
||||
unsigned use_width = lv->lwidth();
|
||||
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. */
|
||||
NetExpr*rv = elab_and_eval(des, scope, rval(), use_width);
|
||||
|
|
@ -2619,11 +2619,17 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const
|
|||
assert(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
|
||||
properly. Then use it to build the assignment statement. */
|
||||
etmp = elab_and_eval(des, scope, expr1_, lv->lwidth());
|
||||
etmp->set_width(lv->lwidth());
|
||||
etmp = pad_to_width(etmp, lv->lwidth());
|
||||
etmp = elab_and_eval(des, scope, expr1_, use_width);
|
||||
etmp->set_width(use_width);
|
||||
etmp = pad_to_width(etmp, use_width);
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_line() << ": debug: FOR initial assign: "
|
||||
|
|
@ -3320,6 +3326,11 @@ Design* elaborate(list<perm_string>roots)
|
|||
|
||||
/*
|
||||
* $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
|
||||
* Expression widths with unsized literals are pseudo-infinite width.
|
||||
*
|
||||
|
|
|
|||
14
netlist.h
14
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.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
|
||||
|
||||
/*
|
||||
|
|
@ -1134,12 +1134,6 @@ class NetExpr : public LineInfo {
|
|||
// width to the l-value width, if possible.
|
||||
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
|
||||
// signed. Unsigned expressions return false.
|
||||
bool has_sign() const;
|
||||
|
|
@ -2682,7 +2676,6 @@ class NetEBAdd : public NetEBinary {
|
|||
virtual ivl_variable_type_t expr_type() const;
|
||||
|
||||
virtual bool set_width(unsigned w, bool last_chance);
|
||||
virtual void relax_width(void);
|
||||
virtual NetEBAdd* dup_expr() const;
|
||||
virtual NetEConst* eval_tree();
|
||||
virtual NetNet* synthesize(Design*);
|
||||
|
|
@ -3574,6 +3567,11 @@ extern ostream& operator << (ostream&, NetNet::Type);
|
|||
|
||||
/*
|
||||
* $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
|
||||
* Expression widths with unsized literals are pseudo-infinite width.
|
||||
*
|
||||
|
|
|
|||
33
set_width.cc
33
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.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
|
||||
|
||||
# include "config.h"
|
||||
|
|
@ -46,14 +46,6 @@ bool NetExpr::set_width(unsigned w, bool)
|
|||
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 flag = true;
|
||||
|
|
@ -117,24 +109,6 @@ bool NetEBAdd::set_width(unsigned w, bool)
|
|||
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
|
||||
* 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 $
|
||||
* 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
|
||||
* Expression widths with unsized literals are pseudo-infinite width.
|
||||
*
|
||||
|
|
|
|||
Loading…
Reference in New Issue