Fix relinking super functions to parametrized class (#6431) (#6438)

Signed-off-by: Artur Bieniek <abieniek@internships.antmicro.com>
This commit is contained in:
Artur Bieniek 2025-09-17 14:07:04 +02:00 committed by GitHub
parent 64dbd4abcc
commit 3c8b8b65d0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 77 additions and 1 deletions

View File

@ -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]";
}

View File

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

View File

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

View File

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