Add --trace-coverage.

This commit is contained in:
Wilson Snyder 2019-10-27 09:27:18 -04:00
parent 8f6015aad5
commit f852ba8a33
14 changed files with 397 additions and 26 deletions

View File

@ -12,6 +12,8 @@ The contributors that suggested a given feature are shown in []. Thanks!
*** Add --protect-ids to obscure information in objects, bug1521. [Todd Strader]
*** Add --trace-coverage.
*** Support multithreading on Windows. [Patrick Stewart]
**** Increase case duplicate/incomplete to 16 bit tables, bug1545. [Yossi Nivin]

View File

@ -377,12 +377,13 @@ detailed descriptions in L</"VERILATION ARGUMENTS"> for more information.
--threads-max-mtasks <mtasks> Tune maximum mtask partitioning
--top-module <topname> Name of top level input module
--trace Enable waveform creation
--trace-depth <levels> Depth of tracing
--trace-coverage Enable tracing of coverage
--trace-fst Enable FST waveform creation
--trace-fst-thread Enable FST threaded waveform creation
--trace-depth <levels> Depth of tracing
--trace-max-array <depth> Maximum bit width for tracing
--trace-max-width <width> Maximum array depth for tracing
--trace-params Enable tracing parameters
--trace-params Enable tracing of parameters
--trace-structs Enable tracing structure names
--trace-underscore Enable tracing of _signals
-U<var> Undefine preprocessor define
@ -1392,6 +1393,25 @@ need to add these to your Makefile manually.
Having tracing compiled in may result in some small performance losses,
even when waveforms are not turned on during model execution.
=item --trace-coverage
With --trace and --coverage-*, enable tracing to include a traced signal
for every --coverage-line or --coverage-user inserted coverage point, to
assist in debugging coverage items. Note --coverage-toggle does not get
additional signals added, as the original signals being toggle-analyzed are
already visible.
The added signal will be a 32-bit value which will increment on each
coverage occurrence. Due to this, this option may greatly increase trace
file sizes and simulation time.
=item --trace-depth I<levels>
Specify the number of levels deep to enable tracing, for example
--trace-level 1 to only see the top level's signals. Defaults to the
entire model. Using a small number will decrease visibility, but greatly
improve runtime and trace file size.
=item --trace-fst
Enable FST waveform tracing in the model. This overrides C<--trace> and
@ -1403,13 +1423,6 @@ Enable FST waveform tracing in the model, using a separate thread. This is
typically faster in runtime but slower in total computes than
C<--trace-fst>. This overrides C<--trace> and C<--trace-fst>.
=item --trace-depth I<levels>
Specify the number of levels deep to enable tracing, for example
--trace-level 1 to only see the top level's signals. Defaults to the
entire model. Using a small number will decrease visibility, but greatly
improve runtime and trace file size.
=item --trace-max-array I<depth>
Rarely needed. Specify the maximum array depth of a signal that may be

View File

@ -121,7 +121,7 @@ private:
// V3Coverage assigned us a bucket to increment.
AstCoverInc* covincp = VN_CAST(snodep->coverincp(), CoverInc);
UASSERT_OBJ(covincp, snodep, "Missing AstCoverInc under assertion");
covincp->unlinkFrBack();
covincp->unlinkFrBackWithNext(); // next() might have AstAssign for trace
if (message!="") covincp->declp()->comment(message);
bodysp = covincp;
}

View File

@ -605,6 +605,9 @@ public:
|| m_e==BLOCKTEMP || m_e==MODULETEMP || m_e==STMTTEMP
|| m_e==XTEMP || m_e==IFACEREF);
}
bool isTemp() const {
return (m_e==BLOCKTEMP || m_e==MODULETEMP || m_e==STMTTEMP || m_e==XTEMP);
}
};
inline bool operator==(AstVarType lhs, AstVarType rhs) { return (lhs.m_e == rhs.m_e); }
inline bool operator==(AstVarType lhs, AstVarType::en rhs) { return (lhs.m_e == rhs); }

View File

@ -1335,9 +1335,7 @@ public:
bool isIfaceRef() const { return (varType()==AstVarType::IFACEREF); }
bool isIfaceParent() const { return m_isIfaceParent; }
bool isSignal() const { return varType().isSignal(); }
bool isTemp() const {
return (varType()==AstVarType::BLOCKTEMP || varType()==AstVarType::MODULETEMP
|| varType()==AstVarType::STMTTEMP || varType()==AstVarType::XTEMP); }
bool isTemp() const { return varType().isTemp(); }
bool isToggleCoverable() const {
return ((isIO() || isSignal())
&& (isIO() || isBitLogic())

View File

@ -96,7 +96,8 @@ private:
}
AstCoverInc* newCoverInc(FileLine* fl, const string& hier,
const string& page_prefix, const string& comment) {
const string& page_prefix, const string& comment,
const string& trace_var_name) {
// For line coverage, we may have multiple if's on one line, so disambiguate if
// everything is otherwise identical
// (Don't set column otherwise as it may result in making bins not match up with
@ -123,9 +124,30 @@ private:
declp->hier(hier);
m_modp->addStmtp(declp);
return new AstCoverInc(fl, declp);
AstCoverInc* incp = new AstCoverInc(fl, declp);
if (!trace_var_name.empty() && v3Global.opt.traceCoverage()) {
AstVar* varp = new AstVar(incp->fileline(),
AstVarType::MODULETEMP, trace_var_name,
VFlagBitPacked(), 32);
varp->trace(true);
varp->fileline()->modifyWarnOff(V3ErrorCode::UNUSED, true);
m_modp->addStmtp(varp);
UINFO(5, "New coverage trace: "<<varp<<endl);
AstAssign* assp = new AstAssign(
incp->fileline(),
new AstVarRef(incp->fileline(), varp, true),
new AstAdd(incp->fileline(),
new AstVarRef(incp->fileline(), varp, false),
new AstConst(incp->fileline(), AstConst::WidthedValue(), 32, 1)));
incp->addNext(assp);
}
return incp;
}
string traceNameForLine(AstNode* nodep, const string& type) {
return "vlCoverageLineTrace_"+nodep->fileline()->filebasenameNoExt()
+"__"+cvtToStr(nodep->fileline()->lineno())
+"_"+type;
}
// VISITORS - BOTH
virtual void visit(AstNodeModule* nodep) {
m_modp = nodep;
@ -190,7 +212,7 @@ private:
AstCoverToggle* newp
= new AstCoverToggle(varp->fileline(),
newCoverInc(varp->fileline(), "", "v_toggle",
varp->name()+above.m_comment),
varp->name()+above.m_comment, ""),
above.m_varRefp->cloneTree(true),
above.m_chgRefp->cloneTree(true));
m_modp->addStmtp(newp);
@ -294,9 +316,11 @@ private:
&& nodep->fileline()->coverageOn() && v3Global.opt.coverageLine()) { // if a "if" branch didn't disable it
UINFO(4," COVER: "<<nodep<<endl);
if (nodep->user1()) {
nodep->addIfsp(newCoverInc(nodep->fileline(), "", "v_line", "elsif"));
nodep->addIfsp(newCoverInc(nodep->fileline(), "", "v_line", "elsif",
traceNameForLine(nodep, "elsif")));
} else {
nodep->addIfsp(newCoverInc(nodep->fileline(), "", "v_line", "if"));
nodep->addIfsp(newCoverInc(nodep->fileline(), "", "v_line", "if",
traceNameForLine(nodep, "if")));
}
}
// Don't do empty else's, only empty if/case's
@ -308,7 +332,8 @@ private:
UINFO(4," COVER: "<<nodep<<endl);
if (!elsif) { // elsif done inside if()
nodep->addElsesp(newCoverInc(nodep->elsesp()->fileline(),
"", "v_line", "else"));
"", "v_line", "else",
traceNameForLine(nodep, "else")));
}
}
}
@ -322,7 +347,8 @@ private:
iterateAndNextNull(nodep->bodysp());
if (m_checkBlock) { // if the case body didn't disable it
UINFO(4," COVER: "<<nodep<<endl);
nodep->addBodysp(newCoverInc(nodep->fileline(), "", "v_line", "case"));
nodep->addBodysp(newCoverInc(nodep->fileline(), "", "v_line", "case",
traceNameForLine(nodep, "case")));
}
m_checkBlock = true; // Reset as a child may have cleared it
}
@ -333,7 +359,8 @@ private:
iterateChildren(nodep);
if (!nodep->coverincp()) {
// Note the name may be overridden by V3Assert processing
nodep->coverincp(newCoverInc(nodep->fileline(), m_beginHier, "v_user", "cover"));
nodep->coverincp(newCoverInc(nodep->fileline(), m_beginHier, "v_user", "cover",
m_beginHier+"_vlCoverageUserTrace"));
}
m_checkBlock = true; // Reset as a child may have cleared it
}

View File

@ -295,7 +295,7 @@ private:
bool mightElimVar(AstVar* nodep) {
return (!nodep->isSigPublic() // Can't elim publics!
&& !nodep->isIO()
&& (nodep->isTemp()
&& ((nodep->isTemp() && !nodep->isTrace())
|| (nodep->isParam() && !nodep->isTrace())
|| m_elimUserVars)); // Post-Trace can kill most anything
}

View File

@ -760,6 +760,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char
else if (!strcmp(sw, "-sv")) { m_defaultLanguage = V3LangCode::L1800_2005; }
else if ( onoff (sw, "-threads-coarsen", flag/*ref*/)) { m_threadsCoarsen = flag; } // Undocumented, debug
else if ( onoff (sw, "-trace", flag/*ref*/)) { m_trace = flag; }
else if ( onoff (sw, "-trace-coverage", flag/*ref*/)) { m_traceCoverage = flag; }
else if ( onoff (sw, "-trace-dups", flag/*ref*/)) { m_traceDups = flag; }
else if ( onoff (sw, "-trace-params", flag/*ref*/)) { m_traceParams = flag; }
else if ( onoff (sw, "-trace-structs", flag/*ref*/)) { m_traceStructs = flag; }
@ -1449,8 +1450,9 @@ V3Options::V3Options() {
m_threadsCoarsen = true;
m_threadsMaxMTasks = 0;
m_trace = false;
m_traceFormat = TraceFormat::VCD;
m_traceCoverage = false;
m_traceDups = false;
m_traceFormat = TraceFormat::VCD;
m_traceParams = true;
m_traceStructs = false;
m_traceUnderscore = false;

View File

@ -152,6 +152,7 @@ class V3Options {
bool m_threadsDpiPure; // main switch: --threads-dpi all/pure
bool m_threadsDpiUnpure; // main switch: --threads-dpi all
bool m_trace; // main switch: --trace
bool m_traceCoverage; // main switch: --trace-coverage
bool m_traceDups; // main switch: --trace-dups
bool m_traceParams; // main switch: --trace-params
bool m_traceStructs; // main switch: --trace-structs
@ -306,6 +307,7 @@ class V3Options {
bool threadsDpiUnpure() const { return m_threadsDpiUnpure; }
bool threadsCoarsen() const { return m_threadsCoarsen; }
bool trace() const { return m_trace; }
bool traceCoverage() const { return m_traceCoverage; }
bool traceDups() const { return m_traceDups; }
bool traceParams() const { return m_traceParams; }
bool traceStructs() const { return m_traceStructs; }

View File

@ -148,8 +148,12 @@ private:
}
virtual void visit(AstVarScope* nodep) {
iterateChildren(nodep);
// Avoid updating this if (), instead see varp->isTrace()
if (!nodep->varp()->isTemp() && !nodep->varp()->isFuncLocal()) {
// Prefilter - things that get through this if will either get
// traced or get a comment as to why not traced.
// Generally this equation doesn't need updating, instead use
// varp->isTrace() and/or vscIgnoreTrace.
if ((!nodep->varp()->isTemp() || nodep->varp()->isTrace())
&& !nodep->varp()->isFuncLocal()) {
UINFO(5, " vsc "<<nodep<<endl);
AstVar* varp = nodep->varp();
AstScope* scopep = nodep->scopep();

View File

@ -0,0 +1,152 @@
$version Generated by VerilatedVcd $end
$date Thu Oct 24 09:45:30 2019
$end
$timescale 1ns $end
$scope module top $end
$var wire 1 1 clk $end
$scope module t $end
$var wire 1 1 clk $end
$var wire 32 $ cyc [31:0] $end
$var wire 8 % cyc_copy [7:0] $end
$var wire 1 # toggle $end
$var wire 32 ) vlCoverageLineTrace_t_cover_line__44_if [31:0] $end
$var wire 32 & vlCoverageLineTrace_t_cover_line__47_if [31:0] $end
$var wire 32 ' vlCoverageLineTrace_t_cover_line__50_elsif [31:0] $end
$var wire 32 ( vlCoverageLineTrace_t_cover_line__57_elsif [31:0] $end
$scope module a1 $end
$var wire 1 1 clk $end
$var wire 1 # toggle $end
$var wire 32 * vlCoverageLineTrace_t_cover_line__78_if [31:0] $end
$upscope $end
$scope module a2 $end
$var wire 1 1 clk $end
$var wire 1 # toggle $end
$var wire 32 + vlCoverageLineTrace_t_cover_line__78_if [31:0] $end
$upscope $end
$scope module b1 $end
$var wire 1 1 clk $end
$var wire 1 # toggle $end
$var wire 32 2 vlCoverageLineTrace_t_cover_line__101_if [31:0] $end
$var wire 32 - vlCoverageLineTrace_t_cover_line__105_if [31:0] $end
$upscope $end
$scope module b2 $end
$var wire 1 1 clk $end
$var wire 1 # toggle $end
$var wire 32 3 vlCoverageLineTrace_t_cover_line__101_if [31:0] $end
$var wire 32 . vlCoverageLineTrace_t_cover_line__105_if [31:0] $end
$upscope $end
$scope module o1 $end
$var wire 1 1 clk $end
$var wire 1 # toggle $end
$var wire 32 , vlCoverageLineTrace_t_cover_line__162_if [31:0] $end
$upscope $end
$scope module t1 $end
$var wire 1 1 clk $end
$var wire 1 # toggle $end
$var wire 32 / vlCoverageLineTrace_t_cover_line__134_if [31:0] $end
$var wire 32 0 vlCoverageLineTrace_t_cover_line__137_if [31:0] $end
$upscope $end
$upscope $end
$upscope $end
$enddefinitions $end
#0
0#
b00000000000000000000000000000001 $
b00000001 %
b00000000000000000000000000000000 &
b00000000000000000000000000000000 '
b00000000000000000000000000000000 (
b00000000000000000000000000000000 )
b00000000000000000000000000000000 *
b00000000000000000000000000000000 +
b00000000000000000000000000000000 ,
b00000000000000000000000000000000 -
b00000000000000000000000000000000 .
b00000000000000000000000000000000 /
b00000000000000000000000000000000 0
01
b00000000000000000000000000000000 2
b00000000000000000000000000000000 3
#10
b00000000000000000000000000000010 $
b00000010 %
b00000000000000000000000000000001 )
11
#15
01
#20
b00000000000000000000000000000011 $
b00000011 %
b00000000000000000000000000000010 )
11
#25
01
#30
1#
b00000000000000000000000000000100 $
b00000100 %
b00000000000000000000000000000001 &
b00000000000000000000000000000011 )
11
#35
01
#40
0#
b00000000000000000000000000000101 $
b00000101 %
b00000000000000000000000000000100 )
b00000000000000000000000000000001 *
b00000000000000000000000000000001 +
b00000000000000000000000000000001 ,
b00000000000000000000000000000001 -
b00000000000000000000000000000001 .
b00000000000000000000000000000001 /
11
#45
01
#50
b00000000000000000000000000000110 $
b00000110 %
b00000000000000000000000000000001 '
b00000000000000000000000000000101 )
b00000000000000000000000000000001 0
11
#55
01
#60
b00000000000000000000000000000111 $
b00000111 %
b00000000000000000000000000000110 )
11
#65
01
#70
b00000000000000000000000000001000 $
b00001000 %
b00000000000000000000000000000111 )
11
#75
01
#80
b00000000000000000000000000001001 $
b00001001 %
b00000000000000000000000000001000 )
11
#85
01
#90
b00000000000000000000000000001010 $
b00001010 %
b00000000000000000000000000001001 )
11
#95
01
#100
b00000000000000000000000000001011 $
b00001011 %
b00000000000000000000000000000001 (
b00000000000000000000000000001010 )
11

View File

@ -0,0 +1,31 @@
#!/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.
scenarios(simulator => 1);
top_filename("t/t_cover_line.v");
compile(
verilator_flags2 => ['--cc --coverage-line --trace --trace-coverage'],
);
execute(
check_finished => 1,
);
run(cmd => ["../bin/verilator_coverage",
"--annotate", "$Self->{obj_dir}/annotated",
"$Self->{obj_dir}/coverage.dat",
]);
files_identical("$Self->{obj_dir}/annotated/t_cover_line.v", "t/t_cover_line.out");
vcd_identical("$Self->{obj_dir}/simx.vcd", $Self->{golden_filename});
ok(1);
1;

View File

@ -0,0 +1,112 @@
$version Generated by VerilatedVcd $end
$date Thu Oct 24 09:44:07 2019
$end
$timescale 1ns $end
$scope module top $end
$var wire 1 ) clk $end
$scope module t $end
$var wire 1 ) clk $end
$var wire 32 # cyc [31:0] $end
$var wire 1 % toggle $end
$scope module suba $end
$var wire 1 ) clk $end
$var wire 32 $ cyc [31:0] $end
$var wire 32 & cyc_eq_5_vlCoverageUserTrace [31:0] $end
$var wire 1 % toggle $end
$upscope $end
$scope module subb $end
$var wire 1 ) clk $end
$var wire 32 $ cyc [31:0] $end
$var wire 32 ' cyc_eq_5_vlCoverageUserTrace [31:0] $end
$var wire 1 % toggle $end
$upscope $end
$scope module subc $end
$var wire 1 ) clk $end
$var wire 32 $ cyc [31:0] $end
$var wire 32 ( cyc_eq_5_vlCoverageUserTrace [31:0] $end
$var wire 1 % toggle $end
$upscope $end
$upscope $end
$upscope $end
$enddefinitions $end
#0
b00000000000000000000000000000001 #
b00000000000000000000000000000001 $
0%
b00000000000000000000000000000000 &
b00000000000000000000000000000000 '
b00000000000000000000000000000000 (
0)
#10
b00000000000000000000000000000010 #
b00000000000000000000000000000010 $
1)
#15
0)
#20
b00000000000000000000000000000011 #
b00000000000000000000000000000011 $
1%
1)
#25
0)
#30
b00000000000000000000000000000100 #
b00000000000000000000000000000100 $
0%
1)
#35
0)
#40
b00000000000000000000000000000101 #
b00000000000000000000000000000101 $
1%
1)
#45
0)
#50
b00000000000000000000000000000110 #
b00000000000000000000000000000110 $
0%
b00000000000000000000000000000001 &
b00000000000000000000000000000001 '
b00000000000000000000000000000001 (
1)
#55
0)
#60
b00000000000000000000000000000111 #
b00000000000000000000000000000111 $
1%
1)
#65
0)
#70
b00000000000000000000000000001000 #
b00000000000000000000000000001000 $
0%
1)
#75
0)
#80
b00000000000000000000000000001001 #
b00000000000000000000000000001001 $
1%
1)
#85
0)
#90
b00000000000000000000000000001010 #
b00000000000000000000000000001010 $
0%
1)
#95
0)
#100
b00000000000000000000000000001011 #
b00000000000000000000000000001011 $
1%
1)

View File

@ -0,0 +1,25 @@
#!/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.
scenarios(simulator => 1);
top_filename("t/t_cover_sva_notflat.v");
compile(
verilator_flags2 => ['--assert --cc --coverage-user --trace --trace-coverage'],
);
execute(
check_finished => 1,
);
vcd_identical("$Self->{obj_dir}/simx.vcd", $Self->{golden_filename});
ok(1);
1;