Add HIERPARAM error code (#6456) (#6484)

This commit is contained in:
Todd Strader 2025-09-25 10:27:26 -04:00 committed by GitHub
parent c9e021924f
commit aa6fbd35db
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 92 additions and 36 deletions

View File

@ -0,0 +1,8 @@
.. comment: generated by t_param_hier_bad
.. code-block:: sv
:linenos:
:emphasize-lines: 3
sub #(.X(MY_X)) u_sub ();
localparam int SUB_Y = u_sub.Y; // <--- BAD: IEEE 1800-2023 6.20.2 no hierarchical

View File

@ -0,0 +1,7 @@
.. comment: generated by t_param_hier_bad
.. code-block::
%Error-HIERPARAM: example.v:1:32 Parameter values cannot use hierarchical values (IEEE 1800-2023 6.20.2)
: ... note: In instance 't'
36 | localparam int SUB_Y = u_sub.Y;
| ^

View File

@ -896,6 +896,25 @@ List Of Warnings
This setting on the top module will be ignored.
.. option:: HIERPARAM
An error that a hierarchical value or function is being used to assign a parameter.
IEEE 1800-2023 6.20.2 requires this error.
Faulty example:
.. include:: ../../docs/gen/ex_HIERPARAM_faulty.rst
Results in:
.. include:: ../../docs/gen/ex_HIERPARAM_msg.rst
Suppressing this error may allow some hierarchical references to work (especially hierarchical
references into interface references), however not all cases are possible, e.g. it cannot
reference the parameter of a lower module in a way that affects determining the parameters
that elaborate that lower module.
.. option:: IFDEPTH
Warns that if/if else statements have exceeded the depth specified with

View File

@ -108,6 +108,7 @@ public:
GENCLK, // Generated Clock. Historical, never issued.
GENUNNAMED, // Generate unnamed, without label
HIERBLOCK, // Ignored hierarchical block setting
HIERPARAM, // Parameter using hierarchical value
IFDEPTH, // If statements too deep
IGNOREDRETURN, // Ignoring return value (function as task)
IMPERFECTSCH, // Imperfect schedule (disabled by default). Historical, never issued.
@ -213,19 +214,19 @@ public:
"CDCRSTLOGIC", "CLKDATA", "CMPCONST", "COLONPLUS", "COMBDLY", "CONSTRAINTIGN",
"CONTASSREG", "COVERIGN", "DECLFILENAME", "DEFOVERRIDE", "DEFPARAM", "DEPRECATED",
"ENCAPSULATED", "ENDLABEL", "ENUMITEMWIDTH", "ENUMVALUE", "EOFNEWLINE", "GENCLK",
"GENUNNAMED", "HIERBLOCK", "IFDEPTH", "IGNOREDRETURN", "IMPERFECTSCH", "IMPLICIT",
"IMPLICITSTATIC", "IMPORTSTAR", "IMPURE", "INCABSPATH", "INFINITELOOP", "INITIALDLY",
"INSECURE", "LATCH", "LITENDIAN", "MINTYPMAXDLY", "MISINDENT", "MODDUP", "MODMISSING",
"MULTIDRIVEN", "MULTITOP", "NEWERSTD", "NOEFFECT", "NOLATCH", "NONSTD", "NULLPORT",
"PARAMNODEFAULT", "PINCONNECTEMPTY", "PINMISSING", "PINNOCONNECT", "PINNOTFOUND",
"PKGNODECL", "PREPROCZERO", "PROCASSINIT", "PROCASSWIRE", "PROFOUTOFDATE", "PROTECTED",
"PROTOTYPEMIS", "RANDC", "REALCVT", "REDEFMACRO", "RISEFALLDLY", "SELRANGE",
"SHORTREAL", "SIDEEFFECT", "SPECIFYIGN", "SPLITVAR", "STATICVAR", "STMTDLY",
"SYMRSVDWORD", "SYNCASYNCNET", "TICKCOUNT", "TIMESCALEMOD", "UNDRIVEN", "UNOPT",
"UNOPTFLAT", "UNOPTTHREADS", "UNPACKED", "UNSIGNED", "UNUSEDGENVAR", "UNUSEDLOOP",
"UNUSEDPARAM", "UNUSEDSIGNAL", "USERERROR", "USERFATAL", "USERINFO", "USERWARN",
"VARHIDDEN", "WAITCONST", "WIDTH", "WIDTHCONCAT", "WIDTHEXPAND", "WIDTHTRUNC",
"WIDTHXZEXPAND", "ZERODLY", "ZEROREPL", " MAX"};
"GENUNNAMED", "HIERBLOCK", "HIERPARAM", "IFDEPTH", "IGNOREDRETURN", "IMPERFECTSCH",
"IMPLICIT", "IMPLICITSTATIC", "IMPORTSTAR", "IMPURE", "INCABSPATH", "INFINITELOOP",
"INITIALDLY", "INSECURE", "LATCH", "LITENDIAN", "MINTYPMAXDLY", "MISINDENT", "MODDUP",
"MODMISSING", "MULTIDRIVEN", "MULTITOP", "NEWERSTD", "NOEFFECT", "NOLATCH", "NONSTD",
"NULLPORT", "PARAMNODEFAULT", "PINCONNECTEMPTY", "PINMISSING", "PINNOCONNECT",
"PINNOTFOUND", "PKGNODECL", "PREPROCZERO", "PROCASSINIT", "PROCASSWIRE",
"PROFOUTOFDATE", "PROTECTED", "PROTOTYPEMIS", "RANDC", "REALCVT", "REDEFMACRO",
"RISEFALLDLY", "SELRANGE", "SHORTREAL", "SIDEEFFECT", "SPECIFYIGN", "SPLITVAR",
"STATICVAR", "STMTDLY", "SYMRSVDWORD", "SYNCASYNCNET", "TICKCOUNT", "TIMESCALEMOD",
"UNDRIVEN", "UNOPT", "UNOPTFLAT", "UNOPTTHREADS", "UNPACKED", "UNSIGNED",
"UNUSEDGENVAR", "UNUSEDLOOP", "UNUSEDPARAM", "UNUSEDSIGNAL", "USERERROR", "USERFATAL",
"USERINFO", "USERWARN", "VARHIDDEN", "WAITCONST", "WIDTH", "WIDTHCONCAT",
"WIDTHEXPAND", "WIDTHTRUNC", "WIDTHXZEXPAND", "ZERODLY", "ZEROREPL", " MAX"};
return names[m_e];
}
// Warnings that default to off
@ -252,10 +253,10 @@ 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 == ENUMITEMWIDTH || m_e == ENUMVALUE || m_e == IMPURE
|| m_e == MODMISSING || m_e == PARAMNODEFAULT || m_e == PINNOTFOUND
|| m_e == PKGNODECL || m_e == PROCASSWIRE || m_e == PROTOTYPEMIS
|| m_e == ZEROREPL // Says IEEE
|| m_e == ENDLABEL || m_e == ENUMITEMWIDTH || m_e == ENUMVALUE || m_e == HIERPARAM
|| m_e == IMPURE || m_e == MODMISSING || m_e == PARAMNODEFAULT
|| m_e == PINNOTFOUND || m_e == PKGNODECL || m_e == PROCASSWIRE
|| m_e == PROTOTYPEMIS || m_e == ZEROREPL // Says IEEE
);
}
// Warnings to mention manual

View File

@ -1361,8 +1361,8 @@ class ParamVisitor final : public VNVisitor {
if (!valuep) return;
valuep->foreachAndNext([&](const AstNodeExpr* exprp) {
if (const AstVarXRef* refp = VN_CAST(exprp, VarXRef)) {
refp->v3error("Parameter values cannot use hierarchical values"
" (IEEE 1800-2023 6.20.2)");
refp->v3warn(HIERPARAM, "Parameter values cannot use hierarchical values"
" (IEEE 1800-2023 6.20.2)");
} else if (const AstNodeFTaskRef* refp = VN_CAST(exprp, NodeFTaskRef)) {
if (refp->dotted() != "") {
refp->v3error("Parameter values cannot call hierarchical functions"

View File

@ -12,7 +12,9 @@ interface intf
endinterface
module sub (intf.modp the_intf_port [4]);
const int intf_foo = the_intf_port[0].FOO;
// verilator lint_off HIERPARAM
localparam intf_foo = the_intf_port[0].FOO;
// verilator lint_on HIERPARAM
initial begin
if (intf_foo != 4) $stop;

View File

@ -35,7 +35,9 @@ module Core(
);
// this will constify and valDiv2 will have the default value
const int valDiv4Upper = intf.valDiv2;
// verilator lint_off HIERPARAM
localparam valDiv4Upper = intf.valDiv2;
// verilator lint_on HIERPARAM
SimpleIntf #(.VAL(68)) core_intf ();

View File

@ -1,12 +1,13 @@
%Error: t/t_interface_param_another_bad.v:9:36: Parameter values cannot use hierarchical values (IEEE 1800-2023 6.20.2)
: ... note: In instance 't'
%Error-HIERPARAM: t/t_interface_param_another_bad.v:9:36: Parameter values cannot use hierarchical values (IEEE 1800-2023 6.20.2)
: ... note: In instance 't'
9 | simple_bus #(.PARAMETER(sb_intf.dummy)) simple();
| ^~~~~
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
... For error description see https://verilator.org/warn/HIERPARAM?v=latest
%Error: t/t_interface_param_another_bad.v:9:36: Expecting expression to be constant, but variable isn't const: 'dummy'
: ... note: In instance 't'
9 | simple_bus #(.PARAMETER(sb_intf.dummy)) simple();
| ^~~~~
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
%Error: t/t_interface_param_another_bad.v:9:18: Can't convert defparam value to constant: Param 'PARAMETER' of 'simple'
: ... note: In instance 't'
9 | simple_bus #(.PARAMETER(sb_intf.dummy)) simple();

View File

@ -45,9 +45,11 @@ module t (/*AUTOARG*/
.intf_array (array_interface)
);
const int THE_TOP_FOO = the_interface.FOO;
const int THE_TOP_FOO_BITS = $bits({the_interface.FOO, the_interface.FOO});
const int THE_ARRAY_FOO = array_interface[0].FOO;
// verilator lint_off HIERPARAM
localparam THE_TOP_FOO = the_interface.FOO;
localparam THE_TOP_FOO_BITS = $bits({the_interface.FOO, the_interface.FOO});
localparam THE_ARRAY_FOO = array_interface[0].FOO;
// verilator lint_on HIERPARAM
initial begin
if (THE_TOP_FOO != 5) begin
@ -75,12 +77,14 @@ module testmod
test_if.mp intf_array [1:0]
);
const int THE_FOO = intf.FOO;
const int THE_OTHER_FOO = intf_no_mp.FOO;
const int THE_ARRAY_FOO = intf_array[0].FOO;
const int THE_BAR = intf.BAR;
const int THE_OTHER_BAR = intf_no_mp.BAR;
const int THE_ARRAY_BAR = intf_array[0].BAR;
// verilator lint_off HIERPARAM
localparam THE_FOO = intf.FOO;
localparam THE_OTHER_FOO = intf_no_mp.FOO;
localparam THE_ARRAY_FOO = intf_array[0].FOO;
localparam THE_BAR = intf.BAR;
localparam THE_OTHER_BAR = intf_no_mp.BAR;
localparam THE_ARRAY_BAR = intf_array[0].BAR;
// verilator lint_on HIERPARAM
always @(posedge clk) begin
if (THE_FOO != 5) begin

View File

@ -1,12 +1,13 @@
%Error: t/t_param_hier_bad.v:36:32: Parameter values cannot use hierarchical values (IEEE 1800-2023 6.20.2)
: ... note: In instance 't'
%Error-HIERPARAM: t/t_param_hier_bad.v:36:32: Parameter values cannot use hierarchical values (IEEE 1800-2023 6.20.2)
: ... note: In instance 't'
36 | localparam int SUB_Y = u_sub.Y;
| ^
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
... For error description see https://verilator.org/warn/HIERPARAM?v=latest
%Error: t/t_param_hier_bad.v:38:35: Parameter values cannot call hierarchical functions (IEEE 1800-2023 6.20.2)
: ... note: In instance 't'
38 | localparam int SUB_FUNC = u_sub.sub_func();
| ^~~~~~~~
... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance.
%Error: t/t_param_hier_bad.v:44:18: Parameter values cannot call hierarchical functions (IEEE 1800-2023 6.20.2)
: ... note: In instance 't'
44 | sub #(.X(block.block_func())) u_sub2 ();

View File

@ -11,6 +11,17 @@ import vltest_bootstrap
test.scenarios('linter')
if not os.path.exists(test.root + "/.git"):
test.skip("Not in a git repository")
test.lint(fails=True, expect_filename=test.golden_filename)
test.extract(in_filename=test.top_filename,
out_filename=test.root + "/docs/gen/ex_HIERPARAM_faulty.rst",
lines="34-36")
test.extract(in_filename=test.golden_filename,
out_filename=test.root + "/docs/gen/ex_HIERPARAM_msg.rst",
lines="1-4")
test.passes()