my $info1 = grok_file $file1;
my $info2 = grok_file $file2;
MODULE:
while ( my ($module, $nets_href) = each %$info1 )
{
unless ( $info2->{$module} )
{
warn "$file2 has no module $module";
next MODULE;
}
NET:
while ( my ($net, $gates_href) = each %$nets_href )
{
unless ( $info2->{$module}->{$net} )
{
warn "$file2 has no net $module/$net";
next NET;
}
GATE:
while ( my ( $gate, $href1 ) = each %$gates_href )
{
my $href2 = $info2->{$module}->{$net}->{$gate};
unless ( $href2 )
{
warn "$file2 has no gate $module/$net/$gate";
next GATE;
}
diff_gates "$module/$net/$gate", $href1, $href2;
} # GATE
} # NET
} # MODULE
####
sub diff_gates ( $ $ $ )
{
my ( $path, $g1, $g2 ) = @_;
my %all_keys = ( %$g1, %$g2 );
foreach my $key ( sort keys %all_keys )
{
if ( ! exists $g2->{$key} )
{
print "$path: g2 missing $key\n";
}
elsif ( ! exists $g1->{$key} )
{
print "$path: g1 missing $key\n";
}
elsif ( $g1->{$key} ne $g2->{$key} )
{
print "$path: $key diff between g1 and g2\n";
}
}
}
####
sub grok_file ( $ )
{
my ( $fh ) = @_;
$fh ||= \*STDIN;
# somewhere to store all the info:
#
# $info{module}{net}{gate_id}{...} = $value
#
# where "..." can be one of these keys:
#
# type
# cap_max
# cap_net
# cap_viol
# trans_max
# trans_worst
# trans_viol
my %info;
# keep track of the last thing we saw
my $last_module;
my $last_net;
my $last_stat; # cap or trans
my $last_gate_href;
# common regex subexpressions
my $float = qr/[\d.\-]+/; # floating point value
my $ind = qr/ /; # indent
# ok, now the main loop.
while (<$fh>)
{
# remove trailing whitespace
s/\s+\z//;
# new module?
# |Module: gg_PCI_PORT_bc_unit_221 [bc_pci_u3/bc_unit_u46]
if ( /^Module: (.*)$/ )
{
$last_module = $1;
print STDERR "module: $last_module\n";
$info{$last_module} ||= {};
}
# new net?
# | Net: inp_c_1
elsif ( /^ Net: (.*)$/ )
{
$last_net = $1;
print STDERR " net: $last_module / $last_net\n";
$info{$last_module}{$last_net} ||= {};
}
# look for individual gates now
# | Max Capacitance = 0.61 (bc_0:A1 [NAN2D1])
# | Max Transition = 1.50 (bc_3:A2 [NAN2D1])
elsif ( / ^ $ind $ind
Max \s (Capacitance|
Transition) \s+ # what
= \s+ ($float) \s+ # amt
\( (\S+) \s+ # id
\[ ([^\]]+) \] \) # type
$ /x )
{
my ( $what, $amt, $id, $type ) = ( $1, $2, $3, $4 );
print STDERR " gate: $id\n";
$last_stat = $what eq 'Capacitance' ? 'cap'
: 'trans';
my $key = $last_stat . '_max';
$info{$last_module}{$last_net}{$id} ||= {};
$last_gate_href = $info{$last_module}{$last_net}{$id};
$last_gate_href->{$key} = $amt;
$last_gate_href->{type} = $type;
}
# finally, a bunch of other values that apply to
# the most recent gate:
# | Pin Worst Transition = 7.48
# | Net Capacitance = 6.04
# | VIOLATION = -5.98
elsif ( / ^ $ind $ind
(?: ( Pin \s Worst \s Transition ) |
( Net \s Capacitance ) |
VIOLATION ) \s+ = \s+
($float) $ /x )
{
my ( $pin, $net, $amt ) = ( $1, $2, $3 );
my $key = $pin ? 'trans_worst' :
$net ? 'cap_net' :
$last_stat . '_viol';
$last_gate_href->{$key} = $amt;
}
else
{
print STDERR "$0: could not parse line $.: $_\n";
}
}
return \%info;
}