From 3fd0948cf2aa475e27be052c91e772075d94e6d0 Mon Sep 17 00:00:00 2001 From: Igor Zaworski Date: Tue, 29 Sep 2026 17:45:28 +0200 Subject: [PATCH] Fix of queue pop return value access (#8529) Fixes #8511, #8380 repair Signed-off-by: Igor Zaworski --- src/V3AstNodes.cpp | 12 ++- test_regress/t/t_queue_access.py | 18 +++++ test_regress/t/t_queue_access.v | 129 +++++++++++++++++++++++++++++++ 3 files changed, 157 insertions(+), 2 deletions(-) create mode 100755 test_regress/t/t_queue_access.py create mode 100644 test_regress/t/t_queue_access.v diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index f8ccddc72..2e5ce7a8d 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -2484,8 +2484,16 @@ const AstNodeExpr* AstNodeExpr::getVAccessTargetRecurse() const { return anodep->lhsp()->getVAccessTargetRecurse(); } if (const AstCMethodHard* const anodep = VN_CAST(this, CMethodHard)) { - // Used for things like Queue/AssocArray/DynArray - return anodep->fromp()->getVAccessTargetRecurse(); + switch (anodep->method()) { + case VCMethod::ARRAY_AT: + case VCMethod::ARRAY_AT_BACK: + case VCMethod::ARRAY_AT_WRITE: + case VCMethod::DYN_AT_WRITE_APPEND: + case VCMethod::DYN_AT_WRITE_APPEND_BACK: + // Used for things like Queue/AssocArray/DynArray + return anodep->fromp()->getVAccessTargetRecurse(); + default: break; + } } return nullptr; // nothing found } diff --git a/test_regress/t/t_queue_access.py b/test_regress/t/t_queue_access.py new file mode 100755 index 000000000..8a938befd --- /dev/null +++ b/test_regress/t/t_queue_access.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_access.v b/test_regress/t/t_queue_access.v new file mode 100644 index 000000000..2d2f69a8f --- /dev/null +++ b/test_regress/t/t_queue_access.v @@ -0,0 +1,129 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain. +// SPDX-FileCopyrightText: 2026 Antmicro +// SPDX-License-Identifier: CC0-1.0 + +// verilog_format: off +`define stop $stop +`define checkd(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0); +// verilog_format: on + +class Foo; + int queue[$]; + Foo fooQ[$]; + int q; + function void modify_q(); + q = 10; + endfunction +endclass + +module t; + int queue2[$]; + Foo fooQ2[$]; + int q[$]; + bit [3:0] nib; + bit [63:0] q64[$]; + bit [63:0] w; + + initial begin + static Foo foo = new; + + `checkd(foo.queue.size(), 0); + `checkd(queue2.size(), 0); + + foo.queue.push_back(7); + `checkd(foo.queue.size(), 1); + `checkd(foo.queue[0], 7); + `checkd(queue2.size(), 0); + + queue2.push_back(foo.queue.pop_front()); + `checkd(foo.queue.size(), 0); + `checkd(queue2.size(), 1); + `checkd(queue2[0], 7); + + foo.queue.push_back(queue2.pop_back()); + `checkd(foo.queue.size(), 1); + `checkd(foo.queue[0], 7); + `checkd(queue2.size(), 0); + + `checkd(foo.fooQ.size(), 0); + `checkd(fooQ2.size(), 0); + + foo.fooQ.push_back(foo); + `checkd(foo.fooQ.size(), 1); + if (foo.fooQ[0] != foo) $stop; + `checkd(fooQ2.size(), 0); + + `checkd(foo.fooQ[0].queue.size(), 1); + `checkd(foo.fooQ[0].queue[0], 7); + + `checkd(foo.fooQ[0].queue.pop_front(), 7); + `checkd(foo.fooQ[0].queue.size(), 0); + + fooQ2.push_back(foo.fooQ.pop_back()); + `checkd(foo.fooQ.size(), 0); + `checkd(fooQ2.size(), 1); + if (fooQ2[0] != foo) $stop; + + foo.fooQ.push_back(fooQ2.pop_back()); + `checkd(foo.fooQ.size(), 1); + if (foo.fooQ[0] != foo) $stop; + `checkd(fooQ2.size(), 0); + + `checkd(foo.fooQ[0].q, 0); + foo.fooQ[0].modify_q(); + `checkd(foo.fooQ[0].q, 10); + foo.fooQ[0].q = 14; + `checkd(foo.fooQ[0].q, 14); + + foo.fooQ[0].queue.push_back(7); + `checkd(foo.fooQ[0].queue.size(), 1); + `checkd(foo.fooQ[0].queue[0], 7); + `checkd(queue2.size(), 0); + + queue2.push_back(foo.fooQ[0].queue.pop_front()); + `checkd(foo.fooQ[0].queue.size(), 0); + `checkd(queue2.size(), 1); + `checkd(queue2[0], 7); + + foo.fooQ[0].queue.push_back(queue2.pop_back()); + `checkd(foo.fooQ[0].queue.size(), 1); + `checkd(foo.fooQ[0].queue[0], 7); + `checkd(queue2.size(), 0); + + foo.fooQ[0] = new; + if (foo.fooQ[0] == foo) $stop; + + q.push_back(32'hA5); + nib = q.pop_front()[3:0] ^ 4'hF; + `checkd(nib, 4'hA); + `checkd(q.size(), 0); + + q.push_back(32'hA5); + `checkd((q.pop_front()[3:0] === 4'h5), 1'b1); + `checkd(q.size(), 0); + + q.push_back(5); + q.push_back(5); + q64.push_back({q.pop_front(), q.pop_front()}); + `checkd(q64.size(), 1); + `checkd(q64[0], 64'h5_0000_0005); + `checkd(q.size(), 0); + + q.push_back(32'hD); + q64.push_back({q.pop_front(), 32'h1}); + `checkd(q64.size(), 2); + `checkd(q64[1], 64'hD_0000_0001); + `checkd(q.size(), 0); + + q.push_back(9); + q.push_back(9); + w = {q.pop_front(), q.pop_front()}; + `checkd(w, 64'h9_0000_0009); + `checkd(q.size(), 0); + + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule