Add `lint_off --contents` in configuration files. (#5606)

This commit is contained in:
Wilson Snyder 2024-11-12 20:21:16 -05:00
parent a5b2cb6ddf
commit 0bf413b260
13 changed files with 226 additions and 33 deletions

View File

@ -19,6 +19,7 @@ Verilator 5.031 devel
* Support `pure constraint`. * Support `pure constraint`.
* Add `--no-std-package` as subset-alias of `--no-std`. * Add `--no-std-package` as subset-alias of `--no-std`.
* Add `--waiver-multiline` for context-sensitive `--waiver-output`. * Add `--waiver-multiline` for context-sensitive `--waiver-output`.
* Add `lint_off --contents` in configuration files. (#5606)
* Add error on illegal enum base type (#3010). [Iztok Jeras] * Add error on illegal enum base type (#3010). [Iztok Jeras]
* Add error on `wait` with missing `.triggered` (#4457). * Add error on `wait` with missing `.triggered` (#4457).
* Add error when improperly storing to parameter (#5147). [Gökçe Aydos] * Add error when improperly storing to parameter (#5147). [Gökçe Aydos]

View File

@ -1364,7 +1364,7 @@ Summary:
.. option:: --no-std .. option:: --no-std
Prevents parsing standard input files, alias for Prevents parsing standard input files, alias for
:vlopt:`--no-std-package`. This may be extended to prevent reading other :opt:`--no-std-package`. This may be extended to prevent reading other
standardized files in future versions. standardized files in future versions.
.. option:: --no-std-package .. option:: --no-std-package
@ -1651,7 +1651,7 @@ Summary:
.. option:: --waiver-multiline .. option:: --waiver-multiline
When using :vlopt:`--waiver-output`, include a match When using :vlopt:`--waiver-output \<filename\>`, include a match
expression that includes the entire multiline error message as a match expression that includes the entire multiline error message as a match
regular expression, as opposed to the default of only matching the first regular expression, as opposed to the default of only matching the first
line of the error message. This provides a starting point for creating line of the error message. This provides a starting point for creating
@ -2088,7 +2088,7 @@ The grammar of configuration commands is as follows:
.. option:: lint_off [-rule <message>] [-file "<filename>" [-lines <line> [ - <line>]]] .. option:: lint_off [-rule <message>] [-file "<filename>" [-lines <line> [ - <line>]]]
.. option:: lint_off [-rule <message>] [-file "<filename>"] [-match "<wildcard>"] .. option:: lint_off [-rule <message>] [-file "<filename>"] [-contents "<wildcard>"] [-match "<wildcard>"]
Enable/disables the specified lint warning, in the specified filename Enable/disables the specified lint warning, in the specified filename
(or wildcard with '\*' or '?', or all files if omitted) and range of (or wildcard with '\*' or '?', or all files if omitted) and range of
@ -2101,9 +2101,19 @@ The grammar of configuration commands is as follows:
:vlopt:`-Wno-lint`) are enabled/disabled. This will override all later :vlopt:`-Wno-lint`) are enabled/disabled. This will override all later
lint warning enables for the specified region. lint warning enables for the specified region.
If :code:`-contents` is provided, the input files must contain the given
wildcard (with '\*' or '?'), and are waived in case they match, provided
the :code:`-rule`, :code:`-file`, and :code:`-contents` also match. The
wildcard should be designed to match a single line; it is unspecified if
the wildcard is allowed to match across multiple lines. The input
contents does not include :vlopt:`--std` standard files, nor
configuration files (with :code:`verilator_config`). Typical use for
this is to match a version number present in the Verilog sources, so
that the waiver will only apply to that version of the sources.
If :code:`-match` is provided, the linter warnings are matched against If :code:`-match` is provided, the linter warnings are matched against
the given wildcard (with '\*' or '?'), and are waived in case they the given wildcard (with '\*' or '?'), and are waived in case they
match, provided the :code:`-rule` and :code:`-file` match, provided the :code:`-rule`, :code:`-file`, and :code:`-contents`
also match. The wildcard is compared across the entire multi-line also match. The wildcard is compared across the entire multi-line
message; see :vlopt:`--waiver-multiline`. message; see :vlopt:`--waiver-multiline`.

View File

@ -118,6 +118,70 @@ public:
using V3ConfigVarResolver = V3ConfigWildcardResolver<V3ConfigVar>; using V3ConfigVarResolver = V3ConfigWildcardResolver<V3ConfigVar>;
//======================================================================
class WildcardContents final {
// Not mutex protected, current calling from V3Config::waive is protected by error's mutex
// MEMBERS
std::map<const std::string, bool> m_mapPatterns; // Pattern match results
std::deque<string> m_lines; // Source text lines
// METHODS
static WildcardContents& s() { // Singleton
static WildcardContents s_s;
return s_s;
}
void clearCacheImp() { m_mapPatterns.clear(); }
void pushTextImp(const string& text) {
// Similar code in VFileContent::pushText()
// Any leftover text is stored on largest line (might be "")
const string leftover = m_lines.back() + text;
m_lines.pop_back();
// Insert line-by-line
string::size_type line_start = 0;
while (true) {
const string::size_type line_end = leftover.find('\n', line_start);
if (line_end != string::npos) {
const string oneline(leftover, line_start, line_end - line_start + 1);
if (oneline.size() > 1) m_lines.push_back(oneline); // Keeps newline
UINFO(9, "Push[+" << (m_lines.size() - 1) << "]: " << oneline);
line_start = line_end + 1;
} else {
break;
}
}
// Keep leftover for next time
m_lines.emplace_back(string(leftover, line_start)); // Might be ""
clearCacheImp();
}
bool resolveUncachedImp(const string& name) {
for (const string& i : m_lines) {
if (VString::wildmatch(i, name)) return true;
}
return false;
}
bool resolveCachedImp(const string& name) {
// Lookup if it was resolved before, typically is
const auto pair = m_mapPatterns.emplace(name, false);
bool& entryr = pair.first->second;
// Resolve entry when first requested, cache the result
if (pair.second) entryr = resolveUncachedImp(name);
return entryr;
}
public:
WildcardContents() {
m_lines.emplace_back(""); // start with no leftover
}
~WildcardContents() = default;
// Return true iff name in parsed contents
static bool resolve(const string& name) { return s().resolveCachedImp(name); }
// Add arbitrary text (need not be line-by-line)
static void pushText(const string& text) { s().pushTextImp(text); }
};
//###################################################################### //######################################################################
// Function or task: Have variables and properties // Function or task: Have variables and properties
@ -256,11 +320,28 @@ std::ostream& operator<<(std::ostream& os, const V3ConfigIgnoresLine& rhs) {
// and multiple attributes can be attached to a line // and multiple attributes can be attached to a line
using V3ConfigLineAttribute = std::bitset<VPragmaType::ENUM_SIZE>; using V3ConfigLineAttribute = std::bitset<VPragmaType::ENUM_SIZE>;
class WaiverSetting final {
public:
V3ErrorCode m_code; // Error code
string m_contents; // --contents regexp
string m_match; // --match regexp
WaiverSetting(V3ErrorCode code, const string& contents, const string& match)
: m_code{code}
, m_contents{contents}
, m_match{match} {}
~WaiverSetting() = default;
WaiverSetting& operator=(const WaiverSetting& rhs) {
m_code = rhs.m_code;
m_contents = rhs.m_contents;
m_match = rhs.m_match;
return *this;
}
};
// File entity // File entity
class V3ConfigFile final { class V3ConfigFile final {
using LineAttrMap = std::map<int, V3ConfigLineAttribute>; // Map line->bitset of attributes using LineAttrMap = std::map<int, V3ConfigLineAttribute>; // Map line->bitset of attributes
using IgnLines = std::multiset<V3ConfigIgnoresLine>; // list of {line,code,on} using IgnLines = std::multiset<V3ConfigIgnoresLine>; // list of {line,code,on}
using WaiverSetting = std::pair<V3ErrorCode, std::string>; // Waive code if string matches
using Waivers = std::vector<WaiverSetting>; // List of {code,wildcard string} using Waivers = std::vector<WaiverSetting>; // List of {code,wildcard string}
LineAttrMap m_lineAttrs; // Attributes to line mapping LineAttrMap m_lineAttrs; // Attributes to line mapping
@ -299,12 +380,12 @@ public:
m_ignLines.insert(V3ConfigIgnoresLine{code, lineno, on}); m_ignLines.insert(V3ConfigIgnoresLine{code, lineno, on});
m_lastIgnore.it = m_ignLines.begin(); m_lastIgnore.it = m_ignLines.begin();
} }
void addIgnoreMatch(V3ErrorCode code, const string& match) { void addIgnoreMatch(V3ErrorCode code, const string& contents, const string& match) {
// Since Verilator 5.031 the error message compared has context, so // Since Verilator 5.031 the error message compared has context, so
// allow old rules to still match using a final '*' // allow old rules to still match using a final '*'
string newMatch = match; string newMatch = match;
if (newMatch.empty() || newMatch.back() != '*') newMatch += '*'; if (newMatch.empty() || newMatch.back() != '*') newMatch += '*';
m_waivers.emplace_back(code, newMatch); m_waivers.emplace_back(WaiverSetting{code, contents, newMatch});
} }
void applyBlock(AstNodeBlock* nodep) { void applyBlock(AstNodeBlock* nodep) {
@ -342,8 +423,9 @@ public:
bool waive(V3ErrorCode code, const string& match) { bool waive(V3ErrorCode code, const string& match) {
if (code.hardError()) return false; if (code.hardError()) return false;
for (const auto& itr : m_waivers) { for (const auto& itr : m_waivers) {
if ((code.isUnder(itr.first) || (itr.first == V3ErrorCode::I_LINT)) if ((code.isUnder(itr.m_code) || (itr.m_code == V3ErrorCode::I_LINT))
&& VString::wildmatch(match, itr.second)) { && VString::wildmatch(match, itr.m_match)
&& WildcardContents::resolve(itr.m_contents)) {
return true; return true;
} }
} }
@ -516,8 +598,9 @@ void V3Config::addIgnore(V3ErrorCode code, bool on, const string& filename, int
} }
} }
void V3Config::addIgnoreMatch(V3ErrorCode code, const string& filename, const string& match) { void V3Config::addIgnoreMatch(V3ErrorCode code, const string& filename, const string& contents,
V3ConfigResolver::s().files().at(filename).addIgnoreMatch(code, match); const string& match) {
V3ConfigResolver::s().files().at(filename).addIgnoreMatch(code, contents, match);
} }
void V3Config::addInline(FileLine* fl, const string& module, const string& ftask, bool on) { void V3Config::addInline(FileLine* fl, const string& module, const string& ftask, bool on) {
@ -651,6 +734,8 @@ bool V3Config::getScopeTraceOn(const string& scope) {
return V3ConfigResolver::s().scopeTraces().getScopeTraceOn(scope); return V3ConfigResolver::s().scopeTraces().getScopeTraceOn(scope);
} }
void V3Config::contentsPushText(const string& text) { return WildcardContents::pushText(text); }
bool V3Config::waive(FileLine* filelinep, V3ErrorCode code, const string& message) { bool V3Config::waive(FileLine* filelinep, V3ErrorCode code, const string& message) {
V3ConfigFile* filep = V3ConfigResolver::s().files().resolve(filelinep->filename()); V3ConfigFile* filep = V3ConfigResolver::s().files().resolve(filelinep->filename());
if (!filep) return false; if (!filep) return false;

View File

@ -34,7 +34,8 @@ public:
static void addCoverageBlockOff(const string& file, int lineno); static void addCoverageBlockOff(const string& file, int lineno);
static void addCoverageBlockOff(const string& module, const string& blockname); static void addCoverageBlockOff(const string& module, const string& blockname);
static void addIgnore(V3ErrorCode code, bool on, const string& filename, int min, int max); static void addIgnore(V3ErrorCode code, bool on, const string& filename, int min, int max);
static void addIgnoreMatch(V3ErrorCode code, const string& filename, const string& match); static void addIgnoreMatch(V3ErrorCode code, const string& filename, const string& contents,
const string& match);
static void addInline(FileLine* fl, const string& module, const string& ftask, bool on); static void addInline(FileLine* fl, const string& module, const string& ftask, bool on);
static void addModulePragma(const string& module, VPragmaType pragma); static void addModulePragma(const string& module, VPragmaType pragma);
static void addProfileData(FileLine* fl, const string& model, const string& key, static void addProfileData(FileLine* fl, const string& model, const string& key,
@ -53,6 +54,9 @@ public:
static uint64_t getProfileData(const string& model, const string& key); static uint64_t getProfileData(const string& model, const string& key);
static FileLine* getProfileDataFileLine(); static FileLine* getProfileDataFileLine();
static bool getScopeTraceOn(const string& scope); static bool getScopeTraceOn(const string& scope);
static void contentsPushText(const string& text);
static bool waive(FileLine* filelinep, V3ErrorCode code, const string& message); static bool waive(FileLine* filelinep, V3ErrorCode code, const string& message);
}; };

View File

@ -147,6 +147,7 @@ FileLineSingleton::msgEnSetIdx_t FileLineSingleton::msgEnAnd(msgEnSetIdx_t lhsId
// VFileContents class functions // VFileContents class functions
void VFileContent::pushText(const string& text) { void VFileContent::pushText(const string& text) {
// Similar code in WildcardContents::pushText()
if (m_lines.size() == 0) { if (m_lines.size() == 0) {
m_lines.emplace_back(""); // no such thing as line [0] m_lines.emplace_back(""); // no such thing as line [0]
m_lines.emplace_back(""); // start with no leftover m_lines.emplace_back(""); // start with no leftover

View File

@ -824,6 +824,21 @@ void V3PreProcImp::openFile(FileLine*, VInFilter* filterp, const string& filenam
flsp->newContent(); flsp->newContent();
for (const string& i : wholefile) flsp->contentp()->pushText(i); for (const string& i : wholefile) flsp->contentp()->pushText(i);
// Save contents for V3Config --contents
if (filename != V3Options::getStdPackagePath()) {
bool containsVlt = false;
for (const string& i : wholefile) {
// TODO this is overly sensitive, might be in a comment
if (i.find("`verilator_config") != string::npos) {
containsVlt = true;
break;
}
}
if (!containsVlt) {
for (const string& i : wholefile) V3Config::contentsPushText(i);
}
}
// Create new stream structure // Create new stream structure
m_lexp->scanNewFile(flsp); m_lexp->scanNewFile(flsp);
addLineComment(1); // Enter addLineComment(1); // Enter

View File

@ -137,6 +137,7 @@ vnum {vnum1}|{vnum2}|{vnum3}|{vnum4}|{vnum5}
"tracing_on" { FL; return yVLT_TRACING_ON; } "tracing_on" { FL; return yVLT_TRACING_ON; }
-?"-block" { FL; return yVLT_D_BLOCK; } -?"-block" { FL; return yVLT_D_BLOCK; }
-?"-contents" { FL; return yVLT_D_CONTENTS; }
-?"-cost" { FL; return yVLT_D_COST; } -?"-cost" { FL; return yVLT_D_COST; }
-?"-file" { FL; return yVLT_D_FILE; } -?"-file" { FL; return yVLT_D_FILE; }
-?"-function" { FL; return yVLT_D_FUNCTION; } -?"-function" { FL; return yVLT_D_FUNCTION; }

View File

@ -495,6 +495,7 @@ BISONPRE_VERSION(3.7,%define api.header.include {"V3ParseBison.h"})
%token<fl> yVLT_TRACING_ON "tracing_on" %token<fl> yVLT_TRACING_ON "tracing_on"
%token<fl> yVLT_D_BLOCK "--block" %token<fl> yVLT_D_BLOCK "--block"
%token<fl> yVLT_D_CONTENTS "--contents"
%token<fl> yVLT_D_COST "--cost" %token<fl> yVLT_D_COST "--cost"
%token<fl> yVLT_D_FILE "--file" %token<fl> yVLT_D_FILE "--file"
%token<fl> yVLT_D_FUNCTION "--function" %token<fl> yVLT_D_FUNCTION "--function"
@ -7572,7 +7573,19 @@ vltItem:
{ if (($1 == V3ErrorCode::I_COVERAGE) || ($1 == V3ErrorCode::I_TRACING)) { { if (($1 == V3ErrorCode::I_COVERAGE) || ($1 == V3ErrorCode::I_TRACING)) {
$<fl>1->v3error("Argument -match only supported for lint_off"); $<fl>1->v3error("Argument -match only supported for lint_off");
} else { } else {
V3Config::addIgnoreMatch($1, *$2, *$3); V3Config::addIgnoreMatch($1, *$2, "", *$3);
}}
| vltOffFront vltDFile vltDContents
{ if (($1 == V3ErrorCode::I_COVERAGE) || ($1 == V3ErrorCode::I_TRACING)) {
$<fl>1->v3error("Argument -match only supported for lint_off");
} else {
V3Config::addIgnoreMatch($1, *$2, *$3, "*");
}}
| vltOffFront vltDFile vltDContents vltDMatch
{ if (($1 == V3ErrorCode::I_COVERAGE) || ($1 == V3ErrorCode::I_TRACING)) {
$<fl>1->v3error("Argument -match only supported for lint_off");
} else {
V3Config::addIgnoreMatch($1, *$2, *$3, *$4);
}} }}
| vltOffFront vltDScope | vltOffFront vltDScope
{ if ($1 != V3ErrorCode::I_TRACING) { { if ($1 != V3ErrorCode::I_TRACING) {
@ -7660,6 +7673,10 @@ vltDBlock<strp>: // --block <arg>
yVLT_D_BLOCK str { $$ = $2; } yVLT_D_BLOCK str { $$ = $2; }
; ;
vltDContents<strp>:
yVLT_D_CONTENTS str { $$ = $2; }
;
vltDCost<nump>: // --cost <arg> vltDCost<nump>: // --cost <arg>
yVLT_D_COST yaINTNUM { $$ = $2; } yVLT_D_COST yaINTNUM { $$ = $2; }
; ;

View File

@ -4,28 +4,38 @@
// any use, without warranty, 2024 by Wilson Snyder. // any use, without warranty, 2024 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0 // SPDX-License-Identifier: CC0-1.0
`ifdef _T_UVM_TODO_VLT_ `else
`define _T_UVM_TODO_VLT_
`verilator_config `verilator_config
// Apply these rules to only UVM base files
`define VLT_UVM_FILES -file "*/uvm_*.svh" -contents "*UVM_VERSION_STRING*"
// Whole-file waivers // Whole-file waivers
lint_off -rule WIDTHEXPAND -file "*/uvm_*.svh" lint_off -rule WIDTHEXPAND `VLT_UVM_FILES
lint_off -rule WIDTHTRUNC -file "*/uvm_*.svh" lint_off -rule WIDTHTRUNC `VLT_UVM_FILES
// Context-sensitive waivers // Context-sensitive waivers
lint_off -rule CASEINCOMPLETE -file "*/uvm_*.svh" -match "* case ({is_R, is_W})*" lint_off -rule CASEINCOMPLETE `VLT_UVM_FILES -match "* case ({is_R, is_W})*"
lint_off -rule CASEINCOMPLETE -file "*/uvm_*.svh" -match "* case(orig_severity)*" lint_off -rule CASEINCOMPLETE `VLT_UVM_FILES -match "* case(orig_severity)*"
lint_off -rule CASTCONST -file "*/uvm_*.svh" -match "*class{}uvm_callback*" lint_off -rule CASTCONST `VLT_UVM_FILES -match "*class{}uvm_callback*"
lint_off -rule CASTCONST -file "*/uvm_*.svh" -match "*class{}uvm_component*" lint_off -rule CASTCONST `VLT_UVM_FILES -match "*class{}uvm_component*"
lint_off -rule CASTCONST -file "*/uvm_*.svh" -match "*class{}uvm_event*" lint_off -rule CASTCONST `VLT_UVM_FILES -match "*class{}uvm_event*"
lint_off -rule CASTCONST -file "*/uvm_*.svh" -match "*class{}uvm_report_object*" lint_off -rule CASTCONST `VLT_UVM_FILES -match "*class{}uvm_report_object*"
lint_off -rule CASTCONST -file "*/uvm_*.svh" -match "*class{}uvm_sequence_item*" lint_off -rule CASTCONST `VLT_UVM_FILES -match "*class{}uvm_sequence_item*"
lint_off -rule MISINDENT -file "*/uvm_*.svh" -match "* foreach (abstractions[i])*" lint_off -rule MISINDENT `VLT_UVM_FILES -match "* foreach (abstractions[i])*"
lint_off -rule MISINDENT -file "*/uvm_*.svh" -match "* foreach (lock_list[i])*" lint_off -rule MISINDENT `VLT_UVM_FILES -match "* foreach (lock_list[i])*"
lint_off -rule MISINDENT -file "*/uvm_*.svh" -match "* rw_access.data=*" lint_off -rule MISINDENT `VLT_UVM_FILES -match "* rw_access.data=*"
lint_off -rule MISINDENT -file "*/uvm_*.svh" -match "* uvm_cmdline_proc =*" lint_off -rule MISINDENT `VLT_UVM_FILES -match "* uvm_cmdline_proc =*"
lint_off -rule REALCVT -file "*/uvm_*.svh" -match "* m_time *" lint_off -rule REALCVT `VLT_UVM_FILES -match "* m_time *"
lint_off -rule REALCVT -file "*/uvm_*.svh" -match "*$realtime*" lint_off -rule REALCVT `VLT_UVM_FILES -match "*$realtime*"
lint_off -rule SYMRSVDWORD -file "*/uvm_*.svh" -match "*'delete'*" lint_off -rule SYMRSVDWORD `VLT_UVM_FILES -match "*'delete'*"
lint_off -rule SYMRSVDWORD -file "*/uvm_*.svh" -match "*'list'*" lint_off -rule SYMRSVDWORD `VLT_UVM_FILES -match "*'list'*"
lint_off -rule SYMRSVDWORD -file "*/uvm_*.svh" -match "*'map'*" lint_off -rule SYMRSVDWORD `VLT_UVM_FILES -match "*'map'*"
lint_off -rule SYMRSVDWORD -file "*/uvm_*.svh" -match "*'override'*" lint_off -rule SYMRSVDWORD `VLT_UVM_FILES -match "*'override'*"
lint_off -rule SYMRSVDWORD -file "*/uvm_*.svh" -match "*'volatile'*" lint_off -rule SYMRSVDWORD `VLT_UVM_FILES -match "*'volatile'*"
`undef VLT_UVM_FILES
`endif // Guard

View File

@ -0,0 +1,7 @@
%Warning-UNUSEDSIGNAL: t/t_vlt_match_contents.v:11:10: Signal is not driven, nor used: 'usignal_contents_mismatch'
: ... note: In instance 't'
11 | logic usignal_contents_mismatch;
| ^~~~~~~~~~~~~~~~~~~~~~~~~
... For warning description see https://verilator.org/warn/UNUSEDSIGNAL?v=latest
... Use "/* verilator lint_off UNUSEDSIGNAL */" and lint_on around source to disable this message.
%Error: Exiting due to

View File

@ -0,0 +1,18 @@
#!/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('vlt')
test.lint(verilator_flags2=["--lint-only -Wall t/t_vlt_match_contents.vlt"],
fails=True,
expect_filename=test.golden_filename)
test.passes()

View File

@ -0,0 +1,12 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2024 by Ethan Sifferman.
// SPDX-License-Identifier: CC0-1.0
string MATCH_VERSION = "10.20";
module t;
logic usignal_contents_suppress; // Suppressed with -contents
logic usignal_contents_mismatch; // Doesn't match -contents
endmodule

View File

@ -0,0 +1,12 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2024 by Ethan Sifferman.
// SPDX-License-Identifier: CC0-1.0
`verilator_config
lint_off -rule DECLFILENAME -file "*/t_vlt_match_contents.v" -contents "* MATCH_VERSION*"
lint_off -rule UNUSEDSIGNAL -file "*/t_vlt_match_contents.v" -contents "* MATCH_VERSION*" -match "*MATCH_VERSION*"
lint_off -rule UNUSEDSIGNAL -file "*/t_vlt_match_contents.v" -contents "* MATCH_VERSION*" -match "*usignal_contents_suppress*"
lint_off -rule UNUSEDSIGNAL -file "*/t_vlt_match_contents.v" -contents "* NOT_VERSION*" -match "*usignal_contents_mismatch*"