From b778784333ba0dda0f13141c5b68db9a11e98509 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Wed, 8 Feb 2023 20:15:11 -0500 Subject: [PATCH] Add --annotate-points option, change multipoint on line reporting (#3876). --- Changes | 1 + bin/verilator_coverage | 1 + docs/guide/exe_verilator_coverage.rst | 27 +- docs/guide/extensions.rst | 2 + src/VlcMain.cpp | 9 +- src/VlcOptions.h | 2 + src/VlcPoint.h | 31 +- src/VlcSource.h | 43 +- src/VlcTop.cpp | 77 +-- test_regress/t/t_cover_line.out | 584 ++++++++++++----------- test_regress/t/t_cover_line_cc.pl | 1 + test_regress/t/t_cover_line_cc_vlt.pl | 1 + test_regress/t/t_cover_line_trace.pl | 1 + test_regress/t/t_cover_toggle.out | 324 ++++++------- test_regress/t/t_cover_toggle.pl | 10 + test_regress/t/t_cover_toggle_points.out | 218 +++++++++ test_regress/t/t_vlcov_info.out | 2 +- 17 files changed, 816 insertions(+), 518 deletions(-) create mode 100644 test_regress/t/t_cover_toggle_points.out diff --git a/Changes b/Changes index a70a03d99..8a55dbf9d 100644 --- a/Changes +++ b/Changes @@ -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. diff --git a/bin/verilator_coverage b/bin/verilator_coverage index 92f1a7c20..19493d44b 100755 --- a/bin/verilator_coverage +++ b/bin/verilator_coverage @@ -169,6 +169,7 @@ L. --annotate Directory name for source annotation. --annotate-all All files should be shown. --annotate-min 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 diff --git a/docs/guide/exe_verilator_coverage.rst b/docs/guide/exe_verilator_coverage.rst index 57eb02808..2c78cf7de 100644 --- a/docs/guide/exe_verilator_coverage.rst +++ b/docs/guide/exe_verilator_coverage.rst @@ -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. diff --git a/docs/guide/extensions.rst b/docs/guide/extensions.rst index b2aba29bd..5994fb770 100644 --- a/docs/guide/extensions.rst +++ b/docs/guide/extensions.rst @@ -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; diff --git a/src/VlcMain.cpp b/src/VlcMain.cpp index 78291e3e6..f6352cb03 100644 --- a/src/VlcMain.cpp +++ b/src/VlcMain.cpp @@ -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); diff --git a/src/VlcOptions.h b/src/VlcOptions.h index c105594d4..5bfd183f5 100644 --- a/src/VlcOptions.h +++ b/src/VlcOptions.h @@ -37,6 +37,7 @@ class VlcOptions final { string m_annotateOut; // main switch: --annotate I bool m_annotateAll = false; // main switch: --annotate-all int m_annotateMin = 10; // main switch: --annotate-min I + 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; } diff --git a/src/VlcPoint.h b/src/VlcPoint.h index bb954bf36..f2ed5b287 100644 --- a/src/VlcPoint.h +++ b/src/VlcPoint.h @@ -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]; } diff --git a/src/VlcSource.h b/src/VlcSource.h index 5c4eedf04..f08188e1e 100644 --- a/src/VlcSource.h +++ b/src/VlcSource.h @@ -21,38 +21,49 @@ #include "verilatedos.h" #include +#include #include #include +class VlcPoint; + //******************************************************************** // VlcColumnCount - count at specific source file, line and column class VlcSourceCount final { private: + // TYPES + using PointsSet = std::set; + // 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; // Map of {column} - using LinenoMap = std::map; // Map of {lineno}{column} + using LinenoMap = std::map; // 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); } }; diff --git a/src/VlcTop.cpp b/src/VlcTop.cpp index db5a9fa03..728813622 100644 --- a/src/VlcTop.cpp +++ b/src/VlcTop.cpp @@ -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 "<second; - for (auto& ci : cmap) { - VlcSourceCount& col = ci.second; - // UINFO(0,"Source - // "<second; + // UINFO(0,"Source + // "<dumpAnnotate(os, opt.annotateMin()); } } - - if (first) os << "\t" << line << '\n'; } } } diff --git a/test_regress/t/t_cover_line.out b/test_regress/t/t_cover_line.out index da95bcf79..ca00845b8 100644 --- a/test_regress/t/t_cover_line.out +++ b/test_regress/t/t_cover_line.out @@ -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 + diff --git a/test_regress/t/t_cover_line_cc.pl b/test_regress/t/t_cover_line_cc.pl index 8c8d785ae..60efcb2da 100755 --- a/test_regress/t/t_cover_line_cc.pl +++ b/test_regress/t/t_cover_line_cc.pl @@ -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, diff --git a/test_regress/t/t_cover_line_cc_vlt.pl b/test_regress/t/t_cover_line_cc_vlt.pl index 6b885fb8f..dac2c2e24 100755 --- a/test_regress/t/t_cover_line_cc_vlt.pl +++ b/test_regress/t/t_cover_line_cc_vlt.pl @@ -25,6 +25,7 @@ execute( inline_checks(); run(cmd => ["../bin/verilator_coverage", + "--annotate-points", "--annotate", "$Self->{obj_dir}/annotated", "$Self->{obj_dir}/coverage.dat", ], diff --git a/test_regress/t/t_cover_line_trace.pl b/test_regress/t/t_cover_line_trace.pl index a3763b8c5..7d52a768f 100755 --- a/test_regress/t/t_cover_line_trace.pl +++ b/test_regress/t/t_cover_line_trace.pl @@ -21,6 +21,7 @@ execute( ); run(cmd => ["../bin/verilator_coverage", + "--annotate-points", "--annotate", "$Self->{obj_dir}/annotated", "$Self->{obj_dir}/coverage.dat", ], diff --git a/test_regress/t/t_cover_toggle.out b/test_regress/t/t_cover_toggle.out index d9dd61b7d..3baf9007b 100644 --- a/test_regress/t/t_cover_toggle.out +++ b/test_regress/t/t_cover_toggle.out @@ -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 + diff --git a/test_regress/t/t_cover_toggle.pl b/test_regress/t/t_cover_toggle.pl index 5564c29d5..45cfb4989 100755 --- a/test_regress/t/t_cover_toggle.pl +++ b/test_regress/t/t_cover_toggle.pl @@ -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; diff --git a/test_regress/t/t_cover_toggle_points.out b/test_regress/t/t_cover_toggle_points.out new file mode 100644 index 000000000..120ddeebd --- /dev/null +++ b/test_regress/t/t_cover_toggle_points.out @@ -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 + diff --git a/test_regress/t/t_vlcov_info.out b/test_regress/t/t_vlcov_info.out index 40b3c320b..bb304d511 100644 --- a/test_regress/t/t_vlcov_info.out +++ b/test_regress/t/t_vlcov_info.out @@ -1,4 +1,4 @@ TN:verilator_coverage SF:file1.sp -DA:159,53 +DA:159,1 end_of_record