Fix class-in-class extends with parameters (#6773).

This commit is contained in:
Wilson Snyder 2025-12-07 13:38:25 -05:00
parent 4b02e32314
commit ba9d6df20c
4 changed files with 141 additions and 4 deletions

View File

@ -72,6 +72,7 @@ Verilator 5.043 devel
* Fix `--prof-exec` using `--lib-create`. [Geza Lore]
* Fix fork scheduling semantics (#6730). [Artur Bieniek, Antmicro Ltd.]
* Fix internal fault when cross-class calling with DPI (#6735) (#6742). [Matthew Ballance]
* Fix class-in-class extends with parameters (#6773).
Verilator 5.042 2025-11-02

View File

@ -4580,6 +4580,15 @@ class LinkDotResolveVisitor final : public VNVisitor {
nodep->taskp(randFuncp);
m_curSymp = m_statep->insertBlock(m_curSymp, nodep->name(), randFuncp, m_modp);
}
if (m_insideClassExtParam) {
// The reference may point to a method declared in a super class, which is proved
// by a parameter. In such a case, it can't be linked at the first stage.
// Must not do any linking, because e.g. might find an extends of an upper class
// because the current class (under parent) isn't yet importing it's extended class
// symbols
return;
}
VSymEnt* const foundp
= m_statep->findSymPrefixed(dotSymp, nodep->name(), baddot, first);
AstNodeFTask* const taskp
@ -4593,10 +4602,6 @@ class LinkDotResolveVisitor final : public VNVisitor {
nodep->taskp(taskp);
nodep->classOrPackagep(foundp->classOrPackagep());
UINFO(7, indent() << "Resolved " << nodep); // Also prints taskp
} else if (m_insideClassExtParam) {
// The reference may point to a method declared in a super class, which is proved
// by a parameter. In such a case, it can't be linked at the first stage.
return;
} else {
// Note ParseRef has similar error handling/message output
UINFO(7, indent() << " ErrFtask curSymp=se" << cvtToHex(m_curSymp)

View File

@ -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(verilator_flags2=['--binary'])
test.execute()
test.passes()

View File

@ -0,0 +1,113 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2025 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
package uvm_pkg;
typedef class uvm_root;
virtual class uvm_coreservice_t;
pure virtual function uvm_root get_root();
static function uvm_coreservice_t get();
return null;
endfunction
endclass
class uvm_default_coreservice_t extends uvm_coreservice_t;
virtual function uvm_root get_root();
return uvm_root::m_uvm_get_root();
endfunction
endclass
virtual class uvm_object;
endclass
class uvm_report_object extends uvm_object;
// Note there's no 'virtual' on this function
function uvm_report_object uvm_get_report_object(); // Wrong target
return null;
endfunction
endclass
class uvm_root extends uvm_report_object;
static function uvm_root m_uvm_get_root();
uvm_root top;
top = new();
return null;
endfunction
endclass
virtual class uvm_process_guard_base extends uvm_object;
pure virtual function void do_trigger();
// Removing m_process member works around the issue
protected process m_target_process;
function new();
m_target_process = process::self();
endfunction
function void m_process_guard(uvm_process_guard_base guard);
// Removing fork/join works around the issue
fork
begin
if (guard.m_target_process != null) begin
guard.do_trigger();
end
end
join_none
endfunction
endclass
class uvm_process_guard #(
type T = int
) extends uvm_process_guard_base;
protected T m_context;
function void do_trigger();
m_context.process_guard_triggered(this);
endfunction
endclass
class uvm_sequence_item;
virtual function uvm_report_object uvm_get_report_object(); // Correct target
uvm_coreservice_t cs = uvm_coreservice_t::get();
return cs.get_root();
endfunction
endclass
virtual class uvm_sequence_base extends uvm_sequence_item;
typedef uvm_process_guard#(uvm_sequence_base) m_guard_t;
function void process_guard_triggered(m_guard_t guard);
uvm_pkg::uvm_report_object _local_report_object_arg_;
_local_report_object_arg_ = uvm_get_report_object();
// ^ calls uvm_sequence_base->virtual uvm_sequence_item::uvm_get_report_object()
endfunction
endclass
virtual class uvm_sequence #(
type RSP = int
) extends uvm_sequence_base;
endclass
endpackage
module t;
import uvm_pkg::*;
class Cls extends uvm_report_object;
class transaction_sequence extends uvm_sequence #(uvm_object);
virtual task body();
uvm_pkg::uvm_report_object _local_report_object_arg_;
_local_report_object_arg_ = uvm_get_report_object();
// ^- calls transaction_sequence->uvm_sequence
// ->uvm_sequence_base->virtual uvm_sequence_item::uvm_get_report_object();
endtask
endclass
endclass
initial begin
Cls c = new();
$finish;
end
endmodule