Fixes #7445.
This commit is contained in:
parent
f3c63d017a
commit
23ca23b7b5
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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)) {
|
||||||
|
|
|
||||||
|
|
@ -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