diff --git a/Changes b/Changes index 04727c088a..5b2c2f8ea2 100644 --- a/Changes +++ b/Changes @@ -50,6 +50,7 @@ Verilator 5.015 devel * Fix error on enum with VARHIDDEN of cell (#4482). [Michail Rontionov] * Fix lint of case statements with enum and wildcard bits (#4464) (#4487). [Anthony Donlon] * Fix reference to extended class in parameterized class (#4466). +* Fix recursive display causing segfault (#4480). [Kuoping Hsu] * Fix the error message when the type of ref argument is wrong (#4490). [Ryszard Rozak, Antmicro Ltd] * Fix display %x formatting of real. * Fix mis-warning on #() in classes' own functions. diff --git a/src/V3EmitCFunc.cpp b/src/V3EmitCFunc.cpp index 8fd63dcf8a..644aa9b782 100644 --- a/src/V3EmitCFunc.cpp +++ b/src/V3EmitCFunc.cpp @@ -314,6 +314,7 @@ void EmitCFunc::displayNode(AstNode* nodep, AstScopeName* scopenamep, const stri // Convert Verilog display to C printf formats // "%0t" becomes "%d" + VL_RESTORER(m_emitDispState); m_emitDispState.clear(); string vfmt; string::const_iterator pos = vformat.begin(); diff --git a/test_regress/t/t_display_recurse.out b/test_regress/t/t_display_recurse.out new file mode 100644 index 0000000000..a06cc8e4cb --- /dev/null +++ b/test_regress/t/t_display_recurse.out @@ -0,0 +1,9 @@ + 0: 0000dead + 4: 0001dead + 8: 0002dead + 12: 0003dead + 16: 0004dead + 20: 0005dead + 24: 0006dead + 28: 0007dead +*-* All Finished *-* diff --git a/test_regress/t/t_display_recurse.pl b/test_regress/t/t_display_recurse.pl new file mode 100755 index 0000000000..6e4e9e2315 --- /dev/null +++ b/test_regress/t/t_display_recurse.pl @@ -0,0 +1,22 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2023 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 + +scenarios(simulator => 1); + +compile( + ); + +execute( + expect_filename => $Self->{golden_filename}, + check_finished => 1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_display_recurse.v b/test_regress/t/t_display_recurse.v new file mode 100644 index 0000000000..877792b0f4 --- /dev/null +++ b/test_regress/t/t_display_recurse.v @@ -0,0 +1,52 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2023 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t(/*AUTOARG*/ + // Inputs + clk + ); + input clk; + + integer i; + integer count = 'd0; + + always @(posedge clk) begin + count <= count + 1; + if (count == 10) begin + for(i=0; i<30; i=i+4) begin + // See issue #4480, verilator may inline getb() which has another display inside it + $display("%d: %02x%02x%02x%02x", i, getb(i+3), getb(i+2), getb(i+1), getb(i)); + end + end + if (count == 11) begin + $write("*-* All Finished *-*\n"); + $finish; + end + end + + localparam SIZE = 64*1024; + localparam ADDRW = $clog2(SIZE/4); + reg [31: 0] ram [(SIZE/4)-1: 0]; + + function [7:0] getb; + input [31:0] address; + if (address[31:ADDRW+2] != 0) begin + $display("Address out of range"); + end + case(address[1:0]) + 0: getb = ram[address[ADDRW+1: 2]][8*0+7:8*0]; + 1: getb = ram[address[ADDRW+1: 2]][8*1+7:8*1]; + 2: getb = ram[address[ADDRW+1: 2]][8*2+7:8*2]; + 3: getb = ram[address[ADDRW+1: 2]][8*3+7:8*3]; + endcase + endfunction + + initial begin + for (i=0; i