Self-determined ternary expressions use better width tester.
When ternary expressions are self-determined, use the test_width method to get a proper reading of the expression width. Also improve the test_width method to handle unsized operands.
This commit is contained in:
parent
46bf03bba4
commit
dc313436c1
41
elab_expr.cc
41
elab_expr.cc
|
|
@ -2166,7 +2166,20 @@ unsigned PETernary::test_width(Design*des, NetScope*scope,
|
||||||
bool&flag) const
|
bool&flag) const
|
||||||
{
|
{
|
||||||
unsigned tru_wid = tru_->test_width(des, scope, min, lval, flag);
|
unsigned tru_wid = tru_->test_width(des, scope, min, lval, flag);
|
||||||
|
bool initial_flag = flag;
|
||||||
unsigned fal_wid = fal_->test_width(des, scope, min, lval, flag);
|
unsigned fal_wid = fal_->test_width(des, scope, min, lval, flag);
|
||||||
|
|
||||||
|
// If the false clause is unsized, then try again with the
|
||||||
|
// true clause, because it might choose a different width if
|
||||||
|
// it is in an unsized context.
|
||||||
|
if (initial_flag == false && flag == true) {
|
||||||
|
if (debug_elaborate)
|
||||||
|
cerr << get_fileline() << ": debug: "
|
||||||
|
<< "False clause is unsized, so retest width of true clause."
|
||||||
|
<< endl;
|
||||||
|
tru_wid = tru_->test_width(des, scope, max(min,fal_wid), lval, flag);
|
||||||
|
}
|
||||||
|
|
||||||
return max(tru_wid,fal_wid);
|
return max(tru_wid,fal_wid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2201,16 +2214,16 @@ NetExpr*PETernary::elaborate_expr(Design*des, NetScope*scope,
|
||||||
assert(tru_);
|
assert(tru_);
|
||||||
assert(fal_);
|
assert(fal_);
|
||||||
|
|
||||||
|
int use_wid = expr_wid >= 0? expr_wid : 0;
|
||||||
|
|
||||||
if (expr_wid < 0) {
|
if (expr_wid < 0) {
|
||||||
bool flag = false;
|
bool flag = expr_wid == -2;
|
||||||
unsigned tru_wid = tru_->test_width(des, scope, 0, 0, flag);
|
use_wid = this->test_width(des, scope, 0, 0, flag);
|
||||||
unsigned fal_wid = fal_->test_width(des, scope, 0, 0, flag);
|
|
||||||
expr_wid = max(tru_wid, fal_wid);
|
|
||||||
if (debug_elaborate)
|
if (debug_elaborate)
|
||||||
cerr << get_fileline() << ": debug: "
|
cerr << get_fileline() << ": debug: "
|
||||||
<< "Self-sized ternary chooses wid="<< expr_wid
|
<< "Self-sized ternary chooses wid="<< use_wid
|
||||||
<< " from " <<tru_wid
|
<< endl;
|
||||||
<< " and " << fal_wid << endl;
|
ivl_assert(*this, use_wid > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Elaborate and evaluate the condition expression. Note that
|
// Elaborate and evaluate the condition expression. Note that
|
||||||
|
|
@ -2237,8 +2250,8 @@ NetExpr*PETernary::elaborate_expr(Design*des, NetScope*scope,
|
||||||
cerr << get_fileline() << ": debug: Short-circuit "
|
cerr << get_fileline() << ": debug: Short-circuit "
|
||||||
"elaborate TRUE clause of ternary."
|
"elaborate TRUE clause of ternary."
|
||||||
<< endl;
|
<< endl;
|
||||||
NetExpr*tru = elab_and_eval(des, scope, tru_, expr_wid);
|
NetExpr*tru = elab_and_eval(des, scope, tru_, use_wid);
|
||||||
return pad_to_width(tru, expr_wid);
|
return pad_to_width(tru, use_wid);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Condition is constant FALSE, so we only need the
|
// Condition is constant FALSE, so we only need the
|
||||||
|
|
@ -2248,7 +2261,7 @@ NetExpr*PETernary::elaborate_expr(Design*des, NetScope*scope,
|
||||||
cerr << get_fileline() << ": debug: Short-circuit "
|
cerr << get_fileline() << ": debug: Short-circuit "
|
||||||
"elaborate FALSE clause of ternary."
|
"elaborate FALSE clause of ternary."
|
||||||
<< endl;
|
<< endl;
|
||||||
NetExpr*fal = elab_and_eval(des, scope, fal_, expr_wid);
|
NetExpr*fal = elab_and_eval(des, scope, fal_, use_wid);
|
||||||
return pad_to_width(fal, expr_wid);
|
return pad_to_width(fal, expr_wid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2256,13 +2269,13 @@ NetExpr*PETernary::elaborate_expr(Design*des, NetScope*scope,
|
||||||
// can't short-circuit.
|
// can't short-circuit.
|
||||||
}
|
}
|
||||||
|
|
||||||
NetExpr*tru = elab_and_eval(des, scope, tru_, expr_wid);
|
NetExpr*tru = elab_and_eval(des, scope, tru_, use_wid);
|
||||||
if (tru == 0) {
|
if (tru == 0) {
|
||||||
delete con;
|
delete con;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
NetExpr*fal = elab_and_eval(des, scope, fal_, expr_wid);
|
NetExpr*fal = elab_and_eval(des, scope, fal_, use_wid);
|
||||||
if (fal == 0) {
|
if (fal == 0) {
|
||||||
delete con;
|
delete con;
|
||||||
delete tru;
|
delete tru;
|
||||||
|
|
@ -2280,8 +2293,8 @@ NetExpr*PETernary::elaborate_expr(Design*des, NetScope*scope,
|
||||||
|
|
||||||
/* Whatever the width we choose for the ternary operator, we
|
/* Whatever the width we choose for the ternary operator, we
|
||||||
need to make sure the operands match. */
|
need to make sure the operands match. */
|
||||||
tru = pad_to_width(tru, expr_wid);
|
tru = pad_to_width(tru, use_wid);
|
||||||
fal = pad_to_width(fal, expr_wid);
|
fal = pad_to_width(fal, use_wid);
|
||||||
|
|
||||||
NetETernary*res = new NetETernary(con, tru, fal);
|
NetETernary*res = new NetETernary(con, tru, fal);
|
||||||
res->set_line(*this);
|
res->set_line(*this);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue