From d2de6b42cf3bd7fef44df3c05dd133dcd873f86a Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Fri, 24 Jul 2026 09:26:01 -0400 Subject: [PATCH] * Fix $fgets being mis-optimized away (#7976). Fixes #7976. --- Changes | 1 + src/V3AstNodeExpr.h | 1 + test_regress/t/t_sys_fgets_loop.dat | 11 ++++++ test_regress/t/t_sys_fgets_loop.py | 18 +++++++++ test_regress/t/t_sys_fgets_loop.v | 57 +++++++++++++++++++++++++++++ 5 files changed, 88 insertions(+) create mode 100644 test_regress/t/t_sys_fgets_loop.dat create mode 100755 test_regress/t/t_sys_fgets_loop.py create mode 100644 test_regress/t/t_sys_fgets_loop.v diff --git a/Changes b/Changes index 354a0dab6..31faa4155 100644 --- a/Changes +++ b/Changes @@ -66,6 +66,7 @@ Verilator 5.051 devel * Fix lost writes when select width exceeds variable width (#7975). [Bartosz Skorowski] * Fix variable scope in unique on dynamic array (#7981). [Kornel Uriasz, Antmicro Ltd.] * Fix table optimization causing not contextually convertible to bool error (#7983). [Jakub Michalski] +* Fix $fgets being mis-optimized away (#7976). [G-A. Kamendje] Verilator 5.050 2026-07-01 diff --git a/src/V3AstNodeExpr.h b/src/V3AstNodeExpr.h index 67a4806b5..46d4c13f9 100644 --- a/src/V3AstNodeExpr.h +++ b/src/V3AstNodeExpr.h @@ -3259,6 +3259,7 @@ public: bool sizeMattersRhs() const override { return false; } bool isSystemFunc() const override { return true; } int instrCount() const override { return widthInstrs() * 64; } + bool isPure() override { return false; } // SPECIAL: $display has 'visual' ordering }; class AstFUngetC final : public AstNodeBiop { public: diff --git a/test_regress/t/t_sys_fgets_loop.dat b/test_regress/t/t_sys_fgets_loop.dat new file mode 100644 index 000000000..0f366c68b --- /dev/null +++ b/test_regress/t/t_sys_fgets_loop.dat @@ -0,0 +1,11 @@ +This is line 0 in test file +This is line 1 in test file +This is line 2 in test file +This is line 3 in test file +This is line 4 in test file +This is line 5 in test file +This is line 6 in test file +This is line 7 in test file +This is line 8 in test file +This is line 8 in test file +This is line 9 in test file diff --git a/test_regress/t/t_sys_fgets_loop.py b/test_regress/t/t_sys_fgets_loop.py new file mode 100755 index 000000000..46d1fe4c0 --- /dev/null +++ b/test_regress/t/t_sys_fgets_loop.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(verilator_flags2=['--binary']) + +test.execute() + +test.passes() diff --git a/test_regress/t/t_sys_fgets_loop.v b/test_regress/t/t_sys_fgets_loop.v new file mode 100644 index 000000000..c44bb300f --- /dev/null +++ b/test_regress/t/t_sys_fgets_loop.v @@ -0,0 +1,57 @@ +// 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 + +module t; + + task test_read(input integer f, output string l); + automatic string line; + automatic string buffer = ""; + automatic integer code; + + if (f == 0) $stop; + while (1) begin + code = $fgets(line, f); + // Uncomment for issue #7976 workaround + // $display("code %d => content: %s", code, line); + buffer = {buffer, line}; + if (line == "") begin + break; + end + end + l = buffer; + endtask + + task test_eof_tsk; + automatic integer fd; + automatic string test_file_name = "t/t_sys_fgets_loop.dat"; + automatic string output_line; + // Open files + fd = $fopen(test_file_name, "r"); + if (fd == 0) begin + $display("ERROR ould not open file '%s' for reading aborting", test_file_name); + $fatal(0); + end + + while (!$feof( + fd + )) begin + test_read(fd, output_line); + end + $fclose(fd); + endtask + + initial begin + test_eof_tsk; + end + + initial begin + #100; + + $write("*-* All Finished *-*\n"); + $finish; + end + +endmodule