Fix parameterized class typedef as interface type parameter (#6983) (#6984)

This commit is contained in:
Leela Pakanati 2026-02-01 21:37:29 -06:00 committed by GitHub
parent 407fc74195
commit b2fa3fb54e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 76 additions and 4 deletions

View File

@ -152,6 +152,7 @@ Krzysztof Sychla
Kuba Ober
Lan Zongwei
Larry Doolittle
Leela Pakanati
Liam Braun
Luca Colagrande
Ludwig Rogiers

View File

@ -810,17 +810,32 @@ class ParamProcessor final {
}
}
// Helper to resolve DOT to RefDType for class type references
// Helper to resolve DOT to RefDType for class type references.
// If the class is parameterized and not yet specialized, specialize it first.
// This handles cases like: iface #(param_class#(value)::typedef_name)
void resolveDotToTypedef(AstNode* exprp) {
AstDot* const dotp = VN_CAST(exprp, Dot);
if (!dotp) return;
const AstClassOrPackageRef* const classRefp = VN_CAST(dotp->lhsp(), ClassOrPackageRef);
AstClassOrPackageRef* const classRefp = VN_CAST(dotp->lhsp(), ClassOrPackageRef);
if (!classRefp) return;
const AstClass* const lhsClassp = VN_CAST(classRefp->classOrPackageSkipp(), Class);
if (!lhsClassp) return;
AstParseRef* const parseRefp = VN_CAST(dotp->rhsp(), ParseRef);
if (!parseRefp) return;
const AstClass* lhsClassp = VN_CAST(classRefp->classOrPackageSkipp(), Class);
if (classRefp->paramsp()) {
// ClassOrPackageRef has parameters - may need to specialize the class
AstClass* const srcClassp = VN_CAST(classRefp->classOrPackageNodep(), Class);
if (srcClassp && srcClassp->hasGParam()) {
// Specialize if the reference still points to the generic class
if (lhsClassp == srcClassp || !lhsClassp) {
UINFO(9, "resolveDotToTypedef: specializing " << srcClassp->name() << endl);
classRefDeparam(classRefp, srcClassp);
lhsClassp = VN_CAST(classRefp->classOrPackageSkipp(), Class);
}
}
}
if (!lhsClassp) return;
AstTypedef* const tdefp
= VN_CAST(m_memberMap.findMember(lhsClassp, parseRefp->name()), Typedef);
if (tdefp) {

View File

@ -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()

View File

@ -0,0 +1,38 @@
// 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
// Test that parameterized class typedefs work as interface type parameters
// See issue #6983
// verilog_format: off
`define stop $stop
`define checkd(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d (%s !== %s)\n", `__FILE__,`__LINE__, (gotv), (expv), `"gotv`", `"expv`"); `stop; end while(0);
// verilog_format: on
class flux_st #(parameter int WIDTH=32);
typedef struct packed { logic [WIDTH-1:0] data; } pld_t;
endclass
interface flux_if #(parameter type PLD_T = logic);
logic rdy;
logic vld;
PLD_T pld;
modport drive (input rdy, output vld, output pld);
modport sink (output rdy, input vld, input pld);
endinterface
module t;
// Test using parameterized class typedef as interface type parameter
flux_if #(flux_st#(64)::pld_t) w_flux_st ();
initial begin
`checkd($bits(w_flux_st.pld), 64);
w_flux_st.pld.data = 64'hDEADBEEF_CAFEBABE;
`checkd(w_flux_st.pld.data, 64'hDEADBEEF_CAFEBABE);
$write("*-* All Finished *-*\n");
$finish;
end
endmodule