diff --git a/Changes b/Changes index d0e4609dd..27e36b294 100644 --- a/Changes +++ b/Changes @@ -5,6 +5,8 @@ indicates the contributor was also the author of the fix; Thanks! * Verilator 3.65** +*** Added verilator_profcfunc utility. [Gene Weber] + *** Treat modules within `celldefine and `endcelldefine as if in library. *** Support functions which return integers. [Mark Nodine] diff --git a/bin/verilator b/bin/verilator index 8977691a7..2714ef7b2 100755 --- a/bin/verilator +++ b/bin/verilator @@ -730,9 +730,9 @@ feedback driven compilation. With GCC, using -fprofile-arcs, then You may uncover further tuning possibilities by profiling the Verilog code. Use Verilator's --profile-cfuncs, then GCC's -g -pg. You can then run -either oprofile or gprof to see where in the C++ code, and by looking at -the mangled function name where in the Verilog code most of the time is -being spent. +either oprofile or gprof to see where in the C++ code the time is spent. +Run the gprof output through verilator_profcfunc and it will tell you what +Verilog line numbers on which most of the time is being spent. When done, please let the author know the results. I like to keep tabs on how Verilator compares, and may be able to suggest additional improvements. @@ -2096,7 +2096,7 @@ Major concepts by Paul Wasson and Duane Galbi. =head1 SEE ALSO -L, L, L +L, L, L, L =cut diff --git a/bin/verilator_difftree b/bin/verilator_difftree index 389afc7c5..1eb305272 100755 --- a/bin/verilator_difftree +++ b/bin/verilator_difftree @@ -35,12 +35,13 @@ my $Opt_A; my $Opt_B; autoflush STDOUT 1; autoflush STDERR 1; +Getopt::Long::config ("no_auto_abbrev"); if (! GetOptions ( "help" => \&usage, "debug" => \&debug, "<>" => \¶meter, )) { - usage(); + die "%Error: Bad usage, try 'verilator_difftree --help'\n"; } defined $Opt_A or die "%Error: No old diff filename\n"; diff --git a/bin/verilator_profcfunc b/bin/verilator_profcfunc new file mode 100755 index 000000000..dfcf7acd8 --- /dev/null +++ b/bin/verilator_profcfunc @@ -0,0 +1,162 @@ +: # -*-Mode: perl;-*- use perl, wherever it is +eval 'exec perl -wS $0 ${1+"$@"}' + if 0; +# $Id$ +###################################################################### +# +# Copyright 2007-2007 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 or the Perl +# Artistic License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +###################################################################### + +require 5.006_001; +use warnings; +use Getopt::Long; +use IO::File; +use Pod::Usage; +use strict; +use vars qw ($Debug); + +#====================================================================== + + +#====================================================================== +# main + +$Debug = 0; +my $Opt_File; +autoflush STDOUT 1; +autoflush STDERR 1; +Getopt::Long::config ("no_auto_abbrev"); +if (! GetOptions ( + "help" => \&usage, + "debug" => \&debug, + "<>" => \¶meter, + )) { + die "%Error: Bad usage, try 'verilator_profcfunc --help'\n"; +} + +defined $Opt_File or die "%Error: No filename given\n"; + +profcfunc($Opt_File); + +#---------------------------------------------------------------------- + +sub usage { + print '$Id$ ', "\n"; + pod2usage(-verbose=>2, -exitval => 2); + exit (1); +} + +sub debug { + $Debug = 1; +} + +sub parameter { + my $param = shift; + if (!defined $Opt_File) { + $Opt_File = $param; + } else { + die "%Error: Unknown parameter: $param\n"; + } +} + +####################################################################### + +sub profcfunc { + my $filename = shift; + # Remove hex numbers before diffing + my $fh = IO::File->new ($filename) or die "%Error: $! $filename,"; + + my %funcs; + + while (defined (my $line=$fh->getline())) { + if ($line =~ /^\s*([0-9.]+)\s+[0-9.]+\s+([0-9.]+)\s+([0-9.]+)\s+.*__PROF__([a-zA-Z_0-9]+)__([0-9]+)\(/) { + my $fileline = sprintf("%s:%d", $4, $5); + $funcs{$fileline}{pct} += $1; + $funcs{$fileline}{sec} += $2; + $funcs{$fileline}{calls} += $3; + } + } + $fh->close; + + + print("Verilog code profile\n"); + print(" % cumulative self \n"); + print(" time seconds seconds calls filename and line number\n"); + + my $cume = 0; + foreach my $fileline (sort {$funcs{$b}{sec} <=> $funcs{$a}{sec} + || $a cmp $b} + (keys %funcs)) { + $cume += $funcs{$fileline}{sec}; + printf +("%6.2f %9.2f %8.2f %8d %s\n", $funcs{$fileline}{pct}, + $cume, $funcs{$fileline}{sec}, + $funcs{$fileline}{calls}, + $fileline); + } +} + +####################################################################### +__END__ + +=pod + +=head1 NAME + +verilator_profcfunc - Read gprof report created with --profile-cfuncs + +=head1 SYNOPSIS + + verilator --profile-cfuncs .... + gcc --ggdb -pg .... + {run executable} + gprof + verilator_profcfuncs gprof.out + +=head1 DESCRIPTION + +Verilator_profcfunc reads a profile report created by gprof. The names of +the functions are then transformed, assuming the user used verilator's +--profile-cfuncs, and a report printed showing the percentage of time, etc, +in each Verilog block. + +=head1 ARGUMENTS + +=over 4 + +=item --help + +Displays this message and program version and exits. + +=back + +=head1 DISTRIBUTION + +The latest version is available from L. + +Copyright 2007-2007 by Wilson Snyder. This package is free software; you +can redistribute it and/or modify it under the terms of either the GNU +Lesser General Public License or the Perl Artistic License. + +=head1 AUTHORS + +Wilson Snyder + +=head1 SEE ALSO + +C + +=cut + +###################################################################### +### Local Variables: +### compile-command: "$V4/bin/verilator_profcfunc $V4/test_c/obj_dir/V*_03_*.tree $V4N/test_c/obj_dir/V*_03_*.tree" +### End: diff --git a/src/verilog.l b/src/verilog.l index 44cc8ad1d..180c65ad8 100644 --- a/src/verilog.l +++ b/src/verilog.l @@ -633,11 +633,11 @@ escid \\[^ \t\f\r\n]+ [0-9][_0-9]* { yylval.nump = V3Read::newNumber(V3Read::fileline(),(char*)yytext); return yaINTNUM; } - [0-9][_0-9]*(\.[0-9]+)([eE][-+]?[0-9]+)? { + [0-9][_0-9]*(\.[_0-9]+)([eE][-+]?[_0-9]+)? { yylval.cdouble = 0; /* Only for delays, not used yet */ return yaFLOATNUM; } - [0-9][_0-9]*(\.[0-9]+)?([eE][-+]?[0-9]+) { + [0-9][_0-9]*(\.[_0-9]+)?([eE][-+]?[_0-9]+) { yylval.cdouble = 0; /* Only for delays, not used yet */ return yaFLOATNUM; } diff --git a/src/verilog.y b/src/verilog.y index 05e9f1b0c..da9ecf78e 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -305,7 +305,7 @@ class AstSenTree; %type defpList defpOne %type sensitivity %type sensitivityE -%type senList senitem senitemEdge +%type senList senitem senitemEdge senitemVar %type stmtBlock stmtList stmt labeledStmt stateCaseForIf %type assertStmt %type beginNamed @@ -687,7 +687,8 @@ instnameList: instnameParen { $$ = $1; } | instnameList ',' instnameParen { $$ = $1->addNext($3); } ; -instnameParen: yaID instRangeE '(' cellpinList ')' { $$ = new AstCell($3,*$1,V3Parse::s_instModule,$4,V3Parse::s_instParamp,$2); $$->pinStar(V3Parse::s_pinStar); } +instnameParen: yaID instRangeE '(' cellpinList ')' { $$ = new AstCell($3, *$1,V3Parse::s_instModule,$4, V3Parse::s_instParamp,$2); $$->pinStar(V3Parse::s_pinStar); } + | yaID instRangeE { $$ = new AstCell(CRELINE(),*$1,V3Parse::s_instModule,NULL,V3Parse::s_instParamp,$2); $$->pinStar(V3Parse::s_pinStar); } ; instRangeE: /* empty */ { $$ = NULL; } @@ -715,19 +716,24 @@ cellpinItemE: /* empty: ',,' is legal */ { $$ = NULL; V3Parse::s_pinNum++; } sensitivityE: /* empty */ { $$ = NULL; } | sensitivity { $$ = $1; } +//IEEE: event_control sensitivity: '@' '(' senList ')' { $$ = new AstSenTree($1,$3); } - | '@' senitem { $$ = new AstSenTree($1,$2); } + | '@' senitemVar { $$ = new AstSenTree($1,$2); } /* For events only */ | '@' '(' '*' ')' { $$ = NULL; $2->v3error("Use @*. always @ (*) to be depreciated in Verilog 2005.\n"); } | '@' '*' { $$ = NULL; } /* Verilog 2001 */ ; +//IEEE: event_expression - split over several senList: senitem { $$ = $1; } | senList yOR senitem { $$ = $1;$1->addNext($3); } | senList ',' senitem { $$ = $1;$1->addNext($3); } /* Verilog 2001 */ ; senitem: senitemEdge { $$ = $1; } - | varRefDotBit { $$ = new AstSenItem(CRELINE(),AstEdgeType::ANYEDGE,$1); } + | senitemVar { $$ = $1; } + ; + +senitemVar: varRefDotBit { $$ = new AstSenItem(CRELINE(),AstEdgeType::ANYEDGE,$1); } ; senitemEdge: yPOSEDGE varRefDotBit { $$ = new AstSenItem($1,AstEdgeType::POSEDGE,$2); } @@ -1097,6 +1103,8 @@ specifyJunk: dlyTerm {} /* ignored */ | yPSL_KET {} | yP_OR_MINUS_GT {} | yP_OR_EQ_GT {} + + | error {} ; //************************************************ diff --git a/test_regress/t/t_inst_v2k.v b/test_regress/t/t_inst_v2k.v index b29690184..b98827272 100644 --- a/test_regress/t/t_inst_v2k.v +++ b/test_regress/t/t_inst_v2k.v @@ -1,4 +1,4 @@ -// $Id:$ +// $Id$ // DESCRIPTION: Verilator: Verilog Test module // // This file ONLY is placed into the Public Domain, for any use, @@ -24,6 +24,8 @@ module t (/*AUTOARG*/ wire [7:0] osizedreg; // From sub of t_inst_v2k_sub.v + hello hsub; + t_inst_v2k_sub sub ( // Outputs @@ -55,6 +57,10 @@ module t (/*AUTOARG*/ endmodule +module hello; + initial $write ("Hello\n"); +endmodule + // Local Variables: // compile-command: "./vlint __FILE__" // End: