From c2d65c2e137bf3a561a76ffca8f9a56f6c4ae079 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Thu, 5 Mar 2026 18:03:58 -0500 Subject: [PATCH] * Fix class extend references between queues (#7195). Fixes #7195. --- Changes | 1 + include/verilated_types.h | 26 ++++++++++++++ test_regress/t/t_queue_inherit_call.py | 18 ++++++++++ test_regress/t/t_queue_inherit_call.v | 47 ++++++++++++++++++++++++++ 4 files changed, 92 insertions(+) create mode 100755 test_regress/t/t_queue_inherit_call.py create mode 100644 test_regress/t/t_queue_inherit_call.v diff --git a/Changes b/Changes index 5245b5f68..3473599e2 100644 --- a/Changes +++ b/Changes @@ -40,6 +40,7 @@ Verilator 5.047 devel * Fix eliminating assignments to DPI-read variables (#7158). [Geza Lore, Testorrent USA, Inc.] * Fix std::randomize() in static function with static class members (#7167) (#7169). [Yilou Wang] * Fix recursive constant function in $unit scope (#7173) (#7174). +* Fix class extend references between queues (#7195). * Fix library/hier_block tracing when top name is empty (#7200). [Geza Lore, Testorrent USA, Inc.] diff --git a/include/verilated_types.h b/include/verilated_types.h index b0ef73039..07c910343 100644 --- a/include/verilated_types.h +++ b/include/verilated_types.h @@ -428,6 +428,9 @@ std::string VL_TO_STRING(const VlWide& obj) { return VL_TO_STRING_W(N_Words, obj.data()); } +template +class VlClassRef; + //=================================================================== // Verilog queue and dynamic array container // There are no multithreaded locks on this; the base variable must @@ -438,6 +441,9 @@ std::string VL_TO_STRING(const VlWide& obj) { template class VlQueue final { private: + template + friend class VlQueue; + // TYPES using Deque = std::deque; @@ -460,6 +466,13 @@ public: VlQueue(VlQueue&&) = default; VlQueue& operator=(const VlQueue&) = default; VlQueue& operator=(VlQueue&&) = default; + + // Template constuctors that construct from containers holding sub-classes + template + inline VlQueue(const VlQueue>&); + template + inline VlQueue(VlQueue>&&); + bool operator==(const VlQueue& rhs) const { return m_deque == rhs.m_deque; } bool operator!=(const VlQueue& rhs) const { return m_deque != rhs.m_deque; } bool operator<(const VlQueue& rhs) const { @@ -2151,4 +2164,17 @@ inline T VL_NULL_CHECK(T t, const char* filename, int linenum) { //====================================================================== +template +template +VlQueue::VlQueue(const VlQueue>& that) + : m_deque{that.m_deque.begin(), that.m_deque.end()} + , m_defaultValue{that.m_defaultValue} {} + +template +template +VlQueue::VlQueue(VlQueue>&& that) + : m_deque{std::make_move_iterator(that.m_deque.begin()), + std::make_move_iterator(that.m_deque.end())} + , m_defaultValue{std::move(that.m_defaultValue)} {} + #endif // Guard diff --git a/test_regress/t/t_queue_inherit_call.py b/test_regress/t/t_queue_inherit_call.py new file mode 100755 index 000000000..8a938befd --- /dev/null +++ b/test_regress/t/t_queue_inherit_call.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# 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-FileCopyrightText: 2026 Wilson Snyder +# 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_queue_inherit_call.v b/test_regress/t/t_queue_inherit_call.v new file mode 100644 index 000000000..e43f5dc1d --- /dev/null +++ b/test_regress/t/t_queue_inherit_call.v @@ -0,0 +1,47 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain. +// SPDX-FileCopyrightText: 2026 Wilson Snyder +// SPDX-License-Identifier: CC0-1.0 + +// Issue #7195 +module t; + + class uvm_reg; + endclass + + class reg_slave_DATA extends uvm_reg; + endclass + + class reg_slave_TABLES extends uvm_reg; + function uvm_reg create(string name = ""); + reg_slave_TABLES tmp; + tmp = new; + return tmp; + endfunction + endclass + + class reg_block_slave; + reg_slave_DATA DATA; + rand reg_slave_TABLES TABLES[4]; + + virtual function void build(); + foreach (TABLES[i]) + TABLES[i] = new; + this.configure(TABLES); // Issue was here + endfunction + + function void configure(uvm_reg reg_a[]); + foreach (reg_a[i]) + $display("%p", reg_a[i]); + endfunction + endclass + + initial begin + reg_block_slave c; + c = new; + c.build; + $finish; + end + +endmodule