diff --git a/Changes b/Changes index 8e7470ac5..da56da5be 100644 --- a/Changes +++ b/Changes @@ -12,6 +12,8 @@ The contributors that suggested a given feature are shown in []. Thanks! *** Add --protect-ids to obscure information in objects, bug1521. [Todd Strader] +*** Add --trace-coverage. + *** Support multithreading on Windows. [Patrick Stewart] **** Increase case duplicate/incomplete to 16 bit tables, bug1545. [Yossi Nivin] diff --git a/bin/verilator b/bin/verilator index 3f2c30892..06f806d8c 100755 --- a/bin/verilator +++ b/bin/verilator @@ -377,12 +377,13 @@ detailed descriptions in L for more information. --threads-max-mtasks Tune maximum mtask partitioning --top-module Name of top level input module --trace Enable waveform creation + --trace-depth Depth of tracing + --trace-coverage Enable tracing of coverage --trace-fst Enable FST waveform creation --trace-fst-thread Enable FST threaded waveform creation - --trace-depth Depth of tracing --trace-max-array Maximum bit width for tracing --trace-max-width Maximum array depth for tracing - --trace-params Enable tracing parameters + --trace-params Enable tracing of parameters --trace-structs Enable tracing structure names --trace-underscore Enable tracing of _signals -U Undefine preprocessor define @@ -1392,6 +1393,25 @@ need to add these to your Makefile manually. Having tracing compiled in may result in some small performance losses, even when waveforms are not turned on during model execution. +=item --trace-coverage + +With --trace and --coverage-*, enable tracing to include a traced signal +for every --coverage-line or --coverage-user inserted coverage point, to +assist in debugging coverage items. Note --coverage-toggle does not get +additional signals added, as the original signals being toggle-analyzed are +already visible. + +The added signal will be a 32-bit value which will increment on each +coverage occurrence. Due to this, this option may greatly increase trace +file sizes and simulation time. + +=item --trace-depth I + +Specify the number of levels deep to enable tracing, for example +--trace-level 1 to only see the top level's signals. Defaults to the +entire model. Using a small number will decrease visibility, but greatly +improve runtime and trace file size. + =item --trace-fst Enable FST waveform tracing in the model. This overrides C<--trace> and @@ -1403,13 +1423,6 @@ Enable FST waveform tracing in the model, using a separate thread. This is typically faster in runtime but slower in total computes than C<--trace-fst>. This overrides C<--trace> and C<--trace-fst>. -=item --trace-depth I - -Specify the number of levels deep to enable tracing, for example ---trace-level 1 to only see the top level's signals. Defaults to the -entire model. Using a small number will decrease visibility, but greatly -improve runtime and trace file size. - =item --trace-max-array I Rarely needed. Specify the maximum array depth of a signal that may be diff --git a/src/V3Assert.cpp b/src/V3Assert.cpp index 9f1d695f8..04c192355 100644 --- a/src/V3Assert.cpp +++ b/src/V3Assert.cpp @@ -121,7 +121,7 @@ private: // V3Coverage assigned us a bucket to increment. AstCoverInc* covincp = VN_CAST(snodep->coverincp(), CoverInc); UASSERT_OBJ(covincp, snodep, "Missing AstCoverInc under assertion"); - covincp->unlinkFrBack(); + covincp->unlinkFrBackWithNext(); // next() might have AstAssign for trace if (message!="") covincp->declp()->comment(message); bodysp = covincp; } diff --git a/src/V3Ast.h b/src/V3Ast.h index 85049c72d..3a669deb9 100644 --- a/src/V3Ast.h +++ b/src/V3Ast.h @@ -605,6 +605,9 @@ public: || m_e==BLOCKTEMP || m_e==MODULETEMP || m_e==STMTTEMP || m_e==XTEMP || m_e==IFACEREF); } + bool isTemp() const { + return (m_e==BLOCKTEMP || m_e==MODULETEMP || m_e==STMTTEMP || m_e==XTEMP); + } }; inline bool operator==(AstVarType lhs, AstVarType rhs) { return (lhs.m_e == rhs.m_e); } inline bool operator==(AstVarType lhs, AstVarType::en rhs) { return (lhs.m_e == rhs); } diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index 83d9a7bb5..ccfeb61f4 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -1335,9 +1335,7 @@ public: bool isIfaceRef() const { return (varType()==AstVarType::IFACEREF); } bool isIfaceParent() const { return m_isIfaceParent; } bool isSignal() const { return varType().isSignal(); } - bool isTemp() const { - return (varType()==AstVarType::BLOCKTEMP || varType()==AstVarType::MODULETEMP - || varType()==AstVarType::STMTTEMP || varType()==AstVarType::XTEMP); } + bool isTemp() const { return varType().isTemp(); } bool isToggleCoverable() const { return ((isIO() || isSignal()) && (isIO() || isBitLogic()) diff --git a/src/V3Coverage.cpp b/src/V3Coverage.cpp index 94323cfc6..5e73a0e8c 100644 --- a/src/V3Coverage.cpp +++ b/src/V3Coverage.cpp @@ -96,7 +96,8 @@ private: } AstCoverInc* newCoverInc(FileLine* fl, const string& hier, - const string& page_prefix, const string& comment) { + const string& page_prefix, const string& comment, + const string& trace_var_name) { // For line coverage, we may have multiple if's on one line, so disambiguate if // everything is otherwise identical // (Don't set column otherwise as it may result in making bins not match up with @@ -123,9 +124,30 @@ private: declp->hier(hier); m_modp->addStmtp(declp); - return new AstCoverInc(fl, declp); + AstCoverInc* incp = new AstCoverInc(fl, declp); + if (!trace_var_name.empty() && v3Global.opt.traceCoverage()) { + AstVar* varp = new AstVar(incp->fileline(), + AstVarType::MODULETEMP, trace_var_name, + VFlagBitPacked(), 32); + varp->trace(true); + varp->fileline()->modifyWarnOff(V3ErrorCode::UNUSED, true); + m_modp->addStmtp(varp); + UINFO(5, "New coverage trace: "<fileline(), + new AstVarRef(incp->fileline(), varp, true), + new AstAdd(incp->fileline(), + new AstVarRef(incp->fileline(), varp, false), + new AstConst(incp->fileline(), AstConst::WidthedValue(), 32, 1))); + incp->addNext(assp); + } + return incp; + } + string traceNameForLine(AstNode* nodep, const string& type) { + return "vlCoverageLineTrace_"+nodep->fileline()->filebasenameNoExt() + +"__"+cvtToStr(nodep->fileline()->lineno()) + +"_"+type; } - // VISITORS - BOTH virtual void visit(AstNodeModule* nodep) { m_modp = nodep; @@ -190,7 +212,7 @@ private: AstCoverToggle* newp = new AstCoverToggle(varp->fileline(), newCoverInc(varp->fileline(), "", "v_toggle", - varp->name()+above.m_comment), + varp->name()+above.m_comment, ""), above.m_varRefp->cloneTree(true), above.m_chgRefp->cloneTree(true)); m_modp->addStmtp(newp); @@ -294,9 +316,11 @@ private: && nodep->fileline()->coverageOn() && v3Global.opt.coverageLine()) { // if a "if" branch didn't disable it UINFO(4," COVER: "<user1()) { - nodep->addIfsp(newCoverInc(nodep->fileline(), "", "v_line", "elsif")); + nodep->addIfsp(newCoverInc(nodep->fileline(), "", "v_line", "elsif", + traceNameForLine(nodep, "elsif"))); } else { - nodep->addIfsp(newCoverInc(nodep->fileline(), "", "v_line", "if")); + nodep->addIfsp(newCoverInc(nodep->fileline(), "", "v_line", "if", + traceNameForLine(nodep, "if"))); } } // Don't do empty else's, only empty if/case's @@ -308,7 +332,8 @@ private: UINFO(4," COVER: "<addElsesp(newCoverInc(nodep->elsesp()->fileline(), - "", "v_line", "else")); + "", "v_line", "else", + traceNameForLine(nodep, "else"))); } } } @@ -322,7 +347,8 @@ private: iterateAndNextNull(nodep->bodysp()); if (m_checkBlock) { // if the case body didn't disable it UINFO(4," COVER: "<addBodysp(newCoverInc(nodep->fileline(), "", "v_line", "case")); + nodep->addBodysp(newCoverInc(nodep->fileline(), "", "v_line", "case", + traceNameForLine(nodep, "case"))); } m_checkBlock = true; // Reset as a child may have cleared it } @@ -333,7 +359,8 @@ private: iterateChildren(nodep); if (!nodep->coverincp()) { // Note the name may be overridden by V3Assert processing - nodep->coverincp(newCoverInc(nodep->fileline(), m_beginHier, "v_user", "cover")); + nodep->coverincp(newCoverInc(nodep->fileline(), m_beginHier, "v_user", "cover", + m_beginHier+"_vlCoverageUserTrace")); } m_checkBlock = true; // Reset as a child may have cleared it } diff --git a/src/V3Dead.cpp b/src/V3Dead.cpp index b8c130081..46beeedab 100644 --- a/src/V3Dead.cpp +++ b/src/V3Dead.cpp @@ -295,7 +295,7 @@ private: bool mightElimVar(AstVar* nodep) { return (!nodep->isSigPublic() // Can't elim publics! && !nodep->isIO() - && (nodep->isTemp() + && ((nodep->isTemp() && !nodep->isTrace()) || (nodep->isParam() && !nodep->isTrace()) || m_elimUserVars)); // Post-Trace can kill most anything } diff --git a/src/V3Options.cpp b/src/V3Options.cpp index fbe391fc9..59e1ae399 100644 --- a/src/V3Options.cpp +++ b/src/V3Options.cpp @@ -760,6 +760,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char else if (!strcmp(sw, "-sv")) { m_defaultLanguage = V3LangCode::L1800_2005; } else if ( onoff (sw, "-threads-coarsen", flag/*ref*/)) { m_threadsCoarsen = flag; } // Undocumented, debug else if ( onoff (sw, "-trace", flag/*ref*/)) { m_trace = flag; } + else if ( onoff (sw, "-trace-coverage", flag/*ref*/)) { m_traceCoverage = flag; } else if ( onoff (sw, "-trace-dups", flag/*ref*/)) { m_traceDups = flag; } else if ( onoff (sw, "-trace-params", flag/*ref*/)) { m_traceParams = flag; } else if ( onoff (sw, "-trace-structs", flag/*ref*/)) { m_traceStructs = flag; } @@ -1449,8 +1450,9 @@ V3Options::V3Options() { m_threadsCoarsen = true; m_threadsMaxMTasks = 0; m_trace = false; - m_traceFormat = TraceFormat::VCD; + m_traceCoverage = false; m_traceDups = false; + m_traceFormat = TraceFormat::VCD; m_traceParams = true; m_traceStructs = false; m_traceUnderscore = false; diff --git a/src/V3Options.h b/src/V3Options.h index de71e864f..465f164c4 100644 --- a/src/V3Options.h +++ b/src/V3Options.h @@ -152,6 +152,7 @@ class V3Options { bool m_threadsDpiPure; // main switch: --threads-dpi all/pure bool m_threadsDpiUnpure; // main switch: --threads-dpi all bool m_trace; // main switch: --trace + bool m_traceCoverage; // main switch: --trace-coverage bool m_traceDups; // main switch: --trace-dups bool m_traceParams; // main switch: --trace-params bool m_traceStructs; // main switch: --trace-structs @@ -306,6 +307,7 @@ class V3Options { bool threadsDpiUnpure() const { return m_threadsDpiUnpure; } bool threadsCoarsen() const { return m_threadsCoarsen; } bool trace() const { return m_trace; } + bool traceCoverage() const { return m_traceCoverage; } bool traceDups() const { return m_traceDups; } bool traceParams() const { return m_traceParams; } bool traceStructs() const { return m_traceStructs; } diff --git a/src/V3TraceDecl.cpp b/src/V3TraceDecl.cpp index 61e168ac2..d6b61d758 100644 --- a/src/V3TraceDecl.cpp +++ b/src/V3TraceDecl.cpp @@ -148,8 +148,12 @@ private: } virtual void visit(AstVarScope* nodep) { iterateChildren(nodep); - // Avoid updating this if (), instead see varp->isTrace() - if (!nodep->varp()->isTemp() && !nodep->varp()->isFuncLocal()) { + // Prefilter - things that get through this if will either get + // traced or get a comment as to why not traced. + // Generally this equation doesn't need updating, instead use + // varp->isTrace() and/or vscIgnoreTrace. + if ((!nodep->varp()->isTemp() || nodep->varp()->isTrace()) + && !nodep->varp()->isFuncLocal()) { UINFO(5, " vsc "<varp(); AstScope* scopep = nodep->scopep(); diff --git a/test_regress/t/t_cover_line_trace.out b/test_regress/t/t_cover_line_trace.out new file mode 100644 index 000000000..bbe500237 --- /dev/null +++ b/test_regress/t/t_cover_line_trace.out @@ -0,0 +1,152 @@ +$version Generated by VerilatedVcd $end +$date Thu Oct 24 09:45:30 2019 + $end +$timescale 1ns $end + + $scope module top $end + $var wire 1 1 clk $end + $scope module t $end + $var wire 1 1 clk $end + $var wire 32 $ cyc [31:0] $end + $var wire 8 % cyc_copy [7:0] $end + $var wire 1 # toggle $end + $var wire 32 ) vlCoverageLineTrace_t_cover_line__44_if [31:0] $end + $var wire 32 & vlCoverageLineTrace_t_cover_line__47_if [31:0] $end + $var wire 32 ' vlCoverageLineTrace_t_cover_line__50_elsif [31:0] $end + $var wire 32 ( vlCoverageLineTrace_t_cover_line__57_elsif [31:0] $end + $scope module a1 $end + $var wire 1 1 clk $end + $var wire 1 # toggle $end + $var wire 32 * vlCoverageLineTrace_t_cover_line__78_if [31:0] $end + $upscope $end + $scope module a2 $end + $var wire 1 1 clk $end + $var wire 1 # toggle $end + $var wire 32 + vlCoverageLineTrace_t_cover_line__78_if [31:0] $end + $upscope $end + $scope module b1 $end + $var wire 1 1 clk $end + $var wire 1 # toggle $end + $var wire 32 2 vlCoverageLineTrace_t_cover_line__101_if [31:0] $end + $var wire 32 - vlCoverageLineTrace_t_cover_line__105_if [31:0] $end + $upscope $end + $scope module b2 $end + $var wire 1 1 clk $end + $var wire 1 # toggle $end + $var wire 32 3 vlCoverageLineTrace_t_cover_line__101_if [31:0] $end + $var wire 32 . vlCoverageLineTrace_t_cover_line__105_if [31:0] $end + $upscope $end + $scope module o1 $end + $var wire 1 1 clk $end + $var wire 1 # toggle $end + $var wire 32 , vlCoverageLineTrace_t_cover_line__162_if [31:0] $end + $upscope $end + $scope module t1 $end + $var wire 1 1 clk $end + $var wire 1 # toggle $end + $var wire 32 / vlCoverageLineTrace_t_cover_line__134_if [31:0] $end + $var wire 32 0 vlCoverageLineTrace_t_cover_line__137_if [31:0] $end + $upscope $end + $upscope $end + $upscope $end +$enddefinitions $end + + +#0 +0# +b00000000000000000000000000000001 $ +b00000001 % +b00000000000000000000000000000000 & +b00000000000000000000000000000000 ' +b00000000000000000000000000000000 ( +b00000000000000000000000000000000 ) +b00000000000000000000000000000000 * +b00000000000000000000000000000000 + +b00000000000000000000000000000000 , +b00000000000000000000000000000000 - +b00000000000000000000000000000000 . +b00000000000000000000000000000000 / +b00000000000000000000000000000000 0 +01 +b00000000000000000000000000000000 2 +b00000000000000000000000000000000 3 +#10 +b00000000000000000000000000000010 $ +b00000010 % +b00000000000000000000000000000001 ) +11 +#15 +01 +#20 +b00000000000000000000000000000011 $ +b00000011 % +b00000000000000000000000000000010 ) +11 +#25 +01 +#30 +1# +b00000000000000000000000000000100 $ +b00000100 % +b00000000000000000000000000000001 & +b00000000000000000000000000000011 ) +11 +#35 +01 +#40 +0# +b00000000000000000000000000000101 $ +b00000101 % +b00000000000000000000000000000100 ) +b00000000000000000000000000000001 * +b00000000000000000000000000000001 + +b00000000000000000000000000000001 , +b00000000000000000000000000000001 - +b00000000000000000000000000000001 . +b00000000000000000000000000000001 / +11 +#45 +01 +#50 +b00000000000000000000000000000110 $ +b00000110 % +b00000000000000000000000000000001 ' +b00000000000000000000000000000101 ) +b00000000000000000000000000000001 0 +11 +#55 +01 +#60 +b00000000000000000000000000000111 $ +b00000111 % +b00000000000000000000000000000110 ) +11 +#65 +01 +#70 +b00000000000000000000000000001000 $ +b00001000 % +b00000000000000000000000000000111 ) +11 +#75 +01 +#80 +b00000000000000000000000000001001 $ +b00001001 % +b00000000000000000000000000001000 ) +11 +#85 +01 +#90 +b00000000000000000000000000001010 $ +b00001010 % +b00000000000000000000000000001001 ) +11 +#95 +01 +#100 +b00000000000000000000000000001011 $ +b00001011 % +b00000000000000000000000000000001 ( +b00000000000000000000000000001010 ) +11 diff --git a/test_regress/t/t_cover_line_trace.pl b/test_regress/t/t_cover_line_trace.pl new file mode 100755 index 000000000..40ff27284 --- /dev/null +++ b/test_regress/t/t_cover_line_trace.pl @@ -0,0 +1,31 @@ +#!/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(simulator => 1); + +top_filename("t/t_cover_line.v"); + +compile( + verilator_flags2 => ['--cc --coverage-line --trace --trace-coverage'], + ); + +execute( + check_finished => 1, + ); + +run(cmd => ["../bin/verilator_coverage", + "--annotate", "$Self->{obj_dir}/annotated", + "$Self->{obj_dir}/coverage.dat", + ]); + +files_identical("$Self->{obj_dir}/annotated/t_cover_line.v", "t/t_cover_line.out"); +vcd_identical("$Self->{obj_dir}/simx.vcd", $Self->{golden_filename}); + +ok(1); +1; diff --git a/test_regress/t/t_cover_sva_trace.out b/test_regress/t/t_cover_sva_trace.out new file mode 100644 index 000000000..948b88e77 --- /dev/null +++ b/test_regress/t/t_cover_sva_trace.out @@ -0,0 +1,112 @@ +$version Generated by VerilatedVcd $end +$date Thu Oct 24 09:44:07 2019 + $end +$timescale 1ns $end + + $scope module top $end + $var wire 1 ) clk $end + $scope module t $end + $var wire 1 ) clk $end + $var wire 32 # cyc [31:0] $end + $var wire 1 % toggle $end + $scope module suba $end + $var wire 1 ) clk $end + $var wire 32 $ cyc [31:0] $end + $var wire 32 & cyc_eq_5_vlCoverageUserTrace [31:0] $end + $var wire 1 % toggle $end + $upscope $end + $scope module subb $end + $var wire 1 ) clk $end + $var wire 32 $ cyc [31:0] $end + $var wire 32 ' cyc_eq_5_vlCoverageUserTrace [31:0] $end + $var wire 1 % toggle $end + $upscope $end + $scope module subc $end + $var wire 1 ) clk $end + $var wire 32 $ cyc [31:0] $end + $var wire 32 ( cyc_eq_5_vlCoverageUserTrace [31:0] $end + $var wire 1 % toggle $end + $upscope $end + $upscope $end + $upscope $end +$enddefinitions $end + + +#0 +b00000000000000000000000000000001 # +b00000000000000000000000000000001 $ +0% +b00000000000000000000000000000000 & +b00000000000000000000000000000000 ' +b00000000000000000000000000000000 ( +0) +#10 +b00000000000000000000000000000010 # +b00000000000000000000000000000010 $ +1) +#15 +0) +#20 +b00000000000000000000000000000011 # +b00000000000000000000000000000011 $ +1% +1) +#25 +0) +#30 +b00000000000000000000000000000100 # +b00000000000000000000000000000100 $ +0% +1) +#35 +0) +#40 +b00000000000000000000000000000101 # +b00000000000000000000000000000101 $ +1% +1) +#45 +0) +#50 +b00000000000000000000000000000110 # +b00000000000000000000000000000110 $ +0% +b00000000000000000000000000000001 & +b00000000000000000000000000000001 ' +b00000000000000000000000000000001 ( +1) +#55 +0) +#60 +b00000000000000000000000000000111 # +b00000000000000000000000000000111 $ +1% +1) +#65 +0) +#70 +b00000000000000000000000000001000 # +b00000000000000000000000000001000 $ +0% +1) +#75 +0) +#80 +b00000000000000000000000000001001 # +b00000000000000000000000000001001 $ +1% +1) +#85 +0) +#90 +b00000000000000000000000000001010 # +b00000000000000000000000000001010 $ +0% +1) +#95 +0) +#100 +b00000000000000000000000000001011 # +b00000000000000000000000000001011 $ +1% +1) diff --git a/test_regress/t/t_cover_sva_trace.pl b/test_regress/t/t_cover_sva_trace.pl new file mode 100755 index 000000000..6a50d7191 --- /dev/null +++ b/test_regress/t/t_cover_sva_trace.pl @@ -0,0 +1,25 @@ +#!/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(simulator => 1); + +top_filename("t/t_cover_sva_notflat.v"); + +compile( + verilator_flags2 => ['--assert --cc --coverage-user --trace --trace-coverage'], + ); + +execute( + check_finished => 1, + ); + +vcd_identical("$Self->{obj_dir}/simx.vcd", $Self->{golden_filename}); + +ok(1); +1;