diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index a2d8c59b6..8930e5a4c 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -463,7 +463,7 @@ void AstNetlist::timeprecisionMerge(FileLine*, const VTimescale& value) { } void AstNew::dump(std::ostream& str) const { - this->AstNode::dump(str); + this->AstNodeFTaskRef::dump(str); if (isImplicit()) str << " [IMPLICIT]"; if (isScoped()) str << " [SCOPED]"; } diff --git a/src/V3Param.cpp b/src/V3Param.cpp index 268029b5e..1de149e8b 100644 --- a/src/V3Param.cpp +++ b/src/V3Param.cpp @@ -239,8 +239,10 @@ class ParamProcessor final { // AstGenFor::user2() // bool True if processed // AstVar::user2() // bool True if constant propagated // AstCell::user2p() // string* Generate portion of hierarchical name + // AstNodeModule:user4p() // AstNodeModule* Parametrized copy with default parameters const VNUser2InUse m_inuser2; const VNUser3InUse m_inuser3; + const VNUser4InUse m_inuser4; // User1 used by constant function simulations // TYPES @@ -1062,10 +1064,12 @@ class ParamProcessor final { ifaceRefRefs /*ref*/); // Default params are resolved as overrides + bool defaultsResolved = false; if (!any_overrides) { for (AstPin* pinp = paramsp; pinp; pinp = VN_AS(pinp->nextp(), Pin)) { if (pinp->modPTypep()) { any_overrides = true; + defaultsResolved = true; break; } } @@ -1106,6 +1110,7 @@ class ParamProcessor final { UINFO(8, " Done with " << modInfop->m_modp); newModp = modInfop->m_modp; } + if (defaultsResolved) { srcModp->user4p(newModp); } for (auto* stmtp = newModp->stmtsp(); stmtp; stmtp = stmtp->nextp()) { if (AstParamTypeDType* dtypep = VN_CAST(stmtp, ParamTypeDType)) { @@ -1774,6 +1779,43 @@ public: // Mark classes which cannot be removed because they are still referenced ClassRefUnlinkerVisitor classUnlinkerVisitor{netlistp}; + netlistp->foreach([](AstNodeFTaskRef* ftaskrefp) { + AstNodeFTask* ftaskp = ftaskrefp->taskp(); + if (!ftaskp || !ftaskp->classMethod()) return; + string funcName = ftaskp->name(); + for (AstNode* backp = ftaskrefp->backp(); backp; backp = backp->backp()) { + if (VN_IS(backp, Class)) { + if (backp == ftaskrefp->classOrPackagep()) + return; // task is in the same class as reference + break; + } + } + AstClass* classp = nullptr; + for (AstNode* backp = ftaskp->backp(); backp; backp = backp->backp()) { + if (VN_IS(backp, Class)) { + classp = VN_AS(backp, Class); + break; + } + } + UASSERT_OBJ(classp, ftaskrefp, "Class method has no class above it"); + if (classp->user3p()) return; // will not get removed, no need to relink + AstClass* parametrizedClassp = VN_CAST(classp->user4p(), Class); + if (!parametrizedClassp) return; + AstNodeFTask* newFuncp = nullptr; + parametrizedClassp->exists([&newFuncp, funcName](AstNodeFTask* ftaskp) { + if (ftaskp->name() == funcName) { + newFuncp = ftaskp; + return true; + } + return false; + }); + if (newFuncp) { + // v3error(ftaskp <<"->" << newFuncp); + ftaskrefp->taskp(newFuncp); + ftaskrefp->classOrPackagep(parametrizedClassp); + } + }); + relinkDots(); resortNetlistModules(netlistp); diff --git a/test_regress/t/t_class_param_super.py b/test_regress/t/t_class_param_super.py new file mode 100755 index 000000000..319c0ff4a --- /dev/null +++ b/test_regress/t/t_class_param_super.py @@ -0,0 +1,16 @@ +#!/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('vlt') + +test.compile() + +test.passes() diff --git a/test_regress/t/t_class_param_super.v b/test_regress/t/t_class_param_super.v new file mode 100644 index 000000000..a61004533 --- /dev/null +++ b/test_regress/t/t_class_param_super.v @@ -0,0 +1,18 @@ +// 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 base #( + type T = int +); + function void fbase(); + endfunction +endclass + +class ext extends base; + function fext(); + super.fbase(); + endfunction +endclass