parent
742c0b134c
commit
a2fcd37c08
|
|
@ -2185,6 +2185,12 @@ public:
|
||||||
&& !isSc() && !isPrimaryIO() && !isConst() && !isDouble() && !isString());
|
&& !isSc() && !isPrimaryIO() && !isConst() && !isDouble() && !isString());
|
||||||
}
|
}
|
||||||
bool isClassMember() const { return varType() == VVarType::MEMBER; }
|
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 isStatementTemp() const { return varType() == VVarType::STMTTEMP; }
|
||||||
bool isXTemp() const { return varType() == VVarType::XTEMP; }
|
bool isXTemp() const { return varType() == VVarType::XTEMP; }
|
||||||
bool isParam() const { return varType().isParam(); }
|
bool isParam() const { return varType().isParam(); }
|
||||||
|
|
|
||||||
|
|
@ -156,8 +156,8 @@ public:
|
||||||
UINFO(6, "New vertex " << vscp);
|
UINFO(6, "New vertex " << vscp);
|
||||||
vVtxp = new GateVarVertex{this, vscp};
|
vVtxp = new GateVarVertex{this, vscp};
|
||||||
vscp->user1p(vVtxp);
|
vscp->user1p(vVtxp);
|
||||||
if (vscp->varp()->sensIfacep()) {
|
if (vscp->varp()->sensIfacep() || vscp->varp()->isVirtIface()) {
|
||||||
// Can be used in a class method, which cannot be tracked statically
|
// Can be read/written to via the referenced actual interface
|
||||||
vVtxp->clearReducibleAndDedupable("VirtIface");
|
vVtxp->clearReducibleAndDedupable("VirtIface");
|
||||||
vVtxp->setConsumed("VirtIface");
|
vVtxp->setConsumed("VirtIface");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -192,6 +192,7 @@ class LocalizeVisitor final : public VNVisitor {
|
||||||
&& !nodep->varp()->isStatic() // Not a static variable
|
&& !nodep->varp()->isStatic() // Not a static variable
|
||||||
&& !nodep->varp()->isClassMember() // Statically exists in design hierarchy
|
&& !nodep->varp()->isClassMember() // Statically exists in design hierarchy
|
||||||
&& !nodep->varp()->sensIfacep() // Not sensitive to an interface
|
&& !nodep->varp()->sensIfacep() // Not sensitive to an interface
|
||||||
|
&& !nodep->varp()->isVirtIface() // Not interface pointer
|
||||||
&& !nodep->varp()->valuep() // Does not have an initializer
|
&& !nodep->varp()->valuep() // Does not have an initializer
|
||||||
) {
|
) {
|
||||||
UINFO(4, "Consider for localization: " << nodep);
|
UINFO(4, "Consider for localization: " << nodep);
|
||||||
|
|
|
||||||
|
|
@ -104,12 +104,13 @@ private:
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// Error on write across a virtual interface boundary
|
// 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;
|
if (!nodep) return;
|
||||||
foreachWrittenVirtIface(nodep, [locationp](AstVarRef* const selp, AstIface*) {
|
foreachWrittenVirtIfaceMember(
|
||||||
selp->v3warn(E_UNSUPPORTED,
|
nodep, [locationp](AstVarRef* const selp, AstIface*, AstVar* varp) {
|
||||||
"Unsupported: Write to virtual interface in " << locationp);
|
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
|
// 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) {
|
AstVarRef* createVirtIfaceTriggerRefp(FileLine* const flp, AstIface* ifacep) {
|
||||||
|
|
@ -164,7 +165,7 @@ private:
|
||||||
iterateChildren(nodep);
|
iterateChildren(nodep);
|
||||||
}
|
}
|
||||||
void visit(AstNodeIf* nodep) override {
|
void visit(AstNodeIf* nodep) override {
|
||||||
unsupportedWriteToVirtIface(nodep->condp(), "if condition");
|
unsupportedWriteToVirtIfaceMember(nodep->condp(), "if condition");
|
||||||
{
|
{
|
||||||
VL_RESTORER(m_trigAssignp);
|
VL_RESTORER(m_trigAssignp);
|
||||||
VL_RESTORER(m_trigAssignIfacep);
|
VL_RESTORER(m_trigAssignIfacep);
|
||||||
|
|
@ -201,7 +202,7 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void visit(AstLoopTest* nodep) override {
|
void visit(AstLoopTest* nodep) override {
|
||||||
unsupportedWriteToVirtIface(nodep->condp(), "loop condition");
|
unsupportedWriteToVirtIfaceMember(nodep->condp(), "loop condition");
|
||||||
}
|
}
|
||||||
void visit(AstJumpBlock* nodep) override {
|
void visit(AstJumpBlock* nodep) override {
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -3371,8 +3371,6 @@ class WidthVisitor final : public VNVisitor {
|
||||||
nodep->varp(varp);
|
nodep->varp(varp);
|
||||||
AstIface* const ifacep = adtypep->ifacep();
|
AstIface* const ifacep = adtypep->ifacep();
|
||||||
varp->sensIfacep(ifacep);
|
varp->sensIfacep(ifacep);
|
||||||
nodep->fromp()->foreach(
|
|
||||||
[ifacep](AstVarRef* const refp) { refp->varp()->sensIfacep(ifacep); });
|
|
||||||
nodep->didWidth(true);
|
nodep->didWidth(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
@ -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
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
%Error-UNSUPPORTED: t/t_interface_virtual_unsup.v:22:22: Unsupported: Write to virtual interface in if condition
|
%Error-UNSUPPORTED: t/t_interface_virtual_unsup.v:24:22: Unsupported: Write to virtual interface in if condition
|
||||||
22 | if (write_data(vif.data)) $write("dummy op");
|
24 | if (write_data(vif.data)) $write("dummy op");
|
||||||
| ^~~
|
| ^~~
|
||||||
... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest
|
... 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
|
%Error-UNSUPPORTED: t/t_interface_virtual_unsup.v:25:25: Unsupported: Write to virtual interface in loop condition
|
||||||
23 | while (write_data(vif.data));
|
25 | while (write_data(vif.data));
|
||||||
| ^~~
|
| ^~~
|
||||||
%Error-UNSUPPORTED: t/t_interface_virtual_unsup.v:24:30: Unsupported: Write to virtual interface in loop condition
|
%Error-UNSUPPORTED: t/t_interface_virtual_unsup.v:26:30: Unsupported: Write to virtual interface in loop condition
|
||||||
24 | do ; while (write_data(vif.data));
|
26 | do ; while (write_data(vif.data));
|
||||||
| ^~~
|
| ^~~
|
||||||
%Error: Exiting due to
|
%Error: Exiting due to
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@
|
||||||
// any use, without warranty, 2023 by Wilson Snyder.
|
// any use, without warranty, 2023 by Wilson Snyder.
|
||||||
// SPDX-License-Identifier: CC0-1.0
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
// NOTE: Once this is supported, t_interface_virtual_cond is no longer needed
|
||||||
|
|
||||||
interface Bus;
|
interface Bus;
|
||||||
logic [15:0] data;
|
logic [15:0] data;
|
||||||
endinterface
|
endinterface
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue