1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
|
#!TCLSH_PATH
#---------------------------------------------------------------------------
# blifanno.tcl ---
#
# Read a BLIF file and a post-placement DEF file. The placement stage is
# assumed to have rewired buffer trees for optimal placement, making the
# BLIF file netlist invalid. The contents of the DEF file are used to
# back-annotate the correct buffer tree connections to the BLIF netlist.
# The output is a corrected BLIF netlist.
#
#---------------------------------------------------------------------------
namespace path {::tcl::mathop ::tcl::mathfunc}
if {$argc < 2} {
puts stdout "Usage: blifanno.tcl <blif_file> <def_file> \[<blif_out>\]"
exit 0
}
puts stdout "Running blifanno.tcl"
# NOTE: There is no scaling. GrayWolf values are in centimicrons,
# as are DEF values (UNITS DISTANCE MICRONS 100)
set blifinname [lindex $argv 0]
set defname [lindex $argv 1]
set units 100 ;# write centimicron units into the DEF file
#-----------------------------------------------------------------
# Open all files for reading and writing
#-----------------------------------------------------------------
if [catch {open $defname r} fdef] {
puts stderr "Error: can't open file $defname for input"
return
}
if [catch {open $blifinname r} fnet] {
puts stderr "Error: can't open file $blifinname for input"
return
}
if {$argc == 3} {
set blifoutname [lindex $argv 2]
if [catch {open $blifoutname w} fout] {
puts stderr "Error: can't open file $blifoutname for output"
return
}
} else {
set fout stdout
}
#----------------------------------------------------------------
# Read through a LEF file section that we don't care about.
#----------------------------------------------------------------
proc skip_section {leffile sectionname} {
while {[gets $leffile line] >= 0} {
if [regexp {[ \t]*END[ \t]+([^ \t]+)[ \t]*$} $line lmatch sectiontest] {
if {"$sectiontest" != "$sectionname"} {
puts -nonewline stderr "Unexpected END statement $line "
puts stderr "while reading section $sectionname"
}
break
}
}
}
#-----------------------------------------------------------------
# Parse the NETS section of the DEF file
# Assuming this file was generated by place2def, each net
# connection should be on a separate line.
#-----------------------------------------------------------------
proc parse_nets {deffile nets} {
upvar $nets rdict
set ignore 0
while {[gets $deffile line] >= 0} {
if [regexp {[ \t]*END[ \t]+([^ \t]+)[ \t\n]*$} $line lmatch sectiontest] {
if {"$sectiontest" == "NETS"} {
break
} else {
puts -nonewline stderr "Unexpected END statement $line "
puts stderr "while reading section NETS"
}
break
} elseif [regexp {[ \t]*-[ \t]+([^ \t]+)} $line lmatch netname] {
set ignore 0
} elseif [regexp {[ \t]*\+[ \t]+([^ \t]+)} $line lmatch option] {
set ignore 1
} elseif {$ignore == 0} {
if [regexp {[ \t]*\([ \t]*([^ \t]+)[ \t]+([^ \t]+)[ \t]*\)[ \t\n;]*$} \
$line lmatch instname pinname] {
dict set rdict ${instname}/${pinname} $netname
}
}
}
}
#-----------------------------------------------------------------
# Read the DEF file once to get the number of rows and the length
# of each row
#-----------------------------------------------------------------
puts stdout "Reading DEF file ${defname}. . ."
flush stdout
while {[gets $fdef line] >= 0} {
if [regexp {[ \t]*COMPONENTS[ \t]+([^ \t]+)[ \t]*;} $line lmatch number] {
skip_section $fdef COMPONENTS
} elseif [regexp {[ \t]*SPECIALNETS[ \t]+([^ \t]+)} $line lmatch netnums] {
skip_section $fdef SPECIALNETS
} elseif [regexp {[ \t]*NETS[ \t]+([^ \t]+)} $line lmatch netnums] {
set nets [dict create]
# Parse the "NETS" section
parse_nets $fdef nets
# puts stdout "Done with NETS section, dict size is [dict size $nets]"
} elseif [regexp {[ \t]*PINS[ \t]+([^ \t]+)} $line lmatch pinnum] {
skip_section $fdef PINS
} elseif [regexp {[ \t]*VIAS[ \t]+(.+)[ \t]*$} $line lmatch number] {
skip_section $fdef VIAS
} elseif [regexp {[ \t]*END[ \t]+DESIGN[ \t]*$} $line lmatch] {
break
} elseif [regexp {^[ \t]*#} $line lmatch] {
# Comment line, ignore.
} elseif ![regexp {^[ \t]*$} $line lmatch] {
# Other things we don't care about
set matches 0
if [regexp {[ \t]*NAMESCASESENSITIVE} $line lmatch] {
incr matches
} elseif [regexp {[ \t]*VERSION} $line lmatch] {
incr matches
} elseif [regexp {[ \t]*BUSBITCHARS} $line lmatch] {
incr matches
} elseif [regexp {[ \t]*DIVIDERCHAR} $line lmatch] {
incr matches
} elseif [regexp {[ \t]*USEMINSPACING} $line lmatch] {
incr matches
} elseif [regexp {[ \t]*CLEARANCEMEASURE} $line lmatch] {
incr matches
} elseif [regexp {[ \t]*MANUFACTURINGGRID} $line lmatch] {
incr matches
} elseif [regexp {[ \t]*UNITS} $line lmatch] {
incr matches
} elseif [regexp {[ \t]*DESIGN} $line lmatch] {
incr matches
} elseif [regexp {[ \t]*DIEAREA} $line lmatch] {
incr matches
} elseif [regexp {[ \t]*TRACKS} $line lmatch] {
incr matches
} else {
puts stderr "Unexpected input in DEF file:"
puts stdout "Line is: $line"
}
}
}
close $fdef
#-----------------------------------------------------------------
# Now read the BLIF netlist, and rewrite all net connections from
# the list found in the DEF file
#-----------------------------------------------------------------
set instcount [dict create]
while {[gets $fnet line] >= 0} {
if [regexp {^[ \t]*\.gate[ \t]+([^ \t]+)[ \t]+(.*)$} \
$line lmatch macroname rest] {
if {[dict exists $instcount $macroname]} {
set iidx [dict get $instcount $macroname]
incr iidx
dict set instcount $macroname $iidx
} else {
dict set instcount $macroname 1
set iidx 1
}
set gateline ".gate $macroname"
while {[regexp {[ \t]*([^ \t]+)[ \t]*=[ \t]*([^ \t]+)[ \t]*(.*)$} \
$rest lmatch pinname netname nextconn] > 0} {
if {[catch {set newnet [dict get $nets ${macroname}_${iidx}/${pinname}]}]} {
# NOTE: Dangling buffer outputs (for debug) do not show up in
# graywolf output. They cannot be sorted, so just copy them
# as they are in the original blif file.
set gateline "${gateline} ${pinname}=${netname}"
} else {
set gateline "${gateline} ${pinname}=${newnet}"
}
set rest $nextconn
}
puts $fout "$gateline"
} else {
puts $fout $line
}
}
#-----------------------------------------------------------------
#-----------------------------------------------------------------
close $fnet
if {$fout != "stdout"} {close $fout}
puts stdout "Done with blifanno.tcl"
|