Fix error message for invalid parameter overrides (#4559)

This commit is contained in:
Anthony Donlon 2023-10-15 17:59:36 +01:00 committed by GitHub
parent 4e2c63c8cb
commit 4427f03b08
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 182 additions and 72 deletions

View File

@ -224,8 +224,22 @@ public:
// METHODS
static string nodeTextType(AstNode* nodep) {
if (VN_IS(nodep, Var)) {
return "variable";
if (const AstVar* const varp = VN_CAST(nodep, Var)) {
if (varp->isIO() || varp->isIfaceRef()) {
return "port";
} else if (varp->isGParam()) {
return "parameter";
} else if (varp->varType() == VVarType::LPARAM) {
return "local parameter";
} else {
return "variable";
}
} else if (const AstParamTypeDType* const dtypep = VN_CAST(nodep, ParamTypeDType)) {
if (dtypep->isGParam()) {
return "type parameter";
} else {
return "local type parameter";
}
} else if (VN_IS(nodep, Cell)) {
return "instance";
} else if (VN_IS(nodep, Task)) {
@ -236,8 +250,6 @@ public:
return "block";
} else if (VN_IS(nodep, Iface)) {
return "interface";
} else if (VN_IS(nodep, ParamTypeDType)) {
return "parameter type";
} else {
return nodep->prettyTypeName();
}
@ -2262,11 +2274,6 @@ private:
m_ds.init(srcp);
iterate(nodep);
}
bool checkPinRef(AstPin* pinp, VVarType refVarType) {
// In instantiations of modules/ifaces, we shouldn't connect port pins to submodule's
// parameters or vice versa
return pinp->param() == refVarType.isParam();
}
void updateVarUse(AstVar* nodep) {
// Avoid dotted.PARAM false positive when in a parameter block
// that is if ()'ed off by same dotted name as another block
@ -2365,49 +2372,57 @@ private:
if (!nodep->modVarp()) {
UASSERT_OBJ(m_pinSymp, nodep, "Pin not under instance?");
VSymEnt* const foundp = m_pinSymp->findIdFlat(nodep->name());
const char* const whatp = nodep->param() ? "parameter pin" : "pin";
bool pinCheckFail = false;
if (foundp) {
if (AstVar* const refp = VN_CAST(foundp->nodep(), Var)) {
if (!refp->isIO() && !refp->isParam() && !refp->isIfaceRef()) {
nodep->v3error(ucfirst(whatp)
<< " is not an in/out/inout/param/interface: "
<< nodep->prettyNameQ());
} else if (!checkPinRef(nodep, refp->varType())) {
pinCheckFail = true;
} else {
nodep->modVarp(refp);
markAndCheckPinDup(nodep, refp, whatp);
}
} else if (AstParamTypeDType* const refp
= VN_CAST(foundp->nodep(), ParamTypeDType)) {
if (!checkPinRef(nodep, refp->varType())) {
pinCheckFail = true;
} else {
nodep->modPTypep(refp);
markAndCheckPinDup(nodep, refp, whatp);
}
} else {
nodep->v3error(ucfirst(whatp) << " not found: " << nodep->prettyNameQ());
}
}
if (!foundp || pinCheckFail) {
const char* const whatp = nodep->param() ? "parameter" : "pin";
if (!foundp) {
if (nodep->name() == "__paramNumber1" && m_cellp
&& VN_IS(m_cellp->modp(), Primitive)) {
// Primitive parameter is really a delay we can just ignore
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
return;
} else {
const string suggest
= (nodep->param() ? m_statep->suggestSymFlat(m_pinSymp, nodep->name(),
LinkNodeMatcherVarParam{})
: m_statep->suggestSymFlat(m_pinSymp, nodep->name(),
LinkNodeMatcherVarIO{}));
nodep->v3warn(PINNOTFOUND,
ucfirst(whatp)
<< " not found: " << nodep->prettyNameQ() << '\n'
<< (suggest.empty() ? "" : nodep->warnMore() + suggest));
return;
}
const string suggest
= (nodep->param() ? m_statep->suggestSymFlat(m_pinSymp, nodep->name(),
LinkNodeMatcherVarParam{})
: m_statep->suggestSymFlat(m_pinSymp, nodep->name(),
LinkNodeMatcherVarIO{}));
nodep->v3warn(PINNOTFOUND,
ucfirst(whatp)
<< " not found: " << nodep->prettyNameQ() << '\n'
<< (suggest.empty() ? "" : nodep->warnMore() + suggest));
}
VVarType refVarType = VVarType::UNKNOWN;
bool wrongPinType = false;
if (AstVar* const varp = VN_CAST(foundp->nodep(), Var)) {
if (varp->isIO() || varp->isParam() || varp->isIfaceRef()) {
refVarType = varp->varType();
nodep->modVarp(varp);
} else {
wrongPinType = true;
}
} else if (AstParamTypeDType* const typep = VN_CAST(foundp->nodep(), ParamTypeDType)) {
refVarType = typep->varType();
nodep->modPTypep(typep);
} else {
wrongPinType = true;
}
// Don't connect parameter pin to module ports or vice versa
if (nodep->param() != (refVarType == VVarType::GPARAM)) wrongPinType = true;
if (wrongPinType) {
string targetType = LinkDotState::nodeTextType(foundp->nodep());
targetType = VString::aOrAn(targetType) + ' ' + targetType;
if (nodep->param()) {
nodep->v3error("Instance attempts to override "
<< nodep->prettyNameQ() << " as a " << whatp << ", but it is "
<< targetType);
} else {
nodep->v3error("Instance attempts to connect to "
<< nodep->prettyNameQ() << ", but it is " << targetType);
}
return;
}
markAndCheckPinDup(nodep, foundp->nodep(), whatp);
}
// Early return() above when deleted
}

View File

@ -699,8 +699,8 @@ class ParamProcessor final : public VNDeleter {
if (!pinp->exprp()) return; // No-connect
if (AstVar* const modvarp = pinp->modVarp()) {
if (!modvarp->isGParam()) {
pinp->v3error("Attempted parameter setting of non-parameter: Param "
<< pinp->prettyNameQ() << " of " << nodep->prettyNameQ());
pinp->v3fatalSrc("Attempted parameter setting of non-parameter: Param "
<< pinp->prettyNameQ() << " of " << nodep->prettyNameQ());
} else if (VN_IS(pinp->exprp(), InitArray) && arraySubDTypep(modvarp->subDTypep())) {
// Array assigned to array
AstNode* const exprp = pinp->exprp();
@ -761,8 +761,8 @@ class ParamProcessor final : public VNDeleter {
}
}
} else {
pinp->v3error("Parameter not found in sub-module: Param "
<< pinp->prettyNameQ() << " of " << nodep->prettyNameQ());
pinp->v3fatalSrc("Parameter not found in sub-module: Param "
<< pinp->prettyNameQ() << " of " << nodep->prettyNameQ());
}
}

View File

@ -273,6 +273,17 @@ bool VString::endsWith(const string& str, const string& suffix) {
if (str.length() < suffix.length()) return false;
return str.compare(str.length() - suffix.length(), suffix.length(), suffix) == 0;
}
string VString::aOrAn(const char* word) {
switch (word[0]) {
case '\0': return "";
case 'a':
case 'e':
case 'i':
case 'o':
case 'u': return "an";
default: return "a";
}
}
//######################################################################
// VHashSha256

View File

@ -130,6 +130,9 @@ public:
static bool endsWith(const string& str, const string& suffix);
// Return true if char is valid character in word
static bool isWordChar(char c) { return isalnum(c) || c == '_'; }
// Return proper article (a/an) for a word. May be inaccurate for some special words
static string aOrAn(const char* word);
static string aOrAn(const string& word) { return aOrAn(word.c_str()); }
};
//######################################################################

View File

@ -1,9 +1,9 @@
%Error-PINNOTFOUND: t/t_class_param_bad1.v:12:11: Parameter pin not found: 'PARAMBAD'
%Error-PINNOTFOUND: t/t_class_param_bad1.v:12:11: Parameter not found: 'PARAMBAD'
: ... Suggested alternative: 'PARAMB'
12 | Cls #(.PARAMBAD(1)) c;
| ^~~~~~~~
... For error description see https://verilator.org/warn/PINNOTFOUND?v=latest
%Error-PINNOTFOUND: t/t_class_param_bad1.v:13:14: Parameter pin not found: '__paramNumber2'
%Error-PINNOTFOUND: t/t_class_param_bad1.v:13:14: Parameter not found: '__paramNumber2'
13 | Cls #(13, 1) cd;
| ^
%Error: Exiting due to

View File

@ -1,14 +1,14 @@
%Error-PINNOTFOUND: t/t_class_param_override_local_bad.v:23:30: Parameter pin not found: '__paramNumber1'
%Error-PINNOTFOUND: t/t_class_param_override_local_bad.v:23:30: Parameter not found: '__paramNumber1'
23 | class Cls3 implements Icls1#(2), Icls2#(0);
| ^
... For error description see https://verilator.org/warn/PINNOTFOUND?v=latest
%Error-PINNOTFOUND: t/t_class_param_override_local_bad.v:23:41: Parameter pin not found: '__paramNumber1'
%Error-PINNOTFOUND: t/t_class_param_override_local_bad.v:23:41: Parameter not found: '__paramNumber1'
23 | class Cls3 implements Icls1#(2), Icls2#(0);
| ^
%Error-PINNOTFOUND: t/t_class_param_override_local_bad.v:29:23: Parameter pin not found: '__paramNumber1'
%Error-PINNOTFOUND: t/t_class_param_override_local_bad.v:29:23: Parameter not found: '__paramNumber1'
29 | automatic Cls1#(bit) cls1 = new;
| ^~~
%Error-PINNOTFOUND: t/t_class_param_override_local_bad.v:30:23: Parameter pin not found: '__paramNumber1'
%Error-PINNOTFOUND: t/t_class_param_override_local_bad.v:30:23: Parameter not found: '__paramNumber1'
30 | automatic Cls2#(1) cls2 = new;
| ^
%Error: Exiting due to

View File

@ -39,7 +39,6 @@ foreach my $s (
'Array initialization has too few elements, need element ',
'Assigned pin is neither input nor output',
'Assignment pattern with no members',
'Attempted parameter setting of non-parameter: Param ',
'Can\'t find varpin scope of ',
'Can\'t resolve module reference: \'',
'Cannot write preprocessor output: ',
@ -60,7 +59,6 @@ foreach my $s (
'Modport not referenced as <interface>.',
'Modport not referenced from underneath an interface: ',
'Non-interface used as an interface: ',
'Parameter not found in sub-module: Param ',
'Parameter type pin value isn\'t a type: Param ',
'Parameter type variable isn\'t a type: Param ',
'Pattern replication value of 0 is not legal.',

View File

@ -0,0 +1,19 @@
%Error: t/t_inst_param_override_bad.v:33:23: Instance attempts to override 'PACKED_DATA_WIDTH' as a parameter, but it is a local parameter
33 | axi_stream_if # (.PACKED_DATA_WIDTH(10)) axis1(clk);
| ^~~~~~~~~~~~~~~~~
%Error: t/t_inst_param_override_bad.v:35:23: Instance attempts to override 'mytask' as a parameter, but it is a task
35 | axi_stream_if # (.mytask(10)) axis2(clk);
| ^~~~~~
%Error: t/t_inst_param_override_bad.v:37:23: Instance attempts to override 'my_genvar' as a parameter, but it is a variable
37 | axi_stream_if # (.my_genvar(10)) axis3(clk);
| ^~~~~~~~~
%Error: t/t_inst_param_override_bad.v:39:23: Instance attempts to override 'clk' as a parameter, but it is a port
39 | axi_stream_if # (.clk(10)) axis4(clk);
| ^~~
%Error: t/t_inst_param_override_bad.v:41:23: Instance attempts to override 'tvalid' as a parameter, but it is a variable
41 | axi_stream_if # (.tvalid(10)) axis5(clk);
| ^~~~~~
%Error: t/t_inst_param_override_bad.v:43:23: Instance attempts to override 'i_sub' as a parameter, but it is an instance
43 | axi_stream_if # (.i_sub(10)) axis6(clk);
| ^~~~~
%Error: Exiting due to

View File

@ -0,0 +1,19 @@
#!/usr/bin/env perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2023 by Wilson Snyder. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(linter => 1);
lint(
fails => 1,
expect_filename => $Self->{golden_filename},
);
ok(1);
1;

View File

@ -0,0 +1,45 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2023 by Anthony Donlon.
// SPDX-License-Identifier: CC0-1.0
module sub();
endmodule
interface axi_stream_if #(
parameter int DATA_WIDTH = 64,
parameter type TUSER_TYPE = logic
) (
input clk
);
task mytask();
endtask : mytask
genvar my_genvar;
logic tvalid;
sub i_sub();
localparam PACKED_DATA_WIDTH = DATA_WIDTH + DATA_WIDTH / 8 + 1 + $bits(TUSER_TYPE);
endinterface
module t;
logic clk;
// overriding a localparam
axi_stream_if # (.PACKED_DATA_WIDTH(10)) axis1(clk);
// overriding a non-var
axi_stream_if # (.mytask(10)) axis2(clk);
// overriding a non-port/interface/param var
axi_stream_if # (.my_genvar(10)) axis3(clk);
// overriding a port
axi_stream_if # (.clk(10)) axis4(clk);
// overriding a signal
axi_stream_if # (.tvalid(10)) axis5(clk);
// overriding an instance
axi_stream_if # (.i_sub(10)) axis6(clk);
endmodule

View File

@ -3,10 +3,10 @@
| ^~~~~
... For warning description see https://verilator.org/warn/PINMISSING?v=latest
... Use "/* verilator lint_off PINMISSING */" and lint_on around source to disable this message.
%Error-PINNOTFOUND: t/t_inst_pin_place_bad.v:22:10: Pin not found: 'PARAM_A'
%Error: t/t_inst_pin_place_bad.v:22:10: Instance attempts to connect to 'PARAM_A', but it is a parameter
22 | .PARAM_A(1)
| ^~~~~~~
%Error-PINNOTFOUND: t/t_inst_pin_place_bad.v:20:10: Parameter pin not found: 'pin_1'
%Error: t/t_inst_pin_place_bad.v:20:10: Instance attempts to override 'pin_1' as a parameter, but it is a port
20 | .pin_1(1)
| ^~~~~
%Error: Exiting due to

View File

@ -13,20 +13,20 @@
: ... Suggested alternative: 'exists'
22 | .nexist(i2)
| ^~~~~~
%Error-PINNOTFOUND: t/t_lint_pindup_bad.v:16:9: Parameter pin not found: 'NEXIST'
%Error-PINNOTFOUND: t/t_lint_pindup_bad.v:16:9: Parameter not found: 'NEXIST'
: ... Suggested alternative: 'EXIST'
16 | .NEXIST(1),
| ^~~~~~
%Error: t/t_lint_pindup_bad.v:17:9: Duplicate parameter pin connection: 'P'
%Error: t/t_lint_pindup_bad.v:17:9: Duplicate parameter connection: 'P'
17 | .P(2),
| ^
t/t_lint_pindup_bad.v:15:8: ... Location of original parameter pin connection
t/t_lint_pindup_bad.v:15:8: ... Location of original parameter connection
15 | #(,
| ^
%Error: t/t_lint_pindup_bad.v:18:9: Duplicate parameter pin connection: 'P'
%Error: t/t_lint_pindup_bad.v:18:9: Duplicate parameter connection: 'P'
18 | .P(3))
| ^
t/t_lint_pindup_bad.v:15:8: ... Location of original parameter pin connection
t/t_lint_pindup_bad.v:15:8: ... Location of original parameter connection
15 | #(,
| ^
%Error: Exiting due to

View File

@ -2,7 +2,7 @@
12 | b b_inst1 (.x(1'b0));
| ^
... For error description see https://verilator.org/warn/PINNOTFOUND?v=latest
%Error-PINNOTFOUND: t/t_lint_pinnotfound_bad.v:13:6: Parameter pin not found: 'PX'
%Error-PINNOTFOUND: t/t_lint_pinnotfound_bad.v:13:6: Parameter not found: 'PX'
13 | b #(.PX(1'b0)) b_inst2 ();
| ^~
%Error: Exiting due to

View File

@ -1,23 +1,23 @@
%Error-PINNOTFOUND: t/t_param_implicit_local_bad.v:15:20: Parameter pin not found: '__paramNumber2'
%Error-PINNOTFOUND: t/t_param_implicit_local_bad.v:15:20: Parameter not found: '__paramNumber2'
15 | NestedCls #(1, 2) cls;
| ^
... For error description see https://verilator.org/warn/PINNOTFOUND?v=latest
%Error-PINNOTFOUND: t/t_param_implicit_local_bad.v:17:21: Parameter pin not found: '__paramNumber3'
%Error-PINNOTFOUND: t/t_param_implicit_local_bad.v:17:21: Parameter not found: '__paramNumber3'
17 | mod1 # ( 3, 4, 5 ) i_mod1 ();
| ^
%Error-PINNOTFOUND: t/t_param_implicit_local_bad.v:19:15: Parameter pin not found: '__paramNumber1'
%Error-PINNOTFOUND: t/t_param_implicit_local_bad.v:19:15: Parameter not found: '__paramNumber1'
19 | mod3 # ( 7, 24, 25 ) i_mod3 ();
| ^
%Error-PINNOTFOUND: t/t_param_implicit_local_bad.v:19:18: Parameter pin not found: '__paramNumber2'
%Error-PINNOTFOUND: t/t_param_implicit_local_bad.v:19:18: Parameter not found: '__paramNumber2'
19 | mod3 # ( 7, 24, 25 ) i_mod3 ();
| ^~
%Error-PINNOTFOUND: t/t_param_implicit_local_bad.v:19:22: Parameter pin not found: '__paramNumber3'
%Error-PINNOTFOUND: t/t_param_implicit_local_bad.v:19:22: Parameter not found: '__paramNumber3'
19 | mod3 # ( 7, 24, 25 ) i_mod3 ();
| ^~
%Error-PINNOTFOUND: t/t_param_implicit_local_bad.v:20:22: Parameter pin not found: '__paramNumber3'
%Error-PINNOTFOUND: t/t_param_implicit_local_bad.v:20:22: Parameter not found: '__paramNumber3'
20 | intf1 # ( 8, 15, 17 ) i_intf1 ();
| ^~
%Error-PINNOTFOUND: t/t_param_implicit_local_bad.v:21:22: Parameter pin not found: '__paramNumber3'
%Error-PINNOTFOUND: t/t_param_implicit_local_bad.v:21:22: Parameter not found: '__paramNumber3'
21 | prgm1 # ( 9, 40, 41 ) i_prgm1 ();
| ^~
%Error: Exiting due to