Add ENUMITEMWIDTH error, and apply to X-extended and ranged values.
This commit is contained in:
parent
cefe1845df
commit
2f199f20cf
1
Changes
1
Changes
|
@ -13,6 +13,7 @@ Verilator 5.039 devel
|
|||
|
||||
**Other:**
|
||||
|
||||
* Add ENUMITEMWIDTH error, and apply to X-extended and ranged values.
|
||||
* Support member-level triggers for virtual interfaces (#5166) (#6148). [Yilou Wang]
|
||||
* Support disable dotted references (#6154). [Ryszard Rozak, Antmicro Ltd.]
|
||||
* Support randomize() on class member selects (#6161). [Igor Zaworski, Antmicro Ltd.]
|
||||
|
|
|
@ -709,6 +709,28 @@ List Of Warnings
|
|||
missing."
|
||||
|
||||
|
||||
.. option:: ENUMITEMWIDTH
|
||||
|
||||
An error that an enum item value is being assigned from a value which
|
||||
would be truncated (similar to :option:`WIDTHTRUNC`), or from a sized
|
||||
literal constant with a different bit width (similar to
|
||||
:option:`WIDTHTRUNC` or :option:`WIDTHEXPAND`). IEEE requires this
|
||||
error, but it may be disabled.
|
||||
|
||||
Faulty example:
|
||||
|
||||
.. code-block:: sv
|
||||
:linenos:
|
||||
:emphasize-lines: 2
|
||||
|
||||
typedef enum [3:0] {
|
||||
WRONG_WIDTH = 33'h3 //<--- Warning
|
||||
} enum_t;
|
||||
|
||||
To repair, correct the size of the item's value directly, or use a cast,
|
||||
so the resulting width matches the enum's width.
|
||||
|
||||
|
||||
.. option:: ENUMVALUE
|
||||
|
||||
An error that an enum data type value is being assigned from another data
|
||||
|
|
|
@ -99,6 +99,7 @@ public:
|
|||
DEPRECATED, // Feature will be deprecated
|
||||
ENCAPSULATED, // Error: local/protected violation
|
||||
ENDLABEL, // End lable name mismatch
|
||||
ENUMITEMWIDTH, // Error: enum item width mismatch
|
||||
ENUMVALUE, // Error: enum type needs explicit cast
|
||||
EOFNEWLINE, // End-of-file missing newline
|
||||
GENCLK, // Generated Clock. Historical, never issued.
|
||||
|
@ -204,8 +205,8 @@ public:
|
|||
"CASEINCOMPLETE", "CASEOVERLAP", "CASEWITHX", "CASEX", "CASTCONST", "CDCRSTLOGIC", "CLKDATA",
|
||||
"CMPCONST", "COLONPLUS", "COMBDLY", "CONSTRAINTIGN", "CONTASSREG", "COVERIGN",
|
||||
"DECLFILENAME", "DEFOVERRIDE", "DEFPARAM", "DEPRECATED",
|
||||
"ENCAPSULATED", "ENDLABEL", "ENUMVALUE", "EOFNEWLINE", "GENCLK",
|
||||
"GENUNNAMED", "HIERBLOCK",
|
||||
"ENCAPSULATED", "ENDLABEL", "ENUMITEMWIDTH", "ENUMVALUE", "EOFNEWLINE",
|
||||
"GENCLK", "GENUNNAMED", "HIERBLOCK",
|
||||
"IFDEPTH", "IGNOREDRETURN",
|
||||
"IMPERFECTSCH", "IMPLICIT", "IMPLICITSTATIC", "IMPORTSTAR", "IMPURE",
|
||||
"INCABSPATH", "INFINITELOOP", "INITIALDLY", "INSECURE",
|
||||
|
@ -219,7 +220,8 @@ public:
|
|||
"UNDRIVEN", "UNOPT", "UNOPTFLAT", "UNOPTTHREADS",
|
||||
"UNPACKED", "UNSIGNED", "UNUSEDGENVAR", "UNUSEDLOOP" ,"UNUSEDPARAM", "UNUSEDSIGNAL",
|
||||
"USERERROR", "USERFATAL", "USERINFO", "USERWARN",
|
||||
"VARHIDDEN", "WAITCONST", "WIDTH", "WIDTHCONCAT", "WIDTHEXPAND", "WIDTHTRUNC", "WIDTHXZEXPAND", "ZERODLY", "ZEROREPL",
|
||||
"VARHIDDEN", "WAITCONST", "WIDTH", "WIDTHCONCAT", "WIDTHEXPAND", "WIDTHTRUNC", "WIDTHXZEXPAND",
|
||||
"ZERODLY", "ZEROREPL",
|
||||
" MAX"
|
||||
};
|
||||
// clang-format on
|
||||
|
@ -249,9 +251,9 @@ public:
|
|||
bool pretendError() const VL_MT_SAFE {
|
||||
return (m_e == ASSIGNIN || m_e == BADSTDPRAGMA || m_e == BADVLTPRAGMA || m_e == BLKANDNBLK
|
||||
|| m_e == BLKLOOPINIT || m_e == CONTASSREG || m_e == ENCAPSULATED
|
||||
|| m_e == ENDLABEL || m_e == ENUMVALUE || m_e == IMPURE || m_e == MODMISSING
|
||||
|| m_e == PINNOTFOUND || m_e == PKGNODECL || m_e == PROCASSWIRE
|
||||
|| m_e == ZEROREPL // Says IEEE
|
||||
|| m_e == ENDLABEL || m_e == ENUMITEMWIDTH || m_e == ENUMVALUE || m_e == IMPURE
|
||||
|| m_e == MODMISSING || m_e == PINNOTFOUND || m_e == PKGNODECL
|
||||
|| m_e == PROCASSWIRE || m_e == ZEROREPL // Says IEEE
|
||||
);
|
||||
}
|
||||
// Warnings to mention manual
|
||||
|
|
|
@ -369,6 +369,10 @@ public:
|
|||
&& m_lastLineno == rhs.m_lastLineno && m_lastColumn == rhs.m_lastColumn
|
||||
&& m_filenameno == rhs.m_filenameno && m_msgEnIdx == rhs.m_msgEnIdx);
|
||||
}
|
||||
bool equalFirstLineCol(const FileLine& rhs) const {
|
||||
return (m_filenameno == rhs.m_filenameno && m_firstLineno == rhs.m_firstLineno
|
||||
&& m_firstColumn == rhs.m_firstColumn);
|
||||
}
|
||||
// Returns -1 if (*this) should come before rhs after sorted. 1 for the opposite case. 0 for
|
||||
// equivalent.
|
||||
int operatorCompare(const FileLine& rhs) const {
|
||||
|
|
|
@ -267,16 +267,17 @@ class LinkParseVisitor final : public VNVisitor {
|
|||
const int left = nodep->rangep()->leftConst();
|
||||
const int right = nodep->rangep()->rightConst();
|
||||
const int increment = (left > right) ? -1 : 1;
|
||||
int offset_from_init = 0;
|
||||
uint32_t offset_from_init = 0;
|
||||
AstEnumItem* addp = nullptr;
|
||||
FileLine* const flp = nodep->fileline();
|
||||
for (int i = left; i != (right + increment); i += increment, offset_from_init++) {
|
||||
for (int i = left; i != (right + increment); i += increment, ++offset_from_init) {
|
||||
const string name = nodep->name() + cvtToStr(i);
|
||||
AstNodeExpr* valuep = nullptr;
|
||||
if (nodep->valuep()) {
|
||||
// V3Width looks for Adds with same fileline as the EnumItem
|
||||
valuep
|
||||
= new AstAdd{flp, nodep->valuep()->cloneTree(true),
|
||||
new AstConst(flp, AstConst::Unsized32{}, offset_from_init)};
|
||||
new AstConst{flp, AstConst::Unsized32{}, offset_from_init}};
|
||||
}
|
||||
addp = AstNode::addNext(addp, new AstEnumItem{flp, name, nullptr, valuep});
|
||||
}
|
||||
|
|
|
@ -1188,7 +1188,7 @@ uint32_t V3Number::countOnes() const {
|
|||
|
||||
uint32_t V3Number::mostSetBitP1() const {
|
||||
for (int bit = width() - 1; bit >= 0; bit--) {
|
||||
if (bitIs1(bit)) return bit + 1;
|
||||
if (!bitIs0(bit)) return bit + 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -2553,9 +2553,16 @@ class WidthVisitor final : public VNVisitor {
|
|||
// Default type is int, but common to assign narrower values, so minwidth from value
|
||||
userIterateAndNext(nodep->valuep(), WidthVP{CONTEXT_DET, PRELIM}.p());
|
||||
bool warnOn = true;
|
||||
if (const AstConst* const constp = VN_CAST(nodep->valuep(), Const)) {
|
||||
AstNodeExpr* valuep = nodep->valuep();
|
||||
if (const AstAdd* const anodep = VN_CAST(valuep, Add)) {
|
||||
// If constructed by V3LinkParse due to "enumitem[N_REPEATS] value"
|
||||
if (anodep->fileline()->equalFirstLineCol(*(nodep->fileline())))
|
||||
valuep = anodep->lhsp();
|
||||
}
|
||||
if (const AstConst* const constp = VN_CAST(valuep, Const)) {
|
||||
if (static_cast<int>(constp->num().mostSetBitP1()) > nodep->width()) {
|
||||
constp->v3error("Enum value exceeds width of enum type (IEEE 1800-2023 6.19)");
|
||||
constp->v3warn(ENUMITEMWIDTH,
|
||||
"Enum value exceeds width of enum type (IEEE 1800-2023 6.19)");
|
||||
warnOn = false; // Prevent normal WIDTHTRUNC
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,20 @@
|
|||
%Error: t/t_enum_bad_value.v:10:19: Enum value exceeds width of enum type (IEEE 1800-2023 6.19)
|
||||
: ... note: In instance 't'
|
||||
10 | VALUE_BAD = 8
|
||||
| ^
|
||||
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
|
||||
%Error-ENUMITEMWIDTH: t/t_enum_bad_value.v:12:37: Enum value exceeds width of enum type (IEEE 1800-2023 6.19)
|
||||
: ... note: In instance 't'
|
||||
12 | typedef enum [2:0] { VALUE_BAD1 = 8 } enum_t;
|
||||
| ^
|
||||
... For error description see https://verilator.org/warn/ENUMITEMWIDTH?v=latest
|
||||
%Error-ENUMITEMWIDTH: t/t_enum_bad_value.v:14:29: Enum value exceeds width of enum type (IEEE 1800-2023 6.19)
|
||||
: ... note: In instance 't'
|
||||
14 | enum bit [4:0] {BAD2[4] = 100} bad2;
|
||||
| ^~~
|
||||
%Warning-WIDTHTRUNC: t/t_enum_bad_value.v:14:19: Operator ADD expects 5 bits on the LHS, but LHS's CONST '?32?sh64' generates 32 or 7 bits.
|
||||
: ... note: In instance 't'
|
||||
14 | enum bit [4:0] {BAD2[4] = 100} bad2;
|
||||
| ^~~~
|
||||
... For warning description see https://verilator.org/warn/WIDTHTRUNC?v=latest
|
||||
... Use "/* verilator lint_off WIDTHTRUNC */" and lint_on around source to disable this message.
|
||||
%Error-ENUMITEMWIDTH: t/t_enum_bad_value.v:16:28: Enum value exceeds width of enum type (IEEE 1800-2023 6.19)
|
||||
: ... note: In instance 't'
|
||||
16 | enum logic [3:0] {BAD3 = 5'bxxxxx} bad3;
|
||||
| ^~~~~~~~
|
||||
%Error: Exiting due to
|
||||
|
|
|
@ -6,8 +6,14 @@
|
|||
|
||||
module t();
|
||||
|
||||
typedef enum [2:0] {
|
||||
VALUE_BAD = 8
|
||||
} enum_t;
|
||||
enum bit signed [3:0] {OK1 = -1} ok1_t; // As is signed, loss of 1 bits is ok per IEEE
|
||||
enum bit signed [3:0] {OK2 = 3} ok2_t;
|
||||
|
||||
typedef enum [2:0] { VALUE_BAD1 = 8 } enum_t;
|
||||
|
||||
enum bit [4:0] {BAD2[4] = 100} bad2;
|
||||
|
||||
enum logic [3:0] {BAD3 = 5'bxxxxx} bad3;
|
||||
|
||||
initial $stop;
|
||||
endmodule
|
||||
|
|
Loading…
Reference in New Issue