Fix local interface parameter hierarchical access (#6661) (#6666)

Co-authored-by: Paul Swirhun <paulswirhun@gmail.com>
This commit is contained in:
Paul Swirhun 2025-11-09 08:48:55 -07:00 committed by GitHub
parent 107776f324
commit aaafa6e8df
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 77 additions and 2 deletions

View File

@ -1283,6 +1283,7 @@ class ParamVisitor final : public VNVisitor {
// STATE - for current visit position (use VL_RESTORER)
AstNodeModule* m_modp; // Module iterating
std::unordered_set<std::string> m_ifacePortNames; // Interface port names in current module
std::unordered_set<std::string> m_ifaceInstNames; // Interface decl names in current module
string m_generateHierName; // Generate portion of hierarchy name
// METHODS
@ -1314,8 +1315,10 @@ class ParamVisitor final : public VNVisitor {
{
VL_RESTORER(m_modp);
VL_RESTORER(m_ifacePortNames);
VL_RESTORER(m_ifaceInstNames);
m_modp = modp;
m_ifacePortNames.clear();
m_ifaceInstNames.clear();
iterateChildren(modp);
}
}
@ -1397,7 +1400,7 @@ class ParamVisitor final : public VNVisitor {
});
}
// Check if cell parameters reference interface ports
// Check if cell parameters reference interface ports or local interface instances
bool cellParamsReferenceIfacePorts(AstCell* cellp) {
if (!cellp->paramsp()) return false;
@ -1406,7 +1409,10 @@ class ParamVisitor final : public VNVisitor {
if (AstNode* const exprp = pinp->exprp()) {
if (const AstVarXRef* const refp = VN_CAST(exprp, VarXRef)) {
const string refname = getRefBaseName(refp);
if (!refname.empty() && m_ifacePortNames.count(refname)) return true;
if (!refname.empty()
&& (m_ifacePortNames.count(refname)
|| m_ifaceInstNames.count(refname)))
return true;
}
}
}
@ -1490,6 +1496,8 @@ class ParamVisitor final : public VNVisitor {
}
void visit(AstCell* nodep) override {
checkParamNotHier(nodep->paramsp());
// Build cache of locally declared interface instance names
if (VN_IS(nodep->modp(), Iface)) { m_ifaceInstNames.insert(nodep->name()); }
visitCellOrClassRef(nodep, VN_IS(nodep->modp(), Iface));
}
void visit(AstIfaceRefDType* nodep) override {

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("simulator_st")
test.compile()
test.passes()

View File

@ -0,0 +1,51 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2025 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
interface intf #(
parameter int FOO = 32
) ();
endinterface
module sub (
intf intf_a,
intf intf_b
);
localparam int INTF_A_FOO = intf_a.FOO;
localparam int INTF_B_FOO = intf_b.FOO;
if (INTF_A_FOO != INTF_B_FOO)
$error("INTF_A_FOO != INTF_B_FOO: %0d != %0d", INTF_A_FOO, INTF_B_FOO);
endmodule
module t;
intf #(.FOO(21)) local_intf ();
intf #(.FOO(21)) intf_a_1 ();
intf #(.FOO(21)) intf_b_1 ();
sub sub_1 (
.intf_a(intf_a_1),
.intf_b(intf_b_1)
);
/* verilator lint_off HIERPARAM */
localparam int LOCAL_INTF_FOO = local_intf.FOO;
/* verilator lint_on HIERPARAM */
intf #(.FOO(LOCAL_INTF_FOO)) intf_a_2 ();
intf #(.FOO(21)) intf_b_2 ();
sub sub_2 (
.intf_a(intf_a_2),
.intf_b(intf_b_2)
);
/* verilator lint_off HIERPARAM */
intf #(.FOO(local_intf.FOO)) intf_a_3 ();
/* verilator lint_on HIERPARAM */
intf #(.FOO(21)) intf_b_3 ();
sub sub_3 (
.intf_a(intf_a_3),
.intf_b(intf_b_3)
);
endmodule