• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2# Copyright © 2019 Intel Corporation
3# SPDX-License-Identifier: MIT
4
5from collections import OrderedDict
6import os
7import pathlib
8import re
9import xml.etree.ElementTree as et
10
11def get_filename(element):
12    return element.attrib['filename']
13
14def get_name(element):
15    return element.attrib['name']
16
17def get_value(element):
18    return int(element.attrib['value'], 0)
19
20def get_start(element):
21    return int(element.attrib['start'], 0)
22
23
24base_types = [
25    'address',
26    'offset',
27    'int',
28    'uint',
29    'bool',
30    'float',
31]
32
33ufixed_pattern = re.compile(r"u(\d+)\.(\d+)")
34sfixed_pattern = re.compile(r"s(\d+)\.(\d+)")
35
36def is_base_type(name):
37    return name in base_types or sfixed_pattern.match(name) or ufixed_pattern.match(name)
38
39def add_struct_refs(items, node):
40    if node.tag == 'field':
41        if 'type' in node.attrib and not is_base_type(node.attrib['type']):
42            t = node.attrib['type']
43            items[t] = True
44        return
45    if node.tag != 'struct' and node.tag != 'group':
46        return
47    for c in node:
48        add_struct_refs(items, c)
49
50
51class Struct(object):
52    def __init__(self, xml):
53        self.xml = xml
54        self.name = xml.attrib['name']
55        self.deps = OrderedDict()
56
57    def find_deps(self, struct_dict, enum_dict):
58        deps = OrderedDict()
59        add_struct_refs(deps, self.xml)
60        for d in deps.keys():
61            if d in struct_dict:
62                self.deps[d] = struct_dict[d]
63            else:
64                assert(d in enum_dict)
65
66    def add_xml(self, items):
67        for d in self.deps.values():
68            d.add_xml(items)
69        items[self.name] = self.xml
70
71
72# ordering of the various tag attributes
73genxml_desc = {
74    'genxml'      : [ 'name', 'gen', ],
75    'enum'        : [ 'name', 'value', 'prefix', ],
76    'struct'      : [ 'name', 'length', ],
77    'field'       : [ 'name', 'start', 'end', 'type', 'default', 'prefix', ],
78    'instruction' : [ 'name', 'bias', 'length', 'engine', ],
79    'value'       : [ 'name', 'value', ],
80    'group'       : [ 'count', 'start', 'size', ],
81    'register'    : [ 'name', 'length', 'num', ],
82}
83
84space_delta = 2
85
86def print_node(f, offset, node):
87    if node.tag in [ 'enum', 'struct', 'instruction', 'register' ]:
88        f.write('\n')
89    spaces = ''.rjust(offset * space_delta)
90    f.write('{0}<{1}'.format(spaces, node.tag))
91    attribs = genxml_desc[node.tag]
92    for a in node.attrib:
93        assert(a in attribs)
94    for a in attribs:
95        if a in node.attrib:
96            f.write(' {0}="{1}"'.format(a, node.attrib[a]))
97    children = list(node)
98    if len(children) > 0:
99        f.write('>\n')
100        for c in children:
101            print_node(f, offset + 1, c)
102        f.write('{0}</{1}>\n'.format(spaces, node.tag))
103    else:
104        f.write('/>\n')
105
106
107def process(filename):
108    xml = et.parse(filename)
109    genxml = xml.getroot()
110
111    enums = sorted(genxml.findall('enum'), key=get_name)
112    enum_dict = {}
113    for e in enums:
114        values = e.findall('./value')
115        e[:] = sorted(e, key=get_value)
116        enum_dict[e.attrib['name']] = e
117
118    # Structs are a bit annoying because they can refer to each other. We sort
119    # them alphabetically and then build a graph of depedencies. Finally we go
120    # through the alphabetically sorted list and print out dependencies first.
121    structs = sorted(xml.findall('./struct'), key=get_name)
122    wrapped_struct_dict = {}
123    for s in structs:
124        s[:] = sorted(s, key=get_start)
125        ws = Struct(s)
126        wrapped_struct_dict[ws.name] = ws
127
128    for s in wrapped_struct_dict:
129        wrapped_struct_dict[s].find_deps(wrapped_struct_dict, enum_dict)
130
131    sorted_structs = OrderedDict()
132    for _s in structs:
133        s = wrapped_struct_dict[_s.attrib['name']]
134        s.add_xml(sorted_structs)
135
136    instructions = sorted(xml.findall('./instruction'), key=get_name)
137    for i in instructions:
138        i[:] = sorted(i, key=get_start)
139
140    registers = sorted(xml.findall('./register'), key=get_name)
141    for r in registers:
142        r[:] = sorted(r, key=get_start)
143
144    genxml[:] = enums + list(sorted_structs.values()) + instructions + registers
145
146    with open(filename, 'w') as f:
147        f.write('<?xml version="1.0" ?>\n')
148        print_node(f, 0, genxml)
149
150
151if __name__ == '__main__':
152    folder = pathlib.Path('.')
153    for f in folder.glob('*.xml'):
154        print('Processing {}... '.format(f), end='', flush=True)
155        process(f)
156        print('done.')
157