From 298922d8872eae94acd9bc68f156fd1bd4ed4479 Mon Sep 17 00:00:00 2001 From: Kristof Marien Date: Sat, 12 Sep 2026 12:31:10 -0700 Subject: [PATCH] Fix parameterized class nested in a parameterized interface (#8328) (#8329) --- docs/CONTRIBUTORS | 1 + src/V3Param.cpp | 6 +++++ .../t/t_interface_param_nested_class.py | 18 ++++++++++++++ .../t/t_interface_param_nested_class.v | 24 +++++++++++++++++++ 4 files changed, 49 insertions(+) create mode 100755 test_regress/t/t_interface_param_nested_class.py create mode 100644 test_regress/t/t_interface_param_nested_class.v diff --git a/docs/CONTRIBUTORS b/docs/CONTRIBUTORS index d2197560f..5f28a1c68 100644 --- a/docs/CONTRIBUTORS +++ b/docs/CONTRIBUTORS @@ -183,6 +183,7 @@ Keith Colbert Kevin Kiningham Kevin Nygaard Kornel Uriasz +Kristof Marien Kritik Bhimani Krzysztof Bieganski Krzysztof Boronski diff --git a/src/V3Param.cpp b/src/V3Param.cpp index 3515d25cd..fac1c757e 100644 --- a/src/V3Param.cpp +++ b/src/V3Param.cpp @@ -961,6 +961,12 @@ class ParamProcessor final { } else { newModp = srcModp->cloneTree(false); } + // AstPin normally retains links to external module formals across cloning. For a cloned + // interface, relink pins whose formals were cloned with the interface while clonep() is + // still valid, so nested parameterized classes use the cloned interface parameters. + if (AstIface* const newIfacep = VN_CAST(newModp, Iface)) { + newIfacep->foreach([](AstPin* pinp) { pinp->cloneRelinkGen(); }); + } // Mark the source module as a parameterized template now that a specialized // clone exists. This suppresses width/type errors on the unresolved template diff --git a/test_regress/t/t_interface_param_nested_class.py b/test_regress/t/t_interface_param_nested_class.py new file mode 100755 index 000000000..faf050124 --- /dev/null +++ b/test_regress/t/t_interface_param_nested_class.py @@ -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('vlt_all') + +test.compile() + +test.execute() + +test.passes() diff --git a/test_regress/t/t_interface_param_nested_class.v b/test_regress/t/t_interface_param_nested_class.v new file mode 100644 index 000000000..ad337ae17 --- /dev/null +++ b/test_regress/t/t_interface_param_nested_class.v @@ -0,0 +1,24 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2026 by Verilator Authors. +// SPDX-FileCopyrightText: 2026 Wilson Snyder +// SPDX-License-Identifier: CC0-1.0 + +// A parameterized class nested in a specialized parameterized interface must +// produce distinct, well-formed class-package names during C++ emission. +interface intf #(int P = 1); + class Cls #(int Q); + endclass + + Cls #(P) obj; +endinterface + +module t; + intf #(2) intf_i(); + + initial begin + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule