Add /*verilator coverage_module_off*/

This commit is contained in:
Wilson Snyder 2008-12-10 17:10:03 -05:00
parent a1e091cff7
commit 0fed1d34d1
11 changed files with 63 additions and 16 deletions

View File

@ -5,6 +5,8 @@ indicates the contributor was also the author of the fix; Thanks!
* Verilator 3.700***
** Add /*verilator coverage_module_off*/.
*** Optimize two-level shift and and/or trees, +23% on one test.
*** Support posedge of bit-selected signals, bug45. [Rodney Sinclair]

View File

@ -311,7 +311,8 @@ corresponding to each counter are written into logs/coverage.pl.
Verilator automatically disables coverage of branches that have a $stop in
them, as it is assumed $stop branches contain an error check that should
not occur. A /*verilator coverage_block_off*/ comment will perform a
similar function on any code in that block or below.
similar function on any code in that block or below, or /*verilator
coverage_module_off*/ will disable coverage on the entire module.
Note Verilator may over-count combinatorial (non-clocked) blocks when those
blocks receive signals which have had the UNOPTFLAT warning disabled; for
@ -1221,7 +1222,13 @@ ignored in the scheduling algorithm, improving performance.
=item /*verilator coverage_block_off*/
Specifies the entire begin/end block should be ignored for coverage analysis.
Specifies the entire begin/end block should be ignored for coverage
analysis purposes.
=item /*verilator coverage_module_off*/
Specifies the entire module should be ignored for coverage analysis
purposes.
=item /*verilator inline_module*/

View File

@ -56,6 +56,7 @@ class AstPragmaType {
public:
enum en {
COVERAGE_BLOCK_OFF,
COVERAGE_MODULE_OFF,
INLINE_MODULE,
NO_INLINE_MODULE,
NO_INLINE_TASK,

View File

@ -574,6 +574,7 @@ struct AstModule : public AstNode {
private:
string m_name; // Name of the module
string m_origName; // Name of the module, ignoring name() changes, for dot lookup
bool m_modCover:1; // Coverage of this module
bool m_modPublic:1; // Module has public references
bool m_modTrace:1; // Tracing this module
bool m_inLibrary:1; // From a library, no error if not used, never top level
@ -583,8 +584,8 @@ private:
public:
AstModule(FileLine* fl, const string& name)
: AstNode (fl)
,m_name(name), m_origName(name), m_modPublic(false)
,m_modTrace(false), m_inLibrary(false)
,m_name(name), m_origName(name), m_modCover(true)
,m_modPublic(false), m_modTrace(false), m_inLibrary(false)
,m_level(0), m_varNum(0), m_clkReqVarp(NULL) { }
ASTNODE_NODE_FUNCS(Module, MODULE)
virtual void dump(ostream& str);
@ -608,6 +609,8 @@ public:
int varNumGetInc() { return ++m_varNum; }
AstVar* clkReqVarp() const { return m_clkReqVarp; }
void clkReqVarp(AstVar* varp) { m_clkReqVarp = varp; }
void modCover(bool flag) { m_modCover = flag; }
bool modCover() const { return m_modCover; }
void modPublic(bool flag) { m_modPublic = flag; }
bool modPublic() const { return m_modPublic; }
void modTrace(bool flag) { m_modTrace = flag; }

View File

@ -73,13 +73,17 @@ private:
return new AstCoverInc(fl, declp);
}
// VISITORS
// VISITORS - BOTH
virtual void visit(AstModule* nodep, AstNUser*) {
m_modp = nodep;
m_fileps.clear();
nodep->iterateChildren(*this);
if (nodep->modCover()) { // Cleared by /*verilator coverage_module_off*/
m_fileps.clear();
nodep->iterateChildren(*this);
}
m_modp = NULL;
}
// VISITORS - LINE COVERAGE
virtual void visit(AstIf* nodep, AstNUser*) {
UINFO(4," IF: "<<nodep<<endl);
if (m_checkBlock) {
@ -157,6 +161,8 @@ private:
}
m_beginHier = oldHier;
}
// VISITORS - BOTH
virtual void visit(AstNode* nodep, AstNUser*) {
// Default: Just iterate
if (m_checkBlock) {

View File

@ -157,12 +157,8 @@ class EmitVBaseVisitor : public EmitCBaseVisitor {
puts((string)"// "+nodep->name()+"\n");
nodep->iterateChildren(*this);
}
virtual void visit(AstCoverDecl*, AstNUser*) {
// N/A
}
virtual void visit(AstCoverInc*, AstNUser*) {
// N/A
}
virtual void visit(AstCoverDecl*, AstNUser*) {} // N/A
virtual void visit(AstCoverInc*, AstNUser*) {} // N/A
void visitNodeDisplay(AstNode* nodep, AstNode* filep, const string& text, AstNode* exprsp) {
putbs(nodep->verilogKwd());

View File

@ -334,6 +334,11 @@ private:
m_modp->modPublic(true); // Need to get to the task...
nodep->unlinkFrBack(); pushDeletep(nodep); nodep=NULL;
}
else if (nodep->pragType() == AstPragmaType::COVERAGE_MODULE_OFF) {
if (!m_modp) nodep->v3fatalSrc("COVERAGE_MODULE_OFF not under a module\n");
m_modp->modCover(false);
nodep->unlinkFrBack(); pushDeletep(nodep); nodep=NULL;
}
else if (nodep->pragType() == AstPragmaType::COVERAGE_BLOCK_OFF) {
if (!v3Global.opt.coverageLine()) { // No need for block statements; may optimize better without
nodep->unlinkFrBack(); pushDeletep(nodep); nodep=NULL;

View File

@ -554,7 +554,8 @@ escid \\[^ \t\f\r\n]+
<V95,V01,V05,S05,PSL>{
"/*verilator"{ws}*"*/" {} /* Ignore empty comments, may be `endif // verilator */
"/*verilator clock_enable*/" {yylval.fileline = CRELINE(); return yVL_CLOCK_ENABLE;}
"/*verilator coverage_block_off*/" {yylval.fileline = CRELINE(); return yVL_COVER_OFF;}
"/*verilator coverage_block_off*/" {yylval.fileline = CRELINE(); return yVL_COVERAGE_BLOCK_OFF;}
"/*verilator coverage_module_off*/" {yylval.fileline = CRELINE(); return yVL_COVERAGE_MODULE_OFF;}
"/*verilator full_case*/" {yylval.fileline = CRELINE(); return yVL_FULL_CASE;}
"/*verilator inline_module*/" {yylval.fileline = CRELINE(); return yVL_INLINE_MODULE;}
"/*verilator isolate_assignments*/" {yylval.fileline = CRELINE(); return yVL_ISOLATE_ASSIGNMENTS;}

View File

@ -268,7 +268,8 @@ class AstSenTree;
%token<fileline> yVL_CLOCK "/*verilator sc_clock*/"
%token<fileline> yVL_CLOCK_ENABLE "/*verilator clock_enable*/"
%token<fileline> yVL_COVER_OFF "/*verilator coverage_block_off*/"
%token<fileline> yVL_COVERAGE_BLOCK_OFF "/*verilator coverage_block_off*/"
%token<fileline> yVL_COVERAGE_MODULE_OFF "/*verilator coverage_module_off*/"
%token<fileline> yVL_FULL_CASE "/*verilator full_case*/"
%token<fileline> yVL_INLINE_MODULE "/*verilator inline_module*/"
%token<fileline> yVL_ISOLATE_ASSIGNMENTS "/*verilator isolate_assignments*/"
@ -629,6 +630,7 @@ modItem<nodep>:
| yaSCIMPH { $$ = new AstScImpHdr(CRELINE(),*$1); }
| yaSCCTOR { $$ = new AstScCtor(CRELINE(),*$1); }
| yaSCDTOR { $$ = new AstScDtor(CRELINE(),*$1); }
| yVL_COVERAGE_MODULE_OFF { $$ = new AstPragma($1,AstPragmaType::COVERAGE_MODULE_OFF); }
| yVL_INLINE_MODULE { $$ = new AstPragma($1,AstPragmaType::INLINE_MODULE); }
| yVL_NO_INLINE_MODULE { $$ = new AstPragma($1,AstPragmaType::NO_INLINE_MODULE); }
| yVL_PUBLIC_MODULE { $$ = new AstPragma($1,AstPragmaType::PUBLIC_MODULE); }
@ -974,7 +976,7 @@ stmt<nodep>:
| yD_FINISH '(' expr ')' ';' { $$ = new AstFinish($1); }
| yD_STOP parenE ';' { $$ = new AstStop($1); }
| yD_STOP '(' expr ')' ';' { $$ = new AstStop($1); }
| yVL_COVER_OFF { $$ = new AstPragma($1,AstPragmaType::COVERAGE_BLOCK_OFF); }
| yVL_COVERAGE_BLOCK_OFF { $$ = new AstPragma($1,AstPragmaType::COVERAGE_BLOCK_OFF); }
| stateCaseForIf { $$ = $1; }
| taskRef ';' { $$ = $1; }

View File

@ -473,6 +473,8 @@ sub execute {
sub inline_checks {
my $self = (ref $_[0]? shift : $Self);
return 1 if $self->errors;
return 1 if !$self->{v3};
my %param = (%{$self}, @_); # Default arguments are from $self
my $covfn = $Self->{coverage_filename};

View File

@ -35,6 +35,10 @@ module t (/*AUTOARG*/
// Inputs
.clk (clk),
.toggle (toggle));
off o1 (/*AUTOINST*/
// Inputs
.clk (clk),
.toggle (toggle));
always @ (posedge clk) begin
if (cyc!=0) begin
@ -134,3 +138,21 @@ module tsk (/*AUTOARG*/
endtask
endmodule
module off (/*AUTOARG*/
// Inputs
clk, toggle
);
input clk;
input toggle;
// verilator coverage_module_off
always @ (posedge clk) begin
if (toggle) begin
// CHECK_COVER_MISSING(-1)
// because under coverage_module_off
end
end
endmodule