Fix type deduction for variable parameterized classes (#6281) (#6813)

This commit is contained in:
em2machine 2025-12-17 14:08:44 +01:00 committed by GitHub
parent fe5d6b213c
commit 6f43ad8607
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 74 additions and 18 deletions

View File

@ -1775,7 +1775,7 @@ void AstCellInlineScope::dumpJson(std::ostream& str) const {
dumpJsonGen(str);
}
bool AstClass::isCacheableChild(const AstNode* nodep) {
return VN_IS(nodep, Var)
return VN_IS(nodep, Var) || VN_IS(nodep, Typedef)
|| (VN_IS(nodep, Constraint) && !VN_AS(nodep, Constraint)->isExternProto())
|| VN_IS(nodep, EnumItemRef)
|| (VN_IS(nodep, NodeFTask) && !VN_AS(nodep, NodeFTask)->isExternProto())

View File

@ -54,6 +54,7 @@
#include "V3EmitV.h"
#include "V3Hasher.h"
#include "V3LinkDotIfaceCapture.h"
#include "V3MemberMap.h"
#include "V3Os.h"
#include "V3Parse.h"
#include "V3Simulate.h"
@ -291,6 +292,9 @@ class ParamProcessor final {
std::vector<std::pair<AstParamTypeDType*, int>> m_classParams;
std::unordered_map<AstParamTypeDType*, int> m_paramIndex;
// member names cached for fast lookup
VMemberMap m_memberMap;
// METHODS
static void makeSmallNames(AstNodeModule* modp) {
@ -846,7 +850,10 @@ class ParamProcessor final {
pinExprp->replaceWith(new AstConst{pinp->fileline(), AstConst::WidthedValue{},
modvarp->width(), 0});
VL_DO_DANGLING(pinExprp->deleteTree(), pinExprp);
} else if (origp && exprp->sameTree(origp)) {
} else if (origp
&& (exprp->sameTree(origp)
|| (exprp->num().width() == origp->num().width()
&& ParameterizedHierBlocks::areSame(exprp, origp)))) {
// Setting parameter to its default value. Just ignore it.
// This prevents making additional modules, and makes coverage more
// obvious as it won't show up under a unique module page name.
@ -1246,17 +1253,13 @@ class ParamProcessor final {
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()) {
if (AstTypedef* const typedefp
= VN_CAST(m_memberMap.findMember(newClassp, refDTypep->name()), Typedef)) {
refDTypep->typedefp(typedefp);
refDTypep->classOrPackagep(newClassp);
UINFO(9, "Resolved parameterized class typedef: "
<< refDTypep->name() << " -> " << typedefp << " in "
UINFO(9, "Resolved parameterized class typedef: " << refDTypep->name() << " -> "
<< typedefp << " in "
<< newClassp->name());
break;
}
}
}
}
return newModp;

View File

@ -16,8 +16,8 @@ class func_c #(parameter p_width=4);
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
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
@ -28,8 +28,8 @@ module the_top();
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)
.sig_a(sig_a),
.sig_b(sig_b)
);
initial begin

View File

@ -35,7 +35,8 @@ endmodule
module the_top #() ();
typedef logic [7:0] my_t;
typedef pipeline_class #(my_t)::if_id_t if_id_t;
typedef pipeline_class #(my_t)::if_id_t if_id2_t;
typedef if_id2_t if_id_t;
pipe_reg #(if_id_t) if_id_reg();
initial begin

View File

@ -0,0 +1,18 @@
#!/usr/bin/env python3
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2025 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,34 @@
// 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 Class_A #(parameter int myparam = 32);
endclass
module tb_top;
localparam int WIDTH_A=32;
localparam int WIDTH_B=2*16;
Class_A#(32) a;
Class_A#(WIDTH_A) b;
Class_A#(WIDTH_B) c;
initial begin
#1;
a = b;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule