diff --git a/include/verilated.cpp b/include/verilated.cpp index 627ca744e..c583e5668 100644 --- a/include/verilated.cpp +++ b/include/verilated.cpp @@ -285,6 +285,7 @@ IData VL_RANDOM_I(int obits) VL_MT_SAFE { QData VL_RANDOM_Q(int obits) VL_MT_SAFE { return vl_rand64() & VL_MASK_Q(obits); } +// VL_RANDOM_W currently unused as $random always 32 bits WDataOutP VL_RANDOM_W(int obits, WDataOutP outwp) VL_MT_SAFE { for (int i=0; im_funcnumMax)) { // m_callbacksp must be declared, as Max'es are > 0 return scopep->m_callbacksp[funcnum]; - } else { - return scopep->exportFindError(funcnum); + } else { // LCOV_EXCL_LINE + return scopep->exportFindError(funcnum); // LCOV_EXCL_LINE } } }; diff --git a/nodist/code_coverage b/nodist/code_coverage index 7b46ae17c..86180a972 100755 --- a/nodist/code_coverage +++ b/nodist/code_coverage @@ -53,6 +53,7 @@ sub test { if ($Opt_Stage <= 1) { print "Stage 1: make examples (with coverage on)\n"; run("make examples"); + run("make test_regress"); } my $cc_dir = "nodist/obj_dir/coverage"; @@ -68,7 +69,7 @@ sub test { } 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"); + run("cd $cc_dir/info ; lcov -c -d ../../../../$dir -o app_test_${outname}.info"); } } @@ -145,7 +146,7 @@ sub clone_sources { chomp $line; if ($line !~ m!// LCOV_EXCL_LINE! && $line =~ /$Exclude_Line_Regexp/) { - $line .= " //code_coverage: // LCOV_EXCL_LINE\n"; + $line .= " //code_coverage: // LCOV_EXCL_LINE"; $excluded_lines++; #print "$infile:$lineno: $line"; } else { @@ -164,9 +165,11 @@ sub cleanup_abs_paths { my $fh = IO::File->new("<$infile") or die "%Error: $! $infile,"; my @lines; while (defined(my $line = $fh->getline)) { - if ($line =~ m!^SF:/!) { + if ($line =~ m!^SF:!) { $line =~ s!$ENV{VERILATOR_ROOT}/!!; $line =~ s!$cc_dir/!!; + $line =~ s!obj_dbg/verilog.y$!verilog.y!; + #print "Remaining SF: ",$line; } push @lines, $line; } diff --git a/src/V3ActiveTop.cpp b/src/V3ActiveTop.cpp index de9da5e24..f567bb4e6 100644 --- a/src/V3ActiveTop.cpp +++ b/src/V3ActiveTop.cpp @@ -101,7 +101,7 @@ private: // Move the active's contents to the other active UINFO(4," merge active "<sensesStorep()) { - if (sensesp != nodep->sensesStorep()) { + if (VL_UNCOVERABLE(sensesp != nodep->sensesStorep())) { nodep->v3fatalSrc("sensesStore should have been deleted earlier if different"); } sensesp->unlinkFrBack(); diff --git a/src/V3Broken.cpp b/src/V3Broken.cpp index f5ce7c0c7..fcec7e9e7 100644 --- a/src/V3Broken.cpp +++ b/src/V3Broken.cpp @@ -60,7 +60,7 @@ public: // Called by operator delete on any node - only if VL_LEAK_CHECKS if (debug()>=9) cout<<"-nodeDel: "<second & FLAG_ALLOCATED)) { + if (VL_UNCOVERABLE(iter==s_nodes.end() || !(iter->second & FLAG_ALLOCATED))) { reinterpret_cast(nodep) ->v3fatalSrc("Deleting AstNode object that was never tracked or already deleted"); } @@ -74,7 +74,7 @@ public: // Called by operator new on any node - only if VL_LEAK_CHECKS if (debug()>=9) cout<<"-nodeNew: "<second & FLAG_ALLOCATED)) { + if (VL_UNCOVERABLE(iter !=s_nodes.end() && (iter->second & FLAG_ALLOCATED))) { nodep->v3fatalSrc("Newing AstNode object that is already allocated"); } if (iter == s_nodes.end()) { @@ -96,17 +96,17 @@ public: if (!linkable) return; // save some time, else the map will get huge! #endif NodeMap::iterator iter = s_nodes.find(nodep); - if (iter == s_nodes.end()) { + if (VL_UNCOVERABLE(iter == s_nodes.end())) { #ifdef VL_LEAK_CHECKS nodep->v3fatalSrc("AstNode is in tree, but not allocated"); #endif } else { - if (!(iter->second & FLAG_ALLOCATED)) { + if (VL_UNCOVERABLE(!(iter->second & FLAG_ALLOCATED))) { #ifdef VL_LEAK_CHECKS nodep->v3fatalSrc("AstNode is in tree, but not allocated"); #endif } - if (iter->second & FLAG_IN_TREE) { + if (VL_UNCOVERABLE(iter->second & FLAG_IN_TREE)) { nodep->v3fatalSrc("AstNode is already in tree at another location"); } } @@ -230,34 +230,35 @@ public: class BrokenCheckVisitor : public AstNVisitor { private: void checkWidthMin(const AstNode* nodep) { - if (nodep->width() != nodep->widthMin() - && v3Global.widthMinUsage()==VWidthMinUsage::MATCHES_WIDTH) { + if (VL_UNCOVERABLE(nodep->width() != nodep->widthMin() + && v3Global.widthMinUsage()==VWidthMinUsage::MATCHES_WIDTH)) { nodep->v3fatalSrc("Width != WidthMin"); } } void processAndIterate(AstNode* nodep) { BrokenTable::setUnder(nodep, true); - if (const char* whyp=nodep->broken()) { + const char* whyp = nodep->broken(); + if (VL_UNCOVERABLE(whyp)) { nodep->v3fatalSrc("Broken link in node (or something without maybePointedTo): "<dtypep()) { - if (!nodep->dtypep()->brokeExists()) { + if (VL_UNCOVERABLE(!nodep->dtypep()->brokeExists())) { nodep->v3fatalSrc("Broken link in node->dtypep() to " <dtypep())); - } else if (!VN_IS(nodep->dtypep(), NodeDType)) { + } else if (VL_UNCOVERABLE(!VN_IS(nodep->dtypep(), NodeDType))) { nodep->v3fatalSrc("Non-dtype link in node->dtypep() to " <dtypep())); } } if (v3Global.assertDTypesResolved()) { if (nodep->hasDType()) { - if (!nodep->dtypep()) nodep->v3fatalSrc( + if (VL_UNCOVERABLE(!nodep->dtypep())) nodep->v3fatalSrc( "No dtype on node with hasDType(): "<prettyTypeName()); } else { - if (nodep->dtypep()) nodep->v3fatalSrc( + if (VL_UNCOVERABLE(nodep->dtypep())) nodep->v3fatalSrc( "DType on node without hasDType(): "<prettyTypeName()); } - if (nodep->getChildDTypep()) nodep->v3fatalSrc( + if (VL_UNCOVERABLE(nodep->getChildDTypep())) nodep->v3fatalSrc( "childDTypep() non-null on node after should have removed"); if (const AstNodeDType* dnodep = VN_CAST(nodep, NodeDType)) checkWidthMin(dnodep); } @@ -267,10 +268,10 @@ private: } virtual void visit(AstNodeAssign* nodep) { processAndIterate(nodep); - if (v3Global.assertDTypesResolved() - && nodep->brokeLhsMustBeLvalue() - && VN_IS(nodep->lhsp(), NodeVarRef) - && !VN_CAST(nodep->lhsp(), NodeVarRef)->lvalue()) { + if (VL_UNCOVERABLE(v3Global.assertDTypesResolved() + && nodep->brokeLhsMustBeLvalue() + && VN_IS(nodep->lhsp(), NodeVarRef) + && !VN_CAST(nodep->lhsp(), NodeVarRef)->lvalue())) { nodep->v3fatalSrc("Assignment LHS is not an lvalue"); } } @@ -291,9 +292,9 @@ public: void V3Broken::brokenAll(AstNetlist* nodep) { //UINFO(9,__FUNCTION__<<": "<unlinkFrBack(); AstRange* rangep = VN_CAST(nrangep, Range); if (!rangep) { - if (!VN_IS(nrangep, UnsizedRange)) { + if (VL_UNCOVERABLE(!VN_IS(nrangep, UnsizedRange))) { nrangep->v3fatalSrc("Expected range or unsized range"); } arrayp = new AstUnsizedArrayDType diff --git a/src/V3Table.cpp b/src/V3Table.cpp index 210939638..4204dfa47 100644 --- a/src/V3Table.cpp +++ b/src/V3Table.cpp @@ -219,7 +219,7 @@ private: nodeap->bodysp()->unlinkFrBackWithNext()->deleteTree(); nodeap->addStmtp(stmtsp); if (debug()>=6) nodeap->dumpTree(cout, " table_new: "); - } else { + } else { // LCOV_EXCL_LINE nodep->v3fatalSrc("Creating table under unknown node type"); } @@ -316,7 +316,7 @@ private: // Simulate simvis.mainTableEmulate(nodep); - if (!simvis.optimizable()) { + if (VL_UNCOVERABLE(!simvis.optimizable())) { simvis.whyNotNodep()->v3fatalSrc("Optimizable cleared, even though earlier test run said not: " <v3fatalSrc("InitArray requires us to have the values in inValue order"); + } AstNode* setp = new AstConst(nodep->fileline(), outputChgMask); VN_CAST(chgVscp->varp()->valuep(), InitArray)->addValuep(setp); } diff --git a/src/V3WidthSel.cpp b/src/V3WidthSel.cpp index b0f1da711..92c85693a 100644 --- a/src/V3WidthSel.cpp +++ b/src/V3WidthSel.cpp @@ -227,9 +227,11 @@ private: subp = newSubNeg(subp, fromRange.lo()); } } - if (!fromRange.elements() || (adtypep->width() % fromRange.elements())!=0) + if (VL_UNCOVERABLE(!fromRange.elements() + || (adtypep->width() % fromRange.elements())!=0)) { adtypep->v3fatalSrc("Array extraction with width miscomputed " <width()<<"/"<width() / fromRange.elements(); AstSel* newp = new AstSel(nodep->fileline(), @@ -316,9 +318,11 @@ private: else if (AstPackArrayDType* adtypep = VN_CAST(ddtypep, PackArrayDType)) { // SELEXTRACT(array, msb, lsb) -> SEL(array, // lsb*width-of-subindex, width-of-subindex*(msb-lsb)) - if (!fromRange.elements() || (adtypep->width() % fromRange.elements())!=0) + if (VL_UNCOVERABLE(!fromRange.elements() + || (adtypep->width() % fromRange.elements())!=0)) { adtypep->v3fatalSrc("Array extraction with width miscomputed " <width()<<"/"<v3fatalSrc("Shouldn't iterate in V3WidthSel"); } diff --git a/src/VlcTest.h b/src/VlcTest.h index 4196eb6bb..e3a60a0f3 100644 --- a/src/VlcTest.h +++ b/src/VlcTest.h @@ -76,9 +76,9 @@ public: cout<<" Covered, Rank, RankPts, Filename"< 1); compile( - v_flags2 => ["--debugi 9"], + v_flags2 => ["--debug --debugi 9"], tee => 0, verilator_make_gcc => 0, make_top_shell => 0, diff --git a/test_regress/t/t_flag_debugi9.v b/test_regress/t/t_flag_debugi9.v index 6b8661775..5d61f1f0d 100644 --- a/test_regress/t/t_flag_debugi9.v +++ b/test_regress/t/t_flag_debugi9.v @@ -3,7 +3,18 @@ // This file ONLY is placed into the Public Domain, for any use, // without warranty, 2008 by Wilson Snyder. -module t; +module t (/*AUTOARG*/ + // Outputs + o, + // Inputs + i + ); + + // Need some logic to get mtask debug fully covered + input i; + output wire o; + assign o = i; + initial begin $write("*-* All Finished *-*\n"); $finish; diff --git a/test_regress/t/t_stop_bad.out b/test_regress/t/t_stop_bad.out new file mode 100644 index 000000000..a5b0b94b3 --- /dev/null +++ b/test_regress/t/t_stop_bad.out @@ -0,0 +1,3 @@ +Intentional stop +%Error: t/t_stop_bad.v:9: Verilog $stop +Aborting... diff --git a/test_regress/t/t_stop_bad.pl b/test_regress/t/t_stop_bad.pl new file mode 100755 index 000000000..477a847d8 --- /dev/null +++ b/test_regress/t/t_stop_bad.pl @@ -0,0 +1,23 @@ +#!/usr/bin/perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003 by Wilson Snyder. This program is free software; you can +# redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. + +scenarios(simulator => 1); + +compile( + ); + +execute( + fails => 1, + check_finished => 0, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); + +1; diff --git a/test_regress/t/t_stop_bad.v b/test_regress/t/t_stop_bad.v new file mode 100644 index 000000000..950a2d00f --- /dev/null +++ b/test_regress/t/t_stop_bad.v @@ -0,0 +1,11 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2019 by Wilson Snyder. + +module t; + initial begin + $write("Intentional stop\n"); + $stop; + end +endmodule diff --git a/test_regress/t/t_sys_system.v b/test_regress/t/t_sys_system.v index eda684c94..612797f7c 100644 --- a/test_regress/t/t_sys_system.v +++ b/test_regress/t/t_sys_system.v @@ -22,6 +22,8 @@ module t; if (i!==0) $stop; i = $system("exit 10"); if (i!==10) $stop; + i = $system("exit 20"); // Wide + if (i!==20) $stop; `endif $write("*-* All Finished *-*\n"); diff --git a/test_regress/t/t_vlcov_debugi.pl b/test_regress/t/t_vlcov_debugi.pl new file mode 100755 index 000000000..a310de3ab --- /dev/null +++ b/test_regress/t/t_vlcov_debugi.pl @@ -0,0 +1,26 @@ +#!/usr/bin/perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003-2009 by Wilson Snyder. This program is free software; you can +# redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. + +scenarios(dist => 1); + +foreach my $basename ("t_vlcov_data_a.dat", + "t_vlcov_data_b.dat", + "t_vlcov_data_c.dat", + "t_vlcov_data_d.dat", + ) { + run(cmd => ["../bin/verilator_coverage", + "t/${basename}", + "--debugi 9", + ], + tee => $Self->{verbose}, + ); +} + +ok(1); +1; diff --git a/test_regress/t/t_vlcov_nfound_bad.out b/test_regress/t/t_vlcov_nfound_bad.out new file mode 100644 index 000000000..e9884e58a --- /dev/null +++ b/test_regress/t/t_vlcov_nfound_bad.out @@ -0,0 +1,2 @@ +%Error: Can't read t/t_NOT_FOUND +%Error: Command Failed diff --git a/test_regress/t/t_vlcov_nfound_bad.pl b/test_regress/t/t_vlcov_nfound_bad.pl new file mode 100755 index 000000000..9b7a627db --- /dev/null +++ b/test_regress/t/t_vlcov_nfound_bad.pl @@ -0,0 +1,20 @@ +#!/usr/bin/perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003-2009 by Wilson Snyder. This program is free software; you can +# redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. + +scenarios(dist => 1); + +run(fails => 1, + cmd => ["../bin/verilator_coverage", + "t/t_NOT_FOUND",], + logfile => $Self->{run_log_filename}, + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1;