V0.8: left shift of integer value needs to use integer size

This is a back port from development of the code to resize an
unsized constant value to 32 bits. Development used integer_width,
but that is not supported in V0.8. Development also supports using
the expression width which V0.8 does not.
This commit is contained in:
Cary R 2008-12-05 10:21:48 -08:00 committed by Stephen Williams
parent 113312a0c1
commit ca5d265350
3 changed files with 53 additions and 8 deletions

View File

@ -376,7 +376,7 @@ class PEBinary : public PExpr {
unsigned long decay, unsigned long decay,
Link::strength_t drive0, Link::strength_t drive0,
Link::strength_t drive1) const; Link::strength_t drive1) const;
virtual NetEBinary*elaborate_expr(Design*des, NetScope*, virtual NetExpr*elaborate_expr(Design*des, NetScope*,
bool sys_task_arg =false) const; bool sys_task_arg =false) const;
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const; virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
virtual verinum* eval_const(const Design*des, const NetScope*sc) const; virtual verinum* eval_const(const Design*des, const NetScope*sc) const;
@ -386,7 +386,7 @@ class PEBinary : public PExpr {
PExpr*left_; PExpr*left_;
PExpr*right_; PExpr*right_;
NetEBinary*elaborate_expr_base_(Design*, NetExpr*lp, NetExpr*rp) const; NetExpr*elaborate_expr_base_(Design*, NetExpr*lp, NetExpr*rp) const;
NetNet* elaborate_net_add_(Design*des, NetScope*scope, NetNet* elaborate_net_add_(Design*des, NetScope*scope,
unsigned lwidth, unsigned lwidth,

View File

@ -43,7 +43,7 @@ NetExpr* PExpr::elaborate_expr(Design*des, NetScope*, bool) const
* and right sides, and creating one of a variety of different NetExpr * and right sides, and creating one of a variety of different NetExpr
* types. * types.
*/ */
NetEBinary* PEBinary::elaborate_expr(Design*des, NetScope*scope, bool) const NetExpr* PEBinary::elaborate_expr(Design*des, NetScope*scope, bool) const
{ {
assert(left_); assert(left_);
assert(right_); assert(right_);
@ -73,7 +73,7 @@ NetEBinary* PEBinary::elaborate_expr(Design*des, NetScope*scope, bool) const
} }
} }
NetEBinary*tmp = elaborate_expr_base_(des, lp, rp); NetExpr*tmp = elaborate_expr_base_(des, lp, rp);
return tmp; return tmp;
} }
@ -82,11 +82,11 @@ NetEBinary* PEBinary::elaborate_expr(Design*des, NetScope*scope, bool) const
* operands are elaborated as necessary, and all I need to do is make * operands are elaborated as necessary, and all I need to do is make
* the correct NetEBinary object and connect the parameters. * the correct NetEBinary object and connect the parameters.
*/ */
NetEBinary* PEBinary::elaborate_expr_base_(Design*des, NetExpr* PEBinary::elaborate_expr_base_(Design*des,
NetExpr*lp, NetExpr*rp) const NetExpr*lp, NetExpr*rp) const
{ {
bool flag; bool flag;
NetEBinary*tmp; NetExpr*tmp;
switch (op_) { switch (op_) {
default: default:
@ -112,6 +112,51 @@ NetEBinary* PEBinary::elaborate_expr_base_(Design*des,
break; break;
case 'l': // << case 'l': // <<
if (NetEConst*lpc = dynamic_cast<NetEConst*> (lp)) {
if (NetEConst*rpc = dynamic_cast<NetEConst*> (rp)) {
// Handle the super-special case that both
// operands are constants. Precalculate the
// entire value here.
verinum lpval = lpc->value();
unsigned shift = rpc->value().as_ulong();
verinum result = lpc->value() << shift;
// If the l-value has explicit size, use that.
if (lpval.has_len()) {
result = verinum(result, lpval.len());
}
tmp = new NetEConst(result);
if (debug_elaborate)
cerr << get_line() << ": debug: "
<< "Precalculate " << *this
<< " to constant " << *tmp << endl;
} else {
// Handle the special case that the left
// operand is constant. If it is unsized, we
// may have to expand it to an integer width.
verinum lpval = lpc->value();
if (lpval.len() < 32 && !lpval.has_len()) {
lpval = verinum(lpval, 32);
lpc = new NetEConst(lpval);
lpc->set_line(*lp);
}
tmp = new NetEBShift(op_, lpc, rp);
if (debug_elaborate)
cerr << get_line() << ": debug: "
<< "Adjust " << *this
<< " to this " << *tmp
<< " to allow for integer widths." << endl;
}
} else {
// Left side is not constant, so handle it the
// default way.
tmp = new NetEBShift(op_, lp, rp);
}
tmp->set_line(*this);
break;
case 'r': // >> case 'r': // >>
case 'R': // >>> case 'R': // >>>
tmp = new NetEBShift(op_, lp, rp); tmp = new NetEBShift(op_, lp, rp);

View File

@ -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); NetExpr*tmp = elaborate_expr_base_(des, lp, rp);
return tmp; return tmp;
} }