verilator/nodist/dot_pruner
2020-03-21 11:24:24 -04:00

206 lines
4.3 KiB
Perl
Executable File

#!/usr/bin/env perl
# See copyright, etc in below POD section.
######################################################################
use warnings;
use Getopt::Long;
use IO::File;
use Pod::Usage;
use Data::Dumper; $Data::Dumper::Indent=1;
use strict;
use vars qw($Debug);
#======================================================================
our @Header;
our %Vertexes;
our %Edges;
our %User;
our %User2;
#======================================================================
# main
$Debug = 0;
my $opt_filename;
my $opt_circle;
autoflush STDOUT 1;
autoflush STDERR 1;
if (! GetOptions(
"help" => \&usage,
"debug" => \&debug,
"<>" => \&parameter,
"circle=s" => \$opt_circle,
)) {
usage();
}
dotread($opt_filename);
circle($opt_circle) if $opt_circle;
simplify();
dotwrite();
#----------------------------------------------------------------------
sub usage {
pod2usage(-verbose=>2, -exitval=>0, -output=>\*STDOUT);
exit(1); # Unreachable
}
sub debug {
$Debug = 1;
}
sub parameter {
my $param = shift;
if (!$opt_filename) {
$opt_filename = $param;
} else {
die "%Error: Unknown parameter: $param\n";
}
}
#######################################################################
sub dotread {
my $filename = shift;
my $fh = IO::File->new($filename) or die "%Error: $! $filename,";
my $header = 1;
while (defined (my $line = $fh->getline)) {
if ($line =~ /^\t([a-zA-Z0-9_]+)\t(.*)$/) {
$header = 0;
$Vertexes{$1} = $2;
}
elsif ($line =~ /^\t([a-zA-Z0-9_]+)\s+->\s+([a-zA-Z0-9_]+)\s+(.*)$/) {
$Edges{$1}{$2} = $3;
}
elsif ($header) {
push @Header, $line;
}
}
}
######################################################################
sub simplify {
foreach my $ver (sort (keys %Vertexes)) {
$Vertexes{$ver} = _simplify($Vertexes{$ver});
}
foreach my $v1 (sort (keys %Edges)) {
foreach my $v2 (sort (keys %{$Edges{$v1}})) {
$Edges{$v1}{$v2} = _simplify($Edges{$v1}{$v2});
}
}
}
sub _simplify {
my $text = shift;
$text =~ s/__DOT__/./g;
return $text;
}
sub dotwrite {
foreach my $line (@Header) {
print "$line";
}
foreach my $ver (sort (keys %Vertexes)) {
print "\t$ver\t$Vertexes{$ver}\n";
}
foreach my $v1 (sort (keys %Edges)) {
foreach my $v2 (sort (keys %{$Edges{$v1}})) {
print "\t$v1 -> $v2\t$Edges{$v1}{$v2}\n";
}
}
print "}\n";
}
######################################################################
sub circle {
my $node = shift;
%User = ();
%User2 = ();
_circle_recurse($node, 1);
foreach my $ver (keys %Vertexes) {
if (!$User{$ver}) {
delete $Vertexes{$ver};
delete $Edges{$ver};
}
}
foreach my $v1 (sort (keys %Edges)) {
foreach my $v2 (sort (keys %{$Edges{$v1}})) {
if (!$Vertexes{$v2}) { delete $Edges{$v1}{$v2}; }
}
}
}
sub _circle_recurse {
my $node = $_[0];
my $level = $_[1];
$Vertexes{$node} or warn "%Warning: Can't find ref node $node\n";
$User{$node} = 1 if (($User2{$node}||0)==1);
return $User{$node} if $User2{$node};
$User2{$node} = 1;
my $r = 0;
foreach my $v2 (keys %{$Edges{$node}}) {
$r |= _circle_recurse($v2,$level++)||0;
}
$User{$node} = 1 if $r;
$User2{$node} = 2;
return $r;
}
#######################################################################
__END__
=pod
=head1 NAME
dot_pruner -
=head1 SYNOPSIS
dot_pruner *.log
=head1 DESCRIPTION
dd
=head1 ARGUMENTS
=over 4
=item --help
Displays this message and program version and exits.
=back
=head1 DISTRIBUTION
Copyright 2005-2020 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 Version 3 or the Perl Artistic License
Version 2.0.
SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
=head1 AUTHORS
Wilson Snyder <wsnyder@wsnyder.org>
=head1 SEE ALSO
=cut
######################################################################
### Local Variables:
### compile-command: "./dot_pruner | tee ~/d/a.dot"
### End: