/usr/lib/qflow/scripts/getfillcell.tcl is in qflow 1.1.37-1+b1.
This file is owned by root:root, with mode 0o755.
The actual contents of the file can be viewed below.
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 | #!/usr/bin/tclsh
#---------------------------------------------------------------------------
# getfillcell.tcl ---
#
# Read the .par file and find the feedthru width
# Read LEF file and parse for fill cells; find the one that
# corresponds to the feedthru width and return its name
#
# NOTE: The eventual goal is to have the .par file automatically
# generated, in which case we really want to do this process in
# reverse.
#
#---------------------------------------------------------------------------
namespace path {::tcl::mathop ::tcl::mathfunc}
if {$argc < 3} {
puts stdout "Usage: getfillcell <project_name> <lef_file> <fill_cell>"
exit 0
}
puts stdout "Running getfillcell.tcl"
set topname [file rootname [lindex $argv 0]]
set lefname [lindex $argv 1]
set fillcell [lindex $argv 2]
set parname ${topname}.par
set units 100 ;# read micron units from the LEF file
;# and convert to centimicrons
#-----------------------------------------------------------------
# Open all files for reading and writing
#-----------------------------------------------------------------
if [catch {open $lefname r} flef] {
puts stderr "Error: can't open file $lefname for input"
return
}
if [catch {open $parname r} fpar] {
puts stderr "Error: can't open file $parname for input"
return
}
#-----------------------------------------------------------------
# Read the .par file and look for "feedThruWidth".
#-----------------------------------------------------------------
puts stdout "Reading .par file ${parname}. . ."
flush stdout
set fwidth 0
while {[gets $fpar line] >= 0} {
if {![regexp {[ \t]*#} $line lmatch]} {
if [regexp {feedThruWidth[ \t]*:[ \t]*([0-9]+)} $line lmatch fwidth] {
break
}
}
}
if {$fwidth == 0} {
puts stdout "(no feedthroughs or width defined as zero)"
}
#----------------------------------------------------------------
# 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]*$} $line lmatch sectiontest] {
if {"$sectiontest" != "$sectionname"} {
puts -nonewline stderr "Unexpected END statement $line "
puts stderr "while reading section $sectionname"
}
break
}
}
}
#----------------------------------------------------------------
# Parse the macro contents of the LEF file and retain the information
# about cell size and pin positions.
#----------------------------------------------------------------
proc parse_macro {leffile macroname} {
global $macroname units
while {[gets $leffile line] >= 0} {
if [regexp {[ \t]*SYMMETRY[ \t]+(.+)[ \t]*;} $line lmatch symmetry] {
set ${macroname}(symmetry) $symmetry
} elseif [regexp {[ \t]*ORIGIN[ \t]+(.+)[ \t]+(.+)[ \t]*;} $line lmatch x y] {
set x [expr {int($x * $units)}]
set y [expr {int($y * $units)}]
set ${macroname}(x) $x
set ${macroname}(y) $y
} elseif [regexp {[ \t]*SIZE[ \t]+(.+)[ \t]+BY[ \t]+(.+)[ \t]*;} \
$line lmatch w h] {
set w [expr {int($w * $units)}]
set h [expr {int($h * $units)}]
set ${macroname}(w) $w
set ${macroname}(h) $h
} elseif [regexp {[ \t]*PIN[ \t]+(.+)[ \t]*$} $line lmatch pinname] {
# The fill cell is not expected to have any usable pins
skip_section $leffile $pinname
} elseif [regexp {[ \t]*END[ \t]+(.+)[ \t]*$} $line lmatch macrotest] {
if {"$macrotest" == "$macroname"} {
break
} else {
puts stderr "Unexpected END statement $line while reading macro $macroname"
}
}
}
}
#-----------------------------------------------------------------
# Read the lef macro file and get the fill cells and their widths
#-----------------------------------------------------------------
puts stdout "Reading ${fillcell} macros from LEF file."
flush stdout
puts stdout "Diagnostic: fill cell width from .par file is $fwidth"
set usefillcell {}
while {[gets $flef line] >= 0} {
if [regexp {[ \t]*MACRO[ \t]+(.+)[ \t]*$} $line lmatch macroname] {
# Parse the "macro" statement
parse_macro $flef $macroname
if {[string first $fillcell $macroname] == 0} {
# Check width against feedthrough width
puts stdout "Diagnostic: macro $macroname width = [subst \$${macroname}(w)]"
if {[subst \$${macroname}(w)] == $fwidth} {
set usefillcell $macroname
}
}
} elseif [regexp {[ \t]*LAYER[ \t]+([^ \t]+)} $line lmatch layername] {
skip_section $flef $layername
} elseif [regexp {[ \t]*VIA[ \t]+([^ \t]+)} $line lmatch vianame] {
skip_section $flef $vianame
} elseif [regexp {[ \t]*VIARULE[ \t]+([^ \t]+)} $line lmatch viarulename] {
skip_section $flef $viarulename
} elseif [regexp {[ \t]*SITE[ \t]+(.+)[ \t]*$} $line lmatch sitename] {
skip_section $flef $sitename
} elseif [regexp {[ \t]*SPACING[ \t]*$} $line lmatch] {
skip_section $flef SPACING
} elseif [regexp {[ \t]*UNITS[ \t]*$} $line lmatch] {
skip_section $flef UNITS
} elseif [regexp {[ \t]*END[ \t]+LIBRARY[ \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
} else {
puts stderr "Unexpected input in LEF file: Only macro defs were expected!"
puts -nonewline stdout "Line is: $line"
flush stdout
}
}
}
close $flef
close $fpar
puts stdout "fill=$usefillcell"
puts stdout "Done with getfillcell.tcl"
|