Fix class-in-class extends with parameters (#6773).
This commit is contained in:
parent
4b02e32314
commit
ba9d6df20c
1
Changes
1
Changes
|
|
@ -72,6 +72,7 @@ Verilator 5.043 devel
|
||||||
* Fix `--prof-exec` using `--lib-create`. [Geza Lore]
|
* Fix `--prof-exec` using `--lib-create`. [Geza Lore]
|
||||||
* Fix fork scheduling semantics (#6730). [Artur Bieniek, Antmicro Ltd.]
|
* Fix fork scheduling semantics (#6730). [Artur Bieniek, Antmicro Ltd.]
|
||||||
* Fix internal fault when cross-class calling with DPI (#6735) (#6742). [Matthew Ballance]
|
* 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
|
Verilator 5.042 2025-11-02
|
||||||
|
|
|
||||||
|
|
@ -4580,6 +4580,15 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
||||||
nodep->taskp(randFuncp);
|
nodep->taskp(randFuncp);
|
||||||
m_curSymp = m_statep->insertBlock(m_curSymp, nodep->name(), randFuncp, m_modp);
|
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
|
VSymEnt* const foundp
|
||||||
= m_statep->findSymPrefixed(dotSymp, nodep->name(), baddot, first);
|
= m_statep->findSymPrefixed(dotSymp, nodep->name(), baddot, first);
|
||||||
AstNodeFTask* const taskp
|
AstNodeFTask* const taskp
|
||||||
|
|
@ -4593,10 +4602,6 @@ class LinkDotResolveVisitor final : public VNVisitor {
|
||||||
nodep->taskp(taskp);
|
nodep->taskp(taskp);
|
||||||
nodep->classOrPackagep(foundp->classOrPackagep());
|
nodep->classOrPackagep(foundp->classOrPackagep());
|
||||||
UINFO(7, indent() << "Resolved " << nodep); // Also prints taskp
|
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 {
|
} else {
|
||||||
// Note ParseRef has similar error handling/message output
|
// Note ParseRef has similar error handling/message output
|
||||||
UINFO(7, indent() << " ErrFtask curSymp=se" << cvtToHex(m_curSymp)
|
UINFO(7, indent() << " ErrFtask curSymp=se" << cvtToHex(m_curSymp)
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
@ -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
|
||||||
Loading…
Reference in New Issue