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
|
"""
Utilities for SDF file parsing to determine cell timings
"""
import sys
class SDFData:
def __init__(self):
self.cells = {}
class Delay:
def __init__(self, minv, typv, maxv):
self.minv = minv
self.typv = typv
self.maxv = maxv
class IOPath:
def __init__(self, from_pin, to_pin, rising, falling):
self.from_pin = from_pin
self.to_pin = to_pin
self.rising = rising
self.falling = falling
class SetupHoldCheck:
def __init__(self, pin, clock, setup, hold):
self.pin = pin
self.clock = clock
self.setup = setup
self.hold = hold
class WidthCheck:
def __init__(self, clock, width):
self.clock = clock
self.width = width
class Interconnect:
def __init__(self, from_net, to_net, rising, falling):
self.from_net = from_net
self.to_net = to_net
self.rising = rising
self.falling = falling
class CellData:
def __init__(self, celltype, inst):
self.type = celltype
self.inst = inst
self.entries = []
self.interconnect = {}
def parse_sexpr(stream):
content = []
buffer = ""
instr = False
while True:
c = stream.read(1)
assert c != "", "unexpected end of file"
if instr:
if c == '"':
instr = False
else:
buffer += c
else:
if c == '(':
content.append(parse_sexpr(stream))
elif c == ')':
if buffer != "":
content.append(buffer)
return content
elif c.isspace():
if buffer != "":
content.append(buffer)
buffer = ""
elif c == '"':
instr = True
else:
buffer += c
def parse_sexpr_file(filename):
with open(filename, 'r') as f:
assert f.read(1) == '('
return parse_sexpr(f)
def parse_delay(delay):
sp = [int(x) for x in delay.split(":")]
assert len(sp) == 3
return Delay(sp[0], sp[1], sp[2])
def parse_sdf_file(filename):
sdata = parse_sexpr_file(filename)
assert sdata[0] == "DELAYFILE"
sdf = SDFData()
for entry in sdata[1:]:
if entry[0] != "CELL":
continue
assert entry[1][0] == "CELLTYPE"
celltype = entry[1][1]
assert entry[2][0] == "INSTANCE"
if len(entry[2]) > 1:
inst = entry[2][1]
else:
inst = "top"
cell = CellData(celltype, inst)
for subentry in entry[3:]:
if subentry[0] == "DELAY":
assert subentry[1][0] == "ABSOLUTE"
for delay in subentry[1][1:]:
if delay[0] == "IOPATH":
cell.entries.append(
IOPath(delay[1], delay[2], parse_delay(delay[3][0]), parse_delay(delay[4][0])))
elif delay[0] == "INTERCONNECT":
cell.interconnect[(delay[1], delay[2])] = Interconnect(delay[1], delay[2],
parse_delay(delay[3][0]),
parse_delay(delay[4][0]))
elif subentry[0] == "TIMINGCHECK":
for check in subentry[1:]:
if check[0] == "SETUPHOLD":
cell.entries.append(
SetupHoldCheck(check[1], check[2], parse_delay(check[3][0]), parse_delay(check[4][0])))
elif check[0] == "WIDTH":
cell.entries.append(WidthCheck(check[1], parse_delay(check[2][0])))
sdf.cells[inst] = cell
return sdf
|