File: parse_sdf.py

package info (click to toggle)
prjtrellis 1.4-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 83,000 kB
  • sloc: cpp: 20,813; python: 16,246; sh: 375; makefile: 262; asm: 80; ansic: 58
file content (131 lines) | stat: -rw-r--r-- 3,815 bytes parent folder | download
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