Check that enum initializations are in range.
This patch adds checks to verify that all enum initializations (explicit or implicit) are in range.
This commit is contained in:
parent
b99846e0eb
commit
fd4f07906d
|
|
@ -152,6 +152,21 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
|
|||
verinum cur_value (0);
|
||||
verinum one_value (1);
|
||||
size_t name_idx = 0;
|
||||
// Find the minimum and maximum allowed enumeration values.
|
||||
verinum min_value (0);
|
||||
verinum max_value (0);
|
||||
if (enum_type->signed_flag) {
|
||||
min_value = v_not((pow(verinum(2),
|
||||
verinum(use_enum->base_width()-1)))) +
|
||||
one_value;
|
||||
max_value = pow(verinum(2), verinum(use_enum->base_width()-1)) -
|
||||
one_value;
|
||||
} else {
|
||||
max_value = pow(verinum(2), verinum(use_enum->base_width())) -
|
||||
one_value;
|
||||
}
|
||||
min_value.has_sign(true);
|
||||
max_value.has_sign(enum_type->signed_flag);
|
||||
for (list<named_pexpr_t>::const_iterator cur = enum_type->names->begin()
|
||||
; cur != enum_type->names->end() ; ++ cur, name_idx += 1) {
|
||||
|
||||
|
|
@ -159,38 +174,60 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
|
|||
if (cur->parm) {
|
||||
// There is an explicit value. elaborate/evaluate
|
||||
// the value and assign it to the enumeration name.
|
||||
NetExpr*val = elab_and_eval(des, scope, cur->parm,
|
||||
use_enum->base_width());
|
||||
NetExpr*val = elab_and_eval(des, scope, cur->parm, -1);
|
||||
NetEConst*val_const = dynamic_cast<NetEConst*> (val);
|
||||
if (val_const == 0) {
|
||||
cerr << "<>:0: error: Enumeration expression is not constant." << endl;
|
||||
cerr << "<>:0: error: Enumeration expression is not "
|
||||
"constant." << endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
cur_value = val_const->value();
|
||||
|
||||
if (enum_type->base_type==IVL_VT_BOOL && ! cur_value.is_defined()) {
|
||||
if (enum_type->base_type==IVL_VT_BOOL &&
|
||||
! cur_value.is_defined()) {
|
||||
cerr << "<>:0: error: Enumeration name " << cur->name
|
||||
<< " cannot have a logic value." << endl;
|
||||
<< " cannot have an undefined value." << endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
} else if (! cur_value.is_defined()) {
|
||||
cerr << "<>:0: error: Enumeration name " << cur->name
|
||||
<< " cannot have an inferred value." << endl;
|
||||
<< " cannot have an undefined inferred value." << endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
// The enumeration value must fit into the enumeration bits.
|
||||
if ((cur_value > max_value) ||
|
||||
(cur_value.has_sign() && (cur_value < min_value))) {
|
||||
cerr << "<>:0: error: Enumeration name " << cur->name
|
||||
<< " cannot have a value equal to " << cur_value
|
||||
<< "." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
// The values are explicitly sized to the width of the
|
||||
// base type of the enumeration.
|
||||
verinum tmp_val (cur_value, use_enum->base_width());
|
||||
verinum tmp_val (0);
|
||||
if (cur_value.len() < use_enum->base_width()) {
|
||||
// Pad the current value if it is narrower than the final
|
||||
// width of the enum.
|
||||
tmp_val = pad_to_width (cur_value, use_enum->base_width());
|
||||
tmp_val.has_len(true);
|
||||
} else {
|
||||
// Truncate an oversized value. We report out of bound
|
||||
// values above. This may create duplicates.
|
||||
tmp_val = verinum(cur_value, use_enum->base_width());
|
||||
}
|
||||
tmp_val.has_sign(enum_type->signed_flag);
|
||||
|
||||
rc_flag = use_enum->insert_name(name_idx, cur->name, tmp_val);
|
||||
rc_flag &= scope->add_enumeration_name(use_enum, cur->name);
|
||||
if (! rc_flag) {
|
||||
cerr << "<>:0: error: Duplicate enumeration name " << cur->name << endl;
|
||||
cerr << "<>:0: error: Duplicate enumeration name "
|
||||
<< cur->name << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue