#!TCLSH_PATH # # Usage: # rtl2sim.tcl [] # # If cel_filename is not specified, then name will be the root name # of the verilog RTL file with the .sim extension. # # "dir" is the directory where .sim views of the standard cells are # located. If .sim views are not available but .mag files are, the # .sim files will be generated automatically. # #------------------------------------------------------------ # Original bdnet2sim.tcl Written by Tim Edwards February 12, 2007 # Modified for Verilog RTL input, Tim Edwards, April 25, 2011 #------------------------------------------------------------ set rtlfile [lindex $argv 0] set cellname [file rootname $rtlfile] if {"$cellname" == "$rtlfile"} { set rtlfile ${cellname}.rtl.v } set prefix "" if {$argc > 2} { if {[lindex $argv [expr {$argc - 2}]] == "-prefix"} { set prefix [lindex $argv [expr {$argc - 1}]]/ incr argc -2 } } if {$argc > 1} { set magdir [lindex $argv 1] } else { set magdir /home/tim/projects/multigig/digital_flow/layout/digital2 } if {$argc == 3} { set simfile [lindex $argv 2] } else { set simfile ${cellname}.sim } set scriptdir [file dirname $argv0] #------------------------------------------------------------- # Open files for read and write if [catch {open $rtlfile r} fnet] { puts stderr "Error: can't open file $rtlfile for reading!" exit 0 } #---------------------------------------------------------------- # First, parse the contents of the RTL file and get a list # of all macro names used. Use also to get the module name, # which we will use for the .sim file name. #---------------------------------------------------------------- puts stdout "1st pass of RTL file ${rtlfile}. . ." flush stdout set macrolist {} while {[gets $fnet line] >= 0} { if [regexp {^[ \t]*//} $line lmatch] { # Comment line---do nothing } elseif [regexp {^module[ \t]+([^ \t]+)[ \t]*\(} $line lmatch cellverify] { if {"$cellname" != "$cellverify"} { puts -nonewline stderr "WARNING: MODEL name ${cellverify} does not" puts stderr " match filename ${cellname}!" set cellname $cellverify if {$argc != 3} {set simfile ${cellname}.sim} } } elseif [regexp {^[ \t]*([^ \t]+)[ \t]+([^ \t]+)[ \t]+\(} $line lmatch macro inst] { if {"$macro" != "module"} { lappend macrolist $macro } } } set macrolist [lsort -unique $macrolist] close $fnet set needsims {} foreach macro $macrolist { if {[glob -nocomplain ${magdir}/${macro}.sim] == {}} { lappend needsims ${macro} } elseif {[file size ${magdir}/${macro}.ext] == 0} { lappend needsims ${macro} } } if {$needsims != {}} { puts stdout "Generating .sim views. . ." flush stdout foreach macro $needsims { puts stdout "Generating ${macro}.sim" flush stdout catch {exec ${scriptdir}/makesim.sh ${magdir}/$macro} } } if [catch {open $simfile w} fsim] { puts stderr "Error: can't open file $simfile for writing!" exit 0 } puts $fsim "| SIM file $simfile generated by rtl2sim" #---------------------------------------------------------------- # Procedure to dump the contents of a subcircuit .sim file to the # top-level .sim file, replacing pin names with net names. #---------------------------------------------------------------- proc dump_sim {fsim mode magdir prefix} { # Pick up variable definition from top-level upvar $mode mname # Make VDD, VSS, and GND show up as globals set mname(VDD) VDD set mname(VDD!) VDD set mname(VSS) VSS set mname(VSS!) VSS set mname(GND) GND set mname(GND!) GND puts $fsim "| ${mode} $mname(count) = $mname(instance)" set fsub [open ${magdir}/${mode}.sim r] while {[gets $fsub line] >= 0} { set mtype [string index $line 0] # Parse .sim file lines. Ignore lumped "R", which is not used by IRSIM. switch -exact $mtype { n - p { regexp {^[pn] ([^ ]+) ([^ ]+) ([^ ]+) (.*)} $line valid \ gate drain source rest puts -nonewline $fsim "$mtype " if {[catch {puts -nonewline $fsim "${prefix}$mname(${gate}) "}]} { puts -nonewline $fsim "${prefix}$mname(instance)/$gate " } if {[catch {puts -nonewline $fsim "${prefix}$mname(${drain}) "}]} { puts -nonewline $fsim "${prefix}$mname(instance)/$drain " } if {[catch {puts -nonewline $fsim "${prefix}$mname(${source}) "}]} { puts -nonewline $fsim "${prefix}$mname(instance)/$source " } puts $fsim $rest } r { regexp {^r ([^ ]+) ([^ ]+) (.*)} $line valid r1 r2 rest puts -nonewline $fsim "r " if {[catch {puts -nonewline $fsim "${prefix}$mname(${r1}) "}]} { puts -nonewline $fsim "${prefix}$mname(instance)/$r1 " } if {[catch {puts -nonewline $fsim "${prefix}$mname(${r2}) "}]} { puts -nonewline $fsim "${prefix}$mname(instance)/$r2 " } puts $fsim $rest } C { regexp {^C ([^ ]+) ([^ ]+) (.*)} $line valid top bottom rest puts -nonewline $fsim "C " if {[catch {puts -nonewline $fsim "${prefix}$mname(${top}) "}]} { puts -nonewline $fsim "${prefix}$mname(instance)/$top " } if {[catch {puts -nonewline $fsim "${prefix}$mname(${bottom}) "}]} { puts -nonewline $fsim "${prefix}$mname(instance)/$bottom " } puts $fsim $rest } | { puts $fsim $line } } } close $fsub } #---------------------------------------------------------------- # Parse the contents of the RTL file again and dump each cell # instance to the .sim file output. puts stdout "2nd pass of RTL file. . ." flush stdout set fnet [open $rtlfile r] set mode none while {[gets $fnet line] >= 0} { if [regexp {^[ \t]*//} $line lmatch] { # Comment line---do nothing } elseif [regexp {^module[ \t]+([^ \t]+)[ \t]*\(} $line lmatch cellverify] { if {"$cellname" != "$cellverify"} { puts -nonewline stderr "WARNING: MODEL name ${cellverify} does not" puts stderr " match filename ${cellname}!" } } elseif [regexp {^[ \t]*([^ \t]+)[ \t]+([^ \t]+)[ \t]+\((.*)$} $line \ lmatch macroname instname rest] { # New instance. First dump the current instance to the sim file if {$mode != "pins" && $mode != "none" && $mode != "wires"} { dump_sim $fsim $mode $magdir $prefix } set mode $macroname if {[catch {incr ${mode}(count)}]} { set ${mode}(count) 0 } else { # Clear pin assignments so that unconnected outputs don't get shorted # to the last instance set qcount [set ${mode}(count)] array unset ${mode} set ${mode}(count) $qcount } set ${mode}(instance) $instname # parse "rest" for any pin information on the first line while {[regexp {[ \t]*.([^(]+)\(([^) \t]+)[ \t]*\),*(.*)$} $rest \ lmatch pinname netname more] > 0} { # puts stderr "pin: ${mode}(${pinname}) $netname" set ${mode}(${pinname}) $netname set rest $more } } elseif [regexp {^endmodule} $line lmatch] { # Dump last "mode" output if {$mode != "pins"} { dump_sim $fsim $mode $magdir $prefix} } elseif [regexp {^[ \t]*input} $line lmatch] { set mode "pins" } elseif [regexp {^[ \t]*output} $line lmatch] { set mode "pins" } elseif [regexp {^[ \t]*wire} $line lmatch] { set mode "wires" } else { while {[regexp {[ \t]*.([^(]+)\(([^) \t]+)[ \t]*\),*(.*)$} $line \ lmatch pinname netname rest] > 0} { # puts stderr "pin: ${mode}(${pinname}) $netname" set ${mode}(${pinname}) $netname set line $rest } } } # Dump the final instance to the sim file, if there was one. if {$mode != "pins" && $mode != "none"} { dump_sim $fsim $mode $magdir $prefix} close $fnet puts stdout "Done!"