Add SYNCASYNCNET

This commit is contained in:
Wilson Snyder 2010-12-31 07:51:14 -05:00
parent 4ca7f8834c
commit 8d21917035
6 changed files with 209 additions and 17 deletions

View File

@ -26,6 +26,8 @@ indicates the contributor was also the author of the fix; Thanks!
*** With --Wall, add INCABSPATH warning on `include with absolute paths.
*** With --Wall, add SYNCASYNCNET warning on mixed sync/async reset nets.
*** With --Wall, add UNDRIVEN warning on undriven nets.
*** With --Wall, add UNUSED warning on unused nets.

View File

@ -872,9 +872,9 @@ Disable the specified warning message.
Disable all lint related warning messages, and all style warnings. This is
equivalent to "-Wno-CASEINCOMPLETE -Wno-CASEOVERLAP -Wno-CASEX
-Wno-CASEWITHX -Wno-CMPCONST -Wno-IMPLICIT -Wno-LITENDIAN -Wno-UNDRIVEN
-Wno-UNSIGNED -Wno-UNUSED -Wno-WIDTH" plus the list shown
for Wno-style.
-Wno-CASEWITHX -Wno-CMPCONST -Wno-IMPLICIT -Wno-LITENDIAN -Wno-SYNCASYNCNET
-Wno-UNDRIVEN -Wno-UNSIGNED -Wno-UNUSED -Wno-WIDTH" plus the list shown for
Wno-style.
It is strongly recommended you cleanup your code rather than using this
option, it is only intended to be use when running test-cases of code
@ -884,7 +884,8 @@ received from third parties.
Disable all code style related warning messages (note by default they are
already disabled). This is equivalent to "-Wno-DECLFILENAME -Wno-DEFPARAM
-Wno-INCABSPATH -Wno-UNDRIVEN -Wno-UNUSED -Wno-VARHIDDEN".
-Wno-INCABSPATH -Wno-SYNCASYNCNET -Wno-UNDRIVEN -Wno-UNUSED
-Wno-VARHIDDEN".
=item -Wwarn-I<message>
@ -895,14 +896,14 @@ Enables the specified warning message.
Enable all lint related warning messages (note by default they are already
enabled), but do not affect style messages. This is equivalent to
"-Wwarn-CASEINCOMPLETE -Wwarn-CASEOVERLAP -Wwarn-CASEX -Wwarn-CASEWITHX
-Wwarn-CMPCONST -Wwarn-IMPLICIT -Wwarn-LITENDIAN -Wwarn-UNDRIVEN
-Wwarn-UNSIGNED -Wwarn-UNUSED -Wwarn-WIDTH".
-Wwarn-CMPCONST -Wwarn-IMPLICIT -Wwarn-LITENDIAN -Wwarn-UNSIGNED
-Wwarn-WIDTH".
=item -Wwarn-style
Enable all code style related warning messages. This is equivalent to
"-Wwarn-DECLFILENAME -Wwarn-DEFPARAM -Wwarn-INCABSPATH -Wwarn-UNDRIVEN
-Wwarn-UNUSED -Wwarn-VARHIDDEN".
"-Wwarn-DECLFILENAME -Wwarn-DEFPARAM -Wwarn-INCABSPATH -Wwarn-SYNCASYNCNET
-Wwarn-UNDRIVEN -Wwarn-UNUSED -Wwarn-VARHIDDEN".
=item -x-assign 0
@ -2565,6 +2566,18 @@ name would result in odd C compiler errors. You may disable this error
message as you would disable warnings, but the symbol will be renamed by
Verilator to avoid the conflict.
=item SYNCASYNCNET
Warns that the specified net is used in at least two different always
statements with posedge/negedges (i.e. a flop). One usage has the signal
in the sensitivity list and body, probably as a async reset, and the other
usage has the signal only in the body, probably as a sync reset. Mixing
sync and async resets is usually a mistake. The warning may be disabled
with a lint_off pragma around the net, or either flopped block.
Disabled by default as this is a code style warning; it will simulate
correctly.
=item TASKNSVAR
Error when a call to a task or function has a output from that task tied to

View File

@ -75,6 +75,7 @@ public:
REDEFMACRO, // Redefining existing define macro
STMTDLY, // Delayed statement
SYMRSVDWORD, // Symbol is Reserved Word
SYNCASYNCNET, // Mixed sync + async reset
UNDRIVEN, // No drivers
UNOPT, // Unoptimizable block
UNOPTFLAT, // Unoptimizable block after flattening
@ -109,7 +110,7 @@ public:
"IFDEPTH", "IMPERFECTSCH", "IMPLICIT", "IMPURE", "INCABSPATH",
"LITENDIAN", "MODDUP",
"MULTIDRIVEN", "REDEFMACRO",
"STMTDLY", "SYMRSVDWORD",
"STMTDLY", "SYMRSVDWORD", "SYNCASYNCNET",
"UNDRIVEN", "UNOPT", "UNOPTFLAT", "UNSIGNED", "UNUSED",
"VARHIDDEN", "WIDTH", "WIDTHCONCAT",
" MAX"
@ -138,6 +139,7 @@ public:
bool styleError() const { return ( m_e==DEFPARAM
|| m_e==DECLFILENAME
|| m_e==INCABSPATH
|| m_e==SYNCASYNCNET
|| m_e==UNDRIVEN
|| m_e==UNUSED
|| m_e==VARHIDDEN ); }

View File

@ -86,19 +86,25 @@ class GateVarVertex : public GateEitherVertex {
AstVarScope* m_varScp;
bool m_isTop;
bool m_isClock;
AstNode* m_rstSyncNodep; // Used as reset and not in SenItem, in clocked always
AstNode* m_rstAsyncNodep; // Used as reset and in SenItem, in clocked always
public:
GateVarVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp)
: GateEitherVertex(graphp, scopep), m_varScp(varScp), m_isTop(false)
, m_isClock(false) {}
, m_isClock(false), m_rstSyncNodep(NULL), m_rstAsyncNodep(NULL) {}
virtual ~GateVarVertex() {}
// Accessors
AstVarScope* varScp() const { return m_varScp; }
virtual string name() const { return (cvtToStr((void*)m_varScp)+" "+varScp()->name()); }
virtual string dotColor() const { return "blue"; }
void setIsTop() { m_isTop = true; }
void setIsClock() { m_isClock = true; setConsumed("isclk"); }
bool isTop() const { return m_isTop; }
void setIsTop() { m_isTop = true; }
bool isClock() const { return m_isClock; }
void setIsClock() { m_isClock = true; setConsumed("isclk"); }
AstNode* rstSyncNodep() const { return m_rstSyncNodep; }
void rstSyncNodep(AstNode* nodep) { m_rstSyncNodep=nodep; }
AstNode* rstAsyncNodep() const { return m_rstAsyncNodep; }
void rstAsyncNodep(AstNode* nodep) { m_rstAsyncNodep=nodep; }
};
class GateLogicVertex : public GateEitherVertex {
@ -236,7 +242,10 @@ private:
//Entire netlist:
// AstVarScope::user1p -> GateVarVertex* for usage var, 0=not set yet
// {statement}Node::user1p -> GateLogicVertex* for this statement
// AstVarScope::user2 -> bool: Signal used in SenItem in *this* always statement
// AstVar::user2 -> bool: Warned about SYNCASYNCNET
AstUser1InUse m_inuser1;
AstUser2InUse m_inuser2;
// STATE
V3Graph m_graph; // Scoreboard of var usages/dependencies
@ -286,12 +295,12 @@ private:
}
if (varscp->varp()->isUsedClock()) vertexp->setConsumed("clock");
}
if (m_inSenItem) vertexp->setIsClock();
return vertexp;
}
void optimizeSignals(bool allowMultiIn);
void optimizeElimVar(AstVarScope* varscp, AstNode* logicp, AstNode* consumerp);
void warnSignals();
void consumedMark();
void consumedMarkRecurse(GateEitherVertex* vertexp);
void consumedMove();
@ -310,6 +319,8 @@ private:
optimizeSignals(false);
// Then propagate more complicated equations
optimizeSignals(true);
// Warn
warnSignals();
consumedMark();
m_graph.dumpDotFilePrefixed("gate_opt");
// Rewrite assignments
@ -334,7 +345,9 @@ private:
UINFO(4," BLOCK "<<nodep<<endl);
m_activeReducible = !(nodep->hasClocked()); // Seq logic outputs aren't reducible
m_activep = nodep;
AstNode::user2ClearTree();
nodep->iterateChildren(*this);
AstNode::user2ClearTree();
m_activep = NULL;
m_activeReducible = true;
}
@ -343,14 +356,24 @@ private:
if (!m_logicVertexp) nodep->v3fatalSrc("Var ref not under a logic block\n");
AstVarScope* varscp = nodep->varScopep();
if (!varscp) nodep->v3fatalSrc("Var didn't get varscoped in V3Scope.cpp\n");
GateVarVertex* varvertexp = makeVarVertex(varscp);
GateVarVertex* vvertexp = makeVarVertex(varscp);
UINFO(5," VARREF to "<<varscp<<endl);
if (m_inSenItem) vvertexp->setIsClock();
// For SYNCASYNCNET
if (m_inSenItem) varscp->user2(true);
else if (m_activep && m_activep->hasClocked() && !nodep->lvalue()) {
if (varscp->user2()) {
if (!vvertexp->rstSyncNodep()) vvertexp->rstSyncNodep(nodep);
} else {
if (!vvertexp->rstAsyncNodep()) vvertexp->rstAsyncNodep(nodep);
}
}
// We use weight of one; if we ref the var more than once, when we simplify,
// the weight will increase
if (nodep->lvalue()) {
new V3GraphEdge(&m_graph, m_logicVertexp, varvertexp, 1);
new V3GraphEdge(&m_graph, m_logicVertexp, vvertexp, 1);
} else {
new V3GraphEdge(&m_graph, varvertexp, m_logicVertexp, 1);
new V3GraphEdge(&m_graph, vvertexp, m_logicVertexp, 1);
}
}
}
@ -449,7 +472,7 @@ void GateVisitor::optimizeSignals(bool allowMultiIn) {
if (0) {
// If we warned here after constant propagation, what the user considered
// reasonable logic may have disappeared. Issuing a warning would
// thus be confusing.
// thus be confusing. V3Undriven now handles this.
vvertexp->varScp()->varp()->v3warn(UNDRIVEN,"Signal has no drivers "
<<vvertexp->scopep()->prettyName()<<"."
<<vvertexp->varScp()->varp()->prettyName());
@ -643,6 +666,34 @@ void GateVisitor::consumedMove() {
}
}
//----------------------------------------------------------------------
void GateVisitor::warnSignals() {
AstNode::user2ClearTree();
for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp=itp->verticesNextp()) {
if (GateVarVertex* vvertexp = dynamic_cast<GateVarVertex*>(itp)) {
AstVarScope* vscp = vvertexp->varScp();
AstNode* sp = vvertexp->rstSyncNodep();
AstNode* ap = vvertexp->rstAsyncNodep();
if (ap && sp && !vscp->varp()->user2()) {
// This is somewhat wrong, as marking one flop as ok for sync
// may mean a different flop now fails. However it's a pain to
// then report a warning in a new place - we should report them all at once.
// Instead we'll disable if any disabled
if (!vscp->fileline()->warnIsOff(V3ErrorCode::SYNCASYNCNET)
&& !ap->fileline()->warnIsOff(V3ErrorCode::SYNCASYNCNET)
&& !sp->fileline()->warnIsOff(V3ErrorCode::SYNCASYNCNET)
) {
vscp->varp()->user2(true); // Warn only once per signal
vscp->v3warn(SYNCASYNCNET,"Signal flopped as both synchronous and async: "<<vscp->prettyName());
ap->v3warn(SYNCASYNCNET,"... Location of async usage");
sp->v3warn(SYNCASYNCNET,"... Location of sync usage");
}
}
}
}
}
//######################################################################
// Push constant into expressions and reevaluate

View File

@ -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 2008 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 (
v_flags2 => ["--lint-only -Wall -Wno-DECLFILENAME --if-depth 10"],
fails=>1,
verilator_make_gcc => 0,
make_top_shell => 0,
make_main => 0,
expect=>
'%Warning-SYNCASYNCNET: t/t_lint_syncasyncnet_bad.v:\d+: Signal flopped as both synchronous and async: TOP->rst_both_l
%Warning-SYNCASYNCNET: Use .* around source to disable this message.
%Warning-SYNCASYNCNET: t/t_lint_syncasyncnet_bad.v:\d+: ... Location of async usage
%Warning-SYNCASYNCNET: t/t_lint_syncasyncnet_bad.v:\d+: ... Location of sync usage
%Error: Exiting due to.*',
) if $Self->{v3};
ok(1);
1;

View File

@ -0,0 +1,98 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2010 by Wilson Snyder.
module t (/*AUTOARG*/
// Inputs
rst_sync_l, rst_both_l, rst_async_l, d, clk
);
/*AUTOINPUT*/
// Beginning of automatic inputs (from unused autoinst inputs)
input clk; // To sub1 of sub1.v, ...
input d; // To sub1 of sub1.v, ...
input rst_async_l; // To sub2 of sub2.v
input rst_both_l; // To sub1 of sub1.v, ...
input rst_sync_l; // To sub1 of sub1.v
// End of automatics
sub1 sub1 (/*AUTOINST*/
// Inputs
.clk (clk),
.rst_both_l (rst_both_l),
.rst_sync_l (rst_sync_l),
.d (d));
sub2 sub2 (/*AUTOINST*/
// Inputs
.clk (clk),
.rst_both_l (rst_both_l),
.rst_async_l (rst_async_l),
.d (d));
endmodule
module sub1 (/*AUTOARG*/
// Inputs
clk, rst_both_l, rst_sync_l, d
);
input clk;
input rst_both_l;
input rst_sync_l;
//input rst_async_l;
input d;
reg q1;
reg q2;
always @(posedge clk) begin
if (~rst_sync_l) begin
/*AUTORESET*/
// Beginning of autoreset for uninitialized flops
q1 <= 1'h0;
// End of automatics
end else begin
q1 <= d;
end
end
always @(posedge clk) begin
q2 <= (~rst_both_l) ? 1'b0 : d;
if (0 && q1 && q2) ;
end
endmodule
module sub2 (/*AUTOARG*/
// Inputs
clk, rst_both_l, rst_async_l, d
);
input clk;
input rst_both_l;
//input rst_sync_l;
input rst_async_l;
input d;
reg q1;
reg q2;
reg q3;
always @(posedge clk or negedge rst_async_l) begin
if (~rst_async_l) begin
/*AUTORESET*/
// Beginning of autoreset for uninitialized flops
q1 <= 1'h0;
// End of automatics
end else begin
q1 <= d;
end
end
always @(posedge clk or negedge rst_both_l) begin
q2 <= (~rst_both_l) ? 1'b0 : d;
end
// Make there be more async uses than sync uses
always @(posedge clk or negedge rst_both_l) begin
q3 <= (~rst_both_l) ? 1'b0 : d;
if (0 && q1 && q2 && q3) ;
end
endmodule