diff --git a/Changes b/Changes index 6f966a0cb..78f6b8440 100644 --- a/Changes +++ b/Changes @@ -4,6 +4,8 @@ The contributors that suggested a given feature are shown in []. Thanks! * Verilator 4.013 devel +*** Add --trace-fst-thread. + **** Support '#' comments in $readmem, bug1411. [Frederick Requin] **** Support "'dx" constants, bug1423. [Udi Finkelstein] diff --git a/bin/verilator b/bin/verilator index 6f4011a22..6cabd4cb9 100755 --- a/bin/verilator +++ b/bin/verilator @@ -361,6 +361,7 @@ detailed descriptions in L for more information. --top-module Name of top level input module --trace Enable waveform creation --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 @@ -1291,7 +1292,14 @@ even when waveforms are not turned on during model execution. =item --trace-fst -Enable FST waveform tracing in the model. This overrides C<--trace>. +Enable FST waveform tracing in the model. This overrides C<--trace> and +C<--trace-fst-thread>. See also C<--trace-fst-thread>. + +=item --trace-fst-thread + +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 @@ -2348,6 +2356,9 @@ Verilated model should not livelock nor deadlock, however, you can expect performance to be far worse than it would be with proper stoichiometry of threads and CPU cores. +With --trace-fst-thread, tracing occurs in a separate thread from the main +simulation thread(s). This option is orthogonal to --threads. + The remainder of this section describe behavior with --threads 1 or --threads N (not --no-threads). diff --git a/include/verilated.mk.in b/include/verilated.mk.in index a7657ddb8..ef284c5f4 100644 --- a/include/verilated.mk.in +++ b/include/verilated.mk.in @@ -116,8 +116,22 @@ endif ifneq ($(VM_THREADS),0) ifneq ($(VM_THREADS),) + CPPFLAGS += -DVL_THREADED + VK_LIBS_THREADED=1 + endif +endif + +ifneq ($(VM_TRACE_THREADED),0) + ifneq ($(VM_TRACE_THREADED),) + CPPFLAGS += -DVL_TRACE_THREADED + VK_LIBS_THREADED=1 + endif +endif + +ifneq ($(VK_LIBS_THREADED),0) + ifneq ($(VK_LIBS_THREADED),) # Need C++11 at least, so always default to newest - CPPFLAGS += -DVL_THREADED $(CFG_CXXFLAGS_STD_NEWEST) + CPPFLAGS += $(CFG_CXXFLAGS_STD_NEWEST) LDLIBS += $(CFG_LDLIBS_THREADS) endif endif diff --git a/include/verilated_fst_c.cpp b/include/verilated_fst_c.cpp index 2055284d4..db2f37b2a 100644 --- a/include/verilated_fst_c.cpp +++ b/include/verilated_fst_c.cpp @@ -24,6 +24,12 @@ #include "verilated.h" #include "verilated_fst_c.h" +// GTKWave configuration +#ifdef VL_TRACE_THREADED +# define HAVE_LIBPTHREAD +# define FST_WRITER_PARALLEL +#endif + // Include the GTKWave implementation directly #include "gtkwave/fastlz.c" #include "gtkwave/fstapi.c" @@ -73,6 +79,9 @@ void VerilatedFst::open(const char* filename) VL_MT_UNSAFE { m_assertOne.check(); m_fst = fstWriterCreate(filename, 1); fstWriterSetPackType(m_fst, FST_WR_PT_LZ4); +#ifdef VL_TRACE_THREADED + fstWriterSetParallelMode(m_fst, 1); +#endif m_curScope.clear(); for (vluint32_t ent = 0; ent< m_callbacks.size(); ++ent) { diff --git a/src/V3EmitC.cpp b/src/V3EmitC.cpp index 6f7c16236..2d243685c 100644 --- a/src/V3EmitC.cpp +++ b/src/V3EmitC.cpp @@ -2887,7 +2887,7 @@ class EmitCTrace : EmitCStmts { puts(","); putsQuoted(nodep->showname()); // Direction - if (v3Global.opt.traceFormat() == TraceFormat::FST) { + if (v3Global.opt.traceFormat().fstFlavor()) { puts(","+cvtToStr(enumNum)); // fstVarDir if (nodep->declDirection().isInoutish()) puts(",FST_VD_INOUT"); @@ -2954,7 +2954,7 @@ class EmitCTrace : EmitCStmts { int emitTraceDeclDType(AstNodeDType* nodep) { // Return enum number or -1 for none - if (v3Global.opt.traceFormat() == TraceFormat::FST) { + if (v3Global.opt.traceFormat().fstFlavor()) { // Skip over refs-to-refs, but stop before final ref so can get data type name // Alternatively back in V3Width we could push enum names from upper typedefs if (AstEnumDType* enump = VN_CAST(nodep->skipRefToEnump(), EnumDType)) { diff --git a/src/V3EmitMk.cpp b/src/V3EmitMk.cpp index b276060b8..26d7f6360 100644 --- a/src/V3EmitMk.cpp +++ b/src/V3EmitMk.cpp @@ -61,6 +61,9 @@ public: of.puts("VM_THREADS = "); of.puts(cvtToStr(v3Global.opt.threads())); of.puts("\n"); of.puts("# Tracing output mode? 0/1 (from --trace)\n"); of.puts("VM_TRACE = "); of.puts(v3Global.opt.trace()?"1":"0"); of.puts("\n"); + of.puts("# Tracing threadeds output mode? 0/1 (from --trace-fst-thread)\n"); + of.puts("VM_TRACE_THREADED = "); of.puts(v3Global.opt.traceFormat().threaded() + ?"1":"0"); of.puts("\n"); of.puts("\n### Object file lists...\n"); for (int support=0; support<3; support++) { diff --git a/src/V3Options.cpp b/src/V3Options.cpp index db953e9ae..6bfdc3a76 100644 --- a/src/V3Options.cpp +++ b/src/V3Options.cpp @@ -699,10 +699,9 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char else if ( onoff (sw, "-stats-vars", flag/*ref*/) ) { m_statsVars = flag; m_stats |= flag; } 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-fst", flag/*ref*/) ) { m_trace = flag; m_traceFormat = TraceFormat::FST; addLdLibs("-lz"); } - 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", flag/*ref*/) ) { m_trace = 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; } else if ( onoff (sw, "-trace-underscore", flag/*ref*/) ) { m_traceUnderscore = flag; } else if ( onoff (sw, "-underline-zero", flag/*ref*/) ) { m_underlineZero = flag; } // Undocumented, old Verilator-2 @@ -869,6 +868,16 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char shift; m_outputSplitCTrace = atoi(argv[i]); } + else if (!strcmp(sw, "-trace-fst")) { + m_trace = true; + m_traceFormat = TraceFormat::FST; + addLdLibs("-lz"); + } + else if (!strcmp(sw, "-trace-fst-thread")) { + m_trace = true; + m_traceFormat = TraceFormat::FST_THREAD; + addLdLibs("-lz"); + } else if ( !strcmp (sw, "-trace-depth") && (i+1)(_e)) {} operator en() const { return m_e; } + bool fstFlavor() const { return m_e == FST || m_e == FST_THREAD; } + bool threaded() const { return m_e == FST_THREAD; } string classBase() const { static const char* const names[] = { "VerilatedVcd", + "VerilatedFst", "VerilatedFst" }; return names[m_e]; @@ -56,6 +60,7 @@ public: string sourceName() const { static const char* const names[] = { "verilated_vcd", + "verilated_fst", "verilated_fst" }; return names[m_e]; diff --git a/test_regress/driver.pl b/test_regress/driver.pl index 7233049e5..0d847c5c3 100755 --- a/test_regress/driver.pl +++ b/test_regress/driver.pl @@ -594,8 +594,9 @@ sub compile_vlt_flags { @{$param{verilator_flags3}}); $self->{sc} = 1 if ($checkflags =~ /-sc\b/); $self->{trace} = ($opt_trace || $checkflags =~ /-trace\b/ - || $checkflags =~ /-trace-fst\b/); - $self->{trace_format} = (($checkflags =~ /-trace-fst\b/ && 'fst-c') + || $checkflags =~ /-trace-fst\b/ + || $checkflags =~ /-trace-fst-thread\b/); + $self->{trace_format} = (($checkflags =~ /-trace-fst/ && 'fst-c') || ($self->{sc} && 'vcd-sc') || (!$self->{sc} && 'vcd-c')); $self->{savable} = 1 if ($checkflags =~ /-savable\b/); @@ -607,6 +608,7 @@ sub compile_vlt_flags { unshift @verilator_flags, "--x-assign unique"; # More likely to be buggy unshift @verilator_flags, "--trace" if $opt_trace; unshift @verilator_flags, "--threads 3" if $param{vltmt}; + unshift @verilator_flags, "--trace-fst-thread" if $param{vltmt} && $checkflags =~ /-trace-fst/; unshift @verilator_flags, "--debug-partition" if $param{vltmt}; if (defined $opt_optimize) { my $letters = ""; diff --git a/test_regress/t/t_trace_complex_fst_thread.out b/test_regress/t/t_trace_complex_fst_thread.out new file mode 100644 index 000000000..6850fcf49 --- /dev/null +++ b/test_regress/t/t_trace_complex_fst_thread.out @@ -0,0 +1,234 @@ +$date + Wed May 1 19:09:18 2019 + +$end +$version + fstWriter +$end +$timescale + 1ns +$end +$scope module top $end +$var wire 1 ! clk $end +$scope module t $end +$var wire 1 ! clk $end +$var integer 32 " cyc $end +$var logic 2 # v_strp $end +$var logic 4 $ v_strp_strp $end +$var logic 2 % v_unip_strp $end +$var logic 2 & v_arrp $end +$var logic 4 ' v_arrp_arrp $end +$var logic 4 ( v_arrp_strp $end +$var logic 1 ) v_arru(1) $end +$var logic 1 * v_arru(2) $end +$var logic 1 + v_arru_arru(3)(1) $end +$var logic 1 , v_arru_arru(3)(2) $end +$var logic 1 - v_arru_arru(4)(1) $end +$var logic 1 . v_arru_arru(4)(2) $end +$var logic 2 / v_arru_arrp(3) $end +$var logic 2 0 v_arru_arrp(4) $end +$var logic 2 1 v_arru_strp(3) $end +$var logic 2 2 v_arru_strp(4) $end +$var real 64 3 v_real $end +$var real 64 4 v_arr_real(0) $end +$var real 64 5 v_arr_real(1) $end +$var logic 64 6 v_str32x2 $end +$attrbegin misc 07 t.enumed_t 4 ZERO ONE TWO THREE 00000000000000000000000000000000 00000000000000000000000000000001 00000000000000000000000000000010 00000000000000000000000000000011 1 $end +$attrbegin misc 07 "" 1 $end +$var logic 32 7 v_enumed $end +$attrbegin misc 07 "" 1 $end +$var logic 32 8 v_enumed2 $end +$attrbegin misc 07 t.enumb_t 4 BZERO BONE BTWO BTHREE 000 001 010 011 2 $end +$attrbegin misc 07 "" 2 $end +$var logic 3 9 v_enumb $end +$scope module unnamedblk1 $end +$var integer 32 : b $end +$scope module unnamedblk2 $end +$var integer 32 ; a $end +$upscope $end +$upscope $end +$scope module p2 $end +$var parameter 32 < PARAM $end +$upscope $end +$scope module p3 $end +$var parameter 32 = PARAM $end +$upscope $end +$upscope $end +$scope module $unit $end +$var bit 1 > global_bit $end +$upscope $end +$upscope $end +$enddefinitions $end +$dumpvars +0! +b00000000000000000000000000000000 " +b00 # +b0000 $ +b00 % +b00 & +b0000 ' +b0000 ( +0) +0* +0+ +0, +0- +0. +b00 / +b00 0 +b00 1 +b00 2 +r0 3 +r0 4 +r0 5 +b0000000000000000000000000000000000000000000000000000000011111111 6 +b00000000000000000000000000000000 7 +b00000000000000000000000000000000 8 +b000 9 +b00000000000000000000000000000000 : +b00000000000000000000000000000000 ; +b00000000000000000000000000000010 < +b00000000000000000000000000000011 = +1> +#10 +b00000000000000000000000000000101 ; +b00000000000000000000000000000101 : +b111 9 +b00000000000000000000000000000010 8 +b00000000000000000000000000000001 7 +b0000000000000000000000000000000100000000000000000000000011111110 6 +r0.3 5 +r0.2 4 +r0.1 3 +b11 2 +b11 1 +b11 0 +b11 / +b1111 ( +b1111 ' +b11 & +b11 % +b1111 $ +b11 # +b00000000000000000000000000000001 " +1! +#15 +0! +#20 +1! +b00000000000000000000000000000010 " +b00 # +b0000 $ +b00 % +b00 & +b0000 ' +b0000 ( +b00 / +b00 0 +b00 1 +b00 2 +r0.2 3 +r0.4 4 +r0.6 5 +b0000000000000000000000000000001000000000000000000000000011111101 6 +b00000000000000000000000000000010 7 +b00000000000000000000000000000100 8 +b110 9 +b00000000000000000000000000000101 : +b00000000000000000000000000000101 ; +#25 +0! +#30 +1! +b00000000000000000000000000000101 ; +b00000000000000000000000000000101 : +b101 9 +b00000000000000000000000000000110 8 +b00000000000000000000000000000011 7 +b0000000000000000000000000000001100000000000000000000000011111100 6 +r0.8999999999999999 5 +r0.6000000000000001 4 +r0.3 3 +b11 2 +b11 1 +b11 0 +b11 / +b1111 ( +b1111 ' +b11 & +b11 % +b1111 $ +b11 # +b00000000000000000000000000000011 " +#35 +0! +#40 +1! +b00000000000000000000000000000100 " +b00 # +b0000 $ +b00 % +b00 & +b0000 ' +b0000 ( +b00 / +b00 0 +b00 1 +b00 2 +r0.4 3 +r0.8 4 +r1.2 5 +b0000000000000000000000000000010000000000000000000000000011111011 6 +b00000000000000000000000000000100 7 +b00000000000000000000000000001000 8 +b100 9 +b00000000000000000000000000000101 : +b00000000000000000000000000000101 ; +#45 +0! +#50 +1! +b00000000000000000000000000000101 ; +b00000000000000000000000000000101 : +b011 9 +b00000000000000000000000000001010 8 +b00000000000000000000000000000101 7 +b0000000000000000000000000000010100000000000000000000000011111010 6 +r1.5 5 +r1 4 +r0.5 3 +b11 2 +b11 1 +b11 0 +b11 / +b1111 ( +b1111 ' +b11 & +b11 % +b1111 $ +b11 # +b00000000000000000000000000000101 " +#55 +0! +#60 +1! +b00000000000000000000000000000110 " +b00 # +b0000 $ +b00 % +b00 & +b0000 ' +b0000 ( +b00 / +b00 0 +b00 1 +b00 2 +r0.6 3 +r1.2 4 +r1.8 5 +b0000000000000000000000000000011000000000000000000000000011111001 6 +b00000000000000000000000000000110 7 +b00000000000000000000000000001100 8 +b010 9 +b00000000000000000000000000000101 : +b00000000000000000000000000000101 ; diff --git a/test_regress/t/t_trace_complex_fst_thread.pl b/test_regress/t/t_trace_complex_fst_thread.pl new file mode 100755 index 000000000..9430e48fb --- /dev/null +++ b/test_regress/t/t_trace_complex_fst_thread.pl @@ -0,0 +1,27 @@ +#!/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_trace_complex.v"); +$Self->{golden_filename} = "t/t_trace_complex_fst.out"; + +compile( + verilator_flags2 => ['--cc --trace-fst-thread'], + ); + +execute( + check_finished => 1, + ); + +fst2vcd($Self->trace_filename, "$Self->{obj_dir}/simx-fst2vcd.vcd"); +vcd_identical("$Self->{obj_dir}/simx-fst2vcd.vcd", $Self->{golden_filename}); + +ok(1); +1;