From 1baa832efc484118c9238d102ab05e0d5a8e9715 Mon Sep 17 00:00:00 2001 From: Geza Lore Date: Mon, 8 Dec 2025 18:42:52 +0000 Subject: [PATCH] Fix reordering of function body inlined on RHS of <= NBA (#6780) --- src/V3Split.cpp | 10 +++- test_regress/t/t_alw_reorder_inlined_func.py | 18 ++++++ test_regress/t/t_alw_reorder_inlined_func.v | 58 ++++++++++++++++++++ 3 files changed, 84 insertions(+), 2 deletions(-) create mode 100755 test_regress/t/t_alw_reorder_inlined_func.py create mode 100644 test_regress/t/t_alw_reorder_inlined_func.v diff --git a/src/V3Split.cpp b/src/V3Split.cpp index 6c986a2eb..f323c32a4 100644 --- a/src/V3Split.cpp +++ b/src/V3Split.cpp @@ -340,11 +340,17 @@ protected: // We don't do AstLoop, due to the standard question of what is before vs. after + void visit(AstExprStmt* nodep) override { + VL_RESTORER(m_inDly); + m_inDly = false; + iterateChildren(nodep); + } void visit(AstAssignDly* nodep) override { + UINFO(4, " ASSIGNDLY " << nodep); + iterate(nodep->rhsp()); VL_RESTORER(m_inDly); m_inDly = true; - UINFO(4, " ASSIGNDLY " << nodep); - iterateChildren(nodep); + iterate(nodep->lhsp()); } void visit(AstVarRef* nodep) override { if (!m_stmtStackps.empty()) { diff --git a/test_regress/t/t_alw_reorder_inlined_func.py b/test_regress/t/t_alw_reorder_inlined_func.py new file mode 100755 index 000000000..f67fb32be --- /dev/null +++ b/test_regress/t/t_alw_reorder_inlined_func.py @@ -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('vlt_all') + +test.compile(verilator_flags2=["--binary"]) + +test.execute() + +test.passes() diff --git a/test_regress/t/t_alw_reorder_inlined_func.v b/test_regress/t/t_alw_reorder_inlined_func.v new file mode 100644 index 000000000..da8fc94cd --- /dev/null +++ b/test_regress/t/t_alw_reorder_inlined_func.v @@ -0,0 +1,58 @@ +// 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 + +`define stop $stop +`define check(got ,exp) do if ((got) !== (exp)) begin $write("%%Error: %s:%0d: $time=%0t got='h%x exp='h%x\n", `__FILE__,`__LINE__, $time, (got), (exp)); `stop; end while(0) + +module t; + + logic clk = 0; + always #5 clk = ~clk; + + int cyc = 0; + always @(posedge clk) cyc <= cyc + 1; + + // Constant 1 set in initial block, but not known at compile time + logic enable = 1'b0; + + int array [32]; + + function automatic int get(logic en, logic [4:0] idx); + if (en) begin // Always taken, but need the 'if' to show bug + int tmp; + idx = ~idx; + tmp = array[~idx]; + return tmp; + end else begin + return 0; + end + endfunction + + int q; + always @(posedge clk) begin + // Function inlined on RHS or NBA used to have its body reordered as if + // assignments in the body were NBAs themselves. + q <= cyc == 0 ? 0 : get(enable, 5'(cyc)); + end + + initial begin + enable = 1'b1; + for (int n = 0; n < 32; ++n) begin + array[n] = 100 + n; + end + + repeat (100) begin + @(posedge clk); + #1; + $display("$08t %3d %3d", $time, cyc - 1, q); + `check(q, cyc == 1 ? 0 : 100 + (cyc - 1) % 32); + end + + $write("*-* All Finished *-*\n"); + $finish; + end + +endmodule