Add error on mixing .name and by-port instantiations.

This commit is contained in:
Wilson Snyder 2023-03-01 21:19:21 -05:00
parent 2c60c5f816
commit 326a60d307
12 changed files with 56 additions and 35 deletions

View File

@ -18,6 +18,7 @@ Verilator 5.007 devel
* Add WIDTHEXPAND and WIDTHTRUNC warnings to replace WIDTH (#3900). [Andrew Nolte] * Add WIDTHEXPAND and WIDTHTRUNC warnings to replace WIDTH (#3900). [Andrew Nolte]
* Add SOURCE_DATE_EPOCH for docs/guide/conf.py (#3918). [Larry Doolittle] * Add SOURCE_DATE_EPOCH for docs/guide/conf.py (#3918). [Larry Doolittle]
* Add /*verilator public[flat|flat_rd|flat_rw| ]*/ metacomments (#3894). [Joseph Nwabueze] * Add /*verilator public[flat|flat_rd|flat_rw| ]*/ metacomments (#3894). [Joseph Nwabueze]
* Add error on mixing .name and by-port instantiations.
* Support unpacked unions. * Support unpacked unions.
* Support interface classes and class implements. * Support interface classes and class implements.
* Support global clocking and $global_clock. * Support global clocking and $global_clock.

View File

@ -1233,7 +1233,8 @@ private:
AstVar* m_modVarp = nullptr; // Input/output this pin connects to on submodule. AstVar* m_modVarp = nullptr; // Input/output this pin connects to on submodule.
AstParamTypeDType* m_modPTypep = nullptr; // Param type this pin connects to on submodule. AstParamTypeDType* m_modPTypep = nullptr; // Param type this pin connects to on submodule.
bool m_param = false; // Pin connects to parameter bool m_param = false; // Pin connects to parameter
bool m_svImplicit = false; // Pin is SystemVerilog .name'ed bool m_svDotName = false; // Pin is SystemVerilog .name'ed
bool m_svImplicit = false; // Pin is SystemVerilog .name'ed, allow implicit
public: public:
AstPin(FileLine* fl, int pinNum, const string& name, AstNode* exprp) AstPin(FileLine* fl, int pinNum, const string& name, AstNode* exprp)
: ASTGEN_SUPER_Pin(fl) : ASTGEN_SUPER_Pin(fl)
@ -1257,6 +1258,8 @@ public:
void modPTypep(AstParamTypeDType* nodep) { m_modPTypep = nodep; } void modPTypep(AstParamTypeDType* nodep) { m_modPTypep = nodep; }
bool param() const { return m_param; } bool param() const { return m_param; }
void param(bool flag) { m_param = flag; } void param(bool flag) { m_param = flag; }
bool svDotName() const { return m_svDotName; }
void svDotName(bool flag) { m_svDotName = flag; }
bool svImplicit() const { return m_svImplicit; } bool svImplicit() const { return m_svImplicit; }
void svImplicit(bool flag) { m_svImplicit = flag; } void svImplicit(bool flag) { m_svImplicit = flag; }
}; };

View File

@ -1724,6 +1724,7 @@ void AstPin::dump(std::ostream& str) const {
} else { } else {
str << " ->UNLINKED"; str << " ->UNLINKED";
} }
if (svDotName()) str << " [.n]";
if (svImplicit()) str << " [.SV]"; if (svImplicit()) str << " [.SV]";
} }
const char* AstPin::broken() const { const char* AstPin::broken() const {

View File

@ -352,8 +352,10 @@ private:
} }
// Convert .* to list of pins // Convert .* to list of pins
bool pinStar = false; bool pinStar = false;
bool pinDotName = false;
for (AstPin *nextp, *pinp = nodep->pinsp(); pinp; pinp = nextp) { for (AstPin *nextp, *pinp = nodep->pinsp(); pinp; pinp = nextp) {
nextp = VN_AS(pinp->nextp(), Pin); nextp = VN_AS(pinp->nextp(), Pin);
if (pinp->svDotName()) pinDotName = true;
if (pinp->dotStar()) { if (pinp->dotStar()) {
if (pinStar) pinp->v3error("Duplicate .* in an instance (IEEE 1800-2017 23.3.2)"); if (pinStar) pinp->v3error("Duplicate .* in an instance (IEEE 1800-2017 23.3.2)");
pinStar = true; pinStar = true;
@ -374,8 +376,8 @@ private:
// Note what pins exist // Note what pins exist
std::unordered_set<string> ports; // Symbol table of all connected port names std::unordered_set<string> ports; // Symbol table of all connected port names
for (AstPin* pinp = nodep->pinsp(); pinp; pinp = VN_AS(pinp->nextp(), Pin)) { for (AstPin* pinp = nodep->pinsp(); pinp; pinp = VN_AS(pinp->nextp(), Pin)) {
if (pinStar && pinp->name().substr(0, 11) == "__pinNumber") { if ((pinStar || pinDotName) && pinp->name().substr(0, 11) == "__pinNumber") {
pinp->v3error("Connect by position is illegal in .* connected instances" pinp->v3error("Mixing positional and .*/named instantiation connection"
" (IEEE 1800-2017 23.3.2)"); " (IEEE 1800-2017 23.3.2)");
} }
if (!pinp->exprp()) { if (!pinp->exprp()) {
@ -404,6 +406,7 @@ private:
nodep->fileline(), 0, portp->name(), nodep->fileline(), 0, portp->name(),
new AstParseRef{nodep->fileline(), VParseRefExp::PX_TEXT, new AstParseRef{nodep->fileline(), VParseRefExp::PX_TEXT,
portp->name(), nullptr, nullptr}}; portp->name(), nullptr, nullptr}};
newp->svDotName(true);
newp->svImplicit(true); newp->svImplicit(true);
nodep->addPinsp(newp); nodep->addPinsp(newp);
} else { // warn on the CELL that needs it, not the port } else { // warn on the CELL that needs it, not the port

View File

@ -3194,18 +3194,22 @@ cellparamItemE<pinp>: // IEEE: named_parameter_assignment + empty
// // Note empty can match either () or (,); V3LinkCells cleans up () // // Note empty can match either () or (,); V3LinkCells cleans up ()
/* empty: ',,' is legal */ { $$ = new AstPin{CRELINE(), PINNUMINC(), "", nullptr}; } /* empty: ',,' is legal */ { $$ = new AstPin{CRELINE(), PINNUMINC(), "", nullptr}; }
| yP_DOTSTAR { $$ = new AstPin{$1, PINNUMINC(), ".*", nullptr}; } | yP_DOTSTAR { $$ = new AstPin{$1, PINNUMINC(), ".*", nullptr}; }
| '.' idAny '(' ')' { $$ = new AstPin{$<fl>2, PINNUMINC(), *$2, nullptr}; } | '.' idAny '(' ')'
{ $$ = new AstPin{$<fl>2, PINNUMINC(), *$2, nullptr};
$$->svDotName(true); }
| '.' idSVKwd | '.' idSVKwd
{ $$ = new AstPin{$<fl>2, PINNUMINC(), *$2, { $$ = new AstPin{$<fl>2, PINNUMINC(), *$2,
new AstParseRef{$<fl>2, VParseRefExp::PX_TEXT, *$2, nullptr, nullptr}}; new AstParseRef{$<fl>2, VParseRefExp::PX_TEXT, *$2, nullptr, nullptr}};
$$->svImplicit(true); } $$->svDotName(true); $$->svImplicit(true); }
| '.' idAny | '.' idAny
{ $$ = new AstPin{$<fl>2, PINNUMINC(), *$2, { $$ = new AstPin{$<fl>2, PINNUMINC(), *$2,
new AstParseRef{$<fl>2, VParseRefExp::PX_TEXT, *$2, nullptr, nullptr}}; new AstParseRef{$<fl>2, VParseRefExp::PX_TEXT, *$2, nullptr, nullptr}};
$$->svImplicit(true); } $$->svDotName(true); $$->svImplicit(true); }
// // mintypmax is expanded here, as it might be a UDP or gate primitive // // mintypmax is expanded here, as it might be a UDP or gate primitive
// // data_type for 'parameter type' hookups // // data_type for 'parameter type' hookups
| '.' idAny '(' exprOrDataType ')' { $$ = new AstPin{$<fl>2, PINNUMINC(), *$2, $4}; } | '.' idAny '(' exprOrDataType ')'
{ $$ = new AstPin{$<fl>2, PINNUMINC(), *$2, $4};
$$->svDotName(true); }
//UNSUP '.' idAny '(' exprOrDataType/*expr*/ ':' expr ')' { } //UNSUP '.' idAny '(' exprOrDataType/*expr*/ ':' expr ')' { }
//UNSUP '.' idAny '(' exprOrDataType/*expr*/ ':' expr ':' expr ')' { } //UNSUP '.' idAny '(' exprOrDataType/*expr*/ ':' expr ':' expr ')' { }
// // data_type for 'parameter type' hookups // // data_type for 'parameter type' hookups
@ -3218,18 +3222,22 @@ cellpinItemE<pinp>: // IEEE: named_port_connection + empty
// // Note empty can match either () or (,); V3LinkCells cleans up () // // Note empty can match either () or (,); V3LinkCells cleans up ()
/* empty: ',,' is legal */ { $$ = new AstPin{CRELINE(), PINNUMINC(), "", nullptr}; } /* empty: ',,' is legal */ { $$ = new AstPin{CRELINE(), PINNUMINC(), "", nullptr}; }
| yP_DOTSTAR { $$ = new AstPin{$1, PINNUMINC(), ".*", nullptr}; } | yP_DOTSTAR { $$ = new AstPin{$1, PINNUMINC(), ".*", nullptr}; }
| '.' idAny '(' ')' { $$ = new AstPin{$<fl>2, PINNUMINC(), *$2, nullptr}; } | '.' idAny '(' ')'
{ $$ = new AstPin{$<fl>2, PINNUMINC(), *$2, nullptr};
$$->svDotName(true); }
| '.' idSVKwd | '.' idSVKwd
{ $$ = new AstPin{$<fl>2, PINNUMINC(), *$2, { $$ = new AstPin{$<fl>2, PINNUMINC(), *$2,
new AstParseRef{$<fl>2, VParseRefExp::PX_TEXT, *$2, nullptr, nullptr}}; new AstParseRef{$<fl>2, VParseRefExp::PX_TEXT, *$2, nullptr, nullptr}};
$$->svImplicit(true);} $$->svDotName(true); $$->svImplicit(true); }
| '.' idAny | '.' idAny
{ $$ = new AstPin{$<fl>2, PINNUMINC(), *$2, { $$ = new AstPin{$<fl>2, PINNUMINC(), *$2,
new AstParseRef{$<fl>2, VParseRefExp::PX_TEXT, *$2, nullptr, nullptr}}; new AstParseRef{$<fl>2, VParseRefExp::PX_TEXT, *$2, nullptr, nullptr}};
$$->svImplicit(true);} $$->svDotName(true); $$->svImplicit(true); }
// // mintypmax is expanded here, as it might be a UDP or gate primitive // // mintypmax is expanded here, as it might be a UDP or gate primitive
//UNSUP pev_expr below //UNSUP pev_expr below
| '.' idAny '(' expr ')' { $$ = new AstPin{$<fl>2, PINNUMINC(), *$2, $4}; } | '.' idAny '(' expr ')'
{ $$ = new AstPin{$<fl>2, PINNUMINC(), *$2, $4};
$$->svDotName(true); }
//UNSUP '.' idAny '(' pev_expr ':' expr ')' { } //UNSUP '.' idAny '(' pev_expr ':' expr ')' { }
//UNSUP '.' idAny '(' pev_expr ':' expr ':' expr ')' { } //UNSUP '.' idAny '(' pev_expr ':' expr ':' expr ')' { }
// //

View File

@ -1,10 +1,4 @@
%Error-UNSUPPORTED: t/t_fuzz_genintf_bad.v:24:12: Unsupported: Member call on object 'VARREF 'j'' which is a 'BASICDTYPE 'integer'' %Error: t/t_fuzz_genintf_bad.v:24:11: Mixing positional and .*/named instantiation connection (IEEE 1800-2017 23.3.2)
: ... In instance t
24 | j.e(0),
| ^
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
%Error: Internal Error: t/t_fuzz_genintf_bad.v:24:11: ../V3Width.cpp:#: Unlinked pin data type
: ... In instance t
24 | j.e(0), 24 | j.e(0),
| ^ | ^
... See the manual at https://verilator.org/verilator_doc.html for more assistance. %Error: Exiting due to

View File

@ -1,7 +1,10 @@
%Error: t/t_inst_2star_bad.v:11:17: Duplicate .* in an instance (IEEE 1800-2017 23.3.2) %Error: t/t_inst_2star_bad.v:12:17: Duplicate .* in an instance (IEEE 1800-2017 23.3.2)
11 | sub sub (.*, .*); 12 | sub sub (.*, .*);
| ^~ | ^~
%Error: t/t_inst_2star_bad.v:13:13: Connect by position is illegal in .* connected instances (IEEE 1800-2017 23.3.2) %Error: t/t_inst_2star_bad.v:14:13: Mixing positional and .*/named instantiation connection (IEEE 1800-2017 23.3.2)
13 | sub sub (foo, .*); 14 | sub sub (foo, .*);
| ^~~
%Error: t/t_inst_2star_bad.v:16:13: Mixing positional and .*/named instantiation connection (IEEE 1800-2017 23.3.2)
16 | sub sub (foo, .bar);
| ^~~ | ^~~
%Error: Exiting due to %Error: Exiting due to

View File

@ -7,12 +7,15 @@
module t (/*AUTOARG*/); module t (/*AUTOARG*/);
wire foo; wire foo;
wire bar;
sub sub (.*, .*); sub sub (.*, .*);
sub sub (foo, .*); sub sub (foo, .*);
sub sub (foo, .bar);
endmodule endmodule
module sub (input foo); module sub (input foo, input bar);
endmodule endmodule

View File

@ -6,9 +6,13 @@
module t (/*AUTOARG*/); module t (/*AUTOARG*/);
wire ok = 1'b0; wire ok = 1'b0;
// verilator lint_off UNDRIVEN
wire nc;
// verilator lint_on UNDRIVEN
// verilator lint_off PINNOCONNECT // verilator lint_off PINNOCONNECT
// verilator lint_off PINCONNECTEMPTY // verilator lint_off PINCONNECTEMPTY
sub sub (.ok(ok), , .nc()); sub sub (ok, , nc);
// verilator lint_on PINCONNECTEMPTY // verilator lint_on PINCONNECTEMPTY
// verilator lint_on PINNOCONNECT // verilator lint_on PINNOCONNECT
endmodule endmodule

View File

@ -1,12 +1,9 @@
%Warning-PINNOCONNECT: t/t_inst_missing_bad.v:9:22: Cell pin is not connected: '__pinNumber2' %Warning-PINNOCONNECT: t/t_inst_missing_bad.v:13:17: Cell pin is not connected: '__pinNumber2'
9 | sub sub (.ok(ok), , .nc()); 13 | sub sub (ok, , nc);
| ^ | ^
... For warning description see https://verilator.org/warn/PINNOCONNECT?v=latest ... For warning description see https://verilator.org/warn/PINNOCONNECT?v=latest
... Use "/* verilator lint_off PINNOCONNECT */" and lint_on around source to disable this message. ... Use "/* verilator lint_off PINNOCONNECT */" and lint_on around source to disable this message.
%Warning-PINCONNECTEMPTY: t/t_inst_missing_bad.v:9:25: Cell pin connected by name with empty reference: 'nc' %Warning-PINMISSING: t/t_inst_missing_bad.v:13:8: Cell has missing pin: 'missing'
9 | sub sub (.ok(ok), , .nc()); 13 | sub sub (ok, , nc);
| ^~
%Warning-PINMISSING: t/t_inst_missing_bad.v:9:8: Cell has missing pin: 'missing'
9 | sub sub (.ok(ok), , .nc());
| ^~~ | ^~~
%Error: Exiting due to %Error: Exiting due to

View File

@ -6,7 +6,11 @@
module t (/*AUTOARG*/); module t (/*AUTOARG*/);
wire ok = 1'b0; wire ok = 1'b0;
sub sub (.ok(ok), , .nc()); // verilator lint_off UNDRIVEN
wire nc;
// verilator lint_on UNDRIVEN
sub sub (ok, , nc);
endmodule endmodule
module sub (input ok, input none, input nc, input missing); module sub (input ok, input none, input nc, input missing);

View File

@ -8,7 +8,7 @@
module t(input clk); module t(input clk);
my_interface iface(); my_interface iface();
my_module m(.clk(clk), iface); my_module m(.clk(clk), .iface);
endmodule endmodule
module my_module(input clk, my_interface.my_port iface); module my_module(input clk, my_interface.my_port iface);