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