Handle implicit cast when short-circuiting ternary expression.

If a ternary expression with mixed logic and real operands is
short-circuited and the logic value is selected, that value
should be cast to a real value.
This commit is contained in:
Martin Whitaker 2013-03-01 23:01:15 +00:00 committed by Stephen Williams
parent e437321ea7
commit ee71ade720
2 changed files with 12 additions and 6 deletions

View File

@ -745,7 +745,7 @@ class PETernary : public PExpr {
private:
NetExpr* elab_and_eval_alternative_(Design*des, NetScope*scope,
PExpr*expr, unsigned expr_wid,
unsigned flags) const;
unsigned flags, bool short_cct) const;
private:
PExpr*expr_;

View File

@ -4490,7 +4490,7 @@ NetExpr*PETernary::elaborate_expr(Design*des, NetScope*scope,
<< endl;
return elab_and_eval_alternative_(des, scope, tru_,
expr_wid, flags);
expr_wid, flags, true);
}
// Condition is constant FALSE, so we only need the
@ -4502,20 +4502,22 @@ NetExpr*PETernary::elaborate_expr(Design*des, NetScope*scope,
<< endl;
return elab_and_eval_alternative_(des, scope, fal_,
expr_wid, flags);
expr_wid, flags, true);
}
// X and Z conditions need to blend both results, so we
// can't short-circuit.
}
NetExpr*tru = elab_and_eval_alternative_(des, scope, tru_, expr_wid, flags);
NetExpr*tru = elab_and_eval_alternative_(des, scope, tru_,
expr_wid, flags, false);
if (tru == 0) {
delete con;
return 0;
}
NetExpr*fal = elab_and_eval_alternative_(des, scope, fal_, expr_wid, flags);
NetExpr*fal = elab_and_eval_alternative_(des, scope, fal_,
expr_wid, flags, false);
if (fal == 0) {
delete con;
delete tru;
@ -4544,7 +4546,7 @@ NetExpr*PETernary::elaborate_expr(Design*des, NetScope*scope,
*/
NetExpr* PETernary::elab_and_eval_alternative_(Design*des, NetScope*scope,
PExpr*expr, unsigned expr_wid,
unsigned flags) const
unsigned flags, bool short_cct) const
{
int context_wid = expr_wid;
if (type_is_vectorable(expr->expr_type()) && !type_is_vectorable(expr_type_)) {
@ -4556,6 +4558,10 @@ NetExpr* PETernary::elab_and_eval_alternative_(Design*des, NetScope*scope,
NetExpr*tmp = expr->elaborate_expr(des, scope, expr_wid, flags);
if (tmp == 0) return 0;
if (short_cct && (expr_type_ == IVL_VT_REAL)
&& (expr->expr_type() != IVL_VT_REAL))
tmp = cast_to_real(tmp);
eval_expr(tmp, context_wid);
return tmp;