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:
parent
22ddb26389
commit
b7d3276e4d
1
PExpr.h
1
PExpr.h
|
|
@ -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 {
|
||||||
|
|
|
||||||
64
elab_expr.cc
64
elab_expr.cc
|
|
@ -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);
|
cerr << get_fileline() << ": internal error: "
|
||||||
tmp->set_line(*this);
|
<< "Elaboration of " << human_readable_op(op_)
|
||||||
flag = tmp->set_width(1);
|
<< " Should have been handled in NetEBComp::elaborate."
|
||||||
if (flag == false) {
|
<< endl;
|
||||||
cerr << get_fileline() << ": internal error: "
|
des->errors += 1;
|
||||||
"expression bit width of comparison != 1." << endl;
|
return 0;
|
||||||
des->errors += 1;
|
|
||||||
}
|
|
||||||
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,
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue