Make binary expressions use their tested width in self-determined context

Operands to reduction unary operators are self determined, so
evaluate the operands that way. But this means that binary expressions
in this context should take pains to use their test_width tested
expression width.

This exposed a case where the test_width methods were not called
for self-determined expressions. Fix that too.
This commit is contained in:
Stephen Williams 2010-04-23 15:29:06 -07:00
parent d7ae1ed204
commit 46a22e9ea2
3 changed files with 25 additions and 3 deletions

View File

@ -30,6 +30,7 @@
PExpr::PExpr()
{
expr_width_ = 0;
expr_type_ = IVL_VT_NO_TYPE;
}

View File

@ -246,8 +246,18 @@ NetExpr* PEBinary::elaborate_expr(Design*des, NetScope*scope,
assert(left_);
assert(right_);
NetExpr*lp = left_->elaborate_expr(des, scope, expr_wid, false);
NetExpr*rp = right_->elaborate_expr(des, scope, expr_wid, false);
// The context passes in the width that this expression is
// expected to use. But if that width is <0, we are in a
// self-determined context and we must use the width that was
// calculated by a previous call to test_with.
int use_wid = expr_wid;
if (use_wid < 0 && expr_type_ != IVL_VT_REAL) {
ivl_assert(*this, expr_width_ > 0);
use_wid = expr_width_;
}
NetExpr*lp = left_->elaborate_expr(des, scope, use_wid, false);
NetExpr*rp = right_->elaborate_expr(des, scope, use_wid, false);
if ((lp == 0) || (rp == 0)) {
delete lp;
delete rp;
@ -3604,7 +3614,12 @@ unsigned PEUnary::test_width(Design*des, NetScope*scope,
{
ivl_variable_type_t sub_type = IVL_VT_NO_TYPE;
bool flag = false;
expr_->test_width(des, scope, 0, 0, sub_type, flag);
unsigned swid = expr_->test_width(des, scope, 0, 0, sub_type, flag);
if (debug_elaborate)
cerr << get_fileline() << ": debug: "
<< "Test width of sub-expression of " << op_
<< " returns " << swid << "." << endl;
expr_type_ = sub_type;
}
expr_width_ = 1;

View File

@ -203,6 +203,12 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
case index_component_t::SEL_IDX_DO:
case index_component_t::SEL_IDX_UP: {
// These are not used, but they need to have a default value.
ivl_variable_type_t expr_type_tmp = IVL_VT_NO_TYPE;
bool unsized_flag_tmp = false;
index_tail.msb->test_width(des, scope,
integer_width, integer_width,
expr_type_tmp, unsized_flag_tmp);
need_constant_expr = true;
NetExpr*tmp_ex = elab_and_eval(des, scope, index_tail.msb, -1);
need_constant_expr = false;