From 98b8d43a4ae52dba9d42422e61c76c52be5d5c0d Mon Sep 17 00:00:00 2001 From: Igor Zaworski Date: Mon, 21 Jul 2025 13:30:10 +0200 Subject: [PATCH] Fix parameter-dependent type linking (#6170) --- src/V3LinkDot.cpp | 7 ++++--- src/V3Param.cpp | 2 +- test_regress/t/t_class_param_subtype2.py | 18 ++++++++++++++++ test_regress/t/t_class_param_subtype2.v | 26 ++++++++++++++++++++++++ 4 files changed, 49 insertions(+), 4 deletions(-) create mode 100755 test_regress/t/t_class_param_subtype2.py create mode 100644 test_regress/t/t_class_param_subtype2.v diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index a654141b8..425bb1f40 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -3589,9 +3589,6 @@ class LinkDotResolveVisitor final : public VNVisitor { UINFO(9, indent() << m_ds.ascii()); VL_RESTORER(m_usedPins); m_usedPins.clear(); - UASSERT_OBJ(m_statep->forPrimary() || VN_IS(nodep->classOrPackageNodep(), ParamTypeDType) - || nodep->classOrPackageSkipp(), - nodep, "ClassRef has unlinked class"); UASSERT_OBJ(m_statep->forPrimary() || !nodep->paramsp(), nodep, "class reference parameter not removed by V3Param"); { @@ -3602,6 +3599,10 @@ class LinkDotResolveVisitor final : public VNVisitor { m_statep->resolveClassOrPackage(m_ds.m_dotSymp, nodep, m_ds.m_dotPos != DP_PACKAGE, false, ":: reference"); } + UASSERT_OBJ(m_statep->forPrimary() + || VN_IS(nodep->classOrPackageNodep(), ParamTypeDType) + || nodep->classOrPackageSkipp(), + nodep, "ClassRef has unlinked class"); // ClassRef's have pins, so track if (nodep->classOrPackageSkipp()) { diff --git a/src/V3Param.cpp b/src/V3Param.cpp index d3ceb7a24..09b527a65 100644 --- a/src/V3Param.cpp +++ b/src/V3Param.cpp @@ -1116,7 +1116,7 @@ class ParamVisitor final : public VNVisitor { } else { cellp->v3fatalSrc("Expected module parameterization"); } - UASSERT_OBJ(srcModp, cellp, "Unlinked class ref"); + if (!srcModp) continue; // Update path string someInstanceName = modp->someInstanceName(); diff --git a/test_regress/t/t_class_param_subtype2.py b/test_regress/t/t_class_param_subtype2.py new file mode 100755 index 000000000..f989a35fb --- /dev/null +++ b/test_regress/t/t_class_param_subtype2.py @@ -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() + +test.execute() + +test.passes() diff --git a/test_regress/t/t_class_param_subtype2.v b/test_regress/t/t_class_param_subtype2.v new file mode 100644 index 000000000..5bb85b6e3 --- /dev/null +++ b/test_regress/t/t_class_param_subtype2.v @@ -0,0 +1,26 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2025 by Antmicro. +// SPDX-License-Identifier: CC0-1.0 + +class Class1 #(type T); + static function int get(); + return T::Helper::getter(); + endfunction +endclass + +class Class2; + typedef Class2 Helper; + static function int getter(); + return 13; + endfunction +endclass + +module t; + initial begin + if (Class1#(Class2)::get() != 13) $stop; + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule