Fix for ariane/CVA6 false member call on object error (#7445) (#7450)

Fixes #7445.
This commit is contained in:
em2machine 2026-04-20 12:21:59 -04:00 committed by GitHub
parent f3c63d017a
commit 23ca23b7b5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 150 additions and 9 deletions

View File

@ -58,6 +58,7 @@ Drew Ranck
Drew Taussig Drew Taussig
Driss Hafdi Driss Hafdi
Edgar E. Iglesias Edgar E. Iglesias
Eric Mejdrich
Eric Müller Eric Müller
Eric Rippey Eric Rippey
Eunseo Song Eunseo Song

View File

@ -1406,13 +1406,16 @@ class ParamProcessor final {
} }
cloneVarp->valuep(exprp->cloneTree(false)); cloneVarp->valuep(exprp->cloneTree(false));
if (AstNodeDType* const origDTypep = modvarp->subDTypep()) { if (AstNodeDType* const origDTypep = modvarp->subDTypep()) {
AstNodeDType* const dtypeClonep = origDTypep->cloneTree(false); // Attach clone under cloneVarp so the root has a back pointer.
// Inline every param ref so widthing doesn't reach back into the template if (cloneVarp->childDTypep())
// (#7411). Cycle detector for dependent parameters in the same module. cloneVarp->childDTypep()->unlinkFrBack()->deleteTree();
cloneVarp->childDTypep(origDTypep->cloneTree(false));
cloneVarp->dtypep(nullptr);
// Inline param refs so widthing doesn't touch the template (#7411).
constexpr int maxSubstIters = 1000; constexpr int maxSubstIters = 1000;
for (int it = 0; it < maxSubstIters; ++it) { for (int it = 0; it < maxSubstIters; ++it) {
bool any = false; bool any = false;
dtypeClonep->foreach([&](AstVarRef* varrefp) { cloneVarp->foreach([&](AstVarRef* varrefp) {
AstVar* const targetp = varrefp->varp(); AstVar* const targetp = varrefp->varp();
AstNode* replacep = nullptr; AstNode* replacep = nullptr;
for (AstPin* pp = paramsp; pp; pp = VN_AS(pp->nextp(), Pin)) { for (AstPin* pp = paramsp; pp; pp = VN_AS(pp->nextp(), Pin)) {
@ -1432,19 +1435,40 @@ class ParamProcessor final {
any = true; any = true;
} }
}); });
// Substitute RefDType to an overridden paramtype. RefDType is
// not a foreach leaf, so collect matches and replace after the
// walk. Reverse order so descendants are replaced before
// ancestors -- replacing an ancestor would free its descendants.
std::vector<std::pair<AstRefDType*, AstNodeDType*>> toReplace;
cloneVarp->foreach([&](AstRefDType* refp) {
AstParamTypeDType* const ptdp
= VN_CAST(refp->refDTypep(), ParamTypeDType);
if (!ptdp) return;
for (AstPin* pp = paramsp; pp; pp = VN_AS(pp->nextp(), Pin)) {
if (pp->modPTypep() == ptdp) {
if (AstNodeDType* const overDtp
= VN_CAST(pp->exprp(), NodeDType)) {
toReplace.emplace_back(refp, overDtp);
}
break;
}
}
});
for (auto it = toReplace.rbegin(); it != toReplace.rend(); ++it) {
AstRefDType* const refp = it->first;
refp->replaceWith(it->second->cloneTree(false));
VL_DO_DANGLING(refp->deleteTree(), refp);
any = true;
}
if (!any) break; if (!any) break;
} }
// Bail if anything still points at the template. // Bail if anything still points at the template.
dtypeClonep->foreach([&](AstVarRef* varrefp) { cloneVarp->foreach([&](AstVarRef* varrefp) {
varrefp->v3fatalSrc( varrefp->v3fatalSrc(
"Unresolved VarRef '" "Unresolved VarRef '"
<< varrefp->prettyName() << "' in pin dtype clone. Pin: " << varrefp->prettyName() << "' in pin dtype clone. Pin: "
<< pinp->prettyNameQ() << " of " << nodep->prettyNameQ()); << pinp->prettyNameQ() << " of " << nodep->prettyNameQ());
}); });
if (cloneVarp->childDTypep())
cloneVarp->childDTypep()->unlinkFrBack()->deleteTree();
cloneVarp->childDTypep(dtypeClonep);
cloneVarp->dtypep(nullptr);
} }
V3Const::constifyParamsEdit(cloneVarp); V3Const::constifyParamsEdit(cloneVarp);
if (AstConst* const widthedp = VN_CAST(cloneVarp->valuep(), Const)) { if (AstConst* const widthedp = VN_CAST(cloneVarp->valuep(), Const)) {

View File

@ -0,0 +1,18 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# 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-FileCopyrightText: 2026 Wilson Snyder
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
import vltest_bootstrap
test.scenarios('simulator')
test.compile(verilator_flags2=["--binary"])
test.execute()
test.passes()

View File

@ -0,0 +1,44 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain.
// SPDX-FileCopyrightText: 2026 Wilson Snyder
// SPDX-License-Identifier: CC0-1.0
// Method/member access on a value-parameter whose type is
// the enclosing module's type-parameter.
typedef struct packed {
logic [7:0] S_TIMER;
logic [7:0] M_TIMER;
logic [7:0] M_EXT;
} my_irq_t;
module leaf #(
parameter type interrupts_t = logic,
parameter interrupts_t INTERRUPTS = '0
) ();
logic [7:0] observed;
always_comb observed = INTERRUPTS.M_TIMER;
endmodule
module mid #(
parameter type interrupts_t = logic,
parameter interrupts_t INTERRUPTS = '0
) ();
leaf #(.interrupts_t(interrupts_t), .INTERRUPTS(INTERRUPTS)) l();
endmodule
module t;
localparam type irq_t = my_irq_t;
localparam irq_t IRQ = '{S_TIMER: 8'hAA, M_TIMER: 8'h55, M_EXT: 8'hCC};
mid #(.interrupts_t(irq_t), .INTERRUPTS(IRQ)) m();
initial begin
#1;
if (m.l.observed !== 8'h55) begin
$write("%%Error: observed=%h expected 55\n", m.l.observed);
$stop;
end
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,18 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# 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-FileCopyrightText: 2026 Wilson Snyder
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
import vltest_bootstrap
test.scenarios('simulator')
test.compile(verilator_flags2=["--binary"])
test.execute()
test.passes()

View File

@ -0,0 +1,36 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain.
// SPDX-FileCopyrightText: 2026 Wilson Snyder
// SPDX-License-Identifier: CC0-1.0
// verilog_format: off
`define stop $stop
`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0);
// verilog_format: on
package pkg;
typedef struct packed {
logic [1:0][31:0] bar;
} T;
localparam T t = 64'h87654321_deadbeef;
endpackage
module foo #(
parameter type T = int,
parameter T t = 0
) ();
initial begin
`checkh(t.bar[0], 32'hdeadbeef);
`checkh(t.bar[1], 32'h87654321);
$write("*-* All Finished *-*\n");
$finish;
end
endmodule
module top;
foo #(
.T(pkg::T),
.t(pkg::t)
) u_foo ();
endmodule