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; }