Make certain all index expressions have their width probed.

It is possible for an identifier to have multiple index expressions.
(For example, a part select of a memory word.) Make sure all the
index expressions are probed for width and type.

And also, note that the unary ! returns BOOL or LOGIC, not just
the type of its operand. It is slightly different from the other
unary operators in that way.
This commit is contained in:
Stephen Williams 2009-02-18 16:02:58 -08:00
parent d94e65de4f
commit b23825e45d
1 changed files with 26 additions and 2 deletions

View File

@ -1864,6 +1864,19 @@ bool PEIdent::calculate_param_range_(Design*des, NetScope*scope,
return true; return true;
} }
static void probe_index_expr_width(Design*des, NetScope*scope,
const name_component_t&name)
{
for (list<index_component_t>::const_iterator cur = name.index.begin()
; cur != name.index.end() ; cur ++) {
if (cur->msb)
probe_expr_width(des, scope, cur->msb);
if (cur->lsb)
probe_expr_width(des, scope, cur->lsb);
}
}
unsigned PEIdent::test_width(Design*des, NetScope*scope, unsigned PEIdent::test_width(Design*des, NetScope*scope,
unsigned min, unsigned lval, unsigned min, unsigned lval,
ivl_variable_type_t&expr_type__, ivl_variable_type_t&expr_type__,
@ -1884,6 +1897,7 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope,
const name_component_t&name_tail = path_.back(); const name_component_t&name_tail = path_.back();
index_component_t::ctype_t use_sel = index_component_t::SEL_NONE; index_component_t::ctype_t use_sel = index_component_t::SEL_NONE;
if (!name_tail.index.empty()) { if (!name_tail.index.empty()) {
probe_index_expr_width(des, scope, name_tail);
const index_component_t&index_tail = name_tail.index.back(); const index_component_t&index_tail = name_tail.index.back();
use_sel = index_tail.sel; use_sel = index_tail.sel;
} }
@ -1913,7 +1927,6 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope,
{ ivl_assert(*this, !name_tail.index.empty()); { ivl_assert(*this, !name_tail.index.empty());
const index_component_t&index_tail = name_tail.index.back(); const index_component_t&index_tail = name_tail.index.back();
ivl_assert(*this, index_tail.msb); ivl_assert(*this, index_tail.msb);
probe_expr_width(des, scope, index_tail.msb);
} }
use_width = 1; use_width = 1;
break; break;
@ -3182,7 +3195,6 @@ unsigned PEUnary::test_width(Design*des, NetScope*scope,
bool&unsized_flag) bool&unsized_flag)
{ {
switch (op_) { switch (op_) {
case '!':
case '&': // Reduction AND case '&': // Reduction AND
case '|': // Reduction OR case '|': // Reduction OR
case '^': // Reduction XOR case '^': // Reduction XOR
@ -3199,6 +3211,18 @@ unsigned PEUnary::test_width(Design*des, NetScope*scope,
expr_type__ = expr_type_; expr_type__ = expr_type_;
return expr_width_; return expr_width_;
case '!':
{
ivl_variable_type_t sub_type = IVL_VT_NO_TYPE;
bool flag = false;
expr_->test_width(des, scope, 0, 0, sub_type, flag);
expr_type_ = (sub_type==IVL_VT_BOOL)? IVL_VT_BOOL : IVL_VT_LOGIC;
}
// Logical ! always returns a single-bit LOGIC or BOOL value.
expr_width_ = 1;
expr_type__ = expr_type_;
return expr_width_;
} }
unsigned test_wid = expr_->test_width(des, scope, min, lval, expr_type__, unsized_flag); unsigned test_wid = expr_->test_width(des, scope, min, lval, expr_type__, unsized_flag);