diff --git a/Changes b/Changes index 89f9229cc..6ae1ec00b 100644 --- a/Changes +++ b/Changes @@ -83,6 +83,7 @@ Verilator 5.035 devel * Fix LATCH warning for automatic variables (#5918). [Yutetsu TAKATSUKASA] * Fix %% on elaboration severity tasks (#5922). [Ethan Sifferman] * Fix port default values with `--coverage-line` creating `0=0` (#5920). [Drew Ranck] +* Fix vlSelf error on fork repeats (#5927). [Drew Ranck] * Fix missing C++ regeneration when Verilog files are updated (#5934). [Zhouyi Shen] * Fix stream expressions (#5938). [Ryszard Rozak, Antmicro Ltd.] * Fix packed selection using over 32-bit index (#5957). diff --git a/src/V3EmitCFunc.cpp b/src/V3EmitCFunc.cpp index bbb139a2d..02ee7d1d5 100644 --- a/src/V3EmitCFunc.cpp +++ b/src/V3EmitCFunc.cpp @@ -610,9 +610,10 @@ void EmitCFunc::emitSetVarConstant(const string& assignString, AstConst* constp) void EmitCFunc::emitVarReset(AstVar* varp, bool constructing) { // 'constructing' indicates that the object was just constructed, so no need to clear it also AstNodeDType* const dtypep = varp->dtypep()->skipRefp(); + const string vlSelf = VSelfPointerText::replaceThis(m_useSelfForThis, "this->"); const string varNameProtected = (VN_IS(m_modp, Class) || varp->isFuncLocal()) ? varp->nameProtect() - : "vlSelf->" + varp->nameProtect(); + : vlSelf + varp->nameProtect(); if (varp->isIO() && m_modp->isTop() && optSystemC()) { // System C top I/O doesn't need loading, as the lower level subinst code does it.} } else if (varp->isParam()) { diff --git a/test_regress/t/t_fork_repeat_reset.py b/test_regress/t/t_fork_repeat_reset.py new file mode 100755 index 000000000..c6e56559a --- /dev/null +++ b/test_regress/t/t_fork_repeat_reset.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('simulator') + +test.compile(verilator_flags2=["--binary"]) + +test.execute() + +test.passes() diff --git a/test_regress/t/t_fork_repeat_reset.v b/test_regress/t/t_fork_repeat_reset.v new file mode 100644 index 000000000..e24b67e9a --- /dev/null +++ b/test_regress/t/t_fork_repeat_reset.v @@ -0,0 +1,60 @@ +// 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 + +module t; + + logic clock; + + initial begin + clock = '0; + forever begin + clock = #5ns ~clock; + end + end + + task static has_fork_task(input [31:0] address); + @(posedge clock); + fork + begin + repeat($urandom_range(9)) @(posedge clock); + end + join + endtask + + // Intentionally created a recursive task chain (that should be unreachable anyway): + // call_task() + // --> (unreachable) --> calls local_sub_task() + // --> calls call_task() + // --> ... + // --> (reachable) --> calls has_fork_task() done. + + task static call_task(input [31:0] address); + if (1) begin + // Workaround1: Comment this out to pass the compile. + has_fork_task(address); + end + else begin + // Workaround2: Comment this out to pass the compile + // Should be unreachable anyway. + local_sub_task(.address(address)); + end + endtask + + task static local_sub_task(input [31:0] address); + logic [63:0] req; + logic [39:0] resp; + req = '0; + call_task(.address(32'h0000_1234)); + resp = '0; + endtask + + initial begin : main + #100ns; + $write("*-* All Finished *-*\n"); + $finish; + end + +endmodule