| DEF to Verilog Script
Go To Script Pool |
|
# Please feel free to modify this script as you see fit. # I hereby release it to the public domain. If you make significant # modifications, please email me a copy at rex@arl.wustl.edu # or send cookies. # # This script converts a DEF-format netlist to a Verilog-format netlist. # It discards the following information: # CREATETIME # SAVETIME # UNITS # HISTORY # VIAS # COMPONENT PLACED data # NET ROUTED data # # The converter does not (yet) handle explicit PIN statements in the # DEF file to determine the pins in a design. (Cell3 doesn't seem to # output them in the DEF file). Instead, it looks for names without a # hierarchy separator in them. This is apparently how the ASPEC # tools determine pins as well. You can change the hierarchy separator # character in the first line of the script below. # # Note that the converter also relies on a consistent naming of inputs # and outputs for cells instantiated in the design. For the ASPEC # TSMC library, the following regular expressions match the pin names # for the following directions: #Output from cell: / [YQ][N]* / # Tristate from cell: / Z[N]* / # Pad cell I/O: / PAD / # Input to cell: (everything else - fall through case) # # If a net connects to a PAD, a second direction resolution is run to # decide what type of pad is driving it. If the script finds / TN / in the # attached instance's final component binding list, the pad is tristateable. # Similarly, the script may find a / A / or / Y / for output and input # pads. Note that a pad can be both I/O if it has all three types in its # instance list. Specifically, I set the type of any pad to inout if it is # tristateable. $hierarchySeparator = '\|'; # Get the DEF file name $defFileName = $ARGV[0]; ($vlogFileName = $defFileName) =~ s/.def/.v/; print("Converting $defFileName to $vlogFileName\n"); open(DEFFILE,$defFileName); open(VLOGFILE,">".$vlogFileName); $| = 1; $linenum = 0; $totalnets = 0; $done = 0; while($done == 0) { $theline = <DEFFILE>; $linenum++; if($theline =~ /^END DESIGN/) { $done = 1; } elsif($theline =~ /^DESIGN/) { &ParseDesign($theline); } elsif($theline =~ /^COMPONENTS/) { &ParseComponents($theline); } elsif($theline =~ /^SPECIALNETS/) { &ParseNets($theline); } elsif($theline =~ /^NETS/) { &ParseNets($theline); } } &ResolvePADDirections(); &WriteVerilogHeader(); &WriteDefs("u"); &WriteDefs("input"); &WriteDefs("output"); &WriteDefs("inout"); &WriteDefs("wire"); &WriteComponents(); &WriteVerilogTrailer(); close(DEFFILE); close(VLOGFILE); #------------------------ Subroutines ---------------------- sub ParseDesign { local($theline) = @_; ($type,$designname,$rest) = split(/\s+/,$theline); print(" Design name: $designname\n"); } # This function scans through the file, looking # at each component in the design. It builds # an associative array of components indexed # by component instance names. sub ParseComponents { local($theline) = @_; local($i); # Set the line separator to ; $/ = ";"; # Find out how many components we should have ($type,$numcomponents,$rest) = split(/\s+/,$theline); print(" Number of components: $numcomponents\n"); # Read in each component for($i=0;$i<$numcomponents;$i++) { $theline = <DEFFILE>; if($theline =~ /END/) { print("Error: END line found - $theline\n"); exit(-1); } &ParseSingleComponent($theline); } # Set the line separator back to newline $/ = "\n"; print(" Done parsing components\n"); } # This function parses a line to find a component # declaration. # # The component should be of the form # - <instname> <compname> +.* # # The component names are stored in an associative # array indexed by the instance name for each component sub ParseSingleComponent { local($theline) = @_; $theline =~ s/\s*-\s*//; ($instname,$compname) = split(/\s+/,$theline); $comparray{$instname} = $compname.":"; } # This function walks through the DEF file, looking at # each net in a NETS section. It adds nets to the # $comparray associative array as a string indicating # that the net is bound to that component. In addition, # it builds a nets array that will allow us to declare # wires in the Verilog file. # XXX SHOULD it do a binding from ORIGINALS? sub ParseNets { local($theline) = @_; local($i); # Set the line separator to ; $/ = ";"; # Find out how many nets we should have ($type,$numnets,$rest) = split(/\s+/,$theline); $totalnets = $totalnets + $numnets; print(" Number of nets: $numnets\n"); print(" Total number of nets so far: $totalnets\n"); # Read in each net for($i=0;$i<$numnets;$i++) { $theline = <DEFFILE>; if($theline =~ /END/) { print("Error: END [SPECIAL]NETS line found - $theline\n"); exit(-1); } &ParseSingleNet($theline); } # Set the line separator back to newline $/ = "\n"; print(" Done parsing nets\n"); } # This function parses a line and extracts the connections for # each net, adding them to the list of connections in the # associative %comparray. Each %comparray entry is composed # of a component type, a colon, and a comma-separated list of # .PIN(netname) pairs. sub ParseSingleNet { local($theline) = @_; local($i); local($pinname,$driven,$sinked,$tristate,$unresolved); # Set the net to neither driven nor sinked. We can # then decipher the direction of the pin: # Driven - output # Sinked - input # Driven and sinked - wire # Driventristate - inout $driven = 0; $sinked = 0; $tristate = 0; $unresolved = 0; # Remove all newlines from the line (remember that # it was a multi-line string because the input record # separator was ';'. $theline =~ s/\n//g; # Remove the initial "-" character $theline =~ s/^\s*\-\s*//; # Remove everything after the first "+" character $theline =~ s/\+.*//; # The line now consists of a net name followed by # a list of (component pin) pairs. # Separate the line into an array by splitting on the # '(' character. The first element in the array # will be the netname and the other elements will be # pin bindings. @bindings = split(/\(/,$theline); ($netname = $bindings[0]) =~ s/\s+//g; if($netname =~ "VDD" || $netname =~ "VSS") { # Do nothing - power or ground net. } else { # Parse each pin binding for($i=1;$i<=$#bindings;$i++) { $pinname = &ParseSinglePinBinding($netname,$bindings[$i]); $pinarray{$pinname} = 1; if($netname =~ /$hierarchySeparator/) { # This is not a top-level net name, so set the # type to "w" (wire). $netarray{$netname} = "wire"; } else { # This is a top-level net name, so decide whether # it is an input/output/bidirect/unresolved. if($bindings[$i] =~ / [YQ][N]* / ) { $driven = 1; } if($bindings[$i] =~ / A /) { $sinked = 1; } if($bindings[$i] =~ / Z[N]* /) { $tristate = 1; } if($bindings[$i] =~ / PAD /) { $unresolved = 1; } } } if(!($netname =~ /$hierarchySeparator/)) { if($unresolved) { $netarray{$netname} = "u"; if($driven) { printf("ERROR: net $netname attached to PAD is also driven\n "); exit(-1); } if($tristate) { printf("ERROR: net $netname attached to PAD is also tristate \n"); exit(-1); } if($sinked) { printf("ERROR: net $netname attached to PAD is also sinked\n "); exit(-1); } } elsif($tristate) { $netarray{$netname} = "inout"; } elsif($driven) { $netarray{$netname} = "output"; } elsif($sinked) { $netarray{$netname} = "input"; } else { printf("ERROR: net $netname is not used anywhere!\n"); exit(-1); } } } } sub ParseSinglePinBinding { local($netname,$binding) = @_; local($pinname); # Remove leading whitespace $binding =~ s/^\s+//; # Split the instance name from the pin name ($instname,$pinname) = split(/\s+/,$binding); if($comparray{$instname} eq "") { print("ERROR: can't find instance $instname referenced by net $netname\n "); exit(-1); } else { $comparray{$instname} = $comparray{$instname}.",.$pinname(\\$netname )"; } return $pinname; } # For every component in the design, find the net that connects to its # PAD pin. It should still be unresolved ("u") in the %netarray array. # Find whether the pad we're looking at is an input, output, or inout # and set the %netarray entry to "input", "output", or "inout".
|
Other Scripts: Batch Simulation
Products: Undertow Suite
|
| Company
Products News
Assistance Download Contact Us Sales Veritools, Inc. |