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
|
#!TCLSH_PATH
#---------------------------------------------------------------------------
# getpowerground.tcl ---
#
# Read LEF file up to the first macro with a PIN record having
# USE POWER and one having USE GROUND. Return the pin names.
#
#---------------------------------------------------------------------------
namespace path {::tcl::mathop ::tcl::mathfunc}
if {$argc < 1} {
puts stdout "Usage: getpowerground <lef_file>"
exit 0
}
puts stdout "Running getpowerground.tcl"
set lefname [lindex $argv 0]
set vddnet ""
set gndnet ""
#-----------------------------------------------------------------
# Open lef file for reading
#-----------------------------------------------------------------
if [catch {open $lefname r} flef] {
puts stderr "Error: can't open file $lefname for input"
return
}
#----------------------------------------------------------------
# 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 pin contents of the LEF file macro
#----------------------------------------------------------------
proc parse_pin {leffile pinname} {
global vddnet
global gndnet
set portuse ""
while {[gets $leffile line] >= 0} {
if [regexp {[ \t]*USE[ \t]+([^ \t]+)[ \t]*;} $line lmatch portuse] {
set portuse [string toupper $portuse]
if {$portuse == "GROUND"} {
set gndnet $pinname
} elseif {$portuse == "POWER"} {
set vddnet $pinname
}
} elseif [regexp {[ \t]*END[ \t]+([^ \t]+)[ \t]*$} $line lmatch pintest] {
if {"$pintest" == "$pinname"} {
break
} else {
puts stdout "Unexpected END statement $line while parsing pin $pinname"
}
}
}
}
#----------------------------------------------------------------
# Parse the macro contents of the LEF file and retain the information
# about pin use.
#----------------------------------------------------------------
proc parse_macro {leffile macroname} {
global vddnet
global gndnet
while {[gets $leffile line] >= 0} {
if [regexp {[ \t]*PIN[ \t]+(.+)[ \t]*$} $line lmatch pinname] {
parse_pin $leffile $pinname
} elseif [regexp {[ \t]*END[ \t]+([^ \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 macros from LEF file."
flush stdout
while {[gets $flef line] >= 0} {
if [regexp {[ \t]*MACRO[ \t]+(.+)[ \t]*$} $line lmatch macroname] {
# Parse the "macro" statement
parse_macro $flef $macroname
# Probably the power and ground nets will be set after the first
# macro is read.
if {($vddnet != "") && ($gndnet != "")} {break}
} 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
}
}
}
close $flef
puts stdout "vddnet=$vddnet"
puts stdout "gndnet=$gndnet"
puts stdout "Done with getpowerground.tcl"
|