From 0fed1d34d174ea1f49949b1ab939e441d799265c Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Wed, 10 Dec 2008 17:10:03 -0500 Subject: [PATCH] Add /*verilator coverage_module_off*/ --- Changes | 2 ++ bin/verilator | 11 +++++++++-- src/V3Ast.h | 1 + src/V3AstNodes.h | 7 +++++-- src/V3Coverage.cpp | 12 +++++++++--- src/V3EmitV.cpp | 8 ++------ src/V3LinkResolve.cpp | 5 +++++ src/verilog.l | 3 ++- src/verilog.y | 6 ++++-- test_regress/driver.pl | 2 ++ test_regress/t/t_cover_line.v | 22 ++++++++++++++++++++++ 11 files changed, 63 insertions(+), 16 deletions(-) diff --git a/Changes b/Changes index 0ba1f6a16..a04a35003 100644 --- a/Changes +++ b/Changes @@ -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] diff --git a/bin/verilator b/bin/verilator index 0baf23369..d701f8f8c 100755 --- a/bin/verilator +++ b/bin/verilator @@ -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*/ diff --git a/src/V3Ast.h b/src/V3Ast.h index e50a3c9a2..a62d65391 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -56,6 +56,7 @@ class AstPragmaType { public: enum en { COVERAGE_BLOCK_OFF, + COVERAGE_MODULE_OFF, INLINE_MODULE, NO_INLINE_MODULE, NO_INLINE_TASK, diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index 6fd381ab9..12668ac91 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -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; } diff --git a/src/V3Coverage.cpp b/src/V3Coverage.cpp index 86bb8d22e..33861524c 100644 --- a/src/V3Coverage.cpp +++ b/src/V3Coverage.cpp @@ -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: "<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()); diff --git a/src/V3LinkResolve.cpp b/src/V3LinkResolve.cpp index eb54cc1a8..2256610d9 100644 --- a/src/V3LinkResolve.cpp +++ b/src/V3LinkResolve.cpp @@ -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; diff --git a/src/verilog.l b/src/verilog.l index d3cd551cc..2e468585c 100644 --- a/src/verilog.l +++ b/src/verilog.l @@ -554,7 +554,8 @@ escid \\[^ \t\f\r\n]+ { "/*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;} diff --git a/src/verilog.y b/src/verilog.y index 42c2a8677..c9f3f1936 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -268,7 +268,8 @@ class AstSenTree; %token yVL_CLOCK "/*verilator sc_clock*/" %token yVL_CLOCK_ENABLE "/*verilator clock_enable*/" -%token yVL_COVER_OFF "/*verilator coverage_block_off*/" +%token yVL_COVERAGE_BLOCK_OFF "/*verilator coverage_block_off*/" +%token yVL_COVERAGE_MODULE_OFF "/*verilator coverage_module_off*/" %token yVL_FULL_CASE "/*verilator full_case*/" %token yVL_INLINE_MODULE "/*verilator inline_module*/" %token yVL_ISOLATE_ASSIGNMENTS "/*verilator isolate_assignments*/" @@ -629,6 +630,7 @@ modItem: | 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: | 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; } diff --git a/test_regress/driver.pl b/test_regress/driver.pl index d4fcb6f5b..6904b8be8 100755 --- a/test_regress/driver.pl +++ b/test_regress/driver.pl @@ -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}; diff --git a/test_regress/t/t_cover_line.v b/test_regress/t/t_cover_line.v index 7e0f3dded..9c50d555d 100644 --- a/test_regress/t/t_cover_line.v +++ b/test_regress/t/t_cover_line.v @@ -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