| #!/usr/bin/perl | |
| use strict; | |
| use Switch; | |
| my $file = $ARGV[$#ARGV-1]; | |
| #my $userfile = $ARGV[$#ARGV]; | |
| if ($ARGV[$#ARGV] eq "-h" || "$#ARGV" eq "-1") { | |
| print "\n\nThe command line syntax for running this script is\n\n"; | |
| print "perl blif2vhd.pl <blif file> \n\n"; | |
| print "Here blif file is the name of your blif file which you want to parse with the .blif extension\n\n"; | |
| print "For example, if you say\n\n"; | |
| print "perl script abc.blif \n\n"; | |
| print "Then the script would parse abc.blif and generate abc.vhd\n"; | |
| } | |
| else { | |
| my $blifString; | |
| die("$file does not .blif extension.\n") unless ($file =~ m/\.blif/); | |
| $file =~ m/(.*?)\.blif/; | |
| my $userfile = $1; | |
| { | |
| print "Parsing $file\n"; | |
| print "Please wait...\n"; | |
| $userfile =~ s/\..*//; | |
| open (OUTFILE, ">$userfile.vhd") || die "Cannot create .vhd :$!"; | |
| open(INFILE, "<$file")|| die "Cannot open blif: $!"; | |
| local $/ = undef ; | |
| $blifString=<INFILE>; | |
| close(INFILE); | |
| } | |
| my @buffer=(); | |
| #$blifString=~ s/(\[)|(\])/x/gm; #get rid of comments and extra lines | |
| $blifString=~ s/([^\w])\[(\d+)\]/$1wire$2/gs; #replace abc berkeley wires | |
| $blifString=~ s/([^\s]+)_+([\s])/$1$2/gs; #replace variables that end in _'s e.g. PKSi_191_ => PKSi_191 | |
| $blifString=~ s/(\w)\.([a-zA-Z])/$1_$2/gs; #replace abc.test with abc_test | |
| $blifString=~ s/([a-zA-Z])\.(\w)/$1_$2/gs; #replace abc.test with abc_test | |
| $blifString=~ s/\[(\d+)\]/xy$1xy/gs; #replace vectors [123] with xy123xy | |
| $blifString=~ s/\<(\d+)\>/yx$1yx/gs; #replace vectors <123> with yx123yx | |
| $blifString=~ s/\*|\$|\//zz/gs; #replace * with zz | |
| $blifString=~ s/\.wire_load_slope 0\.00\s*//gs;#remove .wire_load_slope 0.00 | |
| $blifString=~ s/([a-zA-z]\d+)\.(\d)/$1_$2/gs;#replace x1.2 with x1_2 | |
| #still need to fix headers | |
| $blifString=~ s/\\\s*\n//gm; | |
| $blifString=~ s/[ ]+/ /gm; | |
| my @blifBlocks=split(/\./,$blifString); | |
| shift(@blifBlocks); | |
| my $ending_value = scalar(@blifBlocks) ; | |
| my %primaryVariableHash=(); | |
| my @inputList; | |
| my @outputList; | |
| my @nodeList; | |
| my $circuitName; | |
| # @Array returns a scalar in this context | |
| for(my $counter=0 ; $counter < $ending_value ; $counter++) | |
| { | |
| my @currentLines=split(/\n/,$blifBlocks[$counter]); | |
| my @currentNames=split(/\s/,$currentLines[0]); #split the first line of the block | |
| my $numNames = scalar(@currentNames) ; | |
| switch($currentNames[0]){ | |
| case "inputs" | |
| { | |
| shift(@currentNames); | |
| foreach my $nodeName (@currentNames){ | |
| #$primaryVariableHash{$nodeName}='pin'; | |
| if (not $nodeName eq "") { | |
| push @inputList,$nodeName ; | |
| } | |
| } | |
| } | |
| case "outputs" | |
| { | |
| shift(@currentNames); | |
| foreach my $nodeName (@currentNames){ | |
| $primaryVariableHash{$nodeName}='output'; | |
| if (not $nodeName eq "") { | |
| push @outputList,$nodeName ; | |
| } | |
| } | |
| } | |
| case "names" | |
| { | |
| if(not $primaryVariableHash{$currentNames[$numNames-1]}) | |
| { | |
| #if(not $variableHash{$currentNames[$numNames-1]}){ | |
| push @nodeList,$currentNames[$numNames-1] ; | |
| #} | |
| } | |
| shift(@currentLines); | |
| my $pos; | |
| foreach my $line (@currentLines){ | |
| my @eqn=(); | |
| if($line =~ m/\s1/){ | |
| $line=~s/\s1//; | |
| $pos=1; | |
| }elsif($line =~ m/\s0/){ | |
| $line=~s/\s0//; | |
| $pos=0; | |
| } | |
| else{ | |
| $pos=-1; | |
| } | |
| for(my $NameCounter=1 ; $NameCounter < $numNames-1 ; $NameCounter++){ | |
| if($line=~m/^1/){ #found a 1 | |
| $line=~s/^1(.*)/$1/; | |
| push @eqn," $currentNames[$NameCounter] " ; | |
| } | |
| elsif ($line=~m/^0/){ #found a 0 | |
| $line=~s/^0(.*)/$1/; | |
| push @eqn," (not $currentNames[$NameCounter]) " ; | |
| } | |
| else{ | |
| $line =~ s/-//; | |
| } | |
| } | |
| $line ='(' . join(" and ",@eqn) . ')'; | |
| #if($pos==0){ | |
| # $line="(not $line)"; | |
| #} | |
| } | |
| if(scalar(@currentLines) eq 0){ #prob set eq to logic low | |
| push (@buffer, "$currentNames[$numNames-1] <=((not ". $inputList[0].") and ". $inputList[0].");\n"); | |
| }elsif($pos==-1){ | |
| push (@buffer, "$currentNames[$numNames-1] <=((not ". $inputList[0].") or ". $inputList[0].");\n"); | |
| }elsif($pos==0){ | |
| push (@buffer, "$currentNames[$numNames-1] <=(not(". join(" or \n",@currentLines) . "));\n"); | |
| }else{ | |
| push (@buffer, "$currentNames[$numNames-1] <=". join(" or \n",@currentLines) . ";\n"); | |
| } | |
| } | |
| case "latch" | |
| { | |
| my $input = $currentNames[1]; | |
| my $output = $currentNames[2]; | |
| if(not $primaryVariableHash{$output}) #is it an output | |
| { | |
| push (@nodeList,$output) ; | |
| } | |
| my $init_value; | |
| die("Not supported latch format:".$currentLines[0]) unless (($numNames eq 6) or # | |
| ($numNames eq 5) or | |
| ($numNames eq 4) or | |
| ($numNames eq 3) ); | |
| if( ($numNames - 3) % 2 ) # 1 or 3 arguments => has init value | |
| { | |
| $init_value = $currentNames[$numNames-1]; | |
| die("Don't know how to initialize HVDL without a reset signal (unkown reset value=".$init_value.")") unless (($init_value eq 2) or #don't care | |
| ($init_value eq 3)or #unkown | |
| ($init_value eq 0)); #unkown | |
| } | |
| push @buffer, "process($input"; | |
| my $type =""; | |
| my %types; | |
| if( ($numNames - 3) >= 2 ) # more than 2 arguments => has has type and control | |
| { | |
| my $clock = $currentNames[4]; | |
| if(not $clock eq "NIL") | |
| { | |
| push (@buffer, ",$clock"); | |
| } | |
| $types{"re"}="rising_edge($clock)"; | |
| $types{"fe"}="falling_edge($clock)"; | |
| $types{"ah"}="$clock='1'"; | |
| $types{"al"}="$clock='0'"; | |
| $types{"as"}=$input."'event"; | |
| $type = $currentNames[3]; | |
| die("Type not define:$type") if(not $types{$type}); | |
| } | |
| push @buffer, ")\nbegin\n"; | |
| if(not $type eq "") | |
| { | |
| push (@buffer, "\tif($types{$type}) then\n\t\t$output <= $input;\n\tend if;\n"); | |
| } | |
| else | |
| { | |
| push (@buffer, "\t$output <= $input;\n"); | |
| } | |
| push (@buffer, "end process;\n"); | |
| } | |
| case "end" | |
| { | |
| #do nothing; | |
| } | |
| case "model" | |
| { | |
| $circuitName=$currentNames[1]; | |
| } | |
| case "clock" | |
| { | |
| push (@inputList,$currentNames[1]) ; | |
| } | |
| else | |
| { | |
| die("Cannot handle to following directive: ".$currentNames[0]); | |
| } | |
| }#end switch | |
| } | |
| print OUTFILE | |
| "---Output from blif2vhdl.pl (written by Kirill Minkovich - cory_m\@cs.ucla.edu)\n", | |
| "---From model $circuitName\n", | |
| "Library IEEE;\n", | |
| "\tuse IEEE.std_logic_1164.all;\n", | |
| "entity $userfile is\n", | |
| "\tPort (\n", | |
| "\t",join(",",@inputList), ": in std_logic;\n", | |
| "\t",join(",",@outputList), ": buffer std_logic\n", | |
| ");\n", | |
| "end $userfile;\n\n", | |
| "architecture $userfile\_behav of $userfile is\n", | |
| "signal ",join(",",@nodeList), ": std_logic;\n", | |
| "begin\n\n", | |
| "@buffer\n\nend $userfile\_behav;\n"; | |
| close(OUTFILE); | |
| print("Done\n"); | |
| } |