From 5802818b9acb6b9fab7079666ef5e6bc06dee3d2 Mon Sep 17 00:00:00 2001 From: Fuad Ismail Date: Sat, 16 Mar 2024 19:25:42 +0700 Subject: [PATCH] Add error when pass net to function argument (#4132) (#4966) --- docs/CONTRIBUTORS | 1 + src/V3Undriven.cpp | 13 ++++++++++ .../t/t_lint_ftask_output_assign_bad.out | 10 +++++++ .../t/t_lint_ftask_output_assign_bad.pl | 19 ++++++++++++++ .../t/t_lint_ftask_output_assign_bad.v | 26 +++++++++++++++++++ test_regress/t/t_mem_banks.v | 4 +-- 6 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 test_regress/t/t_lint_ftask_output_assign_bad.out create mode 100755 test_regress/t/t_lint_ftask_output_assign_bad.pl create mode 100644 test_regress/t/t_lint_ftask_output_assign_bad.v diff --git a/docs/CONTRIBUTORS b/docs/CONTRIBUTORS index 82e6160b6..dda0077ab 100644 --- a/docs/CONTRIBUTORS +++ b/docs/CONTRIBUTORS @@ -46,6 +46,7 @@ february cozzocrea Felix Neumärker Felix Yan Frans Skarman +Fuad Ismail G-A. Kamendje Garrett Smith Geza Lore diff --git a/src/V3Undriven.cpp b/src/V3Undriven.cpp index 2b86c8b44..f89d1937a 100644 --- a/src/V3Undriven.cpp +++ b/src/V3Undriven.cpp @@ -278,6 +278,7 @@ class UndrivenVisitor final : public VNVisitorConst { bool m_inBBox = false; // In black box; mark as driven+used bool m_inContAssign = false; // In continuous assignment bool m_inProcAssign = false; // In procedural assignment + bool m_inFTaskRef = false; // In function or task call bool m_inInoutPin = false; // Connected to pin that is inout const AstNodeFTask* m_taskp = nullptr; // Current task const AstAlways* m_alwaysCombp = nullptr; // Current always if combo, otherwise nullptr @@ -390,6 +391,13 @@ class UndrivenVisitor final : public VNVisitorConst { << " (IEEE 1364-2005 6.1; Verilog only, legal in SV): " << nodep->prettyNameQ()); } + if (m_inFTaskRef && nodep->varp()->varType().isNet()) { + nodep->v3warn( + PROCASSWIRE, + "Passed wire on output or inout subroutine argument, expected expression that " + "is valid on the left hand side of a procedural assignment" + << " (IEEE 1800-2023 13.5): " << nodep->prettyNameQ()); + } } for (int usr = 1; usr < (m_alwaysCombp ? 3 : 2); ++usr) { UndrivenVarEntry* const entryp = getEntryp(nodep->varp(), usr); @@ -493,6 +501,11 @@ class UndrivenVisitor final : public VNVisitorConst { if (nodep->keyword() == VAlwaysKwd::ALWAYS_COMB) UINFO(9, " Done " << nodep << endl); } } + void visit(AstNodeFTaskRef* nodep) override { + VL_RESTORER(m_inFTaskRef); + m_inFTaskRef = true; + iterateChildrenConst(nodep); + } void visit(AstNodeFTask* nodep) override { VL_RESTORER(m_taskp); diff --git a/test_regress/t/t_lint_ftask_output_assign_bad.out b/test_regress/t/t_lint_ftask_output_assign_bad.out new file mode 100644 index 000000000..221d7d704 --- /dev/null +++ b/test_regress/t/t_lint_ftask_output_assign_bad.out @@ -0,0 +1,10 @@ +%Error-PROCASSWIRE: t/t_lint_ftask_output_assign_bad.v:21:11: Passed wire on output or inout subroutine argument, expected expression that is valid on the left hand side of a procedural assignment (IEEE 1800-2023 13.5): 'wire_out' + : ... note: In instance 't' + 21 | set_f(wire_out, in); + | ^~~~~~~~ + ... For error description see https://verilator.org/warn/PROCASSWIRE?v=latest +%Error-PROCASSWIRE: t/t_lint_ftask_output_assign_bad.v:23:14: Passed wire on output or inout subroutine argument, expected expression that is valid on the left hand side of a procedural assignment (IEEE 1800-2023 13.5): 'wire_out' + : ... note: In instance 't' + 23 | set_task(wire_out, in); + | ^~~~~~~~ +%Error: Exiting due to diff --git a/test_regress/t/t_lint_ftask_output_assign_bad.pl b/test_regress/t/t_lint_ftask_output_assign_bad.pl new file mode 100755 index 000000000..a5846c699 --- /dev/null +++ b/test_regress/t/t_lint_ftask_output_assign_bad.pl @@ -0,0 +1,19 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003 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(vlt => 1); + +lint( + fails => 1, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_lint_ftask_output_assign_bad.v b/test_regress/t/t_lint_ftask_output_assign_bad.v new file mode 100644 index 000000000..ac8b0c7aa --- /dev/null +++ b/test_regress/t/t_lint_ftask_output_assign_bad.v @@ -0,0 +1,26 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2017 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t ( + input logic in, + output wire wire_out, + output logic reg_out +); + function void set_f(output set_out, input set_in); + set_out = 1; + endfunction + + task set_task(output set_out, input set_in); + set_out = 1; + endtask + + always_comb begin : setCall + set_f(wire_out, in); + set_f(reg_out, in); + set_task(wire_out, in); + set_task(reg_out, in); + end +endmodule diff --git a/test_regress/t/t_mem_banks.v b/test_regress/t/t_mem_banks.v index 0f438eaea..01f6204ca 100644 --- a/test_regress/t/t_mem_banks.v +++ b/test_regress/t/t_mem_banks.v @@ -11,8 +11,8 @@ module t (/*AUTOARG*/); parameter BANKS = 6; parameter ROWS = 8; - wire [2:0] bank; - wire [2:0] row; + reg [2:0] bank; + reg [2:0] row; integer a; integer used[BANKS][ROWS];