Extend -gstrict-expr-width to cover unsized numbers.

To be strictly compliant with the standard and compatible with other
EDA tools, unsized numbers should be treated as having a fixed size
(the same size as an integer). The -gstrict-expr-width option is
extended to allow the user to enable this behaviour.
This commit is contained in:
Martin Whitaker 2013-10-20 23:16:11 +01:00
parent 141a23690e
commit 7e82a37fa3
3 changed files with 38 additions and 4 deletions

View File

@ -129,7 +129,9 @@ standard compliant behavior (with some loss in performance).
.B -gstrict-expr-width\fI|\fP-gno-strict-expr-width
Enable or disable (default) strict compliance with the standard rules
for determining expression bit lengths. When disabled, the RHS of a
parameter assignment is evaluated as a lossless expression.
parameter assignment is evaluated as a lossless expression, as is any
expression containing an unsized constant number, and unsized constant
numbers are not truncated to integer width.
.TP 8
.B -I\fIincludedir\fP
Append directory \fIincludedir\fP to list of directories searched

View File

@ -4721,11 +4721,15 @@ unsigned PENumber::test_width(Design*, NetScope*, width_mode_t&mode)
{
expr_type_ = IVL_VT_LOGIC;
expr_width_ = value_->len();
min_width_ = expr_width_;
signed_flag_ = value_->has_sign();
if ((mode < LOSSLESS) && !value_->has_len() && !value_->is_single())
mode = LOSSLESS;
if (!value_->has_len() && !value_->is_single()) {
if (gn_strict_expr_width_flag)
expr_width_ = integer_width;
else if (mode < LOSSLESS)
mode = LOSSLESS;
}
min_width_ = expr_width_;
return expr_width_;
}

View File

@ -801,6 +801,22 @@ void lex_end_table()
BEGIN(INITIAL);
}
static unsigned truncate_to_integer_width(verinum::V*bits, unsigned size)
{
if (size <= integer_width) return size;
verinum::V pad = bits[size-1];
if (pad == verinum::V1) pad = verinum::V0;
for (unsigned idx = integer_width; idx < size; idx += 1) {
if (bits[idx] != pad) {
yywarn(yylloc, "Unsized numeric constant truncated to integer width.");
break;
}
}
return integer_width;
}
verinum*make_unsized_binary(const char*txt)
{
bool sign_flag = false;
@ -858,6 +874,9 @@ verinum*make_unsized_binary(const char*txt)
ptr += 1;
}
if (gn_strict_expr_width_flag && (based_size == 0))
size = truncate_to_integer_width(bits, size);
verinum*out = new verinum(bits, size, false);
out->has_sign(sign_flag);
out->is_single(single_flag);
@ -926,6 +945,9 @@ verinum*make_unsized_octal(const char*txt)
ptr += 1;
}
if (gn_strict_expr_width_flag && (based_size == 0))
size = truncate_to_integer_width(bits, size);
verinum*out = new verinum(bits, size, false);
out->has_sign(sign_flag);
delete[]bits;
@ -1003,6 +1025,9 @@ verinum*make_unsized_hex(const char*txt)
ptr += 1;
}
if (gn_strict_expr_width_flag && (based_size == 0))
size = truncate_to_integer_width(bits, size);
verinum*out = new verinum(bits, size, false);
out->has_sign(sign_flag);
delete[]bits;
@ -1192,6 +1217,9 @@ verinum*make_unsized_dec(const char*ptr)
number represents we do not check for extra bits. */
// if (based_size > 0) { }
if (gn_strict_expr_width_flag && (based_size == 0))
size = truncate_to_integer_width(bits, size);
verinum*res = new verinum(bits, size, false);
res->has_sign(signed_flag);