Fix resolution of specialized typedefs (#6754) (#6808)

This commit is contained in:
em2machine 2025-12-12 21:20:15 +01:00 committed by GitHub
parent 2995748d46
commit aff501f5c4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 148 additions and 0 deletions

View File

@ -1240,6 +1240,25 @@ class ParamProcessor final {
= nodeDeparamCommon(nodep, srcModp, nodep->paramsp(), nullptr, false);
if (!newModp) return nullptr;
nodep->classOrPackagep(newModp); // Might be unchanged if not cloned (newModp == srcModp)
// If this ClassOrPackageRef is a child of a RefDType (e.g., typedef class#(T)::member_t),
// resolve the RefDType's typedef to point to the typedef inside the specialized class
AstRefDType* const refDTypep = VN_CAST(nodep->backp(), RefDType);
AstClass* const newClassp = refDTypep ? VN_CAST(newModp, Class) : nullptr;
if (newClassp && !refDTypep->typedefp() && !refDTypep->subDTypep()) {
for (AstNode* itemp = newClassp->membersp(); itemp; itemp = itemp->nextp()) {
if (AstTypedef* const typedefp = VN_CAST(itemp, Typedef)) {
if (typedefp->name() == refDTypep->name()) {
refDTypep->typedefp(typedefp);
refDTypep->classOrPackagep(newClassp);
UINFO(9, "Resolved parameterized class typedef: "
<< refDTypep->name() << " -> " << typedefp << " in "
<< newClassp->name());
break;
}
}
}
}
return newModp;
}
AstNodeModule* classRefDeparam(AstClassRefDType* nodep, AstNodeModule* srcModp) {

View File

@ -0,0 +1,18 @@
#!/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')
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 into the Public Domain, for any use,
// without warranty.
// SPDX-License-Identifier: CC0-1.0
class func_c #(parameter p_width=4);
typedef struct packed {
logic[p_width-1:0] data;
} my_type_t;
static function my_type_t func(
input logic[p_width-1:0] inb
);
func.data = inb;
endfunction
endclass
module modA #(parameter p_width = 7)(
input func_c#(p_width)::my_type_t sig_a
,output func_c#(p_width)::my_type_t sig_b
);
assign sig_b.data = func_c#(p_width)::func(sig_a);
endmodule
module the_top();
localparam int Size = 3;
func_c#(Size)::my_type_t sig_a, sig_b, sig_c;
modA #(.p_width(Size)) modA(
.sig_a(sig_a)
,.sig_b(sig_b)
);
initial begin
sig_a.data = 'h3;
sig_c.data = func_c#(Size)::func('h5);
#1;
if(sig_b.data != 'h3) $stop;
if(sig_c.data != 'h5) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule

View File

@ -0,0 +1,18 @@
#!/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')
test.compile(verilator_flags2=["--binary"])
test.execute()
test.passes()

View File

@ -0,0 +1,49 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty.
// SPDX-License-Identifier: CC0-1.0
`define stop $stop
`define checkd(gotv,expv) \
do if ((gotv) !== (expv)) begin \
$write("%%Error: %s:%0d: got=%0d exp=%0d\n", \
`__FILE__,`__LINE__, (gotv), (expv)); \
`stop; \
end while(0);
class pipeline_class #(
parameter type XWORD = logic
);
typedef struct packed {
XWORD pc;
} if_id_t;
endclass
module pipe_reg #(
parameter type T = logic
)();
initial begin
#1;
`checkd($bits(T), 8);
end
endmodule
module the_top #() ();
typedef logic [7:0] my_t;
typedef pipeline_class #(my_t)::if_id_t if_id_t;
pipe_reg #(if_id_t) if_id_reg();
initial begin
#1;
#1;
`checkd($bits(if_id_t), 8);
$write("*-* All Finished *-*\n");
$finish;
end
endmodule