| XNF To VHDL Script
Go To Script Pool |
|
| # This perl script takes an XNF netlist and
returns a VHDL architecture # containing a series of continuous assignments and clocked-register # instantiations that implement the same function specified in the # XNF netlist. This tool is useful when you're not sure whether # Xilinx spit out the correct synthesis result, and you want to # simulate the resulting code against your VHDL behavioral code. # ################################################ # Open the XVF file. Hey Rex! Make this a bit more # pleasant, OK? $xnffilename = $ARGV[0]; $hackfilename = $ARGV[1]; # ################################################ # Read in all signals and figure out which are internal and which # are external. Build signal definitions for all internal signals. &BuildSignalList($xnffilename); # Print the architecture header $archfilename = $xnffilename; $archfilename =~ s/\.xnf/_netlist.vhd/; open(ARCHFILE,"> ".$archfilename); &PrintHeader($archfilename); &PrintSignals(); &HackSignals($hackfilename); &PrintNetlist($xnffilename); &PrintAliases($xnffilename); &HackNetlist($hackfilename); &PrintTrailer($archfilename); # ################################################# # Clean up after yourself... # ################################################# # Some useful subroutines sub BuildSignalList { local($xnffilename) = @_; open(XNFFILE,$xnffilename); while($theline = <XNFFILE>) { # If the line has a PIN declaration, go to work if(($theline =~ /^PIN/) && !($theline =~ /\$\$/)) { # For each PIN declaration, split to find the name ($type, $formal, $direction, $name) = split(/,/,$theline); # Remove spaces and newlines and $ signs $name =~ s/[ \n]+//g; # If the name has a < in it, it's a bus of some sort if($name =~ /\</) { # Split the name out from the bit indicator ($name,$size) = split(/</,$name); # Hack the > off the end of the bit indicator $size =~ s/>//; # Add 1 to it, because we want the number of pins $size = $size + 1; # Check to see if the name is in the assiociative array if($namearray{$name} eq "") { # If not, put it there with the current size estimate $namearray{$name} = $size; } else { # If it's already in, check to see if the new pin # uses a larger bit indicator than the currently # stored one. if($namearray{$name} < $size) { # If this is a higher pin number, put that in # the associative array as the new size estimate $namearray{$name} = $size; } } } else { # For single-bit buses, set the associative array entry # to 1. if($namearray{$name} eq "") { $namearray{$name} = 1; } } } # If the line contains a SYM declaration with a BOUNDS # directive, use the bounds to set the highest bit number for the # bus. if($theline =~ /^SYM/) { if($theline =~ /BUS_DEF/) { # Find the name and the bounds directive in the line ($type, $name, $blocktype, $def, $bounds) = split(/,/,$theline); # Clean up the name $name =~ s/[ \n]+//g; # Clean up the bounds directive and find the upper and lower $bounds =~ s/[\=a-zA-Z]+//g; ($left, $right) = split(/:/,$bounds); if($left > $right) { $aliasarray{$name} = $left + 1; } else { $aliasarray{$name} = $right + 1; } } } # If the line contains an EXT declaration, store it in # the EXT array, with size. if($theline =~ /^EXT/) { # For each EXT declaration, split to find the name ($type, $name, $direction) = split(/,/,$theline); # Remove spaces and newlines $name =~ s/[ \n]+//g; # If the name has a < in it, it's a bus of some sort if($name =~ /\</) { # Split the name out from the bit indicator ($name,$size) = split(/</,$name); # Hack the > off the end of the bit indicator $size =~ s/>//; # Add 1 to it, because we want the number of pins $size = $size + 1; # Check to see if the name is in the assiociative array if($extarray{$name} eq "") { # If not, put it there with the current size estimate $extarray{$name} = $size; } else { # If it's already in, check to see if the new pin # uses a larger bit indicator than the currently # stored one. if($extarray{$name} < $size) { # If this is a higher pin number, put that in # the associative array as the new size estimate $extarray{$name} = $size; } } } else { # For single-bit buses, set the associative array entry # to 1. $extarray{$name} = 1; } } } # foreach $name (sort(keys(%namearray))) { # if($extarray{$name} eq "") { # printf("PIN: %s\t%d\n",$name,$namearray{$name}); # } # } # foreach $name (sort(keys(%extarray))) { # printf("EXT: %s\t%d\n",$name,$extarray{$name}); # } close(XNFFILE); } sub PrintHeader { local($archfilename) = @_; ($entname, $archname) = split(/_/,$archfilename); $archname =~ s/\.vhd//; printf(ARCHFILE "library lib;\n"); printf(ARCHFILE "use ieee.std_logic_arith.all;\n"); printf(ARCHFILE "\n"); printf(ARCHFILE "architecture %s of %s is\n",$archname,$entname); printf(ARCHFILE "\n"); } sub PrintSignals { foreach $signal (sort(keys(%namearray))) { if(($extarray{$signal} eq "") && ($aliasarray{$signal} eq "")) { if($namearray{$signal} == 1) { printf(ARCHFILE "signal %s:std_logic;\n",$signal); } else { printf(ARCHFILE "signal %s:std_logic_vector(%d downto %d);\n", $signal, $namearray{$signal}-1, 0); } } } foreach $signal (sort(keys(%aliasarray))) { if($aliasarray{$signal} ne "") { printf(ARCHFILE "signal %s:std_logic_vector(%d downto %d);\n", $signal, $aliasarray{$signal}-1, 0); } } } sub PrintAliases { local($xnffilename) = @_; # Start building the list signals for each alias we'll need. foreach $signal (sort(keys(%aliasarray))) { $aliaselement{$signal} = ""; } open(XNFFILE,$xnffilename); # For each SYM block found in the file, convert it into a corresponding # function. while($theline = <XNFFILE>) { # Look for a symbol instantiation if($theline =~ /^SYM/) { ($sym, $name, $type) = split(/,/,$theline); $type =~ s/[ \n]+//g; if($type eq "ELEMENT") { &AddElement($theline); } } } # Start building the list signals for each alias we'll need. foreach $signal (sort(keys(%aliasarray))) { &PrintAlias($signal); } close(XNFFILE); } sub PrintNetlist { local($xnffilename) = @_; printf(ARCHFILE "\nbegin\n"); printf(ARCHFILE " VCC <= '1';\n"); printf(ARCHFILE " GND <= '0';\n"); open(XNFFILE,$xnffilename); # For each SYM block found in the file, convert it into a corresponding # function. while($theline = <XNFFILE>) { # Look for a symbol instantiation if($theline =~ /^SYM/) { ($sym, $name, $type) = split(/,/,$theline); $type =~ s/[ \n]+//g; if($type eq "AND") { &PrintGATE($theline,"and"); } if($type eq "OR") { &PrintGATE($theline,"or"); } if($type eq "BUFGP") { &PrintBUF($theline,""); } if($type eq "INV") { &PrintBUF($theline,"not"); } if($type eq "OBUF") { &PrintBUF($theline,""); } if($type eq "IBUF") { &PrintBUF($theline,""); } if($type eq "OBUFT") { &PrintOBUFT($theline); } if($type eq "DFF") { &PrintDFF($theline,0); } if($type eq "OUTFFT") { &PrintDFF($theline,1); } if($type eq "ADD_SUB") { &PrintADDSUB($theline); } if($type eq "COMPARE") { &PrintCOMPARE($theline); } } } close(XNFFILE); } sub PrintGATE { local($theline,$optype) = @_; local(%inputarray,$output); $done = 0; %inputarray = (); while(!$done) { $theline = <XNFFILE>; $theline =~ s/[ \n]+//g; if($theline =~ /END/) { $done = 1; } else { $invert = "NORM"; ($pin, $formal, $direction, $name,$blank,$invert) = split(/,/,$theli ne); $name = &FixName($name); if($direction eq "I") { if($invert eq "INV") { $inputarray{$name} = -1; } else { $inputarray{$name} = 1; } } else { $output = $name; } } } printf(ARCHFILE " %s <=",$output); $firstprinted = 0; foreach $input (sort(keys(%inputarray))) { if($firstprinted) { printf(ARCHFILE " and"); } else { $firstprinted = 1; } if($inputarray{$input} == -1) { printf(ARCHFILE " not"); } printf(ARCHFILE " %s",$input); } printf(ARCHFILE ";\n"); } sub PrintBUF { local($theline,$optype) = @_; local($input,$output); $done = 0; while(!$done) { $theline = <XNFFILE>; $theline =~ s/[ \n]+//g; if($theline =~ /END/) { $done = 1; } else { ($pin, $formal, $direction, $name) = split(/,/,$theline); $name = &FixName($name); if($direction eq "I") { $input = $name; } else { $output = $name; } } } printf(ARCHFILE " %s <=",$output); printf(ARCHFILE " %s",$optype); printf(ARCHFILE " %s",$input); printf(ARCHFILE ";\n"); } sub PrintOBUFT { local($theline) = @_; local($input,$output,$tristate); $done = 0; while(!$done) { $theline = <XNFFILE>; $theline =~ s/[ \n]+//g; if($theline =~ /END/) { $done = 1; } else { ($pin, $formal, $direction, $name) = split(/,/,$theline); $name = &FixName($name); if($formal eq "I") { $input = $name; } if($formal eq "O") { $output = $name; } if($formal eq "T") { $tristate = $name; } } } printf(ARCHFILE " %s <= %s when %s = '0' else 'Z'",$output,$input,$tristate ); printf(ARCHFILE ";\n"); } sub PrintDFF { local($theline,$tristateable) = @_; local($input,$output,$clock,$tristate); $done = 0; while(!$done) { $theline = <XNFFILE>; $theline =~ s/[ \n]+//g; if($theline =~ /END/) { $done = 1; } else { ($pin, $formal, $direction, $name) = split(/,/,$theline); $name = &FixName($name); if($formal eq "D") { $input = $name; } if(($formal eq "Q") || ($formal eq "O")) { $output = $name; } if($formal eq "C") { $clock = $name; } if($formal eq "T") { $tristate = $name; } } } printf(ARCHFILE "process begin\n"); printf(ARCHFILE " wait until %s'event and %s = '1';\n",$clock,$clock); if($tristateable) { printf(ARCHFILE " if(%s = '0') then %s <= %s; else %s <= 'Z'; end if;\n ", $tristate, $output, $input, $output); } else { printf(ARCHFILE " %s <= %s;\n",$output,$input); } printf(ARCHFILE "end process;\n"); } sub PrintADDSUB { local($theline) = @_; local($inputa,$inputb,$output); $done = 0; while(!$done) { $theline = <XNFFILE>; $theline =~ s/[ \n]+//g; if($theline =~ /END/) { $done = 1; } else { ($pin, $formal, $direction, $name) = split(/,/,$theline); $name = &FixName($name); if($formal eq "A") { $inputa = $name; } if($formal eq "B") { $inputb = $name; } if($formal eq "FUNC") { $output = $name; } } } printf(ARCHFILE " %s <= %s + %s;\n",$output,$inputa,$inputb); } sub PrintCOMPARE { local($theline) = @_; local($inputa,$inputb,$output); $done = 0; while(!$done) { $theline = <XNFFILE>; $theline =~ s/[ \n]+//g; if($theline =~ /END/) { $done = 1; } else { ($pin, $formal, $direction, $name) = split(/,/,$theline); $name = &FixName($name); if($formal eq "A") { $inputa = $name; } if($formal eq "B") { $inputb = $name; } if($formal eq "A_EQ_B") { $output = $name; } } } printf(ARCHFILE " %s <= '1' when (%s = %s) else '0';\n",$output,$inputa,$in putb); } sub AddElement { local($theline) = @_; local($busname,$signame); $done = 0; # Extract the element number from the first line ($sym, $name, $type, $def, $elemnum) = split(/,/,$theline); $elemnum =~ s/[ =ELEM]+//g; # Find the bus name and the individual signal name while(!$done) { $theline = <XNFFILE>; $theline =~ s/[ \n]+//g; if($theline =~ /END/) { $done = 1; } else { ($pin, $formal, $direction, $name) = split(/,/,$theline); $name = &FixName($name); if($formal eq "XBLOX_BUS") { $busname = $name; } if($formal eq "ELEM") { $signame = $name; } } } # If the signal name is just the bus-ripped version of the bus name, # clear the list. It will be deleted and no alias will be constructed. # If the signal name is different, add it to the list. if($signame =~ /\(/) { $aliaselement{$busname} = ""; } else { $aliaselement{$busname} = $aliaselement{$busname} . $signame . "," . $elemnum . ":"; } } sub PrintAlias { local($signal) = @_; local($busname,$signame); $elementlist = $aliaselement{$signal}; if($elementlist ne "") { @elementarray = split(/:/,$elementlist); @sortedelement = (); for($i=0; $i<=$#elementarray; $i=$i+1) { ($element,$elemnum) = split(/,/,$elementarray[$i]); $sortedelement[$elemnum] = $element; } printf(ARCHFILE " %s <= (",$signal,$aliasarray{$signal}); for($i=$#sortedelement; $i>=1; $i=$i-1) { printf(ARCHFILE "%s & ",$sortedelement[$i]); } printf(ARCHFILE "%s);\n",$sortedelement[0]); } } sub FixName { local($name) = @_; $name =~ s/\</\(/; $name =~ s/\>/\)/; $name =~ s/\$+//; return $name; } sub PrintTrailer { local($archfilename) = @_; ($entname, $archname) = split(/_/,$archfilename); $archname =~ s/\.vhd//; printf(ARCHFILE "\n"); printf(ARCHFILE "end %s;\n",$archname); } sub HackSignals { local($hackfilename) = @_; open(HACKFILE,$hackfilename); while($theline = <HACKFILE>) { if($theline =~ /^signal/) { printf(ARCHFILE "%s",$theline); } } close(HACKFILE); } sub HackNetlist { local($hackfilename) = @_; open(HACKFILE,$hackfilename); while($theline = <HACKFILE>) { if($theline =~ /<=/) { printf(ARCHFILE "%s",$theline); } } close(HACKFILE); } |
Other Scripts: Batch
Simulation
Products: Undertow Suite
|
| Company
Products News
Assistance Download Contact Us Sales Veritools, Inc. |