diff --git a/src/V3Unknown.cpp b/src/V3Unknown.cpp index f0e227238..e53f48743 100644 --- a/src/V3Unknown.cpp +++ b/src/V3Unknown.cpp @@ -108,6 +108,13 @@ class UnknownVisitor final : public VNVisitor { || VN_IS(prep->backp(), MemberSel) || VN_IS(prep->backp(), StructSel)) { prep = VN_AS(prep->backp(), NodeExpr); } + if (VN_IS(prep->backp(), AssignForce) || VN_IS(prep->backp(), Release)) { + // The conversion done in this function breaks force and release statements + nodep->v3warn(E_UNSUPPORTED, + "Unsupported: Force / release statement with complex select expression"); + VL_DO_DANGLING(condp->deleteTree(), condp); + return; + } FileLine* const fl = nodep->fileline(); VL_DANGLING(nodep); // Zap it so we don't use it by mistake - use prep diff --git a/test_regress/t/t_force_complex_sel_unsup.out b/test_regress/t/t_force_complex_sel_unsup.out new file mode 100644 index 000000000..0643f7fd4 --- /dev/null +++ b/test_regress/t/t_force_complex_sel_unsup.out @@ -0,0 +1,10 @@ +%Error-UNSUPPORTED: t/t_force_complex_sel_unsup.v:37:22: Unsupported: Force / release statement with complex select expression + : ... note: In instance 't' + 37 | force logic_arr[($c(1))] = 0; + | ^ + ... For error description see https://verilator.org/warn/UNSUPPORTED?v=latest +%Error-UNSUPPORTED: t/t_force_complex_sel_unsup.v:44:24: Unsupported: Force / release statement with complex select expression + : ... note: In instance 't' + 44 | release logic_arr[($c(1))]; + | ^ +%Error: Exiting due to diff --git a/test_regress/t/t_force_complex_sel_unsup.py b/test_regress/t/t_force_complex_sel_unsup.py new file mode 100755 index 000000000..44c75cc0f --- /dev/null +++ b/test_regress/t/t_force_complex_sel_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_complex_sel_unsup.v b/test_regress/t/t_force_complex_sel_unsup.v new file mode 100644 index 000000000..d9c243a08 --- /dev/null +++ b/test_regress/t/t_force_complex_sel_unsup.v @@ -0,0 +1,55 @@ +// 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 + +`define stop $stop +`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0) +`define checkr(gotv,expv) do if ((gotv) != (expv)) begin $write("%%Error: %s:%0d: got=%f exp=%f\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0); + +`ifdef VERILATOR +// The '$c(1)' is there to prevent inlining of the signal by V3Gate +`define IMPURE_ONE ($c(1)) +`else +// Use standard $random (chances of getting 2 consecutive zeroes is zero). +`define IMPURE_ONE (|($random | $random)) +`endif + +module t ( /*AUTOARG*/ + // Inputs + clk +); + input clk; + + integer cyc = 0; + + logic [2:0] logic_arr; + + // Test loop + always @(posedge clk) begin + cyc <= cyc + 1; + if (cyc == 0) begin + logic_arr[`IMPURE_ONE] <= 1; + end else if (cyc == 1) begin + `checkh(logic_arr[`IMPURE_ONE], 1); + end else if (cyc == 2) begin + force logic_arr[`IMPURE_ONE] = 0; + end else if (cyc == 3) begin + `checkh(logic_arr[`IMPURE_ONE], 0); + logic_arr[`IMPURE_ONE] <= 1; + end else if (cyc == 4) begin + `checkh(logic_arr[`IMPURE_ONE], 0); + end else if (cyc == 5) begin + release logic_arr[`IMPURE_ONE]; + end else if (cyc == 6) begin + `checkh(logic_arr[`IMPURE_ONE], 0); + logic_arr[`IMPURE_ONE] <= 1; + end else if (cyc == 7) begin + `checkh(logic_arr[`IMPURE_ONE], 1); + end else if (cyc == 8) begin + $write("*-* All Finished *-*\n"); + $finish; + end + end +endmodule