: # -*-Mode: perl;-*- use perl, wherever it is eval 'exec perl -wS $0 ${1+"$@"}' if 0; # $Id$ ###################################################################### # # Copyright 2007-2008 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+.*\s+(\S+)\s*$/) { my $pct=$1; my $sec=$2; my $calls=$3; my $func=$4; $funcs{$func}{pct} += $pct; $funcs{$func}{sec} += $sec; $funcs{$func}{calls} += $calls; } } $fh->close; # Find modules my %verilated_mods; foreach my $func (keys %funcs) { if ($func =~ /(.*)::_eval\(.*__Syms.*\)$/) { $verilated_mods{$1} = qr/^$1/; } } # Resort by Verilog name my %vfuncs; my %groups; foreach my $func (keys %funcs) { my $vfunc = $func; my $design; foreach my $vde (keys %verilated_mods) { if ($func =~ /$verilated_mods{$vde}/) { $design=$vde; last; } } if ($vfunc =~ /__PROF__([a-zA-Z_0-9]+)__([0-9]+)\(/) { $vfunc = sprintf("VBlock %s:%d", $1, $2); $groups{"Verilog Blocks under $design"} += $funcs{$func}{pct}; } else { if ($design) { $vfunc = sprintf("VCommon %s", $func); $groups{"Common code under $design"} += $funcs{$func}{pct}; } else { $vfunc = sprintf("C++ %s", $func); $groups{'C++'} += $funcs{$func}{pct}; } } $vfuncs{$vfunc} = $funcs{$func}; } print("Overall summary:\n"); print(" % time\n"); foreach (sort (keys %groups)) { printf(" %6.2f In all %s\n", $groups{$_}, $_); } print("\n"); print("Verilog code profile:\n"); print(" These are split into three categories:\n"); print(" C++: Time in non-Verilated C++ code\n"); print(" VBlock: Time attributable to a block in a Verilog file and line\n"); print(" VCommon: Time in a Verilated module, due to all parts of the design\n"); print("\n"); print(" % cumulative self \n"); print(" time seconds seconds calls type filename and line number\n"); my $cume = 0; foreach my $func (sort {$vfuncs{$b}{sec} <=> $vfuncs{$a}{sec} || $a cmp $b} (keys %vfuncs)) { $cume += $vfuncs{$func}{sec}; printf +("%6.2f %9.2f %8.2f %8d %s\n", $vfuncs{$func}{pct}, $cume, $vfuncs{$func}{sec}, $vfuncs{$func}{calls}, $func); } } ####################################################################### __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-2008 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: