""" 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: c = f.read(1) while c != '(': assert c == ' ' or c == '\n' or c == '\t' c = f.read(1) return parse_sexpr(f) def parse_delay(delay): sp = [float(x) if x != '' else None 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[(celltype, inst)] = cell return sdf