#! /usr/local/bin/perl # creates an xy scatter plot of slack ratios # from two sets of endpoint timing data # Steve Golson -- Trilobyte Systems -- sgolson@trilobyte.com # @(#)scatter_plot 1.9 01/18/05 21:46:54 require 5.004; use Getopt::Long; use POSIX; # TODO # 1. plot multiple xy file pairs with different colors ########################################################################### # check arguments $myname = `basename $0`; chop $myname ; $argstring = $myname; foreach $arg (@ARGV) { if ( split(" ",$arg) > 1) { $argstring .= " ".quotemeta($arg); } else { $argstring .= " ".$arg; } } $datestring = `date`; chop $datestring ; ##### subroutine for handling non-option arguments $number_of_files=0; sub getfile { $number_of_files++ ; unless ($x_timing_report_file) { $x_timing_report_file = $_[0] ; return; } unless ($y_timing_report_file) { $y_timing_report_file = $_[0] ; return; } warn "Too many filenames"; return 0 ; } ##### get arguments and options $result = &GetOptions( "title=s",\$title, "number",\$title_number, "xlabel=s",\$xlabel, "ylabel=s",\$ylabel, "period=f",\$period, "type=s",\$plot_type, "style=s",\$plot_style, "date",\$date, "xmin=f",\$xmin, "xmax=f",\$xmax, "ymin=f",\$ymin, "ymax=f",\$ymax, "<>",\&getfile) ; ##### set option defaults $xlabel = $x_timing_report_file unless $xlabel ; $ylabel = $y_timing_report_file unless $ylabel ; $plot_type = "x" unless $plot_type ; $plot_style = "dots" unless $plot_style ; ##### print usage on error unless ($result and ($number_of_files==2) and ($plot_type eq "ps" or $plot_type eq "eps" or $plot_type eq "x") and ($plot_style eq "dots" or $plot_style eq "points") ) { select STDERR ; print < defaults to no title -number title shows number of endpoints -xlabel defaults to x_timing_report_file -ylabel defaults to y_timing_report_file -period overrides "Path Required" values -type defaults to x -style defaults to dots -date prints time and date The following four options select the area to be plotted: -xmin defaults to larger of -1.0 or min x value -xmax defaults to 1.0 -ymin defaults to larger of -1.0 or min y value -ymax defaults to 1.0 EOF exit ; } ##### check file status open (XFILE, "$x_timing_report_file") or die "Could not open file $x_timing_report_file : $!\n" ; open (YFILE, "$y_timing_report_file") or die "Could not open file $y_timing_report_file : $!\n" ; ########################################################################### ##### process the x-axis timing report file # skip the preamble while () { if ($_ =~ /^Endpoint\s+Path Delay\s+Path Required\s+Slack/) { last ; } } # skip one more line $_ = ; while () { @line = split ; $endpoint = $line[0] ; $celltype = $line[1] ; $delay = $line[2] ; $risefall = $line[3] ; $required = $line[4] ; $slack = $line[5] ; $required = $period if (defined($period)); if ($required==0) { next ; } $slack_ratio = $slack / $required ; push @{ $xfile_ratio{$endpoint} }, [ $slack_ratio, $required ] ; } ########################################################################### ##### process the y-axis timing report file # skip the preamble while () { if ($_ =~ /^Endpoint\s+Path Delay\s+Path Required\s+Slack/) { last ; } } # skip one more line $_ = ; while () { @line = split ; $endpoint = $line[0] ; $celltype = $line[1] ; $delay = $line[2] ; $risefall = $line[3] ; $required = $line[4] ; $slack = $line[5] ; $required = $period if (defined($period)); if ($required==0) { next ; } $slack_ratio = $slack / $required ; push @{ $yfile_ratio{$endpoint} }, [ $slack_ratio, $required ] ; } ########################################################################### ##### print the data file $number_of_endpoints = 0 ; $smallest_xratio = 1.0 ; $smallest_yratio = 1.0 ; # loop over all yfile endpoints, and find the matching xfile endpoints for $endpoint (keys %yfile_ratio) { @xfile = @{ $xfile_ratio{$endpoint}} ; @yfile = @{ $yfile_ratio{$endpoint}} ; delete $xfile_ratio{$endpoint} ; delete $yfile_ratio{$endpoint} ; $number_of_xfile_paths = scalar @xfile ; $number_of_yfile_paths = scalar @yfile ; # Because of path grouping, it is possible to have >1 path to a given # endpoint. We need to have some way of sorting by required path value. # But for now, just print a warning. # print warning if >1 paths to a given endpoint # or if xfile and yfile have different numbers of paths to a given endpoint if ($number_of_xfile_paths > 1 or $number_of_yfile_paths > 1 or $number_of_yfile_paths != $number_of_xfile_paths) { push( @datafile, sprintf("# Warning! xfile paths %d yfile paths %d for endpoint %s\n", $number_of_xfile_paths, $number_of_yfile_paths, $endpoint)) ; next ; } # print the ratios push( @datafile, sprintf("%f\t%f\t%s\n", $xfile[0][0], $yfile[0][0], $endpoint)); $number_of_endpoints++ ; if ($xfile[0][0] < $smallest_xratio) { $smallest_xratio = $xfile[0][0] ; } if ($yfile[0][0] < $smallest_yratio) { $smallest_yratio = $yfile[0][0] ; } } # warn if any xfile endpoints remain for $endpoint (keys %xfile_ratio) { @xfile = @{ $xfile_ratio{$endpoint}} ; @yfile = @{ $yfile_ratio{$endpoint}} ; delete $xfile_ratio{$endpoint} ; delete $yfile_ratio{$endpoint} ; $number_of_xfile_paths = scalar @xfile ; $number_of_yfile_paths = scalar @yfile ; push( @datafile, sprintf("# Warning! xfile paths %d yfile paths %d for endpoint %s\n", $number_of_xfile_paths, $number_of_yfile_paths, $endpoint)) ; } # print a summary unshift( @datafile, sprintf( "# %f is smallest y ratio\n", $smallest_yratio)) ; unshift( @datafile, sprintf( "# %f is smallest x ratio\n", $smallest_xratio)) ; unshift( @datafile, "# $number_of_endpoints endpoints\n" ) ; ########################################################################### ##### print the gnuplot script select STDOUT ; $xmax = 1.0 unless defined($xmax); $ymax = 1.0 unless defined($ymax); if (!defined($xmin)) { $xmin = floor($smallest_xratio) ; if ($xmin > -1.0) { $xmin = -1.0 ; } } if (!defined($ymin)) { $ymin = floor($smallest_yratio) ; if ($ymin > -1.0) { $ymin = -1.0 ; } } $orientation = "portrait" ; if ($xmin < $ymin) { $orientation = "landscape" ; } $xmin = sprintf("%.1f",$xmin) ; $xmax = sprintf("%.1f",$xmax) ; $ymin = sprintf("%.1f",$ymin) ; $ymax = sprintf("%.1f",$ymax) ; ##### first print a header print <