From ad85d89817d9740fe57876810358b1132eebba34 Mon Sep 17 00:00:00 2001 From: Krzysztof Bieganski Date: Tue, 3 Feb 2026 14:44:18 +0100 Subject: [PATCH] Support `foreach` with nested dots (#6991) Signed-off-by: Krzysztof Bieganski --- src/V3LinkDot.cpp | 8 ++++++-- test_regress/t/t_foreach_nested.py | 18 +++++++++++++++++ test_regress/t/t_foreach_nested.v | 31 ++++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+), 2 deletions(-) create mode 100755 test_regress/t/t_foreach_nested.py create mode 100644 test_regress/t/t_foreach_nested.v diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index a4c98cab6..2f84b2db6 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -1851,11 +1851,15 @@ class LinkDotFindVisitor final : public VNVisitor { m_curSymp->fallbackp(VL_RESTORER_PREV(m_curSymp)); // DOT(x, SELLOOPVARS(var, loops)) -> SELLOOPVARS(DOT(x, var), loops) if (AstDot* const dotp = VN_CAST(nodep->arrayp(), Dot)) { - if (AstSelLoopVars* const loopvarsp = VN_CAST(dotp->rhsp(), SelLoopVars)) { + AstDot* dotAbovep = dotp; + while (AstDot* const dotNextp = VN_CAST(dotAbovep->rhsp(), Dot)) { + dotAbovep = dotNextp; + } + if (AstSelLoopVars* const loopvarsp = VN_CAST(dotAbovep->rhsp(), SelLoopVars)) { AstNodeExpr* const fromp = loopvarsp->fromp()->unlinkFrBack(); loopvarsp->unlinkFrBack(); dotp->replaceWith(loopvarsp); - dotp->rhsp(fromp); + dotAbovep->rhsp(fromp); loopvarsp->fromp(dotp); } } diff --git a/test_regress/t/t_foreach_nested.py b/test_regress/t/t_foreach_nested.py new file mode 100755 index 000000000..8a938befd --- /dev/null +++ b/test_regress/t/t_foreach_nested.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_foreach_nested.v b/test_regress/t/t_foreach_nested.v new file mode 100644 index 000000000..7fb67118b --- /dev/null +++ b/test_regress/t/t_foreach_nested.v @@ -0,0 +1,31 @@ +// 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 + +typedef struct { + int x[9][9]; +} Foo; + +class Bar; + Foo foo; + + function automatic void test(); + foreach(this.foo.x[i]) + foreach(this.foo.x[i][j]) + this.foo.x[i][j] = i * j; + for (int i = 0; i < 9; i++) + for (int j = 0; j < 9; j++) + if (this.foo.x[i][j] != i * j) $stop; + endfunction +endclass + +module t; + initial begin + Bar b = new; + b.test; + $write("*-* All Finished *-*\n"); + $finish; + end +endmodule