#!/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=>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 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 =head1 SEE ALSO =cut ###################################################################### ### Local Variables: ### compile-command: "./vtree_importer " ### End: