From d8f1e1113a35bc47b3e4ff39e024b3a77ba3186a Mon Sep 17 00:00:00 2001 From: Ryszard Rozak Date: Thu, 31 Jul 2025 12:48:37 +0200 Subject: [PATCH] Fix error when force assignment is used with ref function args (#6244) --- src/V3Force.cpp | 9 ++++--- test_regress/t/t_force_readwrite.py | 18 +++++++++++++ test_regress/t/t_force_readwrite.v | 25 +++++++++++++++++ test_regress/t/t_force_readwrite_unsup.out | 8 ++++++ test_regress/t/t_force_readwrite_unsup.py | 16 +++++++++++ test_regress/t/t_force_readwrite_unsup.v | 31 ++++++++++++++++++++++ 6 files changed, 103 insertions(+), 4 deletions(-) create mode 100755 test_regress/t/t_force_readwrite.py create mode 100644 test_regress/t/t_force_readwrite.v create mode 100644 test_regress/t/t_force_readwrite_unsup.out create mode 100755 test_regress/t/t_force_readwrite_unsup.py create mode 100644 test_regress/t/t_force_readwrite_unsup.v diff --git a/src/V3Force.cpp b/src/V3Force.cpp index e22804fae..a09e3288d 100644 --- a/src/V3Force.cpp +++ b/src/V3Force.cpp @@ -364,9 +364,6 @@ class ForceReplaceVisitor final : public VNVisitor { // Replace VarRef from forced LHS with rdVscp. if (ForceState::ForceComponentsVarScope* const fcp = m_state.tryGetForceComponents(nodep)) { - FileLine* const flp = nodep->fileline(); - AstVarRef* const origp = new AstVarRef{flp, nodep->varScopep(), VAccess::READ}; - ForceState::markNonReplaceable(origp); nodep->varp(fcp->m_rdVscp->varp()); nodep->varScopep(fcp->m_rdVscp); } @@ -398,7 +395,11 @@ class ForceReplaceVisitor final : public VNVisitor { break; } default: - nodep->v3error("Unsupported: Signals used via read-write reference cannot be forced"); + if (!m_inLogic) return; + if (m_state.tryGetForceComponents(nodep) || ForceState::getValVscp(nodep)) { + nodep->v3error( + "Unsupported: Signals used via read-write reference cannot be forced"); + } break; } } diff --git a/test_regress/t/t_force_readwrite.py b/test_regress/t/t_force_readwrite.py new file mode 100755 index 000000000..4ff4dfaa5 --- /dev/null +++ b/test_regress/t/t_force_readwrite.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') + +test.compile(verilator_flags2=["--exe", "--main", "--timing"]) + +test.execute() + +test.passes() diff --git a/test_regress/t/t_force_readwrite.v b/test_regress/t/t_force_readwrite.v new file mode 100644 index 000000000..202bfb408 --- /dev/null +++ b/test_regress/t/t_force_readwrite.v @@ -0,0 +1,25 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2025 by Antmicro. +// SPDX-License-Identifier: CC0-1.0 + +class Cls; + task take_ref(ref logic s); + endtask +endclass + +module t; + logic a; + logic b = 1; + logic c; + Cls cls = new; + + initial begin + force a = b; + cls.take_ref(c); + $write("*-* All Finished *-*\n"); + $finish; + end + +endmodule diff --git a/test_regress/t/t_force_readwrite_unsup.out b/test_regress/t/t_force_readwrite_unsup.out new file mode 100644 index 000000000..97d7ed581 --- /dev/null +++ b/test_regress/t/t_force_readwrite_unsup.out @@ -0,0 +1,8 @@ +%Error: t/t_force_readwrite_unsup.v:25:18: Unsupported: Signals used via read-write reference cannot be forced + 25 | cls.take_ref(a); + | ^ + ... See the manual at https://verilator.org/verilator_doc.html?v=latest for more assistance. +%Error: t/t_force_readwrite_unsup.v:26:18: Unsupported: Signals used via read-write reference cannot be forced + 26 | cls.take_ref(b); + | ^ +%Error: Exiting due to diff --git a/test_regress/t/t_force_readwrite_unsup.py b/test_regress/t/t_force_readwrite_unsup.py new file mode 100755 index 000000000..44c75cc0f --- /dev/null +++ b/test_regress/t/t_force_readwrite_unsup.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 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.lint(verilator_flags2=['--timing'], fails=True, expect_filename=test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_force_readwrite_unsup.v b/test_regress/t/t_force_readwrite_unsup.v new file mode 100644 index 000000000..e3f8074b0 --- /dev/null +++ b/test_regress/t/t_force_readwrite_unsup.v @@ -0,0 +1,31 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2025 by Antmicro. +// SPDX-License-Identifier: CC0-1.0 + +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2025 by Antmicro. +// SPDX-License-Identifier: CC0-1.0 + +class Cls; + task take_ref(ref logic s); + endtask +endclass + +module t; + logic a; + logic b = 1; + Cls cls = new; + + initial begin + force a = b; + cls.take_ref(a); + cls.take_ref(b); + $write("*-* All Finished *-*\n"); + $finish; + end + +endmodule