mirror of
https://github.com/verilator/verilator.git
synced 2025-01-06 06:37:45 +00:00
350 lines
12 KiB
Perl
Executable File
350 lines
12 KiB
Perl
Executable File
#!/usr/bin/perl -w
|
|
# See copyright, etc in below POD section.
|
|
######################################################################
|
|
|
|
require 5.006_001;
|
|
use Getopt::Long;
|
|
use IO::File;
|
|
use Pod::Usage;
|
|
use Data::Dumper; $Data::Dumper::Indent=1;
|
|
use strict;
|
|
use vars qw($Debug);
|
|
|
|
#======================================================================
|
|
|
|
our $Tree;
|
|
our %OpMap;
|
|
gentree();
|
|
|
|
#======================================================================
|
|
# main
|
|
|
|
$Debug = 0;
|
|
my $opt_filename;
|
|
autoflush STDOUT 1;
|
|
autoflush STDERR 1;
|
|
if (! GetOptions(
|
|
"help" => \&usage,
|
|
"debug" => \&debug,
|
|
"<>" => \¶meter,
|
|
)) {
|
|
usage();
|
|
}
|
|
|
|
vread($opt_filename);
|
|
#print Dumper($Tree);
|
|
vwrite();
|
|
|
|
print '(query-replace-regexp "(\\([0-9a-z_]+\\))" "\\1" nil nil nil)',"\n";
|
|
|
|
#----------------------------------------------------------------------
|
|
|
|
sub usage {
|
|
pod2usage(-verbose=>2, -exitval=>2, -output=>\*STDOUT);
|
|
exit(1);
|
|
}
|
|
|
|
sub debug {
|
|
$Debug = 1;
|
|
}
|
|
|
|
sub parameter {
|
|
my $param = shift;
|
|
if (!$opt_filename) {
|
|
$opt_filename = $param;
|
|
} else {
|
|
die "%Error: Unknown parameter: $param\n";
|
|
}
|
|
}
|
|
|
|
#######################################################################
|
|
|
|
sub vread {
|
|
my $filename = shift;
|
|
my $fh = IO::File->new($filename) or die "%Error: $! $filename,";
|
|
my $lasthier="";
|
|
$Tree = {
|
|
op => 'NETLIST',
|
|
t => [[],[],[],[],[],],
|
|
};
|
|
my @stack;
|
|
$stack[1] = $Tree;
|
|
while (defined (my $line = $fh->getline)) {
|
|
if ($line =~ /^\s+(\S+):\s+(\S+)\s+0x\S+\s+{(\d+)}\s+w(\d+)\s+(.*)$/) {
|
|
my $hier = $1;
|
|
my $op = $2;
|
|
my $lineno = $3;
|
|
my $width = $4;
|
|
my $etc = $5;
|
|
|
|
$etc =~ s/__DOT__/./g;
|
|
$etc =~ s/__PVT__//g;
|
|
|
|
my $self = {
|
|
op => $op,
|
|
#width => $width,
|
|
#lineno => $lineno,
|
|
#line => $line,
|
|
etc => $etc,
|
|
args => [split(/[ \t]+/,$etc)],
|
|
t => [[],[],[],[],[],],
|
|
};
|
|
|
|
my @hiers = (1,split(/:/,$hier));
|
|
my $depth = $#hiers+1;
|
|
my $newchild = $hiers[$#hiers];
|
|
|
|
#print "DD $depth $newchild $op\n";
|
|
|
|
push @{$stack[$depth-1]->{t}[$newchild]}, $self;
|
|
$stack[$depth] = $self;
|
|
|
|
$lasthier = $hier;
|
|
#print " $lasthier\n";
|
|
#print Dumper($Tree);
|
|
}
|
|
}
|
|
}
|
|
|
|
######################################################################
|
|
|
|
our $Indent = 0;
|
|
use vars qw($Code_Self);
|
|
use vars qw($Avoid_Hex);
|
|
|
|
sub vwrite {
|
|
$Indent = 0;
|
|
print vwrite_rec($Tree);
|
|
}
|
|
|
|
sub vwrite_rec {
|
|
my $self = shift;
|
|
#print "/*$self->{op}*/";
|
|
my $code = $OpMap{$self->{op}} or die "%Error: No map for $self->{op},";
|
|
local $Code_Self = $self;
|
|
#print Dumper($self->{t}[3]),"\n";
|
|
&$code;
|
|
}
|
|
|
|
######################################################################
|
|
# Tree functions
|
|
|
|
sub p { print join("",@_); }
|
|
|
|
sub exists1 { return defined $Code_Self->{t}[1][0]; }
|
|
sub exists2 { return defined $Code_Self->{t}[2][0]; }
|
|
sub exists3 { return defined $Code_Self->{t}[3][0]; }
|
|
sub exists4 { return defined $Code_Self->{t}[4][0]; }
|
|
sub exists5 { return defined $Code_Self->{t}[5][0]; }
|
|
|
|
sub t1 { foreach my $r (@{$Code_Self->{t}[1]}) { vwrite_rec($r); } }
|
|
sub t2 { foreach my $r (@{$Code_Self->{t}[2]}) { vwrite_rec($r); } }
|
|
sub t3 { foreach my $r (@{$Code_Self->{t}[3]}) { vwrite_rec($r); } }
|
|
sub t4 { foreach my $r (@{$Code_Self->{t}[4]}) { vwrite_rec($r); } }
|
|
sub t5 { foreach my $r (@{$Code_Self->{t}[5]}) { vwrite_rec($r); } }
|
|
sub p1 { p "("; t1; p ")";}
|
|
sub p2 { p "("; t2; p ")";}
|
|
sub p3 { p "("; t3; p ")";}
|
|
sub p4 { p "("; t4; p ")";}
|
|
sub p5 { p "("; t5; p ")";}
|
|
sub a1 { p $Code_Self->{args}[0]; }
|
|
sub a2 { p $Code_Self->{args}[1]; }
|
|
sub a3 { p $Code_Self->{args}[2]; }
|
|
sub a4 { p $Code_Self->{args}[3]; }
|
|
sub a5 { p $Code_Self->{args}[4]; }
|
|
sub a6 { p $Code_Self->{args}[5]; }
|
|
sub a7 { p $Code_Self->{args}[6]; }
|
|
|
|
sub indentInc { $Indent+=2; }
|
|
sub indentDec { $Indent-=2; }
|
|
sub nl { p "\n"," "x$Indent; }
|
|
|
|
######################################################################
|
|
|
|
# nl is a newline
|
|
# p# indicates to add parens
|
|
# t# indicates tree reference
|
|
# a# indicates info from dump where n1 is the width.
|
|
|
|
sub gentree {
|
|
%OpMap = (
|
|
'NULLNODE' => sub { "" },
|
|
'NETLIST' => sub { nl;t1;t2;t3;t4;t5; },
|
|
'ACTIVE' => sub { p "always_act @(";t1;p ") begin";indentInc;nl;t2;t3;t4;t5;indentDec;p "end";nl; },
|
|
'ADD' => sub { p1;p " + ";p2; },
|
|
'ALWAYS' => sub { p "always @(";t1;p ") begin";indentInc;nl;t2;t3;t4;t5;indentDec;p "end";nl; },
|
|
'ALWAYSPOST' => sub { p "ALWAYSPOST what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
|
'AND' => sub { p1;p " & ";p2; },
|
|
'ARRAYSEL' => sub { t1;p "[";t2;p "]"; },
|
|
'ASSIGN' => sub { t2;p " = ";t1;p ";";nl; },
|
|
'ASSIGNDLY' => sub { t2;p " <= ";t1;p ";";nl; },
|
|
'ASSIGNPOST' => sub { p "ASSIGNPOST what{";t1;p " = ";t2;p ";";nl; },
|
|
'ASSIGNPRE' => sub { p "ASSIGNPRE what{";t1;p " = ";t2;p ";";nl; },
|
|
'ASSIGNW' => sub { p "assign ";t2;p " = ";t1;p ";";nl; },
|
|
'ATTROF' => sub { p "ATTROF what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
|
'BEGIN' => sub { p "begin";indentInc;nl;t1;t2;t3;t4;t5;indentDec;p "end";nl; },
|
|
'BITSEL' => sub { t1;local $Avoid_Hex=1; p "[";t2;p "]"; },
|
|
'CASE' => sub { p "CASE what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
|
'CASEITEM' => sub { p "CASEITEM what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
|
'CAST' => sub { p "CAST what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
|
'CCALL' => sub { p "CCALL what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
|
'CELL' => sub { a1;p " ";a7;p " (/*CELL*/);"; nl; },
|
|
'CFUNC' => sub { p "CFUNC what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
|
'CHANGEDET' => sub { p "CHANGEDET what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
|
'CINCLUDE' => sub { p "CINCLUDE what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
|
'COMMENT' => sub { p "//COMMENT what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl;nl; },
|
|
'CONCAT' => sub { p "{";p1;p ",";p2;p "}"; },
|
|
'CONDITIONAL' => sub { p1;p " ? ";p2;p " : ";p3; },
|
|
'CONST' => sub { p_const(); },
|
|
'COVER' => sub { p "COVER what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
|
'CRETURN' => sub { p "CRETURN what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
|
'CSTMT' => sub { p "CSTMT what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
|
'DEFPARAM' => sub { p "defparam ";p1;p " = ";p2;p ";";nl; },
|
|
'DISPLAY' => sub { p '$write("';p1;p "\",";p2;p3;p4;p5;p ");";nl; },
|
|
'DIV' => sub { p1;p " / ";p2; },
|
|
'EQ' => sub { p1;p " == ";p2; },
|
|
'EQCASE' => sub { p1;p " === ";p2; },
|
|
'EXTEND' => sub { t1; },
|
|
'EXTRACT' => sub { t1;local $Avoid_Hex=1; p "[";t2;p ":";t3;p "]"; },
|
|
'FINISH' => sub { p '$finish;';nl },
|
|
'FOR' => sub { p "for (";p1;p ",";p2;p ",";p3;p ") begin";indentInc;nl;p4;p5;indentDec;p "end";nl; },
|
|
'FUNC' => sub { p "FUNC what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
|
'FUNCREF' => sub { p "FUNCREF what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
|
'GT' => sub { p1;p " > ";p2; },
|
|
'GTE' => sub { p1;p " >= ";p2; },
|
|
'IF' => sub { p "if (";p1;p ") begin";indentInc;nl;t2;indentDec;if (exists3) {p "end else begin";indentInc;nl;t3;indentDec;} p "end"; nl; },
|
|
'INITARRAY' => sub { p "INITARRAY what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
|
'INITIAL' => sub { p "initial begin";indentInc;nl;t1;t2;t3;t4;t5;indentDec;p "end";nl; },
|
|
'LOGAND' => sub { p1;p " && ";p2; },
|
|
'LOGNOT' => sub { p1;p " || ";p2; },
|
|
'LOGOR' => sub { p "!";p1; },
|
|
'LT' => sub { p1;p " < ";p2; },
|
|
'LTE' => sub { p1;p " <= ";p2; },
|
|
'MODDIV' => sub { p1;p " % ";p2; },
|
|
'MODULE' => sub { p "module ";a1;p " (/*AUTOARG*/);";indentInc;nl;t1;t2;t3;t4;t5;indentDec;nl;p "endmodule";nl; },
|
|
'MUL' => sub { p1;p " * ";p2; },
|
|
'NEQ' => sub { p1;p " != ";p2; },
|
|
'NEQCASE' => sub { p1;p " !== ";p2; },
|
|
'NOT' => sub { p " ~";p1; },
|
|
'OR' => sub { p1;p " | ";p2; },
|
|
'PIN' => sub { p ";p ";p1;p " (";p2;p "),";nl; },
|
|
'PORT' => sub { p ""; },
|
|
'PRAGMA' => sub { p "PRAGMA what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
|
'RAND' => sub { p '$rand'; },
|
|
'RANGE' => sub { t1; local $Avoid_Hex=1; p "[";t2;p ":";t3;p "]"; },
|
|
'REDAND' => sub { p "&(";p1;p ")"; },
|
|
'REDOR' => sub { p "|(";p1;p ")"; },
|
|
'REDXNOR' => sub { p "~|(";p1;p ")"; },
|
|
'REDXOR' => sub { p "~^(";p1;p ")"; },
|
|
'REPLICATE' => sub { p "{";p1;p "{";p2;p "}}"; },
|
|
'SCCTOR' => sub { p "SCCTOR what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
|
'SCHDR' => sub { p "SCHDR what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
|
'SCIMP' => sub { p "SCIMP what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
|
'SCINT' => sub { p "SCINT what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
|
'SCOPE' => sub { t1;t2;t3;t4;t5; },
|
|
'SENITEM' => sub { a1;p " ";t1; },
|
|
'SENTREE' => sub { t1;t2;t3;t4;t5; },
|
|
'SHIFTL' => sub { p1;p " << ";p2; },
|
|
'SHIFTR' => sub { p1;p " >> ";p2; },
|
|
'STOP' => sub { p '$stop;';nl; },
|
|
'SUB' => sub { p1;p " - ";p2; },
|
|
'TASK' => sub { p "TASK what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
|
'TASKREF' => sub { p "TASKREF what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
|
'TEXT' => sub { p "TEXT what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
|
'TIME' => sub { p '$time'; },
|
|
'TOPSCOPE' => sub { t1;t2;t3;t4;t5; },
|
|
'TRACE' => sub { p "TRACE what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
|
'UCFUNC' => sub { p '$c(';p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p ")"; },
|
|
'UCSTMT' => sub { p '$c(';p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p ");";nl; },
|
|
'NEGATE' => sub { p " -";p1; },
|
|
'VAR' => sub { p_var(); },
|
|
'VARPIN' => sub { p "VARPIN what{";p1;p ",";p2;p ",";p3;p ",";p4;p ",";p5;p "}";nl; },
|
|
'VARREF' => sub { a1; },
|
|
'VARSCOPE' => sub { },
|
|
'WHILE' => sub { t1; p "while (";t2;p ") begin";indentInc;nl;t3;t4;indentDec;p "end";nl; },
|
|
'WORDSEL' => sub { p1;p "[";p2;p ":";p3;p "]"; },
|
|
'XNOR' => sub { p1;p " ~^ ";p2; },
|
|
'XOR' => sub { p1;p " ^";p2; },
|
|
);
|
|
}
|
|
|
|
sub p_var {
|
|
my $self = $Code_Self;
|
|
if ($self->{etc} =~ /\[I\]/) {
|
|
print "input";
|
|
} elsif ($self->{etc} =~ /\[O\]/) {
|
|
print "output";
|
|
} else {
|
|
print "reg";
|
|
}
|
|
p "\t";
|
|
{
|
|
local $Avoid_Hex=1;
|
|
t1;
|
|
}
|
|
p "\t";
|
|
a1;
|
|
if (exists2()) {
|
|
p " = ";
|
|
t2;
|
|
}
|
|
p ";";
|
|
nl;
|
|
}
|
|
|
|
sub p_const {
|
|
my $v = $Code_Self->{args}[0];
|
|
if ($v =~ /\?32\?h(.*)$/
|
|
|| ($Avoid_Hex && $v =~ /^[0-9?]*h(.*)$/)) {
|
|
print hex $1;
|
|
} else {
|
|
print $v;
|
|
}
|
|
}
|
|
|
|
#######################################################################
|
|
__END__
|
|
|
|
=pod
|
|
|
|
=head1 NAME
|
|
|
|
vtree_importer -
|
|
|
|
=head1 SYNOPSIS
|
|
|
|
vtree_importer *.log
|
|
|
|
=head1 DESCRIPTION
|
|
|
|
dd
|
|
|
|
=head1 ARGUMENTS
|
|
|
|
=over 4
|
|
|
|
=item --help
|
|
|
|
Displays this message and program version and exits.
|
|
|
|
=back
|
|
|
|
=head1 DISTRIBUTION
|
|
|
|
Copyright 2005-2019 by Wilson Snyder. Verilator 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.
|
|
|
|
=head1 AUTHORS
|
|
|
|
Wilson Snyder <wsnyder@wsnyder.org>
|
|
|
|
=head1 SEE ALSO
|
|
|
|
=cut
|
|
|
|
######################################################################
|
|
### Local Variables:
|
|
### compile-command: "./vtree_importer "
|
|
### End:
|