Fix localparam elaboration (#3858) (#4794)

This commit is contained in:
Andrew Nolte 2024-01-11 07:49:07 -05:00 committed by GitHub
parent 5f52c066e5
commit ab47fc6656
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 67 additions and 62 deletions

View File

@ -825,7 +825,7 @@ class ParamProcessor final {
}
}
void storeOriginalParams(AstClass* const classp) {
void storeOriginalParams(AstNodeModule* const classp) {
for (AstNode* stmtp = classp->stmtsp(); stmtp; stmtp = stmtp->nextp()) {
AstNode* originalParamp = nullptr;
if (AstVar* const varp = VN_CAST(stmtp, Var)) {
@ -870,13 +870,13 @@ class ParamProcessor final {
UINFO(8, "Cell parameters all match original values, skipping expansion.\n");
// If it's the first use of the default instance, create a copy and store it in user3p.
// user3p will also be used to check if the default instance is used.
if (!srcModpr->user3p() && VN_IS(srcModpr, Class)) {
AstClass* classCopyp = VN_AS(srcModpr, Class)->cloneTree(false);
if (!srcModpr->user3p() && (VN_IS(srcModpr, Class) || VN_IS(srcModpr, Iface))) {
AstNodeModule* nodeCopyp = srcModpr->cloneTree(false);
// It is a temporary copy of the original class node, stored in order to create
// another instances. It is needed only during class instantiation.
m_deleter.pushDeletep(classCopyp);
srcModpr->user3p(classCopyp);
storeOriginalParams(classCopyp);
m_deleter.pushDeletep(nodeCopyp);
srcModpr->user3p(nodeCopyp);
storeOriginalParams(nodeCopyp);
}
} else {
const string newname

View File

@ -1,5 +1,3 @@
*-* All Finished *-*
top.t.intf: symbolsPerBeat 16, symbolsPerBeatDivBy2 8, mismatch 0
top.t.theCore.core_intf: symbolsPerBeat 64, symbolsPerBeatDivBy2 8, mismatch 1
%Error: t/t_interface_localparam_unsup.v:23: Verilog $stop
Aborting...
top.t.theCore.core_intf: symbolsPerBeat 64, symbolsPerBeatDivBy2 32, mismatch 0

View File

@ -15,8 +15,6 @@ compile(
execute(
check_finished => 1,
fails => $Self->{vlt_all},
expect_filename => $Self->{golden_filename},
);
ok(1);

View File

@ -0,0 +1,60 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2023 by Justin Thiel.
// SPDX-License-Identifier: CC0-1.0
interface SimpleIntf
#(
parameter int val = 28
)
();
// This value is calculated incorrectly for other instances of
// this interface when it is accessed via the HDL for any other
// instance of this interface
localparam int valDiv2 = val/2;
localparam int valDiv4 = valDiv2/2;
localparam bit mismatch2 = (val != (2*valDiv2) );
localparam bit mismatch4 = (val != (4*valDiv4) );
initial begin
$write("%m: val %0d, valDiv2 %0d, mismatch2 %0d\n",
val, valDiv2, mismatch2);
$write("%m: val %0d, valDiv4 %0d, mismatch4 %0d\n",
val, valDiv4, mismatch2);
if (mismatch2) $stop;
if (mismatch4) $stop;
end
endinterface
module Core(
SimpleIntf intf
);
// this will constify and valDiv2 will have the default value
localparam valDiv4Upper = intf.valDiv2;
SimpleIntf #(.val(68)) core_intf ();
initial begin
if (intf.valDiv2 != valDiv4Upper) begin
$display("%%Error: param = %0d", intf.valDiv2);
end
end
endmodule
module t();
SimpleIntf intf();
Core theCore (.intf);
initial begin
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -1,51 +0,0 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2023 by Justin Thiel.
// SPDX-License-Identifier: CC0-1.0
interface SimpleIntf
#(
parameter int symbolsPerBeat = 16
)
();
// This value is calculated incorrectly for other instances of
// this interface when it is accessed via the HDL for any other
// instance of this interface
localparam int symbolsPerBeatDivBy2 = symbolsPerBeat/2;
localparam bit mismatch = (symbolsPerBeat != (2*symbolsPerBeatDivBy2) );
initial begin
$write("%m: symbolsPerBeat %0d, symbolsPerBeatDivBy2 %0d, mismatch %0d\n",
symbolsPerBeat, symbolsPerBeatDivBy2, mismatch);
if (mismatch) $stop;
end
endinterface
module Core(
SimpleIntf intf
);
// NOTE: When this line is commented out the test will pass
localparam intf_symbolsPerBeatDivBy2 = intf.symbolsPerBeatDivBy2;
localparam int core_intf_symbolsPerBeat = 64;
SimpleIntf #(.symbolsPerBeat(core_intf_symbolsPerBeat)) core_intf ();
endmodule
module t();
SimpleIntf intf();
Core theCore (.intf);
initial begin
$write("*-* All Finished *-*\n");
$finish;
end
endmodule