Add --annotate-points option, change multipoint on line reporting (#3876).

This commit is contained in:
Wilson Snyder 2023-02-08 20:15:11 -05:00
parent 9121a81a74
commit b778784333
17 changed files with 816 additions and 518 deletions

View File

@ -13,6 +13,7 @@ Verilator 5.007 devel
**Minor:**
* Add --annotate-points option, change multipoint on line reporting (#3876). [Nassim Corteggiani]
* Add --verilate-jobs option (#3889). [Kamil Rakoczy, Antmicro Ltd]
* Support unpacked unions.
* Support interface classes and class implements.

View File

@ -169,6 +169,7 @@ L<https://verilator.org/guide/latest/exe_verilator_coverage.html>.
--annotate <output_dir> Directory name for source annotation.
--annotate-all All files should be shown.
--annotate-min <count> Minimum occurrence count for uncovered.
--annotate-points Annotates info from each coverage point.
--help Displays this message and version and exits.
--rank Compute relative importance of tests.
--unlink With --write, unlink all inputs

View File

@ -6,10 +6,10 @@ verilator_coverage
Verilator_coverage processes Verilated model-generated coverage reports.
With --annotate, it reads the specified coverage data file and generates
annotated source code with coverage metrics annotated. If multiple
coverage points exist on the same source code line, additional lines will
be inserted to report the additional points.
With `--annotate`, it reads the specified coverage data file and generates
annotated source code with coverage metrics annotated. With
`--annotate-points` the coverage points corresponding to each line are also
shown.
Additional Verilog-XL-style standard arguments specify the search paths
necessary to find the source code on which the coverage analysis was
@ -58,6 +58,18 @@ to read multiple inputs. If no data file is specified, by default,
Specifies the directory name to which source files with annotated coverage
data should be written.
Converting from the Verilator coverage data format to the info format is
lossy; the info will have all forms of coverage merged line coverage, and
if there are multiple coverage points on a single line they will merge.
The minimum coverage across all merged points will be used to report
coverage of the line.
The first character of the line shows a summary of the coverage; this
allows use of grep to filter the report. `%` indicates at least one point
on the line was below the coverage limit. `+` indicates an
:option:`--annotate-points` point was at or above the limit, and `-` that
the point was below the limit.
.. option:: --annotate-all
Specifies all files should be shown. By default, only those source files
@ -70,6 +82,13 @@ coverage hits, then the coverage point will be considered above the
threshold, and the coverage report will put a "%" to indicate the coverage
is insufficient. Defaults to 10.
.. option:: --annotate-points
Specifies all coverage points should be shown after each line of text. By
default, only source lines are shown.
with low coverage are written to the output directory.
.. option:: --help
Displays a help summary, the program version, and exits.

View File

@ -452,6 +452,7 @@ or "`ifdef`"'s may break other tools.
See attribute above for their respective behavior. Cannot be nested. e.g:
.. code-block:: sv
/*verilator public_flat_rw_on*/
logic clk;
logic rst;
@ -462,6 +463,7 @@ or "`ifdef`"'s may break other tools.
Is equivalent to:
.. code-block:: sv
logic clk /*verilator public_flat_rw*/;
logic rst /*verilator public_flat_rw*/;
parameter width /*verilator public_flat_rw*/ = 8;

View File

@ -58,13 +58,14 @@ void VlcOptions::parseOptsList(int argc, char** argv) {
V3OptionParser::AppendHelper DECL_OPTION{parser};
V3OPTION_PARSER_DECL_TAGS;
DECL_OPTION("-annotate-all", OnOff, &m_annotateAll);
DECL_OPTION("-rank", OnOff, &m_rank);
DECL_OPTION("-unlink", OnOff, &m_unlink);
DECL_OPTION("-annotate-min", Set, &m_annotateMin);
DECL_OPTION("-annotate", Set, &m_annotateOut);
DECL_OPTION("-annotate-all", OnOff, &m_annotateAll);
DECL_OPTION("-annotate-min", Set, &m_annotateMin);
DECL_OPTION("-annotate-points", OnOff, &m_annotatePoints);
DECL_OPTION("-debug", CbCall, []() { V3Error::debugDefault(3); });
DECL_OPTION("-debugi", CbVal, [](int v) { V3Error::debugDefault(v); });
DECL_OPTION("-rank", OnOff, &m_rank);
DECL_OPTION("-unlink", OnOff, &m_unlink);
DECL_OPTION("-V", CbCall, []() {
showVersion(true);
std::exit(0);

View File

@ -37,6 +37,7 @@ class VlcOptions final {
string m_annotateOut; // main switch: --annotate I<output_directory>
bool m_annotateAll = false; // main switch: --annotate-all
int m_annotateMin = 10; // main switch: --annotate-min I<count>
bool m_annotatePoints = false; // main switch: --annotate-points
VlStringSet m_readFiles; // main switch: --read
bool m_rank = false; // main switch: --rank
bool m_unlink = false; // main switch: --unlink
@ -62,6 +63,7 @@ public:
string annotateOut() const { return m_annotateOut; }
bool annotateAll() const { return m_annotateAll; }
int annotateMin() const { return m_annotateMin; }
bool annotatePoints() const { return m_annotatePoints; }
bool rank() const { return m_rank; }
bool unlink() const { return m_unlink; }
string writeFile() const { return m_writeFile; }

View File

@ -54,6 +54,11 @@ public:
void countInc(uint64_t inc) { m_count += inc; }
uint64_t count() const { return m_count; }
void testsCoveringInc() { m_testsCovering++; }
bool ok(unsigned annotateMin) const {
const std::string threshStr = thresh();
unsigned threshi = !threshStr.empty() ? std::atoi(threshStr.c_str()) : annotateMin;
return m_count >= threshi;
}
// KEY ACCESSORS
string filename() const { return keyExtract(VL_CIK_FILENAME); }
string comment() const { return keyExtract(VL_CIK_COMMENT); }
@ -79,15 +84,21 @@ public:
}
return "";
}
static void dumpHeader() {
cout << "Points:\n";
cout << " Num, TestsCover, Count, Name\n";
static void dumpHeader(std::ostream& os) {
os << "Points:\n";
os << " Num, TestsCover, Count, Name\n";
}
void dump() const {
cout << " " << std::setw(8) << std::setfill('0') << pointNum();
cout << ", " << std::setw(7) << std::setfill(' ') << testsCovering();
cout << ", " << std::setw(7) << std::setfill(' ') << count();
cout << ", \"" << name() << "\"\n";
void dump(std::ostream& os) const {
os << " " << std::setw(8) << std::setfill('0') << pointNum();
os << ", " << std::setw(7) << std::setfill(' ') << testsCovering();
os << ", " << std::setw(7) << std::setfill(' ') << count();
os << ", \"" << name() << "\"\n";
}
void dumpAnnotate(std::ostream& os, unsigned annotateMin) const {
os << (ok(annotateMin) ? "+" : "-");
os << std::setw(6) << std::setfill('0') << count();
os << " point: comment=" << comment();
os << "\n";
}
};
@ -118,10 +129,10 @@ public:
// METHODS
void dump() {
UINFO(2, "dumpPoints...\n");
VlcPoint::dumpHeader();
VlcPoint::dumpHeader(cout);
for (const auto& i : *this) {
const VlcPoint& point = pointNumber(i.second);
point.dump();
point.dump(cout);
}
}
VlcPoint& pointNumber(uint64_t num) { return m_points[num]; }

View File

@ -21,38 +21,49 @@
#include "verilatedos.h"
#include <map>
#include <set>
#include <utility>
#include <vector>
class VlcPoint;
//********************************************************************
// VlcColumnCount - count at specific source file, line and column
class VlcSourceCount final {
private:
// TYPES
using PointsSet = std::set<const VlcPoint*>;
// MEMBERS
int m_lineno; ///< Line number
int m_column; ///< Column number
uint64_t m_count = 0; ///< Count
bool m_ok = false; ///< Coverage is above threshold
PointsSet m_points; // Points on this line
public:
// CONSTRUCTORS
VlcSourceCount(int lineno, int column)
: m_lineno{lineno}
, m_column{column} {}
VlcSourceCount(int lineno)
: m_lineno{lineno} {}
~VlcSourceCount() = default;
// ACCESSORS
int lineno() const { return m_lineno; }
int column() const { return m_column; }
uint64_t count() const { return m_count; }
bool ok() const { return m_ok; }
// METHODS
void incCount(uint64_t count, bool ok) {
m_count += count;
if (ok) m_ok = true;
if (!m_count) {
m_count = count;
m_ok = ok;
} else {
m_count = std::min(m_count, count);
if (!ok) m_ok = false;
}
}
void insertPoint(const VlcPoint* pointp) { m_points.emplace(pointp); }
PointsSet& points() { return m_points; }
};
//********************************************************************
@ -61,8 +72,7 @@ public:
class VlcSource final {
public:
// TYPES
using ColumnMap = std::map<int, VlcSourceCount>; // Map of {column}
using LinenoMap = std::map<int, ColumnMap>; // Map of {lineno}{column}
using LinenoMap = std::map<int, VlcSourceCount>; // Map of {column}
private:
// MEMBERS
@ -83,16 +93,13 @@ public:
LinenoMap& lines() { return m_lines; }
// METHODS
void incCount(int lineno, int column, uint64_t count, bool ok) {
LinenoMap::iterator lit = m_lines.find(lineno);
if (lit == m_lines.end()) lit = m_lines.insert(std::make_pair(lineno, ColumnMap())).first;
ColumnMap& cmap = lit->second;
ColumnMap::iterator cit = cmap.find(column);
if (cit == cmap.end()) {
cit = cmap.insert(std::make_pair(column, VlcSourceCount{lineno, column})).first;
}
VlcSourceCount& sc = cit->second;
void lineIncCount(int lineno, uint64_t count, bool ok, const VlcPoint* pointp) {
auto lit = m_lines.find(lineno);
if (lit == m_lines.end())
lit = m_lines.emplace(std::make_pair(lineno, VlcSourceCount{lineno})).first;
VlcSourceCount& sc = lit->second;
sc.incCount(count, ok);
sc.insertPoint(pointp);
}
};

View File

@ -116,20 +116,8 @@ void VlcTop::writeInfo(const string& filename) {
os << "SF:" << source.name() << '\n';
VlcSource::LinenoMap& lines = source.lines();
for (auto& li : lines) {
const int lineno = li.first;
VlcSource::ColumnMap& cmap = li.second;
bool first = true;
uint64_t min_count = 0; // Minimum across all columns on line
for (auto& ci : cmap) {
VlcSourceCount& col = ci.second;
if (first) {
min_count = col.count();
first = false;
} else {
min_count = std::min(min_count, col.count());
}
}
os << "DA:" << lineno << "," << min_count << "\n";
const VlcSourceCount& sc = li.second;
os << "DA:" << sc.lineno() << "," << sc.count() << "\n";
}
os << "end_of_record\n";
}
@ -206,14 +194,11 @@ void VlcTop::annotateCalc() {
const int lineno = point.lineno();
if (!filename.empty() && lineno != 0) {
VlcSource& source = sources().findNewSource(filename);
const string threshStr = point.thresh();
unsigned thresh
= (!threshStr.empty()) ? std::atoi(threshStr.c_str()) : opt.annotateMin();
const bool ok = (point.count() >= thresh);
const bool ok = point.ok(opt.annotateMin());
UINFO(9, "AnnoCalc count " << filename << ":" << lineno << ":" << point.column() << " "
<< point.count() << " " << point.linescov() << '\n');
// Base coverage
source.incCount(lineno, point.column(), point.count(), ok);
source.lineIncCount(lineno, point.count(), ok, &point);
// Additional lines covered by this statement
bool range = false;
int start = 0;
@ -222,7 +207,7 @@ void VlcTop::annotateCalc() {
for (const char* covp = linescov.c_str(); true; ++covp) {
if (!*covp || *covp == ',') { // Ending
for (int lni = start; start && lni <= end; ++lni) {
source.incCount(lni, point.column(), point.count(), ok);
source.lineIncCount(lni, point.count(), ok, &point);
}
if (!*covp) break;
start = 0; // Prep for next
@ -253,16 +238,13 @@ void VlcTop::annotateCalcNeeded() {
if (opt.annotateAll()) source.needed(true);
VlcSource::LinenoMap& lines = source.lines();
for (auto& li : lines) {
VlcSource::ColumnMap& cmap = li.second;
for (auto& ci : cmap) {
VlcSourceCount& col = ci.second;
// UINFO(0,"Source "<<source.name()<<":"<<col.lineno()<<":"<<col.column()<<endl);
++totCases;
if (col.ok()) {
++totOk;
} else {
source.needed(true);
}
VlcSourceCount& sc = li.second;
// UINFO(0, "Source "<<source.name()<<":"<<sc.lineno()<<":"<<sc.column()<<endl);
++totCases;
if (sc.ok()) {
++totOk;
} else {
source.needed(true);
}
}
}
@ -295,39 +277,28 @@ void VlcTop::annotateOutputFiles(const string& dirname) {
return;
}
os << "\t// verilator_coverage annotation\n";
os << "// // verilator_coverage annotation\n";
int lineno = 0;
while (!is.eof()) {
lineno++;
string line = V3Os::getline(is);
bool first = true;
VlcSource::LinenoMap& lines = source.lines();
const auto lit = lines.find(lineno);
if (lit != lines.end()) {
VlcSource::ColumnMap& cmap = lit->second;
for (auto& ci : cmap) {
VlcSourceCount& col = ci.second;
// UINFO(0,"Source
// "<<source.name()<<":"<<col.lineno()<<":"<<col.column()<<endl);
os << (col.ok() ? " " : "%") << std::setfill('0') << std::setw(6)
<< col.count() << "\t" << line << '\n';
if (first) {
first = false;
// Multiple columns on same line; print line just once
string indent;
for (string::const_iterator pos = line.begin();
pos != line.end() && std::isspace(*pos); ++pos) {
indent += *pos;
}
line = indent + "verilator_coverage: (next point on previous line)\n";
}
if (lit == lines.end()) {
os << " " << line << '\n';
} else if (lit != lines.end()) {
VlcSourceCount& sc = lit->second;
// UINFO(0,"Source
// "<<source.name()<<":"<<sc.lineno()<<":"<<sc.column()<<endl);
os << (sc.ok() ? " " : "%") << std::setfill('0') << std::setw(6) << sc.count()
<< " " << line << '\n';
if (opt.annotatePoints()) {
for (auto& pit : sc.points()) pit->dumpAnnotate(os, opt.annotateMin());
}
}
if (first) os << "\t" << line << '\n';
}
}
}

View File

@ -1,266 +1,318 @@
// verilator_coverage annotation
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2008 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
reg toggle;
%000002 initial toggle=0;
integer cyc;
%000002 initial cyc=1;
wire [7:0] cyc_copy = cyc[7:0];
alpha a1 (/*AUTOINST*/
// Inputs
.clk (clk),
.toggle (toggle));
alpha a2 (/*AUTOINST*/
// Inputs
.clk (clk),
.toggle (toggle));
beta b1 (/*AUTOINST*/
// Inputs
.clk (clk),
.toggle (toggle));
beta b2 (/*AUTOINST*/
// Inputs
.clk (clk),
.toggle (toggle));
tsk t1 (/*AUTOINST*/
// Inputs
.clk (clk),
.toggle (toggle));
off o1 (/*AUTOINST*/
// Inputs
.clk (clk),
.toggle (toggle));
000020 always @ (posedge clk) begin
000020 if (cyc!=0) begin
%000000 verilator_coverage: (next point on previous line)
000010 cyc <= cyc + 1;
000010 toggle <= '0;
// Single and multiline if
%000002 if (cyc==3) $write("");
%000009 verilator_coverage: (next point on previous line)
%000002 if (cyc==3)
%000009 verilator_coverage: (next point on previous line)
%000001 begin
%000001 $write("");
end
// Single and multiline else
%000002 if (cyc==3) ; else $write("");
%000018 verilator_coverage: (next point on previous line)
%000002 if (cyc==3) ;
%000009 verilator_coverage: (next point on previous line)
else
%000009 begin
%000009 $write("");
end
// Single and multiline if else
%000002 if (cyc==3) $write(""); else $write("");
%000018 verilator_coverage: (next point on previous line)
%000002 if (cyc==3)
%000009 verilator_coverage: (next point on previous line)
%000001 begin
%000001 $write("");
end
else
%000009 begin
%000009 $write("");
end
// multiline elseif
%000002 if (cyc==3)
%000001 begin
%000001 $write("");
end
%000002 else if (cyc==4)
%000001 begin
%000001 $write("");
end
%000002 else if (cyc==5)
%000007 verilator_coverage: (next point on previous line)
%000001 begin
%000001 $write("");
end
else
%000007 begin
%000007 $write("");
end
// Single and multiline while
%000000 while (0);
%000000 while (0) begin
%000000 $write("");
end
%000000 do ; while (0);
000010 do begin
%000000 verilator_coverage: (next point on previous line)
000010 $write("");
%000000 verilator_coverage: (next point on previous line)
%000000 end while (0);
//===
// Task and complicated
%000002 if (cyc==3) begin
%000001 toggle <= '1;
end
%000002 else if (cyc==5) begin
`ifdef VERILATOR
%000001 $c("this->call_task();");
`else
call_task();
`endif
end
%000002 else if (cyc==10) begin
%000007 verilator_coverage: (next point on previous line)
%000001 $write("*-* All Finished *-*\n");
%000001 $finish;
end
end
end
%000002 task call_task;
/* verilator public */
%000001 t1.center_task(1'b1);
endtask
endmodule
module alpha (/*AUTOARG*/
// Inputs
clk, toggle
);
input clk;
input toggle;
000040 always @ (posedge clk) begin
%000004 if (toggle) begin // CHECK_COVER(0,"top.t.a*",2)
000018 verilator_coverage: (next point on previous line)
%000002 $write("");
// t.a1 and t.a2 collapse to a count of 2
end
000018 if (toggle) begin
$write(""); // CHECK_COVER_MISSING(0)
// This doesn't even get added
`ifdef ATTRIBUTE
// verilator coverage_block_off
`endif
end
end
endmodule
module beta (/*AUTOARG*/
// Inputs
clk, toggle
);
input clk;
input toggle;
/* verilator public_module */
000040 always @ (posedge clk) begin
000020 $write(""); // Always covered
%000000 if (0) begin // CHECK_COVER(0,"top.t.b*",0)
000020 verilator_coverage: (next point on previous line)
// Make sure that we don't optimize away zero buckets
%000000 $write("");
end
%000004 if (toggle) begin // CHECK_COVER(0,"top.t.b*",2)
000018 verilator_coverage: (next point on previous line)
// t.b1 and t.b2 collapse to a count of 2
%000002 $write("");
end
000018 if (toggle) begin : block
// This doesn't
`ifdef ATTRIBUTE
// verilator coverage_block_off
`endif
begin end // Needed for .vlt to attach coverage_block_off
if (1) begin end // CHECK_COVER_MISSING(0)
$write(""); // CHECK_COVER_MISSING(0)
end
end
endmodule
module tsk (/*AUTOARG*/
// Inputs
clk, toggle
);
input clk;
input toggle;
/* verilator public_module */
000020 always @ (posedge clk) begin
000010 center_task(1'b0);
end
000022 task center_task;
input external;
000011 begin
%000002 if (toggle) begin // CHECK_COVER(0,"top.t.t1",1)
000010 verilator_coverage: (next point on previous line)
%000001 $write("");
end
%000002 if (external) begin // CHECK_COVER(0,"top.t.t1",1)
000010 verilator_coverage: (next point on previous line)
%000001 $write("[%0t] Got external pulse\n", $time);
end
end
endtask
endmodule
module off (/*AUTOARG*/
// Inputs
clk, toggle
);
input clk;
input toggle;
// verilator coverage_off
always @ (posedge clk) begin
if (toggle) begin
$write(""); // CHECK_COVER_MISSING(0)
// because under coverage_module_off
end
end
// verilator coverage_on
000020 always @ (posedge clk) begin
%000002 if (toggle) begin
%000009 verilator_coverage: (next point on previous line)
// because under coverage_module_off
%000001 $write("");
%000000 if (0) ; // CHECK_COVER(0,"top.t.o1",1)
%000001 verilator_coverage: (next point on previous line)
end
end
endmodule
// // verilator_coverage annotation
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2008 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
reg toggle;
%000001 initial toggle=0;
-000001 point: comment=block
integer cyc;
%000001 initial cyc=1;
-000001 point: comment=block
wire [7:0] cyc_copy = cyc[7:0];
alpha a1 (/*AUTOINST*/
// Inputs
.clk (clk),
.toggle (toggle));
alpha a2 (/*AUTOINST*/
// Inputs
.clk (clk),
.toggle (toggle));
beta b1 (/*AUTOINST*/
// Inputs
.clk (clk),
.toggle (toggle));
beta b2 (/*AUTOINST*/
// Inputs
.clk (clk),
.toggle (toggle));
tsk t1 (/*AUTOINST*/
// Inputs
.clk (clk),
.toggle (toggle));
off o1 (/*AUTOINST*/
// Inputs
.clk (clk),
.toggle (toggle));
000010 always @ (posedge clk) begin
+000010 point: comment=block
%000000 if (cyc!=0) begin
+000010 point: comment=if
-000000 point: comment=else
000010 cyc <= cyc + 1;
+000010 point: comment=if
000010 toggle <= '0;
+000010 point: comment=if
// Single and multiline if
%000001 if (cyc==3) $write("");
-000001 point: comment=if
-000009 point: comment=else
%000001 if (cyc==3)
-000001 point: comment=if
-000009 point: comment=else
%000001 begin
-000001 point: comment=if
%000001 $write("");
-000001 point: comment=if
end
// Single and multiline else
%000001 if (cyc==3) ; else $write("");
-000001 point: comment=if
-000009 point: comment=else
%000001 if (cyc==3) ;
-000001 point: comment=if
-000009 point: comment=else
else
%000009 begin
-000009 point: comment=else
%000009 $write("");
-000009 point: comment=else
end
// Single and multiline if else
%000001 if (cyc==3) $write(""); else $write("");
-000001 point: comment=if
-000009 point: comment=else
%000001 if (cyc==3)
-000001 point: comment=if
-000009 point: comment=else
%000001 begin
-000001 point: comment=if
%000001 $write("");
-000001 point: comment=if
end
else
%000009 begin
-000009 point: comment=else
%000009 $write("");
-000009 point: comment=else
end
// multiline elseif
%000001 if (cyc==3)
-000001 point: comment=elsif
%000001 begin
-000001 point: comment=elsif
%000001 $write("");
-000001 point: comment=elsif
end
%000001 else if (cyc==4)
-000001 point: comment=elsif
%000001 begin
-000001 point: comment=elsif
%000001 $write("");
-000001 point: comment=elsif
end
%000001 else if (cyc==5)
-000001 point: comment=if
-000007 point: comment=else
%000001 begin
-000001 point: comment=if
%000001 $write("");
-000001 point: comment=if
end
else
%000007 begin
-000007 point: comment=else
%000007 $write("");
-000007 point: comment=else
end
// Single and multiline while
%000000 while (0);
-000000 point: comment=block
%000000 while (0) begin
-000000 point: comment=block
%000000 $write("");
-000000 point: comment=block
end
%000000 do ; while (0);
-000000 point: comment=block
%000000 do begin
+000010 point: comment=if
-000000 point: comment=block
%000000 $write("");
+000010 point: comment=if
-000000 point: comment=block
%000000 end while (0);
-000000 point: comment=block
//===
// Task and complicated
%000001 if (cyc==3) begin
-000001 point: comment=elsif
%000001 toggle <= '1;
-000001 point: comment=elsif
end
%000001 else if (cyc==5) begin
-000001 point: comment=elsif
`ifdef VERILATOR
%000001 $c("this->call_task();");
-000001 point: comment=elsif
`else
call_task();
`endif
end
%000001 else if (cyc==10) begin
-000001 point: comment=if
-000007 point: comment=else
%000001 $write("*-* All Finished *-*\n");
-000001 point: comment=if
%000001 $finish;
-000001 point: comment=if
end
end
end
%000001 task call_task;
-000001 point: comment=block
/* verilator public */
%000001 t1.center_task(1'b1);
-000001 point: comment=block
endtask
endmodule
module alpha (/*AUTOARG*/
// Inputs
clk, toggle
);
input clk;
input toggle;
000020 always @ (posedge clk) begin
+000020 point: comment=block
%000002 if (toggle) begin // CHECK_COVER(0,"top.t.a*",2)
-000002 point: comment=if
+000018 point: comment=else
%000002 $write("");
-000002 point: comment=if
// t.a1 and t.a2 collapse to a count of 2
end
000018 if (toggle) begin
+000018 point: comment=else
$write(""); // CHECK_COVER_MISSING(0)
// This doesn't even get added
`ifdef ATTRIBUTE
// verilator coverage_block_off
`endif
end
end
endmodule
module beta (/*AUTOARG*/
// Inputs
clk, toggle
);
input clk;
input toggle;
/* verilator public_module */
000020 always @ (posedge clk) begin
+000020 point: comment=block
000020 $write(""); // Always covered
+000020 point: comment=block
000020 if (0) begin // CHECK_COVER(0,"top.t.b*",0)
-000000 point: comment=if
+000020 point: comment=else
// Make sure that we don't optimize away zero buckets
%000000 $write("");
-000000 point: comment=if
end
%000002 if (toggle) begin // CHECK_COVER(0,"top.t.b*",2)
-000002 point: comment=if
+000018 point: comment=else
// t.b1 and t.b2 collapse to a count of 2
%000002 $write("");
-000002 point: comment=if
end
000018 if (toggle) begin : block
+000018 point: comment=else
// This doesn't
`ifdef ATTRIBUTE
// verilator coverage_block_off
`endif
begin end // Needed for .vlt to attach coverage_block_off
if (1) begin end // CHECK_COVER_MISSING(0)
$write(""); // CHECK_COVER_MISSING(0)
end
end
endmodule
module tsk (/*AUTOARG*/
// Inputs
clk, toggle
);
input clk;
input toggle;
/* verilator public_module */
000010 always @ (posedge clk) begin
+000010 point: comment=block
000010 center_task(1'b0);
+000010 point: comment=block
end
000011 task center_task;
+000011 point: comment=block
input external;
000011 begin
+000011 point: comment=block
%000001 if (toggle) begin // CHECK_COVER(0,"top.t.t1",1)
-000001 point: comment=if
+000010 point: comment=else
%000001 $write("");
-000001 point: comment=if
end
%000001 if (external) begin // CHECK_COVER(0,"top.t.t1",1)
-000001 point: comment=if
+000010 point: comment=else
%000001 $write("[%0t] Got external pulse\n", $time);
-000001 point: comment=if
end
end
endtask
endmodule
module off (/*AUTOARG*/
// Inputs
clk, toggle
);
input clk;
input toggle;
// verilator coverage_off
always @ (posedge clk) begin
if (toggle) begin
$write(""); // CHECK_COVER_MISSING(0)
// because under coverage_module_off
end
end
// verilator coverage_on
000010 always @ (posedge clk) begin
+000010 point: comment=block
%000001 if (toggle) begin
-000001 point: comment=if
-000009 point: comment=else
// because under coverage_module_off
%000001 $write("");
-000001 point: comment=if
%000001 if (0) ; // CHECK_COVER(0,"top.t.o1",1)
-000000 point: comment=if
-000001 point: comment=else
end
end
endmodule

View File

@ -25,6 +25,7 @@ execute(
inline_checks();
run(cmd => ["../bin/verilator_coverage",
"--annotate-points",
"--annotate", "$Self->{obj_dir}/annotated",
"$Self->{obj_dir}/coverage.dat"],
verilator_run => 1,

View File

@ -25,6 +25,7 @@ execute(
inline_checks();
run(cmd => ["../bin/verilator_coverage",
"--annotate-points",
"--annotate", "$Self->{obj_dir}/annotated",
"$Self->{obj_dir}/coverage.dat",
],

View File

@ -21,6 +21,7 @@ execute(
);
run(cmd => ["../bin/verilator_coverage",
"--annotate-points",
"--annotate", "$Self->{obj_dir}/annotated",
"$Self->{obj_dir}/coverage.dat",
],

View File

@ -1,162 +1,162 @@
// verilator_coverage annotation
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2008 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
module t (/*AUTOARG*/
// Inputs
clk,
check_real,
check_string
);
000019 input clk;
input real check_real; // Check issue #2741
input string check_string; // Check issue #2766
typedef struct packed {
union packed {
logic ua;
logic ub;
} u;
logic b;
} str_t;
%000002 reg toggle; initial toggle='0;
%000004 str_t stoggle; initial stoggle='0;
const reg aconst = '0;
%000002 reg [1:0][1:0] ptoggle; initial ptoggle=0;
integer cyc; initial cyc=1;
000019 wire [7:0] cyc_copy = cyc[7:0];
%000002 wire toggle_up;
alpha a1 (/*AUTOINST*/
// Outputs
.toggle_up (toggle_up),
// Inputs
.clk (clk),
.toggle (toggle),
.cyc_copy (cyc_copy[7:0]));
alpha a2 (/*AUTOINST*/
// Outputs
.toggle_up (toggle_up),
// Inputs
.clk (clk),
.toggle (toggle),
.cyc_copy (cyc_copy[7:0]));
beta b1 (/*AUTOINST*/
// Inputs
.clk (clk),
.toggle_up (toggle_up));
off o1 (/*AUTOINST*/
// Inputs
.clk (clk),
.toggle (toggle));
%000001 reg [1:0] memory[121:110];
wire [1023:0] largeish = {992'h0, cyc};
// CHECK_COVER_MISSING(-1)
always @ (posedge clk) begin
if (cyc!=0) begin
cyc <= cyc + 1;
memory[cyc + 'd100] <= memory[cyc + 'd100] + 2'b1;
toggle <= '0;
stoggle.u <= toggle;
stoggle.b <= toggle;
ptoggle[0][0] <= toggle;
if (cyc==3) begin
toggle <= '1;
end
if (cyc==4) begin
toggle <= '0;
end
else if (cyc==10) begin
$write("*-* All Finished *-*\n");
$finish;
end
end
end
endmodule
module alpha (/*AUTOARG*/
// Outputs
toggle_up,
// Inputs
clk, toggle, cyc_copy
);
// t.a1 and t.a2 collapse to a count of 2
000038 input clk;
%000004 input toggle;
// CHECK_COVER(-1,"top.t.a*",4)
// 2 edges * (t.a1 and t.a2)
000038 input [7:0] cyc_copy;
// CHECK_COVER(-1,"top.t.a*","cyc_copy[0]",22)
// CHECK_COVER(-2,"top.t.a*","cyc_copy[1]",10)
// CHECK_COVER(-3,"top.t.a*","cyc_copy[2]",4)
// CHECK_COVER(-4,"top.t.a*","cyc_copy[3]",2)
// CHECK_COVER(-5,"top.t.a*","cyc_copy[4]",0)
// CHECK_COVER(-6,"top.t.a*","cyc_copy[5]",0)
// CHECK_COVER(-7,"top.t.a*","cyc_copy[6]",0)
// CHECK_COVER(-8,"top.t.a*","cyc_copy[7]",0)
%000004 reg toggle_internal;
// CHECK_COVER(-1,"top.t.a*",4)
// 2 edges * (t.a1 and t.a2)
%000004 output reg toggle_up;
// CHECK_COVER(-1,"top.t.a*",4)
// 2 edges * (t.a1 and t.a2)
always @ (posedge clk) begin
toggle_internal <= toggle;
toggle_up <= toggle;
end
endmodule
module beta (/*AUTOARG*/
// Inputs
clk, toggle_up
);
000019 input clk;
%000002 input toggle_up;
// CHECK_COVER(-1,"top.t.b1","toggle_up",2)
/* verilator public_module */
always @ (posedge clk) begin
if (0 && toggle_up) begin end
end
endmodule
module off (/*AUTOARG*/
// Inputs
clk, toggle
);
// verilator coverage_off
input clk;
// CHECK_COVER_MISSING(-1)
// verilator coverage_on
%000002 input toggle;
// CHECK_COVER(-1,"top.t.o1","toggle",2)
endmodule
// // verilator_coverage annotation
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2008 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
module t (/*AUTOARG*/
// Inputs
clk,
check_real,
check_string
);
000019 input clk;
input real check_real; // Check issue #2741
input string check_string; // Check issue #2766
typedef struct packed {
union packed {
logic ua;
logic ub;
} u;
logic b;
} str_t;
%000002 reg toggle; initial toggle='0;
%000002 str_t stoggle; initial stoggle='0;
const reg aconst = '0;
%000000 reg [1:0][1:0] ptoggle; initial ptoggle=0;
integer cyc; initial cyc=1;
%000000 wire [7:0] cyc_copy = cyc[7:0];
%000002 wire toggle_up;
alpha a1 (/*AUTOINST*/
// Outputs
.toggle_up (toggle_up),
// Inputs
.clk (clk),
.toggle (toggle),
.cyc_copy (cyc_copy[7:0]));
alpha a2 (/*AUTOINST*/
// Outputs
.toggle_up (toggle_up),
// Inputs
.clk (clk),
.toggle (toggle),
.cyc_copy (cyc_copy[7:0]));
beta b1 (/*AUTOINST*/
// Inputs
.clk (clk),
.toggle_up (toggle_up));
off o1 (/*AUTOINST*/
// Inputs
.clk (clk),
.toggle (toggle));
%000000 reg [1:0] memory[121:110];
wire [1023:0] largeish = {992'h0, cyc};
// CHECK_COVER_MISSING(-1)
always @ (posedge clk) begin
if (cyc!=0) begin
cyc <= cyc + 1;
memory[cyc + 'd100] <= memory[cyc + 'd100] + 2'b1;
toggle <= '0;
stoggle.u <= toggle;
stoggle.b <= toggle;
ptoggle[0][0] <= toggle;
if (cyc==3) begin
toggle <= '1;
end
if (cyc==4) begin
toggle <= '0;
end
else if (cyc==10) begin
$write("*-* All Finished *-*\n");
$finish;
end
end
end
endmodule
module alpha (/*AUTOARG*/
// Outputs
toggle_up,
// Inputs
clk, toggle, cyc_copy
);
// t.a1 and t.a2 collapse to a count of 2
000038 input clk;
%000004 input toggle;
// CHECK_COVER(-1,"top.t.a*",4)
// 2 edges * (t.a1 and t.a2)
%000000 input [7:0] cyc_copy;
// CHECK_COVER(-1,"top.t.a*","cyc_copy[0]",22)
// CHECK_COVER(-2,"top.t.a*","cyc_copy[1]",10)
// CHECK_COVER(-3,"top.t.a*","cyc_copy[2]",4)
// CHECK_COVER(-4,"top.t.a*","cyc_copy[3]",2)
// CHECK_COVER(-5,"top.t.a*","cyc_copy[4]",0)
// CHECK_COVER(-6,"top.t.a*","cyc_copy[5]",0)
// CHECK_COVER(-7,"top.t.a*","cyc_copy[6]",0)
// CHECK_COVER(-8,"top.t.a*","cyc_copy[7]",0)
%000004 reg toggle_internal;
// CHECK_COVER(-1,"top.t.a*",4)
// 2 edges * (t.a1 and t.a2)
%000004 output reg toggle_up;
// CHECK_COVER(-1,"top.t.a*",4)
// 2 edges * (t.a1 and t.a2)
always @ (posedge clk) begin
toggle_internal <= toggle;
toggle_up <= toggle;
end
endmodule
module beta (/*AUTOARG*/
// Inputs
clk, toggle_up
);
000019 input clk;
%000002 input toggle_up;
// CHECK_COVER(-1,"top.t.b1","toggle_up",2)
/* verilator public_module */
always @ (posedge clk) begin
if (0 && toggle_up) begin end
end
endmodule
module off (/*AUTOARG*/
// Inputs
clk, toggle
);
// verilator coverage_off
input clk;
// CHECK_COVER_MISSING(-1)
// verilator coverage_on
%000002 input toggle;
// CHECK_COVER(-1,"top.t.o1","toggle",2)
endmodule

View File

@ -35,5 +35,15 @@ run(cmd => ["../bin/verilator_coverage",
files_identical("$Self->{obj_dir}/annotated/$Self->{name}.v", $Self->{golden_filename});
run(cmd => ["../bin/verilator_coverage",
"--annotate-points",
"--annotate", "$Self->{obj_dir}/annotated-points",
"$Self->{obj_dir}/coverage.dat",
],
verilator_run => 1,
);
files_identical("$Self->{obj_dir}/annotated-points/$Self->{name}.v", "t/" . $Self->{name} . "_points.out");
ok(1);
1;

View File

@ -0,0 +1,218 @@
// // verilator_coverage annotation
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2008 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
module t (/*AUTOARG*/
// Inputs
clk,
check_real,
check_string
);
000019 input clk;
+000019 point: comment=clk
input real check_real; // Check issue #2741
input string check_string; // Check issue #2766
typedef struct packed {
union packed {
logic ua;
logic ub;
} u;
logic b;
} str_t;
%000002 reg toggle; initial toggle='0;
-000002 point: comment=toggle
%000002 str_t stoggle; initial stoggle='0;
-000002 point: comment=stoggle.b
-000002 point: comment=stoggle.u.ua
const reg aconst = '0;
%000000 reg [1:0][1:0] ptoggle; initial ptoggle=0;
-000002 point: comment=ptoggle[0][0]
-000000 point: comment=ptoggle[0][1]
-000000 point: comment=ptoggle[1][0]
-000000 point: comment=ptoggle[1][1]
integer cyc; initial cyc=1;
%000000 wire [7:0] cyc_copy = cyc[7:0];
+000011 point: comment=cyc_copy[0]
-000005 point: comment=cyc_copy[1]
-000002 point: comment=cyc_copy[2]
-000001 point: comment=cyc_copy[3]
-000000 point: comment=cyc_copy[4]
-000000 point: comment=cyc_copy[5]
-000000 point: comment=cyc_copy[6]
-000000 point: comment=cyc_copy[7]
%000002 wire toggle_up;
-000002 point: comment=toggle_up
alpha a1 (/*AUTOINST*/
// Outputs
.toggle_up (toggle_up),
// Inputs
.clk (clk),
.toggle (toggle),
.cyc_copy (cyc_copy[7:0]));
alpha a2 (/*AUTOINST*/
// Outputs
.toggle_up (toggle_up),
// Inputs
.clk (clk),
.toggle (toggle),
.cyc_copy (cyc_copy[7:0]));
beta b1 (/*AUTOINST*/
// Inputs
.clk (clk),
.toggle_up (toggle_up));
off o1 (/*AUTOINST*/
// Inputs
.clk (clk),
.toggle (toggle));
%000000 reg [1:0] memory[121:110];
-000001 point: comment=memory[110][0]
-000000 point: comment=memory[110][1]
-000000 point: comment=memory[111][0]
-000000 point: comment=memory[111][1]
-000000 point: comment=memory[112][0]
-000000 point: comment=memory[112][1]
-000000 point: comment=memory[113][0]
-000000 point: comment=memory[113][1]
-000000 point: comment=memory[114][0]
-000000 point: comment=memory[114][1]
-000000 point: comment=memory[115][0]
-000000 point: comment=memory[115][1]
-000000 point: comment=memory[116][0]
-000000 point: comment=memory[116][1]
-000000 point: comment=memory[117][0]
-000000 point: comment=memory[117][1]
-000000 point: comment=memory[118][0]
-000000 point: comment=memory[118][1]
-000000 point: comment=memory[119][0]
-000000 point: comment=memory[119][1]
-000000 point: comment=memory[120][0]
-000000 point: comment=memory[120][1]
-000000 point: comment=memory[121][0]
-000000 point: comment=memory[121][1]
wire [1023:0] largeish = {992'h0, cyc};
// CHECK_COVER_MISSING(-1)
always @ (posedge clk) begin
if (cyc!=0) begin
cyc <= cyc + 1;
memory[cyc + 'd100] <= memory[cyc + 'd100] + 2'b1;
toggle <= '0;
stoggle.u <= toggle;
stoggle.b <= toggle;
ptoggle[0][0] <= toggle;
if (cyc==3) begin
toggle <= '1;
end
if (cyc==4) begin
toggle <= '0;
end
else if (cyc==10) begin
$write("*-* All Finished *-*\n");
$finish;
end
end
end
endmodule
module alpha (/*AUTOARG*/
// Outputs
toggle_up,
// Inputs
clk, toggle, cyc_copy
);
// t.a1 and t.a2 collapse to a count of 2
000038 input clk;
+000038 point: comment=clk
%000004 input toggle;
-000004 point: comment=toggle
// CHECK_COVER(-1,"top.t.a*",4)
// 2 edges * (t.a1 and t.a2)
%000000 input [7:0] cyc_copy;
+000022 point: comment=cyc_copy[0]
+000010 point: comment=cyc_copy[1]
-000004 point: comment=cyc_copy[2]
-000002 point: comment=cyc_copy[3]
-000000 point: comment=cyc_copy[4]
-000000 point: comment=cyc_copy[5]
-000000 point: comment=cyc_copy[6]
-000000 point: comment=cyc_copy[7]
// CHECK_COVER(-1,"top.t.a*","cyc_copy[0]",22)
// CHECK_COVER(-2,"top.t.a*","cyc_copy[1]",10)
// CHECK_COVER(-3,"top.t.a*","cyc_copy[2]",4)
// CHECK_COVER(-4,"top.t.a*","cyc_copy[3]",2)
// CHECK_COVER(-5,"top.t.a*","cyc_copy[4]",0)
// CHECK_COVER(-6,"top.t.a*","cyc_copy[5]",0)
// CHECK_COVER(-7,"top.t.a*","cyc_copy[6]",0)
// CHECK_COVER(-8,"top.t.a*","cyc_copy[7]",0)
%000004 reg toggle_internal;
-000004 point: comment=toggle_internal
// CHECK_COVER(-1,"top.t.a*",4)
// 2 edges * (t.a1 and t.a2)
%000004 output reg toggle_up;
-000004 point: comment=toggle_up
// CHECK_COVER(-1,"top.t.a*",4)
// 2 edges * (t.a1 and t.a2)
always @ (posedge clk) begin
toggle_internal <= toggle;
toggle_up <= toggle;
end
endmodule
module beta (/*AUTOARG*/
// Inputs
clk, toggle_up
);
000019 input clk;
+000019 point: comment=clk
%000002 input toggle_up;
-000002 point: comment=toggle_up
// CHECK_COVER(-1,"top.t.b1","toggle_up",2)
/* verilator public_module */
always @ (posedge clk) begin
if (0 && toggle_up) begin end
end
endmodule
module off (/*AUTOARG*/
// Inputs
clk, toggle
);
// verilator coverage_off
input clk;
// CHECK_COVER_MISSING(-1)
// verilator coverage_on
%000002 input toggle;
-000002 point: comment=toggle
// CHECK_COVER(-1,"top.t.o1","toggle",2)
endmodule

View File

@ -1,4 +1,4 @@
TN:verilator_coverage
SF:file1.sp
DA:159,53
DA:159,1
end_of_record