mirror of
https://github.com/verilator/verilator.git
synced 2025-01-01 04:07:34 +00:00
Internals: Add lcov code coverage markers.
This commit is contained in:
parent
ac43e7322b
commit
01ef7122e9
@ -496,8 +496,9 @@ clean mostlyclean distclean maintainer-clean::
|
||||
rm -f *.pg *.pgs *.toc *.tp *.tps *.vr *.vrs *.idx
|
||||
rm -f *.ev *.evs *.ov *.ovs *.cv *.cvs *.ma *.mas
|
||||
rm -f *.tex
|
||||
rm -rf test_*/obj_dir
|
||||
rm -rf examples/*/obj_dir examples/*/logs
|
||||
rm -rf test_*/obj_dir
|
||||
rm -rf nodist/obj_dir
|
||||
|
||||
distclean maintainer-clean::
|
||||
rm -f *.info* *.1 $(INFOS)
|
||||
|
@ -1093,8 +1093,8 @@ IData VL_FGETS_IXI(int obits, void* destp, IData fpi) VL_MT_SAFE {
|
||||
IData bytes = VL_BYTES_I(obits);
|
||||
char buffer[VL_TO_STRING_MAX_WORDS*VL_WORDSIZE+1];
|
||||
// V3Emit has static check that bytes < VL_TO_STRING_MAX_WORDS, but be safe
|
||||
if (VL_UNLIKELY(bytes > VL_TO_STRING_MAX_WORDS*VL_WORDSIZE)) {
|
||||
VL_FATAL_MT(__FILE__, __LINE__, "", "Internal: fgets buffer overrun");
|
||||
if (VL_UNCOVERABLE(bytes > VL_TO_STRING_MAX_WORDS*VL_WORDSIZE)) {
|
||||
VL_FATAL_MT(__FILE__, __LINE__, "", "Internal: fgets buffer overrun"); // LCOV_EXCL_LINE
|
||||
}
|
||||
|
||||
// We don't use fgets, as we must read \0s.
|
||||
@ -1317,7 +1317,7 @@ const char* memhFormat(int nBits) {
|
||||
case 5: VL_SNPRINTF(buf, 32, "%%06x"); break;
|
||||
case 6: VL_SNPRINTF(buf, 32, "%%07x"); break;
|
||||
case 7: VL_SNPRINTF(buf, 32, "%%08x"); break;
|
||||
default: assert(false); break;
|
||||
default: assert(false); break; // LCOV_EXCL_LINE
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
@ -1842,9 +1842,9 @@ void Verilated::flushCb(VerilatedVoidCb cb) VL_MT_SAFE {
|
||||
VerilatedLockGuard lock(m_mutex);
|
||||
if (s_flushCb == cb) {} // Ok - don't duplicate
|
||||
else if (!s_flushCb) { s_flushCb=cb; }
|
||||
else {
|
||||
else { // LCOV_EXCL_LINE
|
||||
// Someday we may allow multiple callbacks ala atexit(), but until then
|
||||
VL_FATAL_MT("unknown", 0, "",
|
||||
VL_FATAL_MT("unknown", 0, "", // LCOV_EXCL_LINE
|
||||
"Verilated::flushCb called twice with different callbacks");
|
||||
}
|
||||
}
|
||||
@ -2136,8 +2136,8 @@ void VerilatedScope::exportInsert(int finalize, const char* namep, void* cb) VL_
|
||||
// Alternative is to dynamically stretch the array, which is more code, and slower.
|
||||
if (funcnum >= m_funcnumMax) { m_funcnumMax = funcnum+1; }
|
||||
} else {
|
||||
if (VL_UNLIKELY(funcnum >= m_funcnumMax)) {
|
||||
VL_FATAL_MT(__FILE__, __LINE__, "",
|
||||
if (VL_UNCOVERABLE(funcnum >= m_funcnumMax)) {
|
||||
VL_FATAL_MT(__FILE__, __LINE__, "", // LCOV_EXCL_LINE
|
||||
"Internal: Bad funcnum vs. pre-finalize maximum");
|
||||
}
|
||||
if (VL_UNLIKELY(!m_callbacksp)) { // First allocation
|
||||
|
@ -189,8 +189,8 @@ public:
|
||||
// METHODS
|
||||
/// Check that the current thread ID is the same as the construction thread ID
|
||||
void check() VL_MT_UNSAFE_ONE {
|
||||
if (!VL_LIKELY(m_threadid == VL_THREAD_ID())) {
|
||||
fatal_different();
|
||||
if (VL_UNCOVERABLE(m_threadid != VL_THREAD_ID())) {
|
||||
fatal_different(); // LCOV_EXCL_LINE
|
||||
}
|
||||
}
|
||||
static void fatal_different() VL_MT_SAFE;
|
||||
|
@ -221,8 +221,7 @@ void VlThreadPool::profileDump(const char* filenamep, vluint64_t ticksElapsed) {
|
||||
eit->m_cpu,
|
||||
thread_id);
|
||||
break;
|
||||
default: assert(false);
|
||||
break;
|
||||
default: assert(false); break; // LCOV_EXCL_LINE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -74,7 +74,7 @@ public:
|
||||
// We reserve word zero for the next pointer, as that's safer in case a
|
||||
// dangling reference to the original remains around.
|
||||
static const size_t chunk = 96;
|
||||
if (VL_UNLIKELY(size>chunk)) VL_FATAL_MT(__FILE__, __LINE__, "", "increase chunk");
|
||||
if (VL_UNCOVERABLE(size>chunk)) VL_FATAL_MT(__FILE__, __LINE__, "", "increase chunk");
|
||||
if (VL_LIKELY(t_freeHead)) {
|
||||
vluint8_t* newp = t_freeHead;
|
||||
t_freeHead = *((vluint8_t**)newp);
|
||||
@ -348,7 +348,7 @@ public:
|
||||
varop->createPrevDatap();
|
||||
}
|
||||
}
|
||||
if (VL_UNLIKELY(vop->reason() >= CB_ENUM_MAX_VALUE)) {
|
||||
if (VL_UNCOVERABLE(vop->reason() >= CB_ENUM_MAX_VALUE)) {
|
||||
VL_FATAL_MT(__FILE__, __LINE__, "", "vpi bb reason too large");
|
||||
}
|
||||
s_s.m_cbObjLists[vop->reason()].push_back(vop);
|
||||
@ -1255,7 +1255,7 @@ void vpi_get_value(vpiHandle object, p_vpi_value value_p) {
|
||||
return;
|
||||
case VLVT_WDATA: {
|
||||
int words = VL_WORDS_I(vop->varp()->packed().elements());
|
||||
if (VL_UNLIKELY(words >= VL_MULS_MAX_WORDS)) {
|
||||
if (VL_UNCOVERABLE(words >= VL_MULS_MAX_WORDS)) {
|
||||
VL_FATAL_MT(__FILE__, __LINE__, "",
|
||||
"vpi_get_value with more than VL_MULS_MAX_WORDS; increase and recompile");
|
||||
}
|
||||
|
@ -110,6 +110,7 @@
|
||||
# define VL_LIKELY(x) (!!(x)) ///< Boolean expression more often true than false
|
||||
# define VL_UNLIKELY(x) (!!(x)) ///< Boolean expression more often false than true
|
||||
#endif
|
||||
#define VL_UNCOVERABLE(x) VL_UNLIKELY(x) ///< Boolean expression never hit by users (no coverage)
|
||||
#ifndef VL_UNREACHABLE
|
||||
# define VL_UNREACHABLE ///< Point that may never be reached
|
||||
#endif
|
||||
|
260
nodist/code_coverage
Executable file
260
nodist/code_coverage
Executable file
@ -0,0 +1,260 @@
|
||||
#!/usr/bin/perl -w
|
||||
# See copyright, etc in below POD section.
|
||||
######################################################################
|
||||
|
||||
use Cwd;
|
||||
use File::Copy qw(cp);
|
||||
use File::Path qw(mkpath);
|
||||
use Getopt::Long;
|
||||
use IO::File;
|
||||
use Pod::Usage;
|
||||
use strict;
|
||||
use vars qw($Debug);
|
||||
|
||||
our $Exclude_Line_Regexp;
|
||||
our @Remove_Sources;
|
||||
our @Source_Globs;
|
||||
|
||||
#======================================================================
|
||||
# main
|
||||
|
||||
our $Opt_Stage = 0;
|
||||
|
||||
autoflush STDOUT 1;
|
||||
autoflush STDERR 1;
|
||||
Getopt::Long::config("no_auto_abbrev");
|
||||
if (! GetOptions(
|
||||
"debug" => sub { $Debug = 1; },
|
||||
"<>" => sub { die "%Error: Unknown parameter: $_[0]\n"; },
|
||||
"stage=i" => \$Opt_Stage,
|
||||
)) {
|
||||
die "%Error: Bad usage, try 'install_test --help'\n";
|
||||
}
|
||||
|
||||
test();
|
||||
exit(0);
|
||||
|
||||
#######################################################################
|
||||
|
||||
sub test {
|
||||
-r "nodist/code_coverage.dat" or die "%Error: Run from the top of the verilator kit,";
|
||||
require "./nodist/code_coverage.dat";
|
||||
|
||||
if ($Opt_Stage <= 0) {
|
||||
print "Stage 0: configure (coverage on)\n";
|
||||
run("make distclean");
|
||||
run("./configure --enable-longtests CXX='g++ --coverage'");
|
||||
run("make -k");
|
||||
# The optimized versions will not collect good coverage, overwrite them
|
||||
run("cp bin/verilator_bin_dbg bin/verilator_bin");
|
||||
run("cp bin/verilator_coverage_bin_dbg bin/verilator_coverage_bin");
|
||||
}
|
||||
|
||||
if ($Opt_Stage <= 1) {
|
||||
print "Stage 1: make examples (with coverage on)\n";
|
||||
run("make examples");
|
||||
}
|
||||
|
||||
my $cc_dir = "nodist/obj_dir/coverage";
|
||||
if ($Opt_Stage <= 2) {
|
||||
print "Stage 2: Create info files under $cc_dir\n";
|
||||
mkpath($cc_dir);
|
||||
mkpath("$cc_dir/info");
|
||||
my $dats = `find . -print | grep .gcda`;
|
||||
my %dirs;
|
||||
foreach my $dat (split '\n', $dats) {
|
||||
$dat =~ s!/[^/]+$!!;
|
||||
$dirs{$dat} = 1;
|
||||
}
|
||||
foreach my $dir (sort keys %dirs) {
|
||||
(my $outname = $dir) =~ s![^a-zA-Z0-9]+!_!g;
|
||||
run("cd $cc_dir/info ; lcov -c -d ../../../$dir -o app_test_${outname}.info");
|
||||
}
|
||||
}
|
||||
|
||||
if ($Opt_Stage <= 3) {
|
||||
# lcov doesn't have a control file to override single lines, so replicate the sources
|
||||
print "Stage 3: Clone sources under $cc_dir\n";
|
||||
clone_sources($cc_dir);
|
||||
}
|
||||
|
||||
if ($Opt_Stage <= 4) {
|
||||
print "Stage 4: Copy .gcno files\n";
|
||||
my $dats = `find . -print | grep .gcno`;
|
||||
foreach my $dat (split '\n', $dats) {
|
||||
next if $dat =~ /$cc_dir/;
|
||||
my $outdat = $cc_dir."/".$dat;
|
||||
#print "cp $dat, $outdat);\n";
|
||||
cp($dat, $outdat);
|
||||
}
|
||||
}
|
||||
|
||||
if ($Opt_Stage <= 5) {
|
||||
print "Stage 5: Combine data files\n";
|
||||
run("cd $cc_dir ; lcov -c -i -d src/obj_dbg -o app_base.info");
|
||||
run("cd $cc_dir ; lcov -a app_base.info -o app_total.info");
|
||||
my $infos = `cd $cc_dir ; find info -print | grep .info`;
|
||||
my $comb = "";
|
||||
my @infos = (split /\n/, $infos);
|
||||
foreach my $info (@infos) {
|
||||
$comb .= " -a $info";
|
||||
# Need to batch them to avoid overrunning shell command length limit
|
||||
if (length($comb) > 10000 || $info eq $infos[$#infos]) {
|
||||
run("cd $cc_dir ; lcov -a app_total.info $comb -o app_total.info");
|
||||
$comb = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($Opt_Stage <= 6) {
|
||||
print "Stage 6: Filter processed source files\n";
|
||||
my $cmd = '';
|
||||
foreach my $glob (@Remove_Sources) {
|
||||
$cmd .= " '$glob'";
|
||||
}
|
||||
run("cd $cc_dir ; lcov --remove app_total.info $cmd -o app_total.info");
|
||||
}
|
||||
|
||||
if ($Opt_Stage <= 7) {
|
||||
print "Stage 7: Create HTML\n";
|
||||
cleanup_abs_paths($cc_dir, "$cc_dir/app_total.info", "$cc_dir/app_total.info");
|
||||
run("cd $cc_dir ; genhtml app_total.info --demangle-cpp"
|
||||
." --rc lcov_branch_coverage=1 --rc genhtml_hi_limit=100 --output-directory html");
|
||||
}
|
||||
|
||||
if ($Opt_Stage <= 9) {
|
||||
print "*-* All Finished *-*\n";
|
||||
}
|
||||
}
|
||||
|
||||
sub clone_sources {
|
||||
my $cc_dir = shift;
|
||||
my $excluded_lines = 0;
|
||||
foreach my $glob (@Source_Globs) {
|
||||
foreach my $infile (glob $glob) {
|
||||
$infile !~ m!^/!
|
||||
or die "%Error: source globs should be relative not absolute filenames,";
|
||||
my $outfile = $cc_dir."/".$infile;
|
||||
(my $outpath = $outfile) =~ s!/[^/]*$!!;
|
||||
mkpath($outpath);
|
||||
my $fh = IO::File->new("<$infile") or die "%Error: $! $infile,";
|
||||
my $ofh = IO::File->new(">$outfile") or die "%Error: $! $outfile,";
|
||||
my $lineno = 0;
|
||||
while (defined(my $line = $fh->getline)) {
|
||||
$lineno++;
|
||||
chomp $line;
|
||||
if ($line !~ m!// LCOV_EXCL_LINE!
|
||||
&& $line =~ /$Exclude_Line_Regexp/) {
|
||||
$line .= " //code_coverage: // LCOV_EXCL_LINE\n";
|
||||
$excluded_lines++;
|
||||
#print "$infile:$lineno: $line";
|
||||
} else {
|
||||
}
|
||||
$ofh->print("$line\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
print "Source code lines automatically LCOV_EXCL_LINE'ed: $excluded_lines\n";
|
||||
}
|
||||
|
||||
sub cleanup_abs_paths {
|
||||
my $cc_dir = shift;
|
||||
my $infile = shift;
|
||||
my $outfile = shift;
|
||||
my $fh = IO::File->new("<$infile") or die "%Error: $! $infile,";
|
||||
my @lines;
|
||||
while (defined(my $line = $fh->getline)) {
|
||||
if ($line =~ m!^SF:/!) {
|
||||
$line =~ s!$ENV{VERILATOR_ROOT}/!!;
|
||||
$line =~ s!$cc_dir/!!;
|
||||
}
|
||||
push @lines, $line;
|
||||
}
|
||||
my $ofh = IO::File->new(">$outfile") or die "%Error: $! $outfile,";
|
||||
$ofh->print(@lines);
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
# .dat file callbacks
|
||||
|
||||
sub exclude_line_regexp {
|
||||
$Exclude_Line_Regexp = shift;
|
||||
}
|
||||
|
||||
sub remove_source {
|
||||
my @srcs = @_;
|
||||
push @Remove_Sources, @srcs;
|
||||
}
|
||||
|
||||
sub source_globs {
|
||||
my @dirs = @_;
|
||||
push @Source_Globs, @dirs;
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
|
||||
sub run {
|
||||
# Run a system command, check errors
|
||||
my $command = shift;
|
||||
print "\t$command\n";
|
||||
system "$command";
|
||||
my $status = $?;
|
||||
($status == 0) or die "%Error: Command Failed $command, $status, stopped";
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
code_coverage - Build and collect Verilator coverage
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
cd $VERILATOR_ROOT
|
||||
nodist/code_coverage
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
code_coverage builds Verilator with C++ coverage support and runs tests
|
||||
with coverage enabled.
|
||||
|
||||
This will rebuild the current object files.
|
||||
|
||||
=head1 ARGUMENTS
|
||||
|
||||
=over 4
|
||||
|
||||
=item --help
|
||||
|
||||
Displays this message and program version and exits.
|
||||
|
||||
=item -stage I<stage>
|
||||
|
||||
Runs a specific stage (see the script).
|
||||
|
||||
=back
|
||||
|
||||
=head1 DISTRIBUTION
|
||||
|
||||
Copyright 2019-2019 by Wilson Snyder. This package 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.
|
||||
|
||||
=head1 AUTHORS
|
||||
|
||||
Wilson Snyder <wsnyder@wsnyder.org>
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
C<lcov>
|
||||
|
||||
=cut
|
||||
|
||||
######################################################################
|
||||
### Local Variables:
|
||||
### compile-command: "cd .. ; nodist/code_coverage "
|
||||
### End:
|
42
nodist/code_coverage.dat
Normal file
42
nodist/code_coverage.dat
Normal file
@ -0,0 +1,42 @@
|
||||
# -*- Perl -*-
|
||||
# DESCRIPTION: Verilator: Internal C++ code lcov control file
|
||||
#
|
||||
# Copyright 2019-2019 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.
|
||||
|
||||
source_globs("src/*.cpp",
|
||||
"src/*.h",
|
||||
"src/*.l",
|
||||
"src/*.y",
|
||||
"src/obj_dbg/*.h",
|
||||
"src/obj_dbg/*.cpp",
|
||||
"include/*.c",
|
||||
"include/*.cpp",
|
||||
"include/*.h",
|
||||
"include/*/*.h",
|
||||
"include/*/*.cpp",
|
||||
"include/*/*.c",
|
||||
);
|
||||
|
||||
remove_source("/usr/include/*");
|
||||
remove_source("*/include/sysc/*");
|
||||
remove_source("*/V3ClkGater.cpp");
|
||||
remove_source("*/V3ClkGater.h");
|
||||
remove_source("*/V3GraphDfa.cpp");
|
||||
remove_source("*/V3GraphDfa.h");
|
||||
remove_source("*/V3Lexer_pregen.yy.cpp");
|
||||
remove_source("*/V3PreLex_pregen.yy.cpp");
|
||||
remove_source("*/verilog.c");
|
||||
remove_source("*include/gtkwave/*");
|
||||
# Something wrong in generation, unfortunately as would like this
|
||||
#genhtml: ERROR: cannot read /svaha/wsnyder/SandBox/homecvs/v4/verilator/src/obj_dbg/verilog.y
|
||||
#remove_source("*/src/obj_dbg/verilog.y");
|
||||
remove_source("*test_regress/*");
|
||||
remove_source("*examples/*");
|
||||
|
||||
|
||||
exclude_line_regexp(qr/(\bv3fatalSrc\b|\bVL_UNCOVERABLE\b)/);
|
||||
|
||||
1;
|
@ -77,7 +77,7 @@ private:
|
||||
&& VN_IS(sensesp->sensesp(), SenItem)
|
||||
&& VN_CAST(sensesp->sensesp(), SenItem)->isNever()) {
|
||||
// Never executing. Kill it.
|
||||
if (sensesp->sensesp()->nextp()) {
|
||||
if (VL_UNCOVERABLE(sensesp->sensesp()->nextp())) {
|
||||
nodep->v3fatalSrc("Never senitem should be alone, else the never should be eliminated.");
|
||||
}
|
||||
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
|
||||
@ -115,22 +115,22 @@ private:
|
||||
// No need to do statements under it, they're already moved.
|
||||
//iterateChildren(nodep);
|
||||
}
|
||||
virtual void visit(AstInitial* nodep) {
|
||||
virtual void visit(AstInitial* nodep) { // LCOV_EXCL_LINE
|
||||
nodep->v3fatalSrc("Node should have been under ACTIVE");
|
||||
}
|
||||
virtual void visit(AstAssignAlias* nodep) {
|
||||
virtual void visit(AstAssignAlias* nodep) { // LCOV_EXCL_LINE
|
||||
nodep->v3fatalSrc("Node should have been under ACTIVE");
|
||||
}
|
||||
virtual void visit(AstAssignW* nodep) {
|
||||
virtual void visit(AstAssignW* nodep) { // LCOV_EXCL_LINE
|
||||
nodep->v3fatalSrc("Node should have been under ACTIVE");
|
||||
}
|
||||
virtual void visit(AstAlways* nodep) {
|
||||
virtual void visit(AstAlways* nodep) { // LCOV_EXCL_LINE
|
||||
nodep->v3fatalSrc("Node should have been under ACTIVE");
|
||||
}
|
||||
virtual void visit(AstAlwaysPublic* nodep) {
|
||||
virtual void visit(AstAlwaysPublic* nodep) { // LCOV_EXCL_LINE
|
||||
nodep->v3fatalSrc("Node should have been under ACTIVE");
|
||||
}
|
||||
virtual void visit(AstFinal* nodep) {
|
||||
virtual void visit(AstFinal* nodep) { // LCOV_EXCL_LINE
|
||||
nodep->v3fatalSrc("Node should have been deleted");
|
||||
}
|
||||
// Empty visitors, speed things up
|
||||
|
@ -772,14 +772,14 @@ void AstNode::iterateAndNext(AstNVisitor& v) {
|
||||
// there's no lower level reason yet though the back must exist.
|
||||
AstNode* nodep = this;
|
||||
#ifdef VL_DEBUG // Otherwise too hot of a function for debug
|
||||
if (VL_UNLIKELY(nodep && !nodep->m_backp)) nodep->v3fatalSrc("iterateAndNext node has no back");
|
||||
if (VL_UNCOVERABLE(nodep && !nodep->m_backp)) nodep->v3fatalSrc("iterateAndNext node has no back");
|
||||
#endif
|
||||
if (nodep) ASTNODE_PREFETCH(nodep->m_nextp);
|
||||
while (nodep) { // effectively: if (!this) return; // Callers rely on this
|
||||
if (nodep->m_nextp) ASTNODE_PREFETCH(nodep->m_nextp->m_nextp);
|
||||
AstNode* niterp = nodep; // This address may get stomped via m_iterpp if the node is edited
|
||||
// Desirable check, but many places where multiple iterations are OK
|
||||
//if (VL_UNLIKELY(niterp->m_iterpp)) niterp->v3fatalSrc("IterateAndNext under iterateAndNext may miss edits");
|
||||
//if (VL_UNCOVERABLE(niterp->m_iterpp)) niterp->v3fatalSrc("IterateAndNext under iterateAndNext may miss edits");
|
||||
// Optimization note: Doing PREFETCH_RW on m_iterpp is a net even
|
||||
// cppcheck-suppress nullPointer
|
||||
niterp->m_iterpp = &niterp;
|
||||
@ -973,21 +973,21 @@ void AstNode::checkTree() {
|
||||
}
|
||||
}
|
||||
|
||||
void AstNode::dumpGdb() { // For GDB only
|
||||
dumpGdbHeader();
|
||||
cout<<" "; dump(cout); cout<<endl;
|
||||
void AstNode::dumpGdb() { // For GDB only // LCOV_EXCL_LINE
|
||||
dumpGdbHeader(); // LCOV_EXCL_LINE
|
||||
cout<<" "; dump(cout); cout<<endl; // LCOV_EXCL_LINE
|
||||
}
|
||||
void AstNode::dumpGdbHeader() const { // For GDB only
|
||||
dumpPtrs(cout);
|
||||
cout<<" Fileline = "<<fileline()<<endl;
|
||||
void AstNode::dumpGdbHeader() const { // For GDB only // LCOV_EXCL_LINE
|
||||
dumpPtrs(cout); // LCOV_EXCL_LINE
|
||||
cout<<" Fileline = "<<fileline()<<endl; // LCOV_EXCL_LINE
|
||||
}
|
||||
void AstNode::dumpTreeGdb() { // For GDB only
|
||||
dumpGdbHeader();
|
||||
dumpTree(cout);
|
||||
void AstNode::dumpTreeGdb() { // For GDB only // LCOV_EXCL_LINE
|
||||
dumpGdbHeader(); // LCOV_EXCL_LINE
|
||||
dumpTree(cout); // LCOV_EXCL_LINE
|
||||
}
|
||||
void AstNode::dumpTreeFileGdb(const char* filenamep) { // For GDB only
|
||||
string filename = filenamep ? filenamep : v3Global.debugFilename("debug.tree", 98);
|
||||
v3Global.rootp()->dumpTreeFile(filename);
|
||||
void AstNode::dumpTreeFileGdb(const char* filenamep) { // For GDB only // LCOV_EXCL_LINE
|
||||
string filename = filenamep ? filenamep : v3Global.debugFilename("debug.tree", 98); // LCOV_EXCL_LINE
|
||||
v3Global.rootp()->dumpTreeFile(filename); // LCOV_EXCL_LINE
|
||||
}
|
||||
|
||||
void AstNode::checkIter() const {
|
||||
|
@ -51,7 +51,7 @@ typedef std::set<int> MTaskIdSet; // Set of mtaskIds for Var sorting
|
||||
//######################################################################
|
||||
|
||||
// For broken() function, return error string if have a match
|
||||
#define BROKEN_RTN(test) do { if (VL_UNLIKELY(test)) return # test; } while(0)
|
||||
#define BROKEN_RTN(test) do { if (VL_UNCOVERABLE(test)) return # test; } while(0)
|
||||
|
||||
// (V)erilator (N)ode is: True if AstNode is of a a given AstType
|
||||
#define VN_IS(nodep,nodetypename) (AstNode::privateIs ## nodetypename(nodep))
|
||||
|
@ -76,7 +76,7 @@ const char* AstNodeClassDType::broken() const {
|
||||
exists.insert(itemp);
|
||||
}
|
||||
for (MemberNameMap::const_iterator it=m_members.begin(); it!=m_members.end(); ++it) {
|
||||
if (VL_UNLIKELY(exists.find(it->second) == exists.end())) {
|
||||
if (VL_UNCOVERABLE(exists.find(it->second) == exists.end())) {
|
||||
this->v3error("Internal: Structure member broken: "<<it->first);
|
||||
return "member broken";
|
||||
}
|
||||
|
@ -303,7 +303,7 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
string spaces(int level) { string out; while (level--) out += " "; return out; }
|
||||
string spaces(int level) { string out; while (level--) out += " "; return out; } // LCOV_EXCL_LINE
|
||||
|
||||
string pad(unsigned column, const string& in) {
|
||||
string out = in;
|
||||
|
@ -1570,10 +1570,10 @@ void EmitCStmts::displayArg(AstNode* dispp, AstNode** elistp, bool isScan,
|
||||
const string& vfmt, char fmtLetter) {
|
||||
// Print display argument, edits elistp
|
||||
AstNode* argp = *elistp;
|
||||
if (!argp) {
|
||||
if (VL_UNCOVERABLE(!argp)) {
|
||||
// expectDisplay() checks this first, so internal error if found here
|
||||
dispp->v3error("Internal: Missing arguments for $display-like format");
|
||||
return;
|
||||
dispp->v3error("Internal: Missing arguments for $display-like format"); // LCOV_EXCL_LINE
|
||||
return; // LCOV_EXCL_LINE
|
||||
}
|
||||
if (argp->widthMin() > VL_VALUE_STRING_MAX_WIDTH) {
|
||||
dispp->v3error("Exceeded limit of "+cvtToStr(VL_VALUE_STRING_MAX_WIDTH)+" bits for any $display-like arguments");
|
||||
@ -1673,9 +1673,9 @@ void EmitCStmts::displayNode(AstNode* nodep, AstScopeName* scopenamep,
|
||||
}
|
||||
}
|
||||
}
|
||||
if (elistp != NULL) {
|
||||
if (VL_UNCOVERABLE(elistp)) {
|
||||
// expectFormat also checks this, and should have found it first, so internal
|
||||
elistp->v3error("Internal: Extra arguments for $display-like format");
|
||||
elistp->v3error("Internal: Extra arguments for $display-like format"); // LCOV_EXCL_LINE
|
||||
}
|
||||
displayEmit(nodep, isScan);
|
||||
}
|
||||
@ -1722,7 +1722,9 @@ void EmitCImp::emitVarReset(AstVar* varp) {
|
||||
arrayp;
|
||||
arrayp = VN_CAST(arrayp->subDTypep()->skipRefp(), UnpackArrayDType)) {
|
||||
int vecnum = vects++;
|
||||
if (arrayp->msb() < arrayp->lsb()) varp->v3fatalSrc("Should have swapped msb & lsb earlier.");
|
||||
if (VL_UNCOVERABLE(arrayp->msb() < arrayp->lsb())) {
|
||||
varp->v3fatalSrc("Should have swapped msb & lsb earlier.");
|
||||
}
|
||||
string ivar = string("__Vi")+cvtToStr(vecnum);
|
||||
// MSVC++ pre V7 doesn't support 'for (int ...)', so declare in sep block
|
||||
puts("{ int __Vi"+cvtToStr(vecnum)+"="+cvtToStr(0)+";");
|
||||
@ -1960,7 +1962,7 @@ void EmitCImp::emitSavableImp(AstNodeModule* modp) {
|
||||
arrayp;
|
||||
arrayp = VN_CAST(elementp, UnpackArrayDType)) {
|
||||
int vecnum = vects++;
|
||||
if (arrayp->msb() < arrayp->lsb()) {
|
||||
if (VL_UNCOVERABLE(arrayp->msb() < arrayp->lsb())) {
|
||||
varp->v3fatalSrc("Should have swapped msb & lsb earlier.");
|
||||
}
|
||||
string ivar = string("__Vi")+cvtToStr(vecnum);
|
||||
@ -2060,7 +2062,7 @@ void EmitCImp::emitSensitives() {
|
||||
arrayp;
|
||||
arrayp = VN_CAST(arrayp->subDTypep()->skipRefp(), UnpackArrayDType)) {
|
||||
int vecnum = vects++;
|
||||
if (arrayp->msb() < arrayp->lsb()) {
|
||||
if (VL_UNCOVERABLE(arrayp->msb() < arrayp->lsb())) {
|
||||
varp->v3fatalSrc("Should have swapped msb & lsb earlier.");
|
||||
}
|
||||
string ivar = string("__Vi")+cvtToStr(vecnum);
|
||||
|
@ -228,7 +228,7 @@ public:
|
||||
}
|
||||
|
||||
//--------------------
|
||||
virtual void visit(AstNode* nodep) {
|
||||
virtual void visit(AstNode* nodep) { // LCOV_EXCL_LINE
|
||||
nodep->v3fatalSrc("No visitors implemented.");
|
||||
}
|
||||
|
||||
|
@ -73,8 +73,7 @@ void V3Error::init() {
|
||||
s_describedEachWarn[i] = false;
|
||||
s_pretendError[i] = V3ErrorCode(i).pretendError();
|
||||
}
|
||||
|
||||
if (string(V3ErrorCode(V3ErrorCode::_ENUM_MAX).ascii()) != " MAX") {
|
||||
if (VL_UNCOVERABLE(string(V3ErrorCode(V3ErrorCode::_ENUM_MAX).ascii()) != " MAX")) {
|
||||
v3fatalSrc("Enum table in V3ErrorCode::EC_ascii() is munged");
|
||||
}
|
||||
}
|
||||
|
@ -301,8 +301,8 @@ inline void v3errorEndFatal(std::ostringstream& sstr) {
|
||||
::v3errorEndFatal((V3Error::v3errorPrep(V3ErrorCode::EC_FATAL), \
|
||||
(V3Error::v3errorStr()<<msg), V3Error::v3errorStr()));
|
||||
|
||||
#define UINFO(level,stmsg) {if(VL_UNLIKELY(debug()>=(level))) { cout<<"- "<<V3Error::lineStr(__FILE__,__LINE__)<<stmsg; }}
|
||||
#define UINFONL(level,stmsg) {if(VL_UNLIKELY(debug()>=(level))) { cout<<stmsg; } }
|
||||
#define UINFO(level,stmsg) {if (VL_UNCOVERABLE(debug()>=(level))) { cout<<"- "<<V3Error::lineStr(__FILE__,__LINE__)<<stmsg; }}
|
||||
#define UINFONL(level,stmsg) {if (VL_UNCOVERABLE(debug()>=(level))) { cout<<stmsg; } }
|
||||
|
||||
#ifdef VL_DEBUG
|
||||
# define UDEBUGONLY(stmts) {stmts}
|
||||
@ -310,10 +310,10 @@ inline void v3errorEndFatal(std::ostringstream& sstr) {
|
||||
# define UDEBUGONLY(stmts) {if (0) {stmts}}
|
||||
#endif
|
||||
|
||||
#define UASSERT(condition,stmsg) { if (VL_UNLIKELY(!(condition))) { v3fatalSrc(stmsg); }}
|
||||
#define UASSERT(condition,stmsg) { if (VL_UNCOVERABLE(!(condition))) { v3fatalSrc(stmsg); }}
|
||||
// For use in V3Ast static functions only
|
||||
#define UASSERT_STATIC(condition,stmsg) \
|
||||
{ if (VL_UNLIKELY(!(condition))) { \
|
||||
{ if (VL_UNCOVERABLE(!(condition))) { \
|
||||
std::cerr<<"Internal Error: "<<__FILE__<<":"<<std::dec<<__LINE__<<":"<<(stmsg)<<std::endl; abort(); } }
|
||||
// Check self test values for expected value. Safe from side-effects.
|
||||
// Type argument can be removed when go to C++11 (use auto).
|
||||
|
@ -239,7 +239,7 @@ private:
|
||||
}
|
||||
bool expandWide(AstNodeAssign* nodep, AstArraySel* rhsp) {
|
||||
UINFO(8," Wordize ASSIGN(ARRAYSEL) "<<nodep<<endl);
|
||||
if (VN_IS(nodep->dtypep()->skipRefp(), UnpackArrayDType)) {
|
||||
if (VL_UNCOVERABLE(VN_IS(nodep->dtypep()->skipRefp(), UnpackArrayDType))) {
|
||||
nodep->v3fatalSrc("ArraySel with unpacked arrays should have been removed in V3Slice");
|
||||
}
|
||||
for (int w=0; w<nodep->widthWords(); w++) {
|
||||
|
@ -94,7 +94,7 @@ void GraphPathChecker::initHalfCriticalPaths(GraphWay way, bool checkOnly) {
|
||||
|
||||
GraphPCNode* ourUserp = static_cast<GraphPCNode*>(vertexp->userp());
|
||||
if (checkOnly) {
|
||||
if (ourUserp->m_cp[way] != critPathCost) {
|
||||
if (VL_UNCOVERABLE(ourUserp->m_cp[way] != critPathCost)) {
|
||||
vertexp->v3fatalSrc("Validation of critical paths failed");
|
||||
}
|
||||
} else {
|
||||
|
@ -60,7 +60,9 @@ private:
|
||||
// Decrement blocking edges count, return true if the vertex is
|
||||
// newly unblocked
|
||||
bool unblock() {
|
||||
if (m_numBlockingEdges <= 0) vertexp()->v3fatalSrc("Underflow of blocking edges");
|
||||
if (VL_UNCOVERABLE(m_numBlockingEdges <= 0)) {
|
||||
vertexp()->v3fatalSrc("Underflow of blocking edges");
|
||||
}
|
||||
m_numBlockingEdges--;
|
||||
return (m_numBlockingEdges == 0);
|
||||
}
|
||||
@ -208,7 +210,7 @@ private:
|
||||
|
||||
typename WaitingVertices::iterator it =
|
||||
m_waitingVertices.find(toVertexp);
|
||||
if (it == m_waitingVertices.end()) {
|
||||
if (VL_UNCOVERABLE(it == m_waitingVertices.end())) {
|
||||
toVertexp->v3fatalSrc("Found edge into vertex not in waiting list.");
|
||||
}
|
||||
if (it->second.unblock()) {
|
||||
@ -223,7 +225,7 @@ private:
|
||||
|
||||
typename WaitingVertices::iterator it =
|
||||
m_waitingVertices.find(fromVertexp);
|
||||
if (it == m_waitingVertices.end()) {
|
||||
if (VL_UNCOVERABLE(it == m_waitingVertices.end())) {
|
||||
fromVertexp->v3fatalSrc("Found edge into vertex not in waiting list.");
|
||||
}
|
||||
if (it->second.unblock()) {
|
||||
|
@ -124,7 +124,7 @@ private:
|
||||
if (nodep->pragType() == AstPragmaType::INLINE_MODULE) {
|
||||
//UINFO(0,"PRAG MARK "<<m_modp<<endl);
|
||||
if (!m_modp) {
|
||||
nodep->v3error("Inline pragma not under a module");
|
||||
nodep->v3error("Inline pragma not under a module"); // LCOV_EXCL_LINE
|
||||
} else if (m_modp->user2() == CIL_MAYBE
|
||||
|| m_modp->user2() == CIL_NOTSOFT) {
|
||||
m_modp->user2(CIL_USER);
|
||||
@ -132,7 +132,7 @@ private:
|
||||
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep); // Remove so don't propagate to upper cell...
|
||||
} else if (nodep->pragType() == AstPragmaType::NO_INLINE_MODULE) {
|
||||
if (!m_modp) {
|
||||
nodep->v3error("Inline pragma not under a module");
|
||||
nodep->v3error("Inline pragma not under a module"); // LCOV_EXCL_LINE
|
||||
} else {
|
||||
cantInline("Pragma NO_INLINE_MODULE", false);
|
||||
}
|
||||
|
@ -331,7 +331,7 @@ V3Number& V3Number::setLongS(vlsint32_t value) {
|
||||
return *this;
|
||||
}
|
||||
V3Number& V3Number::setDouble(double value) {
|
||||
if (VL_UNLIKELY(width()!=64)) {
|
||||
if (VL_UNCOVERABLE(width()!=64)) {
|
||||
v3fatalSrc("Real operation on wrong sized number");
|
||||
}
|
||||
m_double = true;
|
||||
@ -685,11 +685,8 @@ uint32_t V3Number::toUInt() const {
|
||||
}
|
||||
|
||||
double V3Number::toDouble() const {
|
||||
if (VL_UNLIKELY(!isDouble())) {
|
||||
v3fatalSrc("Real conversion on non-real number");
|
||||
}
|
||||
if (VL_UNLIKELY(width()!=64)) {
|
||||
v3fatalSrc("Real operation on wrong sized number");
|
||||
if (VL_UNCOVERABLE(!isDouble() || width()!=64)) {
|
||||
v3fatalSrc("Real operation on wrong sized/non-real number");
|
||||
}
|
||||
union { double d; uint32_t u[2]; } u;
|
||||
u.u[0] = m_value[0]; u.u[1] = m_value[1];
|
||||
|
@ -215,9 +215,9 @@ private:
|
||||
}
|
||||
void statePop() {
|
||||
m_states.pop();
|
||||
if (m_states.empty()) {
|
||||
error("InternalError: Pop of parser state with nothing on stack");
|
||||
m_states.push(ps_TOP);
|
||||
if (VL_UNCOVERABLE(m_states.empty())) {
|
||||
error("InternalError: Pop of parser state with nothing on stack"); // LCOV_EXCL_LINE
|
||||
m_states.push(ps_TOP); // LCOV_EXCL_LINE
|
||||
}
|
||||
}
|
||||
void stateChange(ProcState state) {
|
||||
|
@ -125,7 +125,7 @@ public:
|
||||
return;
|
||||
}
|
||||
// Try the previous value?
|
||||
if (m_valIt == m_sbvmp->m_vals.begin()) {
|
||||
if (VL_UNCOVERABLE(m_valIt == m_sbvmp->m_vals.begin())) {
|
||||
// No more values but it's not defined to decrement an
|
||||
// iterator past the beginning.
|
||||
v3fatalSrc("Decremented iterator past beginning");
|
||||
|
@ -161,7 +161,7 @@ class SliceVisitor : public AstNVisitor {
|
||||
}
|
||||
|
||||
virtual void visit(AstInitArray* nodep) {
|
||||
if (m_assignp) {
|
||||
if (VL_UNCOVERABLE(m_assignp)) {
|
||||
nodep->v3fatalSrc("Array initialization should have been removed earlier");
|
||||
}
|
||||
}
|
||||
|
@ -276,15 +276,15 @@ void VHashSha1::selfTestOne(const string& data, const string& data2,
|
||||
const string& exp, const string& exp64) {
|
||||
VHashSha1 digest (data);
|
||||
if (data2!="") digest.insert(data2);
|
||||
if (digest.digestHex() != exp) {
|
||||
std::cerr << "%Error: When hashing '"<<data+data2<<"'"<<endl;
|
||||
std::cerr << "%Error: got="<<digest.digestHex()<<endl;
|
||||
std::cerr << "%Error: exp="<<exp<<endl;
|
||||
if (VL_UNCOVERABLE(digest.digestHex() != exp)) {
|
||||
std::cerr << "%Error: When hashing '"<<data+data2<<"'"<<endl // LCOV_EXCL_LINE
|
||||
<< " ... got="<<digest.digestHex()<<endl // LCOV_EXCL_LINE
|
||||
<< " ... exp="<<exp<<endl; // LCOV_EXCL_LINE
|
||||
}
|
||||
if (digest.digestSymbol() != exp64) {
|
||||
std::cerr << "%Error: When hashing '"<<data+data2<<"'"<<endl;
|
||||
std::cerr << "%Error: got="<<digest.digestSymbol()<<endl;
|
||||
std::cerr << "%Error: exp="<<exp64<<endl;
|
||||
if (VL_UNCOVERABLE(digest.digestSymbol() != exp64)) {
|
||||
std::cerr << "%Error: When hashing '"<<data+data2<<"'"<<endl // LCOV_EXCL_LINE
|
||||
<< " ... got="<<digest.digestSymbol()<<endl // LCOV_EXCL_LINE
|
||||
<< " ... exp="<<exp64<<endl; // LCOV_EXCL_LINE
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -598,7 +598,7 @@ void V3TSP::selfTestStates() {
|
||||
expect.push_back(&s20);
|
||||
expect.push_back(&s10);
|
||||
expect.push_back(&s5);
|
||||
if (expect != result) {
|
||||
if (VL_UNCOVERABLE(expect != result)) {
|
||||
for (V3TSP::StateVec::iterator it = result.begin();
|
||||
it != result.end(); ++it) {
|
||||
const TspTestState* statep = dynamic_cast<const TspTestState*>(*it);
|
||||
@ -641,7 +641,7 @@ void V3TSP::selfTestStates() {
|
||||
expect.push_back(&d);
|
||||
expect.push_back(&e);
|
||||
|
||||
if (expect != result) {
|
||||
if (VL_UNCOVERABLE(expect != result)) {
|
||||
for (V3TSP::StateVec::iterator it = result.begin();
|
||||
it != result.end(); ++it) {
|
||||
const TspTestState* statep = dynamic_cast<const TspTestState*>(*it);
|
||||
@ -689,7 +689,7 @@ void V3TSP::selfTestString() {
|
||||
expect.push_back("2");
|
||||
expect.push_back("3");
|
||||
|
||||
if (expect != result) {
|
||||
if (VL_UNCOVERABLE(expect != result)) {
|
||||
for (std::vector<string>::iterator it = result.begin(); it != result.end(); ++it) {
|
||||
cout<<*it<<" ";
|
||||
}
|
||||
|
@ -4033,7 +4033,7 @@ private:
|
||||
//----------------------------------------------------------------------
|
||||
// METHODS - special type detection
|
||||
void assertAtStatement(AstNode* nodep) {
|
||||
if (VL_UNLIKELY(m_vup && !m_vup->selfDtm())) {
|
||||
if (VL_UNCOVERABLE(m_vup && !m_vup->selfDtm())) {
|
||||
UINFO(1,"-: "<<m_vup<<endl);
|
||||
nodep->v3fatalSrc("No dtype expected at statement "<<nodep->prettyTypeName());
|
||||
}
|
||||
|
@ -152,7 +152,7 @@ private:
|
||||
iterateChildren(nodep);
|
||||
nodep->virtRefDTypep(editOneDType(nodep->virtRefDTypep()));
|
||||
}
|
||||
virtual void visit(AstNodePreSel* nodep) {
|
||||
virtual void visit(AstNodePreSel* nodep) { // LCOV_EXCL_LINE
|
||||
// This check could go anywhere after V3Param
|
||||
nodep->v3fatalSrc("Presels should have been removed before this point");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user