forked from github/verilator
Support verilator_coverage --write-info for lcov HTML reports.
This commit is contained in:
parent
6fd7f45cef
commit
d33d0301f8
2
Changes
2
Changes
@ -5,6 +5,8 @@ The contributors that suggested a given feature are shown in []. Thanks!
|
||||
|
||||
* Verilator 4.035 devel
|
||||
|
||||
*** Support verilator_coverage --write-info for lcov HTML reports.
|
||||
|
||||
**** Support multi channel descriptor I/O (#2190) [Stephen Henry]
|
||||
|
||||
**** Support $countbits. (#2287) [Yossi Nivin]
|
||||
|
@ -5171,6 +5171,10 @@ For an example, after running 'make test' in the Verilator distribution,
|
||||
see the examples/make_tracing_c/logs directory. Grep for lines starting
|
||||
with '%' to see what lines Verilator believes need more coverage.
|
||||
|
||||
Info files can be written by verilator_coverage for import to C<lcov>.
|
||||
This enables use of C<genhtml> for HTML reports and importing reports to
|
||||
sites such as L<https://codecov.io>.
|
||||
|
||||
=item Where is the translate_off command? (How do I ignore a construct?)
|
||||
|
||||
Translate on/off pragmas are generally a bad idea, as it's easy to have
|
||||
|
@ -156,6 +156,8 @@ verilator_coverage - Verilator coverage analyzer
|
||||
|
||||
verilator_coverage -write merged.dat -read <datafiles>...
|
||||
|
||||
verilator_coverage -write-info merged.info -read <datafiles>...
|
||||
|
||||
Verilator_coverage processes Verilator coverage reports.
|
||||
|
||||
With --anotate, it reads the specified data file and generates annotated
|
||||
@ -224,8 +226,20 @@ Displays program version and exits.
|
||||
=item --write I<filename>
|
||||
|
||||
Specifies the aggregate coverage results, summed across all the files,
|
||||
should be written to the given filename. This is useful in scripts to
|
||||
combine many sequential runs into one master coverage file.
|
||||
should be written to the given filename in verilator_coverage data format.
|
||||
This is useful in scripts to combine many sequential runs into one master
|
||||
coverage file.
|
||||
|
||||
=item --write-info I<filename.info>
|
||||
|
||||
Specifies the aggregate coverage results, summed across all the files,
|
||||
should be written to the given filename in C<lcov> .info format.
|
||||
This may be used to use C<lcov> to aggregate or generate reports.
|
||||
|
||||
The info format loses data compared to the Verilator coverage data format;
|
||||
the info will all forms of coverage converted to line style coverage, and
|
||||
if there are multiple coverage points on a single line, the minimum
|
||||
coverage across those points will be used to report coverage of the line.
|
||||
|
||||
=back
|
||||
|
||||
@ -277,7 +291,7 @@ Wilson Snyder <wsnyder@wsnyder.org>
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
C<verilator>
|
||||
C<verilator>, C<lcov>
|
||||
|
||||
L<verilator_coverage --help> which is the source for this document.
|
||||
|
||||
|
@ -108,6 +108,9 @@ void VlcOptions::parseOptsList(int argc, char** argv) {
|
||||
} else if (!strcmp(sw, "-write") && (i + 1) < argc) {
|
||||
shift;
|
||||
m_writeFile = argv[i];
|
||||
} else if (!strcmp(sw, "-write-info") && (i + 1) < argc) {
|
||||
shift;
|
||||
m_writeInfoFile = argv[i];
|
||||
} else {
|
||||
v3fatal("Invalid option: " << argv[i]);
|
||||
}
|
||||
@ -170,8 +173,9 @@ int main(int argc, char** argv, char** /*env*/) {
|
||||
top.tests().dump(false);
|
||||
}
|
||||
|
||||
if (!top.opt.writeFile().empty()) {
|
||||
top.writeCoverage(top.opt.writeFile());
|
||||
if (!top.opt.writeFile().empty() || !top.opt.writeInfoFile().empty()) {
|
||||
if (!top.opt.writeFile().empty()) top.writeCoverage(top.opt.writeFile());
|
||||
if (!top.opt.writeInfoFile().empty()) top.writeInfo(top.opt.writeInfoFile());
|
||||
V3Error::abortIfWarnings();
|
||||
if (top.opt.unlink()) {
|
||||
const VlStringSet& readFiles = top.opt.readFiles();
|
||||
|
@ -42,6 +42,7 @@ class VlcOptions {
|
||||
bool m_rank; // main switch: --rank
|
||||
bool m_unlink; // main switch: --unlink
|
||||
string m_writeFile; // main switch: --write
|
||||
string m_writeInfoFile; // main switch: --write-info
|
||||
// clang-format on
|
||||
|
||||
private:
|
||||
@ -72,6 +73,7 @@ public:
|
||||
bool rank() const { return m_rank; }
|
||||
bool unlink() const { return m_unlink; }
|
||||
string writeFile() const { return m_writeFile; }
|
||||
string writeInfoFile() const { return m_writeInfoFile; }
|
||||
|
||||
// METHODS (from main)
|
||||
static string version();
|
||||
|
@ -77,6 +77,61 @@ void VlcTop::writeCoverage(const string& filename) {
|
||||
}
|
||||
}
|
||||
|
||||
void VlcTop::writeInfo(const string& filename) {
|
||||
UINFO(2, "writeInfo " << filename << endl);
|
||||
|
||||
std::ofstream os(filename.c_str());
|
||||
if (!os) {
|
||||
v3fatal("Can't write " << filename);
|
||||
return;
|
||||
}
|
||||
|
||||
annotateCalc();
|
||||
|
||||
// See 'man lcov' for format details
|
||||
// TN:<trace_file_name>
|
||||
// Source file:
|
||||
// SF:<absolute_path_to_source_file>
|
||||
// FN:<line_number_of_function_start>,<function_name>
|
||||
// FNDA:<execution_count>,<function_name>
|
||||
// FNF:<number_functions_found>
|
||||
// FNH:<number_functions_hit>
|
||||
// Branches:
|
||||
// BRDA:<line_number>,<block_number>,<branch_number>,<taken_count_or_-_for_zero>
|
||||
// BRF:<number_of_branches_found>
|
||||
// BRH:<number_of_branches_hit>
|
||||
// Line counts:
|
||||
// DA:<line_number>,<execution_count>
|
||||
// LF:<number_of_lines_found>
|
||||
// LH:<number_of_lines_hit>
|
||||
// Section ending:
|
||||
// end_of_record
|
||||
|
||||
os << "TN:verilator_coverage\n";
|
||||
for (VlcSources::NameMap::iterator sit = m_sources.begin(); sit != m_sources.end(); ++sit) {
|
||||
VlcSource& source = sit->second;
|
||||
os << "SF:" << source.name() << endl;
|
||||
VlcSource::LinenoMap& lines = source.lines();
|
||||
for (VlcSource::LinenoMap::iterator lit = lines.begin(); lit != lines.end(); ++lit) {
|
||||
int lineno = lit->first;
|
||||
VlcSource::ColumnMap& cmap = lit->second;
|
||||
bool first = true;
|
||||
vluint64_t min_count = 0; // Minimum across all columns on line
|
||||
for (VlcSource::ColumnMap::iterator cit = cmap.begin(); cit != cmap.end(); ++cit) {
|
||||
VlcSourceCount& col = cit->second;
|
||||
if (first) {
|
||||
min_count = col.count();
|
||||
first = false;
|
||||
} else {
|
||||
min_count = std::min(min_count, col.count());
|
||||
}
|
||||
}
|
||||
os << "DA:" << lineno << "," << min_count << "\n";
|
||||
}
|
||||
os << "end_of_record\n";
|
||||
}
|
||||
}
|
||||
|
||||
//********************************************************************
|
||||
|
||||
struct CmpComputrons {
|
||||
|
@ -58,6 +58,7 @@ public:
|
||||
void annotate(const string& dirname);
|
||||
void readCoverage(const string& filename, bool nonfatal = false);
|
||||
void writeCoverage(const string& filename);
|
||||
void writeInfo(const string& filename);
|
||||
|
||||
void rank();
|
||||
};
|
||||
|
@ -31,5 +31,24 @@ run(cmd => ["../bin/verilator_coverage",
|
||||
|
||||
files_identical("$Self->{obj_dir}/annotated/t_cover_line.v", "t/t_cover_line.out");
|
||||
|
||||
# Also try lcov
|
||||
run(cmd => ["../bin/verilator_coverage",
|
||||
"--write-info", "$Self->{obj_dir}/coverage.info",
|
||||
"$Self->{obj_dir}/coverage.dat"],
|
||||
verilator_run => 1,
|
||||
);
|
||||
|
||||
# If installed
|
||||
if (`lcov --help` !~ /Usage:/
|
||||
|| `genhtml --help` !~ /Usage:/) {
|
||||
skip("lcov or genhtml not installed");
|
||||
} else {
|
||||
run(cmd => ["genhtml",
|
||||
"$Self->{obj_dir}/coverage.info",
|
||||
"--output-directory $Self->{obj_dir}/html",
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
|
4
test_regress/t/t_vlcov_info.out
Normal file
4
test_regress/t/t_vlcov_info.out
Normal file
@ -0,0 +1,4 @@
|
||||
TN:verilator_coverage
|
||||
SF:file1.sp
|
||||
DA:159,53
|
||||
end_of_record
|
26
test_regress/t/t_vlcov_info.pl
Executable file
26
test_regress/t/t_vlcov_info.pl
Executable file
@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env 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.
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
scenarios(dist => 1);
|
||||
|
||||
run(cmd => ["../bin/verilator_coverage",
|
||||
"--write-info", "$Self->{obj_dir}/coverage.info",
|
||||
"t/t_vlcov_data_a.dat",
|
||||
"t/t_vlcov_data_b.dat",
|
||||
"t/t_vlcov_data_c.dat",
|
||||
"t/t_vlcov_data_d.dat",
|
||||
],
|
||||
verilator_run => 1,
|
||||
);
|
||||
|
||||
files_identical("$Self->{obj_dir}/coverage.info", $Self->{golden_filename});
|
||||
|
||||
ok(1);
|
||||
1;
|
Loading…
Reference in New Issue
Block a user