Throw UNUSED/UNDRIVEN only once per net in a parametrized module.

This commit is contained in:
Wilson Snyder 2011-01-18 21:28:51 -05:00
parent 481b261458
commit a435ae98f9
7 changed files with 88 additions and 2 deletions

View File

@ -5,6 +5,8 @@ indicates the contributor was also the author of the fix; Thanks!
* Verilator 3.81***
**** Throw UNUSED/UNDRIVEN only once per net in a parametrized module.
**** Fix false BLKSEQ on non-unrolled for loop indexes. [Jeff Winston]
**** Fix block comment not separating identifiers, bug311. [Gene Sullivan]

View File

@ -162,7 +162,7 @@ private:
m_ifDepth = -1;
} else if (++m_ifDepth > v3Global.opt.ifDepth()) {
nodep->v3warn(IFDEPTH,"Deep 'if' statement; suggest unique/priority to avoid slow logic");
nodep->fileline()->warnOn(V3ErrorCode::IFDEPTH, false); // Warn only once
nodep->fileline()->modifyWarnOff(V3ErrorCode::IFDEPTH, true); // Warn only once
m_ifDepth = -1;
}
nodep->iterateChildren(*this);

View File

@ -33,6 +33,7 @@
#include <cstdarg>
#include <unistd.h>
#include <map>
#include <set>
#include <algorithm>
#include <vector>
@ -47,11 +48,14 @@ class LinkParseVisitor : public AstNVisitor {
private:
// NODE STATE
// Cleared on netlist
// AstNode::user() -> bool. True if processed
// AstNode::user1() -> bool. True if processed
// AstNode::user2() -> bool. True if fileline recomputed
AstUser1InUse m_inuser1;
AstUser2InUse m_inuser2;
// TYPES
typedef map <pair<void*,string>,AstTypedef*> ImplTypedefMap;
typedef set <FileLine*> FileLineSet;
// STATE
string m_dotText; // Dotted module text we are building for a dotted node, passed up
@ -60,6 +64,7 @@ private:
AstText* m_baseTextp; // Lowest TEXT node that needs replacement with varref
AstVar* m_varp; // Variable we're under
ImplTypedefMap m_implTypedef; // Created typedefs for each <container,name>
FileLineSet m_filelines; // Filelines that have been seen
// METHODS
static int debug() {
@ -68,6 +73,21 @@ private:
return level;
}
void cleanFileline(AstNode* nodep) {
if (!nodep->user2Inc()) { // Process once
// We make all filelines unique per AstNode. This allows us to
// later turn off messages on a fileline when an issue is found
// so that messages on replicated blocks occur only once,
// without suppressing other token's messages as a side effect.
// We could have verilog.l create a new one on every token,
// but that's a lot more structures than only doing AST nodes.
if (m_filelines.find(nodep->fileline()) != m_filelines.end()) {
nodep->fileline(new FileLine(nodep->fileline()));
}
m_filelines.insert(nodep->fileline());
}
}
void checkExpected(AstNode* nodep) {
if (m_exp != AstParseRefExp::PX_NONE) {
nodep->v3fatalSrc("Tree syntax error: Not expecting "<<nodep->type()<<" under a "<<nodep->backp()->type());
@ -78,6 +98,7 @@ private:
// VISITs
virtual void visit(AstNodeFTaskRef* nodep, AstNUser*) {
if (!nodep->user1Inc()) { // Process only once.
cleanFileline(nodep);
UINFO(5," "<<nodep<<endl);
checkExpected(nodep);
// Due to a need to get the arguments, the ParseRefs are under here,
@ -141,6 +162,7 @@ private:
}
virtual void visit(AstDot* nodep, AstNUser*) {
UINFO(5," "<<nodep<<endl);
cleanFileline(nodep);
if (m_inModDot) { // Already under dot, so this is {modulepart} DOT {modulepart}
m_dotText = "";
nodep->lhsp()->iterateAndNext(*this);
@ -165,6 +187,7 @@ private:
}
virtual void visit(AstSelBit* nodep, AstNUser*) {
if (!nodep->user1Inc()) { // Process only once.
cleanFileline(nodep);
if (m_inModDot) { // Already under dot, so this is {modulepart} DOT {modulepart}
m_dotText = "";
nodep->lhsp()->iterateAndNext(*this);
@ -193,6 +216,7 @@ private:
virtual void visit(AstNodePreSel* nodep, AstNUser*) {
// Excludes simple AstSel, see above
if (!nodep->user1Inc()) { // Process only once.
cleanFileline(nodep);
if (m_inModDot) { // Already under dot, so this is {modulepart} DOT {modulepart}
nodep->v3error("Syntax Error: Range ':', '+:' etc are not allowed in the cell part of a dotted reference");
} else if (m_exp==AstParseRefExp::PX_FUNC) {
@ -215,6 +239,7 @@ private:
}
virtual void visit(AstText* nodep, AstNUser*) {
if (!nodep->user1Inc()) { // Process only once.
cleanFileline(nodep);
if (m_exp != AstParseRefExp::PX_NONE) {
UINFO(7," "<<nodep<<endl);
if (m_inModDot) { // Dotted part, just pass up
@ -228,6 +253,7 @@ private:
}
virtual void visit(AstEnumItem* nodep, AstNUser*) {
// Expand ranges
cleanFileline(nodep);
nodep->iterateChildren(*this);
if (nodep->rangep()) {
if (!nodep->rangep()->msbp()->castConst()
@ -251,12 +277,14 @@ private:
virtual void visit(AstVar* nodep, AstNUser*) {
cleanFileline(nodep);
m_varp = nodep;
nodep->iterateChildren(*this);
m_varp = NULL;
}
virtual void visit(AstAttrOf* nodep, AstNUser*) {
cleanFileline(nodep);
nodep->iterateChildren(*this);
if (nodep->attrType() == AstAttrType::VAR_CLOCK) {
if (!m_varp) nodep->v3fatalSrc("Attribute not attached to variable");
@ -303,6 +331,7 @@ private:
virtual void visit(AstAlwaysPublic* nodep, AstNUser*) {
// AlwaysPublic was attached under a var, but it's a statement that should be
// at the same level as the var
cleanFileline(nodep);
nodep->iterateChildren(*this);
if (m_varp) {
nodep->unlinkFrBack();
@ -315,6 +344,7 @@ private:
}
virtual void visit(AstDefImplicitDType* nodep, AstNUser*) {
cleanFileline(nodep);
UINFO(8," DEFIMPLICIT "<<nodep<<endl);
// Must remember what names we've already created, and combine duplicates
// so that for "var enum {...} a,b" a & b will share a common typedef
@ -351,6 +381,7 @@ private:
virtual void visit(AstNode* nodep, AstNUser*) {
// Default: Just iterate
cleanFileline(nodep);
checkExpected(nodep); // So we detect node types we forgot to list here
nodep->iterateChildren(*this);
}

View File

@ -170,27 +170,36 @@ public:
// thus undriven+unused bits get UNUSED warnings, as they're not as buggy.
if (!unusedMatch(nodep)) {
nodep->v3warn(UNUSED, "Signal is not driven, nor used: "<<nodep->prettyName());
nodep->fileline()->modifyWarnOff(V3ErrorCode::UNUSED, true); // Warn only once
}
} else if (allD && !anyU) {
if (!unusedMatch(nodep)) {
nodep->v3warn(UNUSED, "Signal is not used: "<<nodep->prettyName());
nodep->fileline()->modifyWarnOff(V3ErrorCode::UNUSED, true); // Warn only once
}
} else if (!anyD && allU) {
nodep->v3warn(UNDRIVEN, "Signal is not driven: "<<nodep->prettyName());
nodep->fileline()->modifyWarnOff(V3ErrorCode::UNDRIVEN, true); // Warn only once
} else {
// Bits have different dispositions
bool setU=false; bool setD=false;
if (anynotDU && !unusedMatch(nodep)) {
nodep->v3warn(UNUSED, "Bits of signal are not driven, nor used: "<<nodep->prettyName()
<<bitNames(BN_BOTH));
setU=true;
}
if (anyDnotU && !unusedMatch(nodep)) {
nodep->v3warn(UNUSED, "Bits of signal are not used: "<<nodep->prettyName()
<<bitNames(BN_UNUSED));
setU=true;
}
if (anyUnotD) {
nodep->v3warn(UNDRIVEN, "Bits of signal are not driven: "<<nodep->prettyName()
<<bitNames(BN_UNDRIVEN));
setD=true;
}
if (setU) nodep->fileline()->modifyWarnOff(V3ErrorCode::UNUSED, true); // Warn only once
if (setD) nodep->fileline()->modifyWarnOff(V3ErrorCode::UNDRIVEN, true); // Warn only once
}
}
}

View File

@ -16,6 +16,7 @@ compile (
%Warning-CDCRSTLOGIC: Use "/\* verilator lint_off CDCRSTLOGIC \*/" and lint_on around source to disable this message.
%Warning-CDCRSTLOGIC: See details in obj_dir/t_cdc_async_bad/Vt_cdc_async_bad__cdc.txt
%Warning-CDCRSTLOGIC: t/t_cdc_async_bad.v:\d+: Logic in path that feeds async reset, via signal: v.rst6a_bad_n
%Warning-CDCRSTLOGIC: t/t_cdc_async_bad.v:\d+: Logic in path that feeds async reset, via signal: v.rst6b_bad_n
%Warning-CDCRSTLOGIC: t/t_cdc_async_bad.v:\d+: Logic in path that feeds async reset, via signal: v.rst3_bad_n
%Error: Exiting due to.*',
);

View File

@ -0,0 +1,24 @@
#!/usr/bin/perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003-2009 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.
compile (
make_top_shell => 0,
make_main => 0,
v_flags2 => ["--lint-only -Wwarn-UNUSED"],
verilator_make_gcc => 0,
fails=>1,
expect=>
'%Warning-UNUSED: t/t_lint_once_bad.v:\d+: Signal is not driven, nor used: unus1
%Warning-UNUSED: Use .* to disable this message.
%Warning-UNUSED: t/t_lint_once_bad.v:\d+: Signal is not driven, nor used: unus2
%Error: Exiting due to.*',
) if $Self->{v3};
ok(1);
1;

View File

@ -0,0 +1,19 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2006 by Wilson Snyder.
// Check that we report warnings only once on parameterized modules
// Also check that we don't suppress warnings on the same line
module t ();
sub #(.A(1)) sub1();
sub #(.A(2)) sub2();
sub #(.A(3)) sub3();
endmodule
module sub;
parameter A = 0;
reg [A:0] unus1; reg [A:0] unus2;
endmodule