Enforce bit width of operands of comparisons operators.

The comparison operator operands are self determined, but are forced
to be the width of the wider operand. This means that the operands must
be evaluated with their widths truncated. In spite of all this, note
that comparisons expression results are 1 bit wide.
This commit is contained in:
Stephen Williams 2008-10-29 19:34:44 -07:00
parent 22ddb26389
commit b7d3276e4d
4 changed files with 61 additions and 30 deletions

View File

@ -494,6 +494,7 @@ class PEBComp : public PEBinary {
NetExpr* elaborate_expr(Design*des, NetScope*scope, NetExpr* elaborate_expr(Design*des, NetScope*scope,
int expr_width, bool sys_task_arg) const; int expr_width, bool sys_task_arg) const;
NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
}; };
class PEBShift : public PEBinary { class PEBShift : public PEBinary {

View File

@ -279,8 +279,6 @@ NetExpr* PEBinary::elaborate_expr_base_(Design*des,
NetExpr*lp, NetExpr*rp, NetExpr*lp, NetExpr*rp,
int expr_wid) const int expr_wid) const
{ {
bool flag;
if (debug_elaborate) { if (debug_elaborate) {
cerr << get_fileline() << ": debug: elaborate expression " cerr << get_fileline() << ": debug: elaborate expression "
<< *this << " expr_wid=" << expr_wid << endl; << *this << " expr_wid=" << expr_wid << endl;
@ -341,38 +339,18 @@ NetExpr* PEBinary::elaborate_expr_base_(Design*des,
case 'E': /* === */ case 'E': /* === */
case 'N': /* !== */ case 'N': /* !== */
if (lp->expr_type() == IVL_VT_REAL ||
rp->expr_type() == IVL_VT_REAL) {
cerr << get_fileline() << ": error: "
<< human_readable_op(op_)
<< "may not have real operands." << endl;
return 0;
}
/* Fall through... */
case 'e': /* == */ case 'e': /* == */
case 'n': /* != */ case 'n': /* != */
if (dynamic_cast<NetEConst*>(rp)
&& (lp->expr_width() > rp->expr_width()))
rp->set_width(lp->expr_width());
if (dynamic_cast<NetEConst*>(lp)
&& (lp->expr_width() < rp->expr_width()))
lp->set_width(rp->expr_width());
/* from here, handle this like other compares. */
case 'L': /* <= */ case 'L': /* <= */
case 'G': /* >= */ case 'G': /* >= */
case '<': case '<':
case '>': case '>':
tmp = new NetEBComp(op_, lp, rp);
tmp->set_line(*this);
flag = tmp->set_width(1);
if (flag == false) {
cerr << get_fileline() << ": internal error: " cerr << get_fileline() << ": internal error: "
"expression bit width of comparison != 1." << endl; << "Elaboration of " << human_readable_op(op_)
<< " Should have been handled in NetEBComp::elaborate."
<< endl;
des->errors += 1; des->errors += 1;
} return 0;
break;
case 'm': // min(l,r) case 'm': // min(l,r)
case 'M': // max(l,r) case 'M': // max(l,r)
@ -790,7 +768,35 @@ NetExpr* PEBComp::elaborate_expr(Design*des, NetScope*scope,
if (type_is_vectorable(rp->expr_type())) if (type_is_vectorable(rp->expr_type()))
rp = pad_to_width(rp, use_wid); rp = pad_to_width(rp, use_wid);
return elaborate_eval_expr_base_(des, lp, rp, use_wid); eval_expr(lp, use_wid);
eval_expr(rp, use_wid);
// Handle some operand-specific special cases...
switch (op_) {
case 'E': /* === */
case 'N': /* !== */
if (lp->expr_type() == IVL_VT_REAL ||
rp->expr_type() == IVL_VT_REAL) {
cerr << get_fileline() << ": error: "
<< human_readable_op(op_)
<< "may not have real operands." << endl;
return 0;
}
break;
default:
break;
}
NetEBComp*tmp = new NetEBComp(op_, lp, rp);
tmp->set_line(*this);
bool flag = tmp->set_width(1);
if (flag == false) {
cerr << get_fileline() << ": internal error: "
"expression bit width of comparison != 1." << endl;
des->errors += 1;
}
return tmp;
} }
unsigned PEBShift::test_width(Design*des, NetScope*scope, unsigned PEBShift::test_width(Design*des, NetScope*scope,

View File

@ -57,6 +57,30 @@ NetExpr*PEBinary::elaborate_pexpr (Design*des, NetScope*scope) const
return tmp; return tmp;
} }
NetExpr*PEBComp::elaborate_pexpr(Design*des, NetScope*scope) const
{
NetExpr*lp = left_->elaborate_pexpr(des, scope);
NetExpr*rp = right_->elaborate_pexpr(des, scope);
if ((lp == 0) || (rp == 0)) {
delete lp;
delete rp;
return 0;
}
suppress_binary_operand_sign_if_needed_(lp, rp);
NetEBComp*tmp = new NetEBComp(op_, lp, rp);
tmp->set_line(*this);
bool flag = tmp->set_width(1);
if (flag == false) {
cerr << get_fileline() << ": internal error: "
"expression bit width of comparison != 1." << endl;
des->errors += 1;
}
return tmp;
}
/* /*
* Event though parameters are not generally sized, parameter * Event though parameters are not generally sized, parameter
* expressions can include concatenation expressions. This requires * expressions can include concatenation expressions. This requires

View File

@ -3233,7 +3233,7 @@ class NetEBComp : public NetEBinary {
NetEBComp(char op, NetExpr*l, NetExpr*r); NetEBComp(char op, NetExpr*l, NetExpr*r);
~NetEBComp(); ~NetEBComp();
virtual bool set_width(unsigned w, bool last_chance); virtual bool set_width(unsigned w, bool last_chance =false);
/* A compare expression has a definite width. */ /* A compare expression has a definite width. */
virtual bool has_width() const; virtual bool has_width() const;