diff --git a/Changes b/Changes index 699de9efb..889f493b0 100644 --- a/Changes +++ b/Changes @@ -5,6 +5,9 @@ The contributors that suggested a given feature are shown in []. Thanks! * Verilator 4.035 devel +** Add --waiver-output flag that writes a verilator config file (.vlt) with + waivers to the warnings emitted during a Verilator run. + *** Support verilator_coverage --write-info for lcov HTML reports. **** Support multi channel descriptor I/O (#2190) [Stephen Henry] diff --git a/bin/verilator b/bin/verilator index 8189e8c82..e3de112cc 100755 --- a/bin/verilator +++ b/bin/verilator @@ -399,6 +399,7 @@ detailed descriptions in L for more information. +verilog2001ext+ Synonym for +1364-2001ext+ --version Displays program version and exits --vpi Enable VPI compiles + --waiver-output Create a waiver file based on the linter warnings -Wall Enable all style warnings -Werror- Convert warnings to errors -Wfuture- Disable unknown message warnings @@ -1606,6 +1607,17 @@ Displays program version and exits. Enable use of VPI and linking against the verilated_vpi.cpp files. +=item --waiver-output + +Generate a waiver file which contains all waiver statements to suppress the +warnings emitted during this Verilator run. This is in particular useful as +a starting point for solving linter warnings or suppressing them +systematically. + +The generated file is in the Verilator Configuration format, see +L, and can directly be consumed by Verilator. The +standard file extension is .vlt. + =item -Wall Enable all code style warnings, including code style warnings that are diff --git a/src/Makefile_obj.in b/src/Makefile_obj.in index 911f97e1f..4b8d75548 100644 --- a/src/Makefile_obj.in +++ b/src/Makefile_obj.in @@ -246,6 +246,7 @@ RAW_OBJS = \ V3Undriven.o \ V3Unknown.o \ V3Unroll.o \ + V3Waiver.o \ V3Width.o \ V3WidthSel.o \ diff --git a/src/V3FileLine.cpp b/src/V3FileLine.cpp index b69161489..915de3bbf 100644 --- a/src/V3FileLine.cpp +++ b/src/V3FileLine.cpp @@ -28,6 +28,7 @@ # include "V3Config.h" # include "V3File.h" #endif +#include "V3Waiver.h" // clang-format on #include @@ -366,6 +367,7 @@ void FileLine::v3errorEnd(std::ostringstream& sstr, const string& locationStr) { } else if (!V3Error::errorContexted()) { nsstr << warnContextPrimary(); } + if (!m_waive) { V3Waiver::addEntry(V3Error::errorCode(), filename(), sstr.str()); } V3Error::v3errorEnd(nsstr, lstr.str()); } diff --git a/src/V3Options.cpp b/src/V3Options.cpp index 1cdd942db..0c88e6030 100644 --- a/src/V3Options.cpp +++ b/src/V3Options.cpp @@ -1197,6 +1197,9 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char parseOptsFile(fl, parseFileArg(optdir, argv[i]), false); } else if (!strcmp(sw, "-gdb")) { // Used only in perl shell + } else if (!strcmp(sw, "-waiver-output") && (i + 1) < argc) { + shift; + m_waiverOutput = argv[i]; } else if (!strcmp(sw, "-rr")) { // Used only in perl shell } else if (!strcmp(sw, "-gdbbt")) { @@ -1627,6 +1630,7 @@ V3Options::V3Options() { m_makeDir = "obj_dir"; m_bin = ""; m_flags = ""; + m_waiverOutput = ""; m_l2Name = ""; m_unusedRegexp = "*unused*"; m_xAssign = "fast"; diff --git a/src/V3Options.h b/src/V3Options.h index 7813f236d..af90dfbbf 100644 --- a/src/V3Options.h +++ b/src/V3Options.h @@ -317,6 +317,7 @@ private: string m_protectLib; // main switch: --protect-lib {lib_name} string m_topModule; // main switch: --top-module string m_unusedRegexp; // main switch: --unused-regexp + string m_waiverOutput; // main switch: --waiver-output {filename} string m_xAssign; // main switch: --x-assign string m_xInitial; // main switch: --x-initial string m_xmlOutput; // main switch: --xml-output @@ -522,6 +523,8 @@ public: } string topModule() const { return m_topModule; } string unusedRegexp() const { return m_unusedRegexp; } + string waiverOutput() const { return m_waiverOutput; } + bool isWaiverOutput() const { return !m_waiverOutput.empty(); } string xAssign() const { return m_xAssign; } string xInitial() const { return m_xInitial; } string xmlOutput() const { return m_xmlOutput; } diff --git a/src/V3Waiver.cpp b/src/V3Waiver.cpp new file mode 100644 index 000000000..153c1c12f --- /dev/null +++ b/src/V3Waiver.cpp @@ -0,0 +1,57 @@ +// -*- mode: C++; c-file-style: "cc-mode" -*- +//************************************************************************* +// DESCRIPTION: Verilator: Emit waivers into a config file +// +// Code available from: https://verilator.org +// +//************************************************************************* +// +// Copyright 2020 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 +// +//************************************************************************* + +#include "verilatedos.h" + +#include "V3File.h" +#include "V3Waiver.h" + +#include +#include +#include + +void V3Waiver::addEntry(V3ErrorCode errorCode, const std::string& filename, + const std::string& str) { + std::stringstream entry; + entry << "lint_off -rule " << errorCode.ascii() << " -file \"*" << filename << "\" -match \"" + << str << "\""; + s_waiverList.push_back(entry.str()); +} + +void V3Waiver::write(const std::string& filename) { + const vl_unique_ptr ofp(V3File::new_ofstream(filename)); + if (ofp->fail()) v3fatal("Can't write " << filename); + + *ofp << "// DESCR" + "IPTION: Verilator output: Waivers generated with --waiver-output" + << std::endl + << endl; + + *ofp << "`verilator_config" << endl << endl; + + *ofp << "// Below you find suggested waivers. You have three options:" << endl; + *ofp << "// 1. Fix the reason for the linter warning" << endl; + *ofp << "// 2. Keep the waiver permanently if you are sure this is okay" << endl; + *ofp << "// 3. Keep the waiver temporarily to suppress the output" << endl << endl; + + if (s_waiverList.size() == 0) { *ofp << "// No waivers needed - great!" << endl; } + + for (V3Waiver::WaiverList::const_iterator it = s_waiverList.begin(); it != s_waiverList.end(); + ++it) { + *ofp << "// " << *it << std::endl << endl; + } +} + +V3Waiver::WaiverList V3Waiver::s_waiverList; diff --git a/src/V3Waiver.h b/src/V3Waiver.h new file mode 100644 index 000000000..67d4d65a0 --- /dev/null +++ b/src/V3Waiver.h @@ -0,0 +1,35 @@ +// -*- mode: C++; c-file-style: "cc-mode" -*- +//************************************************************************* +// DESCRIPTION: Verilator: Emit Waivers +// +// Code available from: https://verilator.org +// +//************************************************************************* +// +// Copyright 2003-2020 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 +// +//************************************************************************* + +#ifndef _V3WAIVER_H_ +#define _V3WAIVER_H_ 1 + +#include "V3Error.h" + +#include +#include + +class V3Waiver { + // TYPES + typedef std::vector WaiverList; + static WaiverList s_waiverList; + +public: + static void addEntry(V3ErrorCode errorCode, const string& filename, const std::string& str); + static void write(const std::string& filename); +}; + +#endif // Guard diff --git a/src/Verilator.cpp b/src/Verilator.cpp index 690874d29..c58d26c91 100644 --- a/src/Verilator.cpp +++ b/src/Verilator.cpp @@ -93,6 +93,7 @@ #include "V3Undriven.h" #include "V3Unknown.h" #include "V3Unroll.h" +#include "V3Waiver.h" #include "V3Width.h" #include @@ -542,6 +543,14 @@ static void verilate(const string& argString) { // Final steps V3Global::dumpCheckGlobalTree("final", 990, v3Global.opt.dumpTreeLevel(__FILE__) >= 3); + + V3Error::abortIfErrors(); + + if (v3Global.opt.isWaiverOutput()) { + // Create waiver output, must be just before we exit on warnings + V3Waiver::write(v3Global.opt.waiverOutput()); + } + V3Error::abortIfWarnings(); if (v3Global.opt.makeDepend().isTrue()) { diff --git a/test_regress/t/t_waiveroutput.out b/test_regress/t/t_waiveroutput.out new file mode 100644 index 000000000..01132a95d --- /dev/null +++ b/test_regress/t/t_waiveroutput.out @@ -0,0 +1,13 @@ +// DESCRIPTION: Verilator output: Waivers generated with --waiver-output + +`verilator_config + +// Below you find suggested waivers. You have three options: +// 1. Fix the reason for the linter warning +// 2. Keep the waiver permanently if you are sure this is okay +// 3. Keep the waiver temporarily to suppress the output + +// lint_off -rule WIDTH -file "*t/t_waiveroutput.v" -match "Operator ASSIGN expects 1 bits on the Assign RHS, but Assign RHS's CONST '2'h3' generates 2 bits." + +// lint_off -rule UNUSED -file "*t/t_waiveroutput.v" -match "Signal is not used: 'width_warn'" + diff --git a/test_regress/t/t_waiveroutput.pl b/test_regress/t/t_waiveroutput.pl new file mode 100755 index 000000000..08f77ed08 --- /dev/null +++ b/test_regress/t/t_waiveroutput.pl @@ -0,0 +1,30 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2012 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); + +my $out_filename = "$Self->{obj_dir}/$Self->{name}_waiver_gen.vlt"; +my $waiver_filename = "$Self->{obj_dir}/$Self->{name}_waiver.vlt"; + +compile( + v_flags2 => ['--waiver-output', $out_filename], + fails => 1, + ); + +files_identical("$out_filename", $Self->{golden_filename}); + +run(cmd=>["sed 's/\\/\\/ lint_off/lint_off/g' $out_filename > $waiver_filename"]); + +compile( + v_flags2 => [$waiver_filename], + ); + +ok(1); +1; diff --git a/test_regress/t/t_waiveroutput.v b/test_regress/t/t_waiveroutput.v new file mode 100644 index 000000000..c84e9dec4 --- /dev/null +++ b/test_regress/t/t_waiveroutput.v @@ -0,0 +1,10 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2012 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t_waiveroutput; + + reg width_warn = 2'b11; // Width warning - must be line 18 +endmodule diff --git a/test_regress/t/t_waiveroutput_allgood.out b/test_regress/t/t_waiveroutput_allgood.out new file mode 100644 index 000000000..673c0445a --- /dev/null +++ b/test_regress/t/t_waiveroutput_allgood.out @@ -0,0 +1,10 @@ +// DESCRIPTION: Verilator output: Waivers generated with --waiver-output + +`verilator_config + +// Below you find suggested waivers. You have three options: +// 1. Fix the reason for the linter warning +// 2. Keep the waiver permanently if you are sure this is okay +// 3. Keep the waiver temporarily to suppress the output + +// No waivers needed - great! diff --git a/test_regress/t/t_waiveroutput_allgood.pl b/test_regress/t/t_waiveroutput_allgood.pl new file mode 100755 index 000000000..8a1846a0d --- /dev/null +++ b/test_regress/t/t_waiveroutput_allgood.pl @@ -0,0 +1,25 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2012 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); + +my $out_filename = "$Self->{obj_dir}/$Self->{name}_waiver_gen.vlt"; +my $waiver_filename = "t/$Self->{name}.vlt"; + +top_filename("t/t_waiveroutput.v"); + +compile( + v_flags2 => [$waiver_filename, '--waiver-output', $out_filename], + ); + +files_identical("$out_filename", $Self->{golden_filename}); + +ok(1); +1; diff --git a/test_regress/t/t_waiveroutput_allgood.vlt b/test_regress/t/t_waiveroutput_allgood.vlt new file mode 100644 index 000000000..2f6af4e29 --- /dev/null +++ b/test_regress/t/t_waiveroutput_allgood.vlt @@ -0,0 +1,12 @@ +// DESCRIPTION: Verilator output: Waivers generated with --waiver-output + +`verilator_config + +// Below you find suggested waivers. You have three options: +// 1. Fix the reason for the linter warning +// 2. Keep the waiver permanently if you are sure this is okay +// 3. Keep the waiver temporarily to suppress the output + +lint_off -rule WIDTH -file "*t/t_waiveroutput.v" -match "Operator ASSIGN expects 1 bits on the Assign RHS, but Assign RHS's CONST '2'h3' generates 2 bits." + +lint_off -rule UNUSED -file "*t/t_waiveroutput.v" -match "Signal is not used: 'width_warn'" diff --git a/test_regress/t/t_wire_beh1364_bad.pl b/test_regress/t/t_wire_beh1364_bad.pl index 77f34c903..ee98f2262 100755 --- a/test_regress/t/t_wire_beh1364_bad.pl +++ b/test_regress/t/t_wire_beh1364_bad.pl @@ -10,11 +10,17 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di scenarios(vlt => 1); +my $waiver_filename = "$Self->{obj_dir}/$Self->{name}_waiver.vlt"; + lint( - verilator_flags2 => ["--lint-only --language 1364-2001"], + verilator_flags2 => ["--lint-only --language 1364-2001 --waiver-output ${waiver_filename}"], fails => 1, expect_filename => $Self->{golden_filename}, ); +if (-e $waiver_filename) { + error("Waiver file generated, not expected.."); +} + ok(1); 1;