From 801b71895357d8826536c393ab2cc0fd349c55f5 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Sat, 14 Dec 2013 19:13:31 -0500 Subject: [PATCH] Add --trace-structs to show struct names, bug673. --- Changes | 2 + bin/verilator | 8 + src/V3Dead.cpp | 6 + src/V3Options.cpp | 2 + src/V3Options.h | 2 + src/V3TraceDecl.cpp | 65 ++++-- test_regress/t/t_trace_complex.out | 148 ++++++++++++ test_regress/t/t_trace_complex.pl | 2 + test_regress/t/t_trace_complex.v | 7 + test_regress/t/t_trace_complex_structs.out | 260 +++++++++++++++++++++ test_regress/t/t_trace_complex_structs.pl | 33 +++ 11 files changed, 519 insertions(+), 16 deletions(-) create mode 100644 test_regress/t/t_trace_complex.out create mode 100644 test_regress/t/t_trace_complex_structs.out create mode 100755 test_regress/t/t_trace_complex_structs.pl diff --git a/Changes b/Changes index 04fcb1eaa..60a9feb69 100644 --- a/Changes +++ b/Changes @@ -5,6 +5,8 @@ indicates the contributor was also the author of the fix; Thanks! * Verilator 3.855 devel +*** Add --trace-structs to show struct names, bug673. [Chris Randall] + **** Fix tracing of packed structs, bug705. [Jie Xu] **** Fix --lint-only with MinGW, msg1283. [HyungKi Jeong] diff --git a/bin/verilator b/bin/verilator index b255ac723..b3fcab346 100755 --- a/bin/verilator +++ b/bin/verilator @@ -325,6 +325,7 @@ descriptions in the next sections for more information. --trace-depth Depth of tracing --trace-max-array Maximum bit width for tracing --trace-max-width Maximum array depth for tracing + --trace-structs Enable tracing structure names --trace-underscore Enable tracing of _signals -U Undefine preprocessor define --unroll-count Tune maximum loop iterations @@ -1021,6 +1022,13 @@ Rarely needed. Specify the maximum bit width of a signal that may be traced. Defaults to 256, as tracing large vectors may greatly slow traced simulations. +=item --trace-structs + +Enable tracing to show the name of packed structure, union, and packed +array fields, rather than a simgle combined packed bus. Due to VCD file +format constraints this may result in significantly slower trace times and +larger trace files. + =item --trace-underscore Enable tracing of signals that start with an underscore. Normally, these diff --git a/src/V3Dead.cpp b/src/V3Dead.cpp index ba7c08a8f..a20265e14 100644 --- a/src/V3Dead.cpp +++ b/src/V3Dead.cpp @@ -144,6 +144,12 @@ private: nodep->packagep()->user1Inc(); } } + virtual void visit(AstMemberDType* nodep, AstNUser*) { + // Keep member names iff upper type exists + nodep->iterateChildren(*this); + // No checkDType(nodep) + checkAll(nodep); + } virtual void visit(AstNodeDType* nodep, AstNUser*) { nodep->iterateChildren(*this); checkDType(nodep); diff --git a/src/V3Options.cpp b/src/V3Options.cpp index 444f6bf8d..a21972f61 100644 --- a/src/V3Options.cpp +++ b/src/V3Options.cpp @@ -756,6 +756,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, "-trace", flag/*ref*/) ) { m_trace = flag; } else if ( onoff (sw, "-trace-dups", flag/*ref*/) ) { m_traceDups = 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 else if ( onoff (sw, "-x-initial-edge", flag/*ref*/) ) { m_xInitialEdge = flag; } @@ -1222,6 +1223,7 @@ V3Options::V3Options() { m_systemPerl = false; m_trace = false; m_traceDups = false; + m_traceStructs = false; m_traceUnderscore = false; m_underlineZero = false; m_reportUnoptflat = false; diff --git a/src/V3Options.h b/src/V3Options.h index 695d552e8..9848a2246 100644 --- a/src/V3Options.h +++ b/src/V3Options.h @@ -90,6 +90,7 @@ class V3Options { bool m_stats; // main switch: --stats bool m_trace; // main switch: --trace bool m_traceDups; // main switch: --trace-dups + bool m_traceStructs; // main switch: --trace-structs bool m_traceUnderscore;// main switch: --trace-underscore bool m_underlineZero;// main switch: --underline-zero; undocumented old Verilator 2 bool m_reportUnoptflat; // main switch: --report-unoptflat @@ -214,6 +215,7 @@ class V3Options { bool exe() const { return m_exe; } bool trace() const { return m_trace; } bool traceDups() const { return m_traceDups; } + bool traceStructs() const { return m_traceStructs; } bool traceUnderscore() const { return m_traceUnderscore; } bool orderClockDly() const { return m_orderClockDly; } bool outFormatOk() const { return m_outFormatOk; } diff --git a/src/V3TraceDecl.cpp b/src/V3TraceDecl.cpp index 5371a875c..c7866d74d 100644 --- a/src/V3TraceDecl.cpp +++ b/src/V3TraceDecl.cpp @@ -221,26 +221,59 @@ private: } virtual void visit(AstPackArrayDType* nodep, AstNUser*) { if (m_traVscp) { - // Everything downstream is packed, so deal with as one trace unit - // This may not be the nicest for user presentation, but is a much faster way to trace - addTraceDecl(VNumRange()); - } - } - virtual void visit(AstNodeClassDType* nodep, AstNUser*) { - if (m_traVscp) { - if (nodep->packed()) { + if (!v3Global.opt.traceStructs()) { // Everything downstream is packed, so deal with as one trace unit // This may not be the nicest for user presentation, but is a much faster way to trace addTraceDecl(VNumRange()); } else { - addIgnore("Unsupported: Unpacked struct/union"); - // Once we have an UnpackedMemberSel which works, this code is straight forward: - //for (AstMemberDType* itemp = adtypep->membersp(); itemp; itemp=itemp->nextp()->castMemberDType()) { - // AstNodeDType* subtypep = itemp->subDTypep()->skipRefp(); - // ... - // m_traShowname += string(" ")+itemp->name(); - // m_traValuep = new AstMemberSel(nodep->fileline(), m_traValuep->cloneTree(true), ... - // and iterate + AstNodeDType* subtypep = nodep->subDTypep()->skipRefp(); + for (int i=nodep->lsb(); i<=nodep->msb(); ++i) { + string oldShowname = m_traShowname; + AstNode* oldValuep = m_traValuep; + { + m_traShowname += string("(")+cvtToStr(i)+string(")"); + m_traValuep = new AstSel(nodep->fileline(), m_traValuep->cloneTree(true), + (i - nodep->lsb())*subtypep->width(), + subtypep->width()); + subtypep->accept(*this); + m_traValuep->deleteTree(); m_traValuep = NULL; + } + m_traShowname = oldShowname; + m_traValuep = oldValuep; + } + } + } + } + virtual void visit(AstNodeClassDType* nodep, AstNUser*) { + if (m_traVscp) { + if (nodep->packed() && !v3Global.opt.traceStructs()) { + // Everything downstream is packed, so deal with as one trace unit + // This may not be the nicest for user presentation, but is a much faster way to trace + addTraceDecl(VNumRange()); + } else { + if (!nodep->packed()) { + addIgnore("Unsupported: Unpacked struct/union"); + } else { + for (AstMemberDType* itemp = nodep->membersp(); itemp; itemp=itemp->nextp()->castMemberDType()) { + AstNodeDType* subtypep = itemp->subDTypep()->skipRefp(); + string oldShowname = m_traShowname; + AstNode* oldValuep = m_traValuep; + { + m_traShowname += string(" ")+itemp->prettyName(); + m_traValuep->dumpTree(cout, "-tv: "); + if (nodep->castStructDType()) { + m_traValuep = new AstSel(nodep->fileline(), m_traValuep->cloneTree(true), + itemp->lsb(), subtypep->width()); + subtypep->accept(*this); + m_traValuep->deleteTree(); m_traValuep = NULL; + } else { // Else union, replicate fields + subtypep->accept(*this); + } + } + m_traShowname = oldShowname; + m_traValuep = oldValuep; + } + } } } } diff --git a/test_regress/t/t_trace_complex.out b/test_regress/t/t_trace_complex.out new file mode 100644 index 000000000..ce048267c --- /dev/null +++ b/test_regress/t/t_trace_complex.out @@ -0,0 +1,148 @@ +$version Generated by VerilatedVcd $end +$date Sat Dec 14 19:07:34 2013 + $end +$timescale 1ns $end + + $scope module top $end + $var wire 1 0 clk $end + $scope module v $end + $var wire 1 0 clk $end + $var wire 32 # cyc [31:0] $end + $var wire 2 ' v_arrp [2:1] $end + $var wire 2 ( v_arrp_arrp [2:1] $end + $var wire 2 ) v_arrp_strp [1:0] $end + $var wire 1 1 v_arru(1) $end + $var wire 1 2 v_arru(2) $end + $var wire 2 * v_arru_arrp(3) [2:1] $end + $var wire 2 + v_arru_arrp(4) [2:1] $end + $var wire 1 3 v_arru_arru(3)(1) $end + $var wire 1 4 v_arru_arru(3)(2) $end + $var wire 1 5 v_arru_arru(4)(1) $end + $var wire 1 6 v_arru_arru(4)(2) $end + $var wire 2 , v_arru_strp(3) [1:0] $end + $var wire 2 - v_arru_strp(4) [1:0] $end + $var wire 2 $ v_strp [1:0] $end + $var wire 4 % v_strp_strp [3:0] $end + $var wire 2 & v_unip_strp [1:0] $end + $scope module unnamedblk1 $end + $var wire 32 . b [31:0] $end + $scope module unnamedblk2 $end + $var wire 32 / a [31:0] $end + $upscope $end + $upscope $end + $upscope $end + $upscope $end +$enddefinitions $end + + +#0 +b00000000000000000000000000000000 # +b00 $ +b0000 % +b00 & +b00 ' +b0000 ( +b0000 ) +b00 * +b00 + +b00 , +b00 - +b00000000000000000000000000000000 . +b00000000000000000000000000000000 / +00 +01 +02 +03 +04 +05 +06 +#10 +b00000000000000000000000000000001 # +b11 $ +b1111 % +b11 & +b11 ' +b1111 ( +b1111 ) +b11 * +b11 + +b11 , +b11 - +b00000000000000000000000000000101 . +b00000000000000000000000000000101 / +10 +#15 +00 +#20 +b00000000000000000000000000000010 # +b00 $ +b0000 % +b00 & +b00 ' +b0000 ( +b0000 ) +b00 * +b00 + +b00 , +b00 - +10 +#25 +00 +#30 +b00000000000000000000000000000011 # +b11 $ +b1111 % +b11 & +b11 ' +b1111 ( +b1111 ) +b11 * +b11 + +b11 , +b11 - +10 +#35 +00 +#40 +b00000000000000000000000000000100 # +b00 $ +b0000 % +b00 & +b00 ' +b0000 ( +b0000 ) +b00 * +b00 + +b00 , +b00 - +10 +#45 +00 +#50 +b00000000000000000000000000000101 # +b11 $ +b1111 % +b11 & +b11 ' +b1111 ( +b1111 ) +b11 * +b11 + +b11 , +b11 - +10 +#55 +00 +#60 +b00000000000000000000000000000110 # +b00 $ +b0000 % +b00 & +b00 ' +b0000 ( +b0000 ) +b00 * +b00 + +b00 , +b00 - +10 diff --git a/test_regress/t/t_trace_complex.pl b/test_regress/t/t_trace_complex.pl index 83d039acc..1e6cacc6c 100755 --- a/test_regress/t/t_trace_complex.pl +++ b/test_regress/t/t_trace_complex.pl @@ -25,5 +25,7 @@ file_grep ("$Self->{obj_dir}/simx.vcd", qr/ v_arru_arru\(/); file_grep ("$Self->{obj_dir}/simx.vcd", qr/ v_arru_arrp\(/); file_grep ("$Self->{obj_dir}/simx.vcd", qr/ v_arru_strp\(/); +vcd_identical ("$Self->{obj_dir}/simx.vcd", "t/$Self->{name}.out"); + ok(1); 1; diff --git a/test_regress/t/t_trace_complex.v b/test_regress/t/t_trace_complex.v index 490fc87be..03e331e1d 100644 --- a/test_regress/t/t_trace_complex.v +++ b/test_regress/t/t_trace_complex.v @@ -17,6 +17,11 @@ module t (clk); strp_t x0; } strp_strp_t; + typedef union packed { + strp_t x1; + strp_t x0; + } unip_strp_t; + typedef bit [2:1] arrp_t; typedef arrp_t [4:3] arrp_arrp_t; @@ -29,6 +34,7 @@ module t (clk); strp_t v_strp; strp_strp_t v_strp_strp; + unip_strp_t v_unip_strp; arrp_t v_arrp; arrp_arrp_t v_arrp_arrp; arrp_strp_t v_arrp_strp; @@ -41,6 +47,7 @@ module t (clk); cyc <= cyc + 1; v_strp <= ~v_strp; v_strp_strp <= ~v_strp_strp; + v_unip_strp <= ~v_unip_strp; v_arrp_strp <= ~v_arrp_strp; v_arrp <= ~v_arrp; v_arrp_arrp <= ~v_arrp_arrp; diff --git a/test_regress/t/t_trace_complex_structs.out b/test_regress/t/t_trace_complex_structs.out new file mode 100644 index 000000000..fc168e557 --- /dev/null +++ b/test_regress/t/t_trace_complex_structs.out @@ -0,0 +1,260 @@ +$version Generated by VerilatedVcd $end +$date Sat Dec 14 18:56:47 2013 + $end +$timescale 1ns $end + + $scope module top $end + $var wire 1 ; clk $end + $scope module v $end + $var wire 1 ; clk $end + $var wire 32 # cyc [31:0] $end + $var wire 2 , v_arrp [2:1] $end + $var wire 2 - v_arrp_arrp(3) [1:0] $end + $var wire 2 . v_arrp_arrp(4) [1:0] $end + $var wire 1 < v_arru(1) $end + $var wire 1 = v_arru(2) $end + $var wire 2 3 v_arru_arrp(3) [2:1] $end + $var wire 2 4 v_arru_arrp(4) [2:1] $end + $var wire 1 > v_arru_arru(3)(1) $end + $var wire 1 ? v_arru_arru(3)(2) $end + $var wire 1 @ v_arru_arru(4)(1) $end + $var wire 1 A v_arru_arru(4)(2) $end + $scope module unnamedblk1 $end + $var wire 32 9 b [31:0] $end + $scope module unnamedblk2 $end + $var wire 32 : a [31:0] $end + $upscope $end + $upscope $end + $scope module v_arrp_strp(3) $end + $var wire 1 0 b0 $end + $var wire 1 / b1 $end + $upscope $end + $scope module v_arrp_strp(4) $end + $var wire 1 2 b0 $end + $var wire 1 1 b1 $end + $upscope $end + $scope module v_arru_strp(3) $end + $var wire 1 6 b0 $end + $var wire 1 5 b1 $end + $upscope $end + $scope module v_arru_strp(4) $end + $var wire 1 8 b0 $end + $var wire 1 7 b1 $end + $upscope $end + $scope module v_strp $end + $var wire 1 % b0 $end + $var wire 1 $ b1 $end + $upscope $end + $scope module v_strp_strp $end + $scope module x0 $end + $var wire 1 ) b0 $end + $var wire 1 ( b1 $end + $upscope $end + $scope module x1 $end + $var wire 1 ' b0 $end + $var wire 1 & b1 $end + $upscope $end + $upscope $end + $scope module v_unip_strp $end + $scope module x0 $end + $var wire 1 + b0 $end + $var wire 1 * b1 $end + $upscope $end + $scope module x1 $end + $var wire 1 + b0 $end + $var wire 1 * b1 $end + $upscope $end + $upscope $end + $upscope $end + $upscope $end +$enddefinitions $end + + +#0 +b00000000000000000000000000000000 # +0$ +0% +0& +0' +0( +0) +0* +0+ +b00 , +b00 - +b00 . +0/ +00 +01 +02 +b00 3 +b00 4 +05 +06 +07 +08 +b00000000000000000000000000000000 9 +b00000000000000000000000000000000 : +0; +0< +0= +0> +0? +0@ +0A +#10 +b00000000000000000000000000000001 # +1$ +1% +1& +1' +1( +1) +1* +1+ +b11 , +b11 - +b11 . +1/ +10 +11 +12 +b11 3 +b11 4 +15 +16 +17 +18 +b00000000000000000000000000000101 9 +b00000000000000000000000000000101 : +1; +#15 +0; +#20 +b00000000000000000000000000000010 # +0$ +0% +0& +0' +0( +0) +0* +0+ +b00 , +b00 - +b00 . +0/ +00 +01 +02 +b00 3 +b00 4 +05 +06 +07 +08 +1; +#25 +0; +#30 +b00000000000000000000000000000011 # +1$ +1% +1& +1' +1( +1) +1* +1+ +b11 , +b11 - +b11 . +1/ +10 +11 +12 +b11 3 +b11 4 +15 +16 +17 +18 +1; +#35 +0; +#40 +b00000000000000000000000000000100 # +0$ +0% +0& +0' +0( +0) +0* +0+ +b00 , +b00 - +b00 . +0/ +00 +01 +02 +b00 3 +b00 4 +05 +06 +07 +08 +1; +#45 +0; +#50 +b00000000000000000000000000000101 # +1$ +1% +1& +1' +1( +1) +1* +1+ +b11 , +b11 - +b11 . +1/ +10 +11 +12 +b11 3 +b11 4 +15 +16 +17 +18 +1; +#55 +0; +#60 +b00000000000000000000000000000110 # +0$ +0% +0& +0' +0( +0) +0* +0+ +b00 , +b00 - +b00 . +0/ +00 +01 +02 +b00 3 +b00 4 +05 +06 +07 +08 +1; diff --git a/test_regress/t/t_trace_complex_structs.pl b/test_regress/t/t_trace_complex_structs.pl new file mode 100755 index 000000000..1d374806d --- /dev/null +++ b/test_regress/t/t_trace_complex_structs.pl @@ -0,0 +1,33 @@ +#!/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_trace_complex.v"); + +compile ( + verilator_flags2 => ['--cc --trace --trace-structs'], + ); + +execute ( + check_finished=>1, + ); + +file_grep ("$Self->{obj_dir}/simx.vcd", qr/ v_strp /); +file_grep ("$Self->{obj_dir}/simx.vcd", qr/ v_strp_strp /); +file_grep ("$Self->{obj_dir}/simx.vcd", qr/ v_arrp /); +file_grep_not ("$Self->{obj_dir}/simx.vcd", qr/ v_arrp_arrp /); +file_grep_not ("$Self->{obj_dir}/simx.vcd", qr/ v_arrp_strp /); +file_grep ("$Self->{obj_dir}/simx.vcd", qr/ v_arru\(/); +file_grep ("$Self->{obj_dir}/simx.vcd", qr/ v_arru_arru\(/); +file_grep ("$Self->{obj_dir}/simx.vcd", qr/ v_arru_arrp\(/); +file_grep ("$Self->{obj_dir}/simx.vcd", qr/ v_arru_strp\(/); + +vcd_identical ("$Self->{obj_dir}/simx.vcd", "t/$Self->{name}.out"); + +ok(1); +1;