blob: 67bf0a0ce760f97f72aa74815082543fa2bae660 [file] [log] [blame]
#!/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");
}