File: reg2json.py

package info (click to toggle)
m1n1 1.5.2-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 5,468 kB
  • sloc: python: 42,002; ansic: 33,376; asm: 1,101; makefile: 271; xml: 177; sh: 116
file content (137 lines) | stat: -rw-r--r-- 3,919 bytes parent folder | download | duplicates (3)
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
import sys, re, json
from xml.etree import ElementTree

def insert_n(s, nb):
    sout = ""
    def sub(g):
        if g.group(2):
            a, b = int(g.group(1)), int(g.group(2)[1:])
            return nb[-a - 1:-b or None]
        else:
            a = int(g.group(1))
            return nb[-a - 1]

    s = re.sub(r'n\[(\d+)(:\d+)?\]', sub, s)
    s = "".join(s.split(":"))
    return int(s.replace("0b", ""), 2)

def parse_one(regs, xml):
    t = ElementTree.parse(xml)

    for reg in t.findall('registers/register'):
        data = {}

        name = reg.find('reg_short_name').text
        fullname = reg.find('reg_long_name').text

        if name.startswith("S3_") or name.startswith("SYS S1_"):
            continue

        array = reg.find('reg_array')

        start = end = 0

        if array:
            start = int(array.find("reg_array_start").text)
            end = int(array.find("reg_array_end").text)

        encs = {}
        accessors = {}

        for am in reg.findall('access_mechanisms/access_mechanism'):
            accessor = am.attrib["accessor"]
            if accessor.startswith("MSRimmediate"):
                continue
            ins = am.find("encoding/access_instruction").text.split(" ")[0]
            regname = accessor.split(" ", 1)[1]
            enc = {}
            for e in am.findall("encoding/enc"):
                enc[e.attrib["n"]] = e.attrib["v"]

            enc = enc["op0"], enc["op1"], enc["CRn"], enc["CRm"], enc["op2"]
            if regname in encs:
                assert encs[regname] == enc
            encs[regname] = enc
            accessors.setdefault(regname, set()).add(ins)

        if not encs:
            continue

        fieldsets = []

        width = None

        for fields_elem in reg.findall('reg_fieldsets/fields'):

            fieldset = {}

            if (instance_elem := fields_elem.find('fields_instance')) is not None:
                fieldset["instance"] = instance_elem.text

            fields = []

            set_width = int(fields_elem.attrib["length"])

            if width is None:
                width = set_width
            else:
                assert width == set_width

            single_field = False

            for f in fields_elem.findall('field'):

                if f.attrib.get("rwtype", None) in ("RES0", "RES1", "RAZ", "RAZ/WI", "RAO/WI", "UNKNOWN"):
                    continue
                msb, lsb = int(f.find('field_msb').text), int(f.find('field_lsb').text)

                assert not single_field

                if msb == width - 1 and lsb == 0:
                    continue

                if (name_elem := f.find('field_name')) is not None:
                    name = name_elem.text
                else:
                    assert not fields
                    continue

                field = {
                    "name": name,
                    "msb": msb,
                    "lsb": lsb,
                }
                fields.append(field)

            fields.sort(key=lambda x: x["lsb"], reverse=True)

            fieldset["fields"] = fields
            fieldsets.append(fieldset)

        for idx, n in enumerate(range(start, end + 1)):
            nb = "{0:064b}".format(n)[::-1]
            for name, enc in sorted(encs.items()):
                enc = tuple(insert_n(i, nb) for i in enc)
                data = {
                    "index": idx,
                    "name": name.replace("<n>", "%d" % n),
                    "fullname": fullname,
                    "enc": enc,
                    "accessors": sorted(list(accessors[name])),
                    "fieldsets": fieldsets,
                }

                if width is not None:
                    data["width"] = width

                yield data

if __name__ == "__main__":
    regs = []
    for i in sys.argv[1:]:
        regs.extend(parse_one(regs, i))

    json.dump(regs, sys.stdout)