diff --git a/Changes b/Changes index 460708884..3d604cac7 100644 --- a/Changes +++ b/Changes @@ -8,6 +8,8 @@ The contributors that suggested a given feature are shown in []. Thanks! *** Support $fread. [Leendert van Doorn] +*** Add IGNOREDRETURN warning. + **** Report PORTSHORT errors on concat constants, bug 1400. [Will Korteland] **** Fix VERILATOR_GDB being ignored, msg2860. [Yu Sheng Lin] diff --git a/bin/verilator b/bin/verilator index 3f91adc89..8d92efc0f 100755 --- a/bin/verilator +++ b/bin/verilator @@ -3580,6 +3580,14 @@ code to a case statement, or a SystemVerilog 'unique if' or 'priority if'. Disabled by default as this is a code style warning; it will simulate correctly. +=item IGNOREDRETURN + +Warns that a non-void function is being called as a task, and hence the +return value is being ignored. This warning is required by IEEE. + +Ignoring this warning will only suppress the lint check, it will simulate +correctly. + =item IMPERFECTSCH Warns that the scheduling of the model is not absolutely perfect, and some diff --git a/src/V3Error.h b/src/V3Error.h index a2761299d..d1685d92c 100644 --- a/src/V3Error.h +++ b/src/V3Error.h @@ -78,7 +78,8 @@ public: ENDLABEL, // End lable name mismatch GENCLK, // Generated Clock IFDEPTH, // If statements too deep - IMPERFECTSCH, // Imperfect schedule (disabled by default) + IGNOREDRETURN, // Ignoring return value (funcation as task) + IMPERFECTSCH, // Imperfect schedule (disabled by default) IMPLICIT, // Implicit wire IMPORTSTAR, // Import::* in $unit IMPURE, // Impure function not being inlined @@ -139,7 +140,8 @@ public: "CMPCONST", "COLONPLUS", "COMBDLY", "CONTASSREG", "DEFPARAM", "DECLFILENAME", "ENDLABEL", "GENCLK", - "IFDEPTH", "IMPERFECTSCH", "IMPLICIT", "IMPORTSTAR", "IMPURE", + "IFDEPTH", "IGNOREDRETURN", + "IMPERFECTSCH", "IMPLICIT", "IMPORTSTAR", "IMPURE", "INCABSPATH", "INFINITELOOP", "INITIALDLY", "LITENDIAN", "MODDUP", "MULTIDRIVEN", diff --git a/src/V3Task.cpp b/src/V3Task.cpp index 50de23605..33144ea85 100644 --- a/src/V3Task.cpp +++ b/src/V3Task.cpp @@ -1170,11 +1170,15 @@ private: nodep->replaceWith(outrefp); // Insert new statements visitp = insertBeforeStmt(nodep, beginp); - } else { - // outvscp maybe non-NULL if calling a function in a taskref, - // but if so we want to simply ignore the function result - nodep->replaceWith(beginp); - } + } else { + if (nodep->taskp()->isFunction()) { + nodep->v3warn(IGNOREDRETURN, + "Ignoring return value of non-void function (IEEE 2017 13.4.1)"); + } + // outvscp maybe non-NULL if calling a function in a taskref, + // but if so we want to simply ignore the function result + nodep->replaceWith(beginp); + } // Cleanup nodep->deleteTree(); VL_DANGLING(nodep); UINFO(4," FTask REF Done.\n"); diff --git a/test_regress/t/t_dpi_shortcircuit2.v b/test_regress/t/t_dpi_shortcircuit2.v index 1ec645f87..81db3530c 100644 --- a/test_regress/t/t_dpi_shortcircuit2.v +++ b/test_regress/t/t_dpi_shortcircuit2.v @@ -46,7 +46,9 @@ module t (/*AUTOARG*/); // Test loop initial begin // bug963 + // verilator lint_off IGNOREDRETURN dpii_clear(); + // verilator lint_on IGNOREDRETURN j = 0; for (i=0; i<64; i++) begin if (i[0]) diff --git a/test_regress/t/t_func.v b/test_regress/t/t_func.v index 05bd3007a..c9b71194f 100644 --- a/test_regress/t/t_func.v +++ b/test_regress/t/t_func.v @@ -50,12 +50,15 @@ module t; if (n !== 10) $stop; // Functions called as tasks + // verilator lint_off IGNOREDRETURN rglobal = 32'h4; if (inc_and_return(32'h2) != 32'h6) $stop; if (rglobal !== 32'h6) $stop; rglobal = 32'h6; + inc_and_return(32'h3); if (rglobal !== 32'h9) $stop; + // verilator lint_on IGNOREDRETURN $write("*-* All Finished *-*\n"); $finish; diff --git a/test_regress/t/t_func_tie_bad.v b/test_regress/t/t_func_tie_bad.v index 8ca74c2a6..350a5e3ca 100644 --- a/test_regress/t/t_func_tie_bad.v +++ b/test_regress/t/t_func_tie_bad.v @@ -6,6 +6,7 @@ module t (/*AUTOARG*/); initial begin + // verilator lint_off IGNOREDRETURN func(0, 1'b1); end diff --git a/test_regress/t/t_func_void.pl b/test_regress/t/t_func_void.pl new file mode 100755 index 000000000..89a4e77d9 --- /dev/null +++ b/test_regress/t/t_func_void.pl @@ -0,0 +1,20 @@ +#!/usr/bin/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. + +scenarios(simulator => 1); + +compile( + ); + +execute( + check_finished => 1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_func_void.v b/test_regress/t/t_func_void.v new file mode 100644 index 000000000..63d6dd657 --- /dev/null +++ b/test_regress/t/t_func_void.v @@ -0,0 +1,36 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2003 by Wilson Snyder. + +module t (clk); + input clk; + + int side_effect; + + function int f1; + input int in; + f1 = in + 1; + side_effect += in + 1; + endfunction + + initial begin + int got; + side_effect = 1; + // + got = f1(10); + if (got != 11) $stop; + if (side_effect != 12) $stop; + // verilator lint_off IGNOREDRETURN + f1(20); + // verilator lint_on IGNOREDRETURN + if (side_effect != 33) $stop; + // +// void'f1(30); +// if (side_effect != 64) $stop; + // + $write("*-* All Finished *-*\n"); + $finish; + end + +endmodule diff --git a/test_regress/t/t_func_void_bad.out b/test_regress/t/t_func_void_bad.out new file mode 100644 index 000000000..d136ba931 --- /dev/null +++ b/test_regress/t/t_func_void_bad.out @@ -0,0 +1,3 @@ +%Warning-IGNOREDRETURN: t/t_func_void_bad.v:25: Ignoring return value of non-void function (IEEE 2017 13.4.1) +%Warning-IGNOREDRETURN: Use "/* verilator lint_off IGNOREDRETURN */" and lint_on around source to disable this message. +%Error: Exiting due to diff --git a/test_regress/t/t_func_void_bad.pl b/test_regress/t/t_func_void_bad.pl new file mode 100755 index 000000000..3361369bf --- /dev/null +++ b/test_regress/t/t_func_void_bad.pl @@ -0,0 +1,18 @@ +#!/usr/bin/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. + +scenarios(simulator => 1); + +compile( + fails => 1, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_func_void_bad.v b/test_regress/t/t_func_void_bad.v new file mode 100644 index 000000000..228d5204d --- /dev/null +++ b/test_regress/t/t_func_void_bad.v @@ -0,0 +1,35 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2003 by Wilson Snyder. + +module t (clk); + input clk; + + int side_effect; + + function int f1; + input int in; + f1 = in + 1; + side_effect += in + 1; + endfunction + + initial begin + int got; + side_effect = 1; + // + got = f1(10); + if (got != 11) $stop; + if (side_effect != 12) $stop; + // + f1(20); + if (side_effect != 33) $stop; + // +// void'f1(30); +// if (side_effect != 64) $stop; + // + $write("*-* All Finished *-*\n"); + $finish; + end + +endmodule