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 .B -gstrict-expr-width\fI|\fP-gno-strict-expr-width
Enable or disable (default) strict compliance with the standard rules Enable or disable (default) strict compliance with the standard rules
for determining expression bit lengths. When disabled, the RHS of a 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 .TP 8
.B -I\fIincludedir\fP .B -I\fIincludedir\fP
Append directory \fIincludedir\fP to list of directories searched 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_type_ = IVL_VT_LOGIC;
expr_width_ = value_->len(); expr_width_ = value_->len();
min_width_ = expr_width_;
signed_flag_ = value_->has_sign(); signed_flag_ = value_->has_sign();
if ((mode < LOSSLESS) && !value_->has_len() && !value_->is_single()) if (!value_->has_len() && !value_->is_single()) {
if (gn_strict_expr_width_flag)
expr_width_ = integer_width;
else if (mode < LOSSLESS)
mode = LOSSLESS; mode = LOSSLESS;
}
min_width_ = expr_width_;
return expr_width_; return expr_width_;
} }

View File

@ -801,6 +801,22 @@ void lex_end_table()
BEGIN(INITIAL); 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) verinum*make_unsized_binary(const char*txt)
{ {
bool sign_flag = false; bool sign_flag = false;
@ -858,6 +874,9 @@ verinum*make_unsized_binary(const char*txt)
ptr += 1; 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); verinum*out = new verinum(bits, size, false);
out->has_sign(sign_flag); out->has_sign(sign_flag);
out->is_single(single_flag); out->is_single(single_flag);
@ -926,6 +945,9 @@ verinum*make_unsized_octal(const char*txt)
ptr += 1; 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); verinum*out = new verinum(bits, size, false);
out->has_sign(sign_flag); out->has_sign(sign_flag);
delete[]bits; delete[]bits;
@ -1003,6 +1025,9 @@ verinum*make_unsized_hex(const char*txt)
ptr += 1; 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); verinum*out = new verinum(bits, size, false);
out->has_sign(sign_flag); out->has_sign(sign_flag);
delete[]bits; delete[]bits;
@ -1192,6 +1217,9 @@ verinum*make_unsized_dec(const char*ptr)
number represents we do not check for extra bits. */ number represents we do not check for extra bits. */
// if (based_size > 0) { } // 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); verinum*res = new verinum(bits, size, false);
res->has_sign(signed_flag); res->has_sign(signed_flag);