Fixes #7445.
This commit is contained in:
parent
f3c63d017a
commit
23ca23b7b5
|
|
@ -58,6 +58,7 @@ Drew Ranck
|
|||
Drew Taussig
|
||||
Driss Hafdi
|
||||
Edgar E. Iglesias
|
||||
Eric Mejdrich
|
||||
Eric Müller
|
||||
Eric Rippey
|
||||
Eunseo Song
|
||||
|
|
|
|||
|
|
@ -1406,13 +1406,16 @@ class ParamProcessor final {
|
|||
}
|
||||
cloneVarp->valuep(exprp->cloneTree(false));
|
||||
if (AstNodeDType* const origDTypep = modvarp->subDTypep()) {
|
||||
AstNodeDType* const dtypeClonep = origDTypep->cloneTree(false);
|
||||
// Inline every param ref so widthing doesn't reach back into the template
|
||||
// (#7411). Cycle detector for dependent parameters in the same module.
|
||||
// Attach clone under cloneVarp so the root has a back pointer.
|
||||
if (cloneVarp->childDTypep())
|
||||
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;
|
||||
for (int it = 0; it < maxSubstIters; ++it) {
|
||||
bool any = false;
|
||||
dtypeClonep->foreach([&](AstVarRef* varrefp) {
|
||||
cloneVarp->foreach([&](AstVarRef* varrefp) {
|
||||
AstVar* const targetp = varrefp->varp();
|
||||
AstNode* replacep = nullptr;
|
||||
for (AstPin* pp = paramsp; pp; pp = VN_AS(pp->nextp(), Pin)) {
|
||||
|
|
@ -1432,19 +1435,40 @@ class ParamProcessor final {
|
|||
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;
|
||||
}
|
||||
// Bail if anything still points at the template.
|
||||
dtypeClonep->foreach([&](AstVarRef* varrefp) {
|
||||
cloneVarp->foreach([&](AstVarRef* varrefp) {
|
||||
varrefp->v3fatalSrc(
|
||||
"Unresolved VarRef '"
|
||||
<< varrefp->prettyName() << "' in pin dtype clone. Pin: "
|
||||
<< pinp->prettyNameQ() << " of " << nodep->prettyNameQ());
|
||||
});
|
||||
if (cloneVarp->childDTypep())
|
||||
cloneVarp->childDTypep()->unlinkFrBack()->deleteTree();
|
||||
cloneVarp->childDTypep(dtypeClonep);
|
||||
cloneVarp->dtypep(nullptr);
|
||||
}
|
||||
V3Const::constifyParamsEdit(cloneVarp);
|
||||
if (AstConst* const widthedp = VN_CAST(cloneVarp->valuep(), Const)) {
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
@ -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
|
||||
|
|
@ -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()
|
||||
|
|
@ -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
|
||||
Loading…
Reference in New Issue