Fix unsupported `if` virtual interface warning (#6558) (#6861)

This commit is contained in:
Krzysztof Bieganski 2025-12-23 16:12:34 +01:00 committed by GitHub
parent 742c0b134c
commit a2fcd37c08
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 68 additions and 17 deletions

View File

@ -2185,6 +2185,12 @@ public:
&& !isSc() && !isPrimaryIO() && !isConst() && !isDouble() && !isString());
}
bool isClassMember() const { return varType() == VVarType::MEMBER; }
bool isVirtIface() const {
if (AstIfaceRefDType* const dtp = VN_CAST(dtypep(), IfaceRefDType)) {
return dtp->isVirtual();
}
return false;
}
bool isStatementTemp() const { return varType() == VVarType::STMTTEMP; }
bool isXTemp() const { return varType() == VVarType::XTEMP; }
bool isParam() const { return varType().isParam(); }

View File

@ -156,8 +156,8 @@ public:
UINFO(6, "New vertex " << vscp);
vVtxp = new GateVarVertex{this, vscp};
vscp->user1p(vVtxp);
if (vscp->varp()->sensIfacep()) {
// Can be used in a class method, which cannot be tracked statically
if (vscp->varp()->sensIfacep() || vscp->varp()->isVirtIface()) {
// Can be read/written to via the referenced actual interface
vVtxp->clearReducibleAndDedupable("VirtIface");
vVtxp->setConsumed("VirtIface");
}

View File

@ -192,6 +192,7 @@ class LocalizeVisitor final : public VNVisitor {
&& !nodep->varp()->isStatic() // Not a static variable
&& !nodep->varp()->isClassMember() // Statically exists in design hierarchy
&& !nodep->varp()->sensIfacep() // Not sensitive to an interface
&& !nodep->varp()->isVirtIface() // Not interface pointer
&& !nodep->varp()->valuep() // Does not have an initializer
) {
UINFO(4, "Consider for localization: " << nodep);

View File

@ -104,12 +104,13 @@ private:
});
}
// Error on write across a virtual interface boundary
static void unsupportedWriteToVirtIface(AstNode* nodep, const char* locationp) {
static void unsupportedWriteToVirtIfaceMember(AstNode* nodep, const char* locationp) {
if (!nodep) return;
foreachWrittenVirtIface(nodep, [locationp](AstVarRef* const selp, AstIface*) {
selp->v3warn(E_UNSUPPORTED,
"Unsupported: Write to virtual interface in " << locationp);
});
foreachWrittenVirtIfaceMember(
nodep, [locationp](AstVarRef* const selp, AstIface*, AstVar* varp) {
selp->v3warn(E_UNSUPPORTED,
"Unsupported: Write to virtual interface in " << locationp);
});
}
// Create trigger var for the given interface if it doesn't exist; return a write ref to it
AstVarRef* createVirtIfaceTriggerRefp(FileLine* const flp, AstIface* ifacep) {
@ -164,7 +165,7 @@ private:
iterateChildren(nodep);
}
void visit(AstNodeIf* nodep) override {
unsupportedWriteToVirtIface(nodep->condp(), "if condition");
unsupportedWriteToVirtIfaceMember(nodep->condp(), "if condition");
{
VL_RESTORER(m_trigAssignp);
VL_RESTORER(m_trigAssignIfacep);
@ -201,7 +202,7 @@ private:
}
}
void visit(AstLoopTest* nodep) override {
unsupportedWriteToVirtIface(nodep->condp(), "loop condition");
unsupportedWriteToVirtIfaceMember(nodep->condp(), "loop condition");
}
void visit(AstJumpBlock* nodep) override {
{

View File

@ -3371,8 +3371,6 @@ class WidthVisitor final : public VNVisitor {
nodep->varp(varp);
AstIface* const ifacep = adtypep->ifacep();
varp->sensIfacep(ifacep);
nodep->fromp()->foreach(
[ifacep](AstVarRef* const refp) { refp->varp()->sensIfacep(ifacep); });
nodep->didWidth(true);
return;
}

View File

@ -0,0 +1,16 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2024 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
import vltest_bootstrap
test.scenarios('linter')
test.compile()
test.passes()

View File

@ -0,0 +1,27 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2025 by Antmicro.
// SPDX-License-Identifier: CC0-1.0
interface Bus;
logic [15:0] data;
endinterface
module t;
Bus intf();
virtual Bus vif;
function logic get_vif(inout virtual Bus vif);
vif = intf;
return 0;
endfunction
initial begin
if (get_vif(vif));
while (get_vif(vif));
do ; while (get_vif(vif));
for (int i = 0; get_vif(vif); i++);
end
endmodule

View File

@ -1,11 +1,11 @@
%Error-UNSUPPORTED: t/t_interface_virtual_unsup.v:22:22: Unsupported: Write to virtual interface in if condition
22 | if (write_data(vif.data)) $write("dummy op");
%Error-UNSUPPORTED: t/t_interface_virtual_unsup.v:24:22: Unsupported: Write to virtual interface in if condition
24 | if (write_data(vif.data)) $write("dummy op");
| ^~~
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
%Error-UNSUPPORTED: t/t_interface_virtual_unsup.v:23:25: Unsupported: Write to virtual interface in loop condition
23 | while (write_data(vif.data));
%Error-UNSUPPORTED: t/t_interface_virtual_unsup.v:25:25: Unsupported: Write to virtual interface in loop condition
25 | while (write_data(vif.data));
| ^~~
%Error-UNSUPPORTED: t/t_interface_virtual_unsup.v:24:30: Unsupported: Write to virtual interface in loop condition
24 | do ; while (write_data(vif.data));
%Error-UNSUPPORTED: t/t_interface_virtual_unsup.v:26:30: Unsupported: Write to virtual interface in loop condition
26 | do ; while (write_data(vif.data));
| ^~~
%Error: Exiting due to

View File

@ -4,6 +4,8 @@
// any use, without warranty, 2023 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
// NOTE: Once this is supported, t_interface_virtual_cond is no longer needed
interface Bus;
logic [15:0] data;
endinterface