Careful not to lose bits parameter add expression

Parameter expressions that do not otherwise have a size should
evaluate expressions losslessly, expanding as necessary to prevent
overflow of data.

Signed-off-by: Stephen Williams <steve@icarus.com>
This commit is contained in:
Stephen Williams 2007-06-27 21:51:31 -07:00
parent 59a43ab2ce
commit a6f898a702
6 changed files with 21 additions and 9 deletions

12
PExpr.h
View File

@ -79,9 +79,15 @@ class PExpr : public LineInfo {
// Procedural elaboration of the expression. The expr_width is
// the width of the context of the expression (i.e. the
// l-value width of an assignment) or -1 if the expression is
// self-determinted. The sys_task_arg flag is true if
// expressions are allowed to be incomplete.
// l-value width of an assignment),
//
// ... or -1 if the expression is self-determined. or
// ... or -2 if the expression is losslessly
// self-determined. This can happen in situations where the
// result is going to a pseudo-infinitely wide context.
//
// The sys_task_arg flag is true if expressions are allowed to
// be incomplete.
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
int expr_width, bool sys_task_arg) const;

View File

@ -208,7 +208,7 @@ NetEBinary* PEBinary::elaborate_expr_base_(Design*des,
case '+':
case '-':
tmp = new NetEBAdd(op_, lp, rp);
tmp = new NetEBAdd(op_, lp, rp, expr_wid==-2? true : false);
if (expr_wid > 0 && (tmp->expr_type() == IVL_VT_BOOL
|| tmp->expr_type() == IVL_VT_LOGIC))
tmp->set_width(expr_wid);

View File

@ -54,7 +54,7 @@ NetExpr*PEBinary::elaborate_pexpr (Design*des, NetScope*scope) const
return 0;
}
NetEBinary*tmp = elaborate_expr_base_(des, lp, rp, -1);
NetEBinary*tmp = elaborate_expr_base_(des, lp, rp, -2);
return tmp;
}

View File

@ -1754,6 +1754,10 @@ NetProc* PCondit::elaborate(Design*des, NetScope*scope) const
{
assert(scope);
if (debug_elaborate)
cerr << get_line() << ": debug: Elaborate condition statement"
<< " with conditional: " << *expr_ << endl;
// Elaborate and try to evaluate the conditional expression.
NetExpr*expr = elab_and_eval(des, scope, expr_, -1);
if (expr == 0) {

View File

@ -37,7 +37,7 @@ ivl_variable_type_t NetExpr::expr_type() const
* Create an add/sub node from the two operands. Make a best guess of
* the
*/
NetEBAdd::NetEBAdd(char op, NetExpr*l, NetExpr*r)
NetEBAdd::NetEBAdd(char op, NetExpr*l, NetExpr*r, bool lossless_flag)
: NetEBinary(op, l, r)
{
NetEConst* tmp;
@ -75,14 +75,16 @@ NetEBAdd::NetEBAdd(char op, NetExpr*l, NetExpr*r)
}
unsigned pad_width = lossless_flag? 1 : 0;
/* 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());
expr_width(r->expr_width() + pad_width);
} else {
expr_width(l->expr_width());
expr_width(l->expr_width() + pad_width);
}
cast_signed(l->has_sign() && r->has_sign());

View File

@ -2636,7 +2636,7 @@ class NetEBinary : public NetExpr {
class NetEBAdd : public NetEBinary {
public:
NetEBAdd(char op, NetExpr*l, NetExpr*r);
NetEBAdd(char op, NetExpr*l, NetExpr*r, bool lossless_flag =false);
~NetEBAdd();
virtual ivl_variable_type_t expr_type() const;