diff --git a/Changes b/Changes index 1b276018a..4c4378b06 100644 --- a/Changes +++ b/Changes @@ -13,6 +13,9 @@ indicates the contributor was also the author of the fix; Thanks! *** Support $fopen and I/O with integer instead of `verilator_file_descriptor. +*** Support coverage in -cc and -sc output modes. [John Li] + Note this requires SystemPerl 1.338 or newer. + **** Fix vpi_register_cb using bad s_cb_data, bug370. [by Thomas Watts] **** Fix $display missing leading zeros in %0d, bug367. [Alex Solomatnikov] diff --git a/bin/verilator b/bin/verilator index bcfbfb2a0..27f208c05 100755 --- a/bin/verilator +++ b/bin/verilator @@ -3054,8 +3054,8 @@ network disk. Network disks are generally far slower. =item How do I do coverage analysis? Verilator supports both block (line) coverage and user inserted functional -coverage. Both currently require SystemPerl output mode and the SystemPerl -package. +coverage. Both require the SystemPerl package to be installed but do not +require use of the SystemPerl output mode. First, run verilator with the --coverage option. If you're using your own makefile, compile the model with the GCC flag -DSP_COVERAGE_ENABLE (if diff --git a/include/verilated.mk.in b/include/verilated.mk.in index 3057ce848..1cdfc1802 100644 --- a/include/verilated.mk.in +++ b/include/verilated.mk.in @@ -116,6 +116,10 @@ ifeq ($(VM_SP),1) $(SP_PREPROC) -M sp_preproc.d --tree $(VM_PREFIX).sp_tree \ --preproc $(VK_CLASSES_SP) else + ifeq ($(VM_COVERAGE),1) + CPPFLAGS += -I$(SYSTEMPERL_INCLUDE) + VPATH += $(SYSTEMPERL_INCLUDE) + endif preproc: endif diff --git a/src/V3EmitMk.cpp b/src/V3EmitMk.cpp index 6499588a1..e18d0adc4 100644 --- a/src/V3EmitMk.cpp +++ b/src/V3EmitMk.cpp @@ -84,10 +84,15 @@ public: if (v3Global.opt.systemPerl()) { putMakeClassEntry(of, "Sp.cpp"); // Note Sp.cpp includes SpTraceVcdC } - else if (v3Global.opt.trace()) { - putMakeClassEntry(of, "verilated_vcd_c.cpp"); - if (v3Global.opt.systemC()) { - putMakeClassEntry(of, "verilated_vcd_sc.cpp"); + else { + if (v3Global.opt.coverage()) { + putMakeClassEntry(of, "SpCoverage.cpp"); + } + if (v3Global.opt.trace()) { + putMakeClassEntry(of, "verilated_vcd_c.cpp"); + if (v3Global.opt.systemC()) { + putMakeClassEntry(of, "verilated_vcd_sc.cpp"); + } } } } diff --git a/src/Verilator.cpp b/src/Verilator.cpp index ef45c4f93..196c6f714 100644 --- a/src/Verilator.cpp +++ b/src/Verilator.cpp @@ -567,9 +567,6 @@ int main(int argc, char** argv, char** env) { v3Global.opt.bin(argv[0]); string argString = V3Options::argString(argc-1, argv+1); v3Global.opt.parseOpts(new FileLine("COMMAND_LINE",0), argc-1, argv+1); - if (v3Global.opt.coverage() && !v3Global.opt.systemPerl() && !v3Global.opt.lintOnly()) { - v3fatal("Unsupported: Coverage analysis requires --sp output."); - } if (!v3Global.opt.outFormatOk() && !v3Global.opt.preprocOnly() && !v3Global.opt.lintOnly() diff --git a/test_regress/driver.pl b/test_regress/driver.pl index 62c9b0ba7..ab2239514 100755 --- a/test_regress/driver.pl +++ b/test_regress/driver.pl @@ -897,8 +897,12 @@ sub _make_main { print $fh ' vl_fatal(__FILE__,__LINE__,"main", "%Error: Timeout; never got a $finish");',"\n"; print $fh " }\n"; print $fh " topp->final();\n"; - print $fh " SpCoverage::write(\"",$self->{coverage_filename},"\");\n" if $self->{coverage}; + if ($self->{coverage}) { + $fh->print("#if VM_COVERAGE\n"); + $fh->print(" SpCoverage::write(\"",$self->{coverage_filename},"\");\n"); + $fh->print("#endif //VM_COVERAGE\n"); + } if ($self->{trace}) { $fh->print("#if VM_TRACE\n"); $fh->print(" if (tfp) tfp->close();\n"); diff --git a/test_regress/t/t_cover_line_cc.pl b/test_regress/t/t_cover_line_cc.pl new file mode 100755 index 000000000..0b803ddc1 --- /dev/null +++ b/test_regress/t/t_cover_line_cc.pl @@ -0,0 +1,24 @@ +#!/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. + +top_filename("t/t_cover_line.v"); + +compile ( + verilator_flags2 => ['--cc --coverage-line'], + ); + +execute ( + check_finished=>1, + ); + +# Read the input .v file and do any CHECK_COVER requests +inline_checks(); + +ok(1); +1; diff --git a/test_regress/t/t_cover_line_sc.pl b/test_regress/t/t_cover_line_sc.pl new file mode 100755 index 000000000..2d5faf39d --- /dev/null +++ b/test_regress/t/t_cover_line_sc.pl @@ -0,0 +1,24 @@ +#!/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. + +top_filename("t/t_cover_line.v"); + +compile ( + verilator_flags2 => ['--sc --coverage-line'], + ); + +execute ( + check_finished=>1, + ); + +# Read the input .v file and do any CHECK_COVER requests +inline_checks(); + +ok(1); +1; diff --git a/test_regress/t/t_cover_line.pl b/test_regress/t/t_cover_line_sp.pl similarity index 94% rename from test_regress/t/t_cover_line.pl rename to test_regress/t/t_cover_line_sp.pl index 14d2fe474..05afc6bb0 100755 --- a/test_regress/t/t_cover_line.pl +++ b/test_regress/t/t_cover_line_sp.pl @@ -7,6 +7,8 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di # Lesser General Public License Version 3 or the Perl Artistic License # Version 2.0. +top_filename("t/t_cover_line.v"); + compile ( verilator_flags2 => ['--sp --coverage-line'], ); diff --git a/test_sc/sc_main.cpp b/test_sc/sc_main.cpp index f509fdc84..789e947bc 100644 --- a/test_sc/sc_main.cpp +++ b/test_sc/sc_main.cpp @@ -99,7 +99,7 @@ int sc_main(int argc, char* argv[]) { //========== // Waves -#if WAVES +#if VM_TRACE // Before any evaluation, need to know to calculate those signals only used for tracing Verilated::traceEverOn(true); #endif @@ -117,7 +117,7 @@ int sc_main(int argc, char* argv[]) { //========== // Waves -#if WAVES +#if VM_TRACE cout << "Enabling waves...\n"; # ifdef SYSTEMPERL SpTraceFile* tfp = new SpTraceFile; @@ -135,7 +135,7 @@ int sc_main(int argc, char* argv[]) { reset_l = 1; while (VL_TIME_Q() < 60 && !passed && !Verilated::gotFinish()) { -#if WAVES +#if VM_TRACE // Flush the wave files each cycle so we can immediately see the output // Don't do this in "real" programs, do it in a abort() handler instead if (tfp) tfp->flush(); @@ -156,7 +156,7 @@ int sc_main(int argc, char* argv[]) { //========== // Close Waves -#if WAVES +#if VM_TRACE if (tfp) tfp->close(); #endif @@ -168,7 +168,7 @@ int sc_main(int argc, char* argv[]) { //========== // Coverage analysis (since test passed) mkdir("logs", 0777); -#ifdef SYSTEMPERL +#if VM_COVERAGE SpCoverage::write(); // Writes logs/coverage.pl #endif