Add INFINITELOOP warning, bug1254.
This commit is contained in:
parent
f98940e40a
commit
4901668f13
2
Changes
2
Changes
|
|
@ -8,6 +8,8 @@ The contributors that suggested a given feature are shown in []. Thanks!
|
||||||
|
|
||||||
*** Support DPI open arrays, bug909, bug1245. [David Pierce, Victor Besyakov]
|
*** Support DPI open arrays, bug909, bug1245. [David Pierce, Victor Besyakov]
|
||||||
|
|
||||||
|
*** Add INFINITELOOP warning, bug1254. [Alex Solomatnikov]
|
||||||
|
|
||||||
**** Support > 64 bit decimal $display.
|
**** Support > 64 bit decimal $display.
|
||||||
|
|
||||||
**** Support DPI time and svLogicVal. [Victor Besyakov]
|
**** Support DPI time and svLogicVal. [Victor Besyakov]
|
||||||
|
|
|
||||||
|
|
@ -3275,6 +3275,18 @@ command line to specify the top include source directories.
|
||||||
Disabled by default as this is a code style warning; it will simulate
|
Disabled by default as this is a code style warning; it will simulate
|
||||||
correctly.
|
correctly.
|
||||||
|
|
||||||
|
=item INFINITELOOP
|
||||||
|
|
||||||
|
Warns that a while or for statement has a condition that is always true.
|
||||||
|
and thus result in an infinite loop if the statement ever executes.
|
||||||
|
|
||||||
|
This might be unintended behavior if the loop body contains statements that
|
||||||
|
in other statements that would make time pass, which Verilator is ignoring
|
||||||
|
due to e.g. STMTDLY warnings being disabled.
|
||||||
|
|
||||||
|
Ignoring this warning will only suppress the lint check, it will simulate
|
||||||
|
correctly (i.e. hang due to the infinite loop).
|
||||||
|
|
||||||
=item INITIALDLY
|
=item INITIALDLY
|
||||||
|
|
||||||
Warns that you have a delayed assignment inside of an initial or final
|
Warns that you have a delayed assignment inside of an initial or final
|
||||||
|
|
|
||||||
|
|
@ -107,6 +107,7 @@ private:
|
||||||
bool m_doShort; // Remove expressions that short circuit
|
bool m_doShort; // Remove expressions that short circuit
|
||||||
bool m_doV; // Verilog, not C++ conversion
|
bool m_doV; // Verilog, not C++ conversion
|
||||||
bool m_doGenerate; // Postpone width checking inside generate
|
bool m_doGenerate; // Postpone width checking inside generate
|
||||||
|
bool m_hasJumpGo; // JumpGo under this while
|
||||||
AstNodeModule* m_modp; // Current module
|
AstNodeModule* m_modp; // Current module
|
||||||
AstArraySel* m_selp; // Current select
|
AstArraySel* m_selp; // Current select
|
||||||
AstNode* m_scopep; // Current scope
|
AstNode* m_scopep; // Current scope
|
||||||
|
|
@ -2039,7 +2040,13 @@ private:
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
}
|
}
|
||||||
virtual void visit(AstWhile* nodep) {
|
virtual void visit(AstWhile* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
bool oldHasJumpGo = m_hasJumpGo;
|
||||||
|
m_hasJumpGo = false;
|
||||||
|
{
|
||||||
|
nodep->iterateChildren(*this);
|
||||||
|
}
|
||||||
|
bool thisWhileHasJumpGo = m_hasJumpGo;
|
||||||
|
m_hasJumpGo = thisWhileHasJumpGo || oldHasJumpGo;
|
||||||
if (m_doNConst) {
|
if (m_doNConst) {
|
||||||
if (nodep->condp()->isZero()) {
|
if (nodep->condp()->isZero()) {
|
||||||
UINFO(4,"WHILE(0) => nop "<<nodep<<endl);
|
UINFO(4,"WHILE(0) => nop "<<nodep<<endl);
|
||||||
|
|
@ -2047,6 +2054,12 @@ private:
|
||||||
else nodep->unlinkFrBack();
|
else nodep->unlinkFrBack();
|
||||||
nodep->deleteTree(); VL_DANGLING(nodep);
|
nodep->deleteTree(); VL_DANGLING(nodep);
|
||||||
}
|
}
|
||||||
|
else if (nodep->condp()->isNeqZero()) {
|
||||||
|
if (!thisWhileHasJumpGo) {
|
||||||
|
nodep->v3warn(INFINITELOOP, "Infinite loop (condition always true)");
|
||||||
|
nodep->fileline()->modifyWarnOff(V3ErrorCode::INFINITELOOP, true); // Complain just once
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (operandBoolShift(nodep->condp())) {
|
else if (operandBoolShift(nodep->condp())) {
|
||||||
replaceBoolShift(nodep->condp());
|
replaceBoolShift(nodep->condp());
|
||||||
}
|
}
|
||||||
|
|
@ -2080,6 +2093,7 @@ private:
|
||||||
|
|
||||||
virtual void visit(AstJumpGo* nodep) {
|
virtual void visit(AstJumpGo* nodep) {
|
||||||
nodep->iterateChildren(*this);
|
nodep->iterateChildren(*this);
|
||||||
|
m_hasJumpGo = true;
|
||||||
if (m_doExpensive) { nodep->labelp()->user4(true); }
|
if (m_doExpensive) { nodep->labelp()->user4(true); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2460,6 +2474,7 @@ public:
|
||||||
m_doShort = true; // Presently always done
|
m_doShort = true; // Presently always done
|
||||||
m_doV = false;
|
m_doV = false;
|
||||||
m_doGenerate = false; // Inside generate conditionals
|
m_doGenerate = false; // Inside generate conditionals
|
||||||
|
m_hasJumpGo = false;
|
||||||
m_warn = false;
|
m_warn = false;
|
||||||
m_wremove = true; // Overridden in visitors
|
m_wremove = true; // Overridden in visitors
|
||||||
m_modp = NULL;
|
m_modp = NULL;
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,7 @@ public:
|
||||||
IMPLICIT, // Implicit wire
|
IMPLICIT, // Implicit wire
|
||||||
IMPURE, // Impure function not being inlined
|
IMPURE, // Impure function not being inlined
|
||||||
INCABSPATH, // Include has absolute path
|
INCABSPATH, // Include has absolute path
|
||||||
|
INFINITELOOP, // Infinite loop
|
||||||
INITIALDLY, // Initial delayed statement
|
INITIALDLY, // Initial delayed statement
|
||||||
LITENDIAN, // Little bit endian vector
|
LITENDIAN, // Little bit endian vector
|
||||||
MODDUP, // Duplicate module
|
MODDUP, // Duplicate module
|
||||||
|
|
@ -132,7 +133,7 @@ public:
|
||||||
"CMPCONST", "COLONPLUS", "COMBDLY", "DEFPARAM", "DECLFILENAME",
|
"CMPCONST", "COLONPLUS", "COMBDLY", "DEFPARAM", "DECLFILENAME",
|
||||||
"ENDLABEL", "GENCLK",
|
"ENDLABEL", "GENCLK",
|
||||||
"IFDEPTH", "IMPERFECTSCH", "IMPLICIT", "IMPURE",
|
"IFDEPTH", "IMPERFECTSCH", "IMPLICIT", "IMPURE",
|
||||||
"INCABSPATH", "INITIALDLY",
|
"INCABSPATH", "INFINITELOOP", "INITIALDLY",
|
||||||
"LITENDIAN", "MODDUP",
|
"LITENDIAN", "MODDUP",
|
||||||
"MULTIDRIVEN",
|
"MULTIDRIVEN",
|
||||||
"PINMISSING", "PINNOCONNECT", "PINCONNECTEMPTY",
|
"PINMISSING", "PINNOCONNECT", "PINCONNECTEMPTY",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
#!/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.
|
||||||
|
|
||||||
|
$Self->{vlt} or $Self->skip("Verilator only test");
|
||||||
|
|
||||||
|
compile (
|
||||||
|
v_flags2 => ["--lint-only"],
|
||||||
|
make_top_shell => 0,
|
||||||
|
make_main => 0,
|
||||||
|
verilator_make_gcc => 0,
|
||||||
|
fails=>1,
|
||||||
|
expect=>
|
||||||
|
'%Warning-INFINITELOOP: t/t_lint_infinite.v:\d+: Infinite loop \(condition always true\)
|
||||||
|
%Warning-INFINITELOOP: Use .*
|
||||||
|
%Warning-INFINITELOOP: t/t_lint_infinite.v:\d+: Infinite loop \(condition always true\)
|
||||||
|
.*',
|
||||||
|
);
|
||||||
|
|
||||||
|
ok(1);
|
||||||
|
1;
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
|
// without warranty, 2017 by Wilson Snyder.
|
||||||
|
|
||||||
|
module t ();
|
||||||
|
|
||||||
|
initial begin
|
||||||
|
forever begin end
|
||||||
|
// verilator lint_off UNSIGNED
|
||||||
|
for (reg [31:0] i=0; i>=0; i=i+1) begin end
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
|
|
@ -25,7 +25,9 @@ module t (/*AUTOARG*/);
|
||||||
end
|
end
|
||||||
if (times != 10) $stop;
|
if (times != 10) $stop;
|
||||||
//
|
//
|
||||||
|
// verilator lint_off INFINITELOOP
|
||||||
forever begin
|
forever begin
|
||||||
|
// verilator lint_on INFINITELOOP
|
||||||
$write("*-* All Finished *-*\n");
|
$write("*-* All Finished *-*\n");
|
||||||
$finish;
|
$finish;
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue