Support `foreach` with nested dots (#6991)

Signed-off-by: Krzysztof Bieganski <kbieganski@antmicro.com>
This commit is contained in:
Krzysztof Bieganski 2026-02-03 14:44:18 +01:00 committed by GitHub
parent f9c76e84a6
commit ad85d89817
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 55 additions and 2 deletions

View File

@ -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);
}
}

View File

@ -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()

View File

@ -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