1b8e80941Smrg#encoding=utf-8
2b8e80941Smrg
3b8e80941Smrg# Copyright (C) 2016 Intel Corporation
4b8e80941Smrg# Copyright (C) 2016 Broadcom
5b8e80941Smrg#
6b8e80941Smrg# Permission is hereby granted, free of charge, to any person obtaining a
7b8e80941Smrg# copy of this software and associated documentation files (the "Software"),
8b8e80941Smrg# to deal in the Software without restriction, including without limitation
9b8e80941Smrg# the rights to use, copy, modify, merge, publish, distribute, sublicense,
10b8e80941Smrg# and/or sell copies of the Software, and to permit persons to whom the
11b8e80941Smrg# Software is furnished to do so, subject to the following conditions:
12b8e80941Smrg#
13b8e80941Smrg# The above copyright notice and this permission notice (including the next
14b8e80941Smrg# paragraph) shall be included in all copies or substantial portions of the
15b8e80941Smrg# Software.
16b8e80941Smrg#
17b8e80941Smrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18b8e80941Smrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19b8e80941Smrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20b8e80941Smrg# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21b8e80941Smrg# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22b8e80941Smrg# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
23b8e80941Smrg# IN THE SOFTWARE.
24b8e80941Smrg
25b8e80941Smrgfrom __future__ import (
26b8e80941Smrg    absolute_import, division, print_function, unicode_literals
27b8e80941Smrg)
28b8e80941Smrgimport xml.parsers.expat
29b8e80941Smrgimport re
30b8e80941Smrgimport sys
31b8e80941Smrgimport copy
32b8e80941Smrg
33b8e80941Smrglicense =  """/* Generated code, see packets.xml and gen_packet_header.py */
34b8e80941Smrg"""
35b8e80941Smrg
36b8e80941Smrgpack_header = """%(license)s
37b8e80941Smrg
38b8e80941Smrg/* Packets, enums and structures for %(platform)s.
39b8e80941Smrg *
40b8e80941Smrg * This file has been generated, do not hand edit.
41b8e80941Smrg */
42b8e80941Smrg
43b8e80941Smrg#ifndef %(guard)s
44b8e80941Smrg#define %(guard)s
45b8e80941Smrg
46b8e80941Smrg#include "cle/v3d_packet_helpers.h"
47b8e80941Smrg
48b8e80941Smrg"""
49b8e80941Smrg
50b8e80941Smrgdef to_alphanum(name):
51b8e80941Smrg    substitutions = {
52b8e80941Smrg        ' ': '_',
53b8e80941Smrg        '/': '_',
54b8e80941Smrg        '[': '',
55b8e80941Smrg        ']': '',
56b8e80941Smrg        '(': '',
57b8e80941Smrg        ')': '',
58b8e80941Smrg        '-': '_',
59b8e80941Smrg        ':': '',
60b8e80941Smrg        '.': '',
61b8e80941Smrg        ',': '',
62b8e80941Smrg        '=': '',
63b8e80941Smrg        '>': '',
64b8e80941Smrg        '#': '',
65b8e80941Smrg        'α': 'alpha',
66b8e80941Smrg        '&': '',
67b8e80941Smrg        '*': '',
68b8e80941Smrg        '"': '',
69b8e80941Smrg        '+': '',
70b8e80941Smrg        '\'': '',
71b8e80941Smrg    }
72b8e80941Smrg
73b8e80941Smrg    for i, j in substitutions.items():
74b8e80941Smrg        name = name.replace(i, j)
75b8e80941Smrg
76b8e80941Smrg    return name
77b8e80941Smrg
78b8e80941Smrgdef safe_name(name):
79b8e80941Smrg    name = to_alphanum(name)
80b8e80941Smrg    if not name[0].isalpha():
81b8e80941Smrg        name = '_' + name
82b8e80941Smrg
83b8e80941Smrg    return name
84b8e80941Smrg
85b8e80941Smrgdef prefixed_upper_name(prefix, name):
86b8e80941Smrg    if prefix:
87b8e80941Smrg        name = prefix + "_" + name
88b8e80941Smrg    return safe_name(name).upper()
89b8e80941Smrg
90b8e80941Smrgdef num_from_str(num_str):
91b8e80941Smrg    if num_str.lower().startswith('0x'):
92b8e80941Smrg        return int(num_str, base=16)
93b8e80941Smrg    else:
94b8e80941Smrg        assert(not num_str.startswith('0') and 'octals numbers not allowed')
95b8e80941Smrg        return int(num_str)
96b8e80941Smrg
97b8e80941Smrgclass Field(object):
98b8e80941Smrg    ufixed_pattern = re.compile(r"u(\d+)\.(\d+)")
99b8e80941Smrg    sfixed_pattern = re.compile(r"s(\d+)\.(\d+)")
100b8e80941Smrg
101b8e80941Smrg    def __init__(self, parser, attrs):
102b8e80941Smrg        self.parser = parser
103b8e80941Smrg        if "name" in attrs:
104b8e80941Smrg            self.name = safe_name(attrs["name"]).lower()
105b8e80941Smrg
106b8e80941Smrg        if str(attrs["start"]).endswith("b"):
107b8e80941Smrg            self.start = int(attrs["start"][:-1]) * 8
108b8e80941Smrg        else:
109b8e80941Smrg            self.start = int(attrs["start"])
110b8e80941Smrg        # packet <field> entries in XML start from the bit after the
111b8e80941Smrg        # opcode, so shift everything up by 8 since we'll also have a
112b8e80941Smrg        # Field for the opcode.
113b8e80941Smrg        if not parser.struct:
114b8e80941Smrg            self.start += 8
115b8e80941Smrg
116b8e80941Smrg        self.end = self.start + int(attrs["size"]) - 1
117b8e80941Smrg        self.type = attrs["type"]
118b8e80941Smrg
119b8e80941Smrg        if self.type == 'bool' and self.start != self.end:
120b8e80941Smrg            print("#error Field {} has bool type but more than one bit of size".format(self.name));
121b8e80941Smrg
122b8e80941Smrg        if "prefix" in attrs:
123b8e80941Smrg            self.prefix = safe_name(attrs["prefix"]).upper()
124b8e80941Smrg        else:
125b8e80941Smrg            self.prefix = None
126b8e80941Smrg
127b8e80941Smrg        if "default" in attrs:
128b8e80941Smrg            self.default = int(attrs["default"])
129b8e80941Smrg        else:
130b8e80941Smrg            self.default = None
131b8e80941Smrg
132b8e80941Smrg        if "minus_one" in attrs:
133b8e80941Smrg            assert(attrs["minus_one"] == "true")
134b8e80941Smrg            self.minus_one = True
135b8e80941Smrg        else:
136b8e80941Smrg            self.minus_one = False
137b8e80941Smrg
138b8e80941Smrg        ufixed_match = Field.ufixed_pattern.match(self.type)
139b8e80941Smrg        if ufixed_match:
140b8e80941Smrg            self.type = 'ufixed'
141b8e80941Smrg            self.fractional_size = int(ufixed_match.group(2))
142b8e80941Smrg
143b8e80941Smrg        sfixed_match = Field.sfixed_pattern.match(self.type)
144b8e80941Smrg        if sfixed_match:
145b8e80941Smrg            self.type = 'sfixed'
146b8e80941Smrg            self.fractional_size = int(sfixed_match.group(2))
147b8e80941Smrg
148b8e80941Smrg    def emit_template_struct(self, dim):
149b8e80941Smrg        if self.type == 'address':
150b8e80941Smrg            type = '__gen_address_type'
151b8e80941Smrg        elif self.type == 'bool':
152b8e80941Smrg            type = 'bool'
153b8e80941Smrg        elif self.type == 'float':
154b8e80941Smrg            type = 'float'
155b8e80941Smrg        elif self.type == 'f187':
156b8e80941Smrg            type = 'float'
157b8e80941Smrg        elif self.type == 'ufixed':
158b8e80941Smrg            type = 'float'
159b8e80941Smrg        elif self.type == 'sfixed':
160b8e80941Smrg            type = 'float'
161b8e80941Smrg        elif self.type == 'uint' and self.end - self.start > 32:
162b8e80941Smrg            type = 'uint64_t'
163b8e80941Smrg        elif self.type == 'offset':
164b8e80941Smrg            type = 'uint64_t'
165b8e80941Smrg        elif self.type == 'int':
166b8e80941Smrg            type = 'int32_t'
167b8e80941Smrg        elif self.type == 'uint':
168b8e80941Smrg            type = 'uint32_t'
169b8e80941Smrg        elif self.type in self.parser.structs:
170b8e80941Smrg            type = 'struct ' + self.parser.gen_prefix(safe_name(self.type))
171b8e80941Smrg        elif self.type in self.parser.enums:
172b8e80941Smrg            type = 'enum ' + self.parser.gen_prefix(safe_name(self.type))
173b8e80941Smrg        elif self.type == 'mbo':
174b8e80941Smrg            return
175b8e80941Smrg        else:
176b8e80941Smrg            print("#error unhandled type: %s" % self.type)
177b8e80941Smrg            type = "uint32_t"
178b8e80941Smrg
179b8e80941Smrg        print("   %-36s %s%s;" % (type, self.name, dim))
180b8e80941Smrg
181b8e80941Smrg        for value in self.values:
182b8e80941Smrg            name = prefixed_upper_name(self.prefix, value.name)
183b8e80941Smrg            print("#define %-40s %d" % (name, value.value))
184b8e80941Smrg
185b8e80941Smrg    def overlaps(self, field):
186b8e80941Smrg        return self != field and max(self.start, field.start) <= min(self.end, field.end)
187b8e80941Smrg
188b8e80941Smrg
189b8e80941Smrgclass Group(object):
190b8e80941Smrg    def __init__(self, parser, parent, start, count):
191b8e80941Smrg        self.parser = parser
192b8e80941Smrg        self.parent = parent
193b8e80941Smrg        self.start = start
194b8e80941Smrg        self.count = count
195b8e80941Smrg        self.size = 0
196b8e80941Smrg        self.fields = []
197b8e80941Smrg        self.min_ver = 0
198b8e80941Smrg        self.max_ver = 0
199b8e80941Smrg
200b8e80941Smrg    def emit_template_struct(self, dim):
201b8e80941Smrg        if self.count == 0:
202b8e80941Smrg            print("   /* variable length fields follow */")
203b8e80941Smrg        else:
204b8e80941Smrg            if self.count > 1:
205b8e80941Smrg                dim = "%s[%d]" % (dim, self.count)
206b8e80941Smrg
207b8e80941Smrg            for field in self.fields:
208b8e80941Smrg                field.emit_template_struct(dim)
209b8e80941Smrg
210b8e80941Smrg    class Byte:
211b8e80941Smrg        def __init__(self):
212b8e80941Smrg            self.size = 8
213b8e80941Smrg            self.fields = []
214b8e80941Smrg            self.address = None
215b8e80941Smrg
216b8e80941Smrg    def collect_bytes(self, bytes):
217b8e80941Smrg        for field in self.fields:
218b8e80941Smrg            first_byte = field.start // 8
219b8e80941Smrg            last_byte = field.end // 8
220b8e80941Smrg
221b8e80941Smrg            for b in range(first_byte, last_byte + 1):
222b8e80941Smrg                if not b in bytes:
223b8e80941Smrg                    bytes[b] = self.Byte()
224b8e80941Smrg
225b8e80941Smrg                bytes[b].fields.append(field)
226b8e80941Smrg
227b8e80941Smrg                if field.type == "address":
228b8e80941Smrg                    # assert bytes[index].address == None
229b8e80941Smrg                    bytes[b].address = field
230b8e80941Smrg
231b8e80941Smrg    def emit_pack_function(self, start):
232b8e80941Smrg        # Determine number of bytes in this group.
233b8e80941Smrg        self.length = max(field.end // 8 for field in self.fields) + 1
234b8e80941Smrg
235b8e80941Smrg        bytes = {}
236b8e80941Smrg        self.collect_bytes(bytes)
237b8e80941Smrg
238b8e80941Smrg        relocs_emitted = set()
239b8e80941Smrg        memcpy_fields = set()
240b8e80941Smrg
241b8e80941Smrg        for field in self.fields:
242b8e80941Smrg            if field.minus_one:
243b8e80941Smrg                print("   assert(values->%s >= 1);" % field.name)
244b8e80941Smrg
245b8e80941Smrg        for index in range(self.length):
246b8e80941Smrg            # Handle MBZ bytes
247b8e80941Smrg            if not index in bytes:
248b8e80941Smrg                print("   cl[%2d] = 0;" % index)
249b8e80941Smrg                continue
250b8e80941Smrg            byte = bytes[index]
251b8e80941Smrg
252b8e80941Smrg            # Call out to the driver to note our relocations.  Inside of the
253b8e80941Smrg            # packet we only store offsets within the BOs, and we store the
254b8e80941Smrg            # handle to the packet outside.  Unlike Intel genxml, we don't
255b8e80941Smrg            # need to have the other bits that will be stored together with
256b8e80941Smrg            # the address during the reloc process, so there's no need for the
257b8e80941Smrg            # complicated combine_address() function.
258b8e80941Smrg            if byte.address and byte.address not in relocs_emitted:
259b8e80941Smrg                print("   __gen_emit_reloc(data, &values->%s);" % byte.address.name)
260b8e80941Smrg                relocs_emitted.add(byte.address)
261b8e80941Smrg
262b8e80941Smrg            # Special case: floats can't have any other fields packed into
263b8e80941Smrg            # them (since they'd change the meaning of the float), and the
264b8e80941Smrg            # per-byte bitshifting math below bloats the pack code for floats,
265b8e80941Smrg            # so just copy them directly here.  Also handle 16/32-bit
266b8e80941Smrg            # uints/ints with no merged fields.
267b8e80941Smrg            if len(byte.fields) == 1:
268b8e80941Smrg                field = byte.fields[0]
269b8e80941Smrg                if field.type in ["float", "uint", "int"] and field.start % 8 == 0 and field.end - field.start == 31 and not field.minus_one:
270b8e80941Smrg                    if field in memcpy_fields:
271b8e80941Smrg                        continue
272b8e80941Smrg
273b8e80941Smrg                    if not any(field.overlaps(scan_field) for scan_field in self.fields):
274b8e80941Smrg                        assert(field.start == index * 8)
275b8e80941Smrg                        print("")
276b8e80941Smrg                        print("   memcpy(&cl[%d], &values->%s, sizeof(values->%s));" %
277b8e80941Smrg                                (index, field.name, field.name))
278b8e80941Smrg                        memcpy_fields.add(field)
279b8e80941Smrg                        continue
280b8e80941Smrg
281b8e80941Smrg            byte_start = index * 8
282b8e80941Smrg
283b8e80941Smrg            v = None
284b8e80941Smrg            prefix = "   cl[%2d] =" % index
285b8e80941Smrg
286b8e80941Smrg            field_index = 0
287b8e80941Smrg            for field in byte.fields:
288b8e80941Smrg                if field.type != "mbo":
289b8e80941Smrg                    name = field.name
290b8e80941Smrg
291b8e80941Smrg                start = field.start
292b8e80941Smrg                end = field.end
293b8e80941Smrg                field_byte_start = (field.start // 8) * 8
294b8e80941Smrg                start -= field_byte_start
295b8e80941Smrg                end -= field_byte_start
296b8e80941Smrg                extra_shift = 0
297b8e80941Smrg
298b8e80941Smrg                value = "values->%s" % name
299b8e80941Smrg                if field.minus_one:
300b8e80941Smrg                    value = "%s - 1" % value
301b8e80941Smrg
302b8e80941Smrg                if field.type == "mbo":
303b8e80941Smrg                    s = "__gen_mbo(%d, %d)" % \
304b8e80941Smrg                        (start, end)
305b8e80941Smrg                elif field.type == "address":
306b8e80941Smrg                    extra_shift = (31 - (end - start)) // 8 * 8
307b8e80941Smrg                    s = "__gen_address_offset(&values->%s)" % byte.address.name
308b8e80941Smrg                elif field.type == "uint":
309b8e80941Smrg                    s = "__gen_uint(%s, %d, %d)" % \
310b8e80941Smrg                        (value, start, end)
311b8e80941Smrg                elif field.type in self.parser.enums:
312b8e80941Smrg                    s = "__gen_uint(%s, %d, %d)" % \
313b8e80941Smrg                        (value, start, end)
314b8e80941Smrg                elif field.type == "int":
315b8e80941Smrg                    s = "__gen_sint(%s, %d, %d)" % \
316b8e80941Smrg                        (value, start, end)
317b8e80941Smrg                elif field.type == "bool":
318b8e80941Smrg                    s = "__gen_uint(%s, %d, %d)" % \
319b8e80941Smrg                        (value, start, end)
320b8e80941Smrg                elif field.type == "float":
321b8e80941Smrg                    s = "#error %s float value mixed in with other fields" % name
322b8e80941Smrg                elif field.type == "f187":
323b8e80941Smrg                    s = "__gen_uint(fui(%s) >> 16, %d, %d)" % \
324b8e80941Smrg                        (value, start, end)
325b8e80941Smrg                elif field.type == "offset":
326b8e80941Smrg                    s = "__gen_offset(%s, %d, %d)" % \
327b8e80941Smrg                        (value, start, end)
328b8e80941Smrg                elif field.type == 'ufixed':
329b8e80941Smrg                    s = "__gen_ufixed(%s, %d, %d, %d)" % \
330b8e80941Smrg                        (value, start, end, field.fractional_size)
331b8e80941Smrg                elif field.type == 'sfixed':
332b8e80941Smrg                    s = "__gen_sfixed(%s, %d, %d, %d)" % \
333b8e80941Smrg                        (value, start, end, field.fractional_size)
334b8e80941Smrg                elif field.type in self.parser.structs:
335b8e80941Smrg                    s = "__gen_uint(v%d_%d, %d, %d)" % \
336b8e80941Smrg                        (index, field_index, start, end)
337b8e80941Smrg                    field_index = field_index + 1
338b8e80941Smrg                else:
339b8e80941Smrg                    print("/* unhandled field %s, type %s */\n" % (name, field.type))
340b8e80941Smrg                    s = None
341b8e80941Smrg
342b8e80941Smrg                if not s == None:
343b8e80941Smrg                    shift = byte_start - field_byte_start + extra_shift
344b8e80941Smrg                    if shift:
345b8e80941Smrg                        s = "%s >> %d" % (s, shift)
346b8e80941Smrg
347b8e80941Smrg                    if field == byte.fields[-1]:
348b8e80941Smrg                        print("%s %s;" % (prefix, s))
349b8e80941Smrg                    else:
350b8e80941Smrg                        print("%s %s |" % (prefix, s))
351b8e80941Smrg                    prefix = "           "
352b8e80941Smrg
353b8e80941Smrg            print("")
354b8e80941Smrg            continue
355b8e80941Smrg
356b8e80941Smrg    def emit_unpack_function(self, start):
357b8e80941Smrg        for field in self.fields:
358b8e80941Smrg            if field.type != "mbo":
359b8e80941Smrg                convert = None
360b8e80941Smrg
361b8e80941Smrg                args = []
362b8e80941Smrg                args.append('cl')
363b8e80941Smrg                args.append(str(start + field.start))
364b8e80941Smrg                args.append(str(start + field.end))
365b8e80941Smrg
366b8e80941Smrg                if field.type == "address":
367b8e80941Smrg                    convert = "__gen_unpack_address"
368b8e80941Smrg                elif field.type == "uint":
369b8e80941Smrg                    convert = "__gen_unpack_uint"
370b8e80941Smrg                elif field.type in self.parser.enums:
371b8e80941Smrg                    convert = "__gen_unpack_uint"
372b8e80941Smrg                elif field.type == "int":
373b8e80941Smrg                    convert = "__gen_unpack_sint"
374b8e80941Smrg                elif field.type == "bool":
375b8e80941Smrg                    convert = "__gen_unpack_uint"
376b8e80941Smrg                elif field.type == "float":
377b8e80941Smrg                    convert = "__gen_unpack_float"
378b8e80941Smrg                elif field.type == "f187":
379b8e80941Smrg                    convert = "__gen_unpack_f187"
380b8e80941Smrg                elif field.type == "offset":
381b8e80941Smrg                    convert = "__gen_unpack_offset"
382b8e80941Smrg                elif field.type == 'ufixed':
383b8e80941Smrg                    args.append(str(field.fractional_size))
384b8e80941Smrg                    convert = "__gen_unpack_ufixed"
385b8e80941Smrg                elif field.type == 'sfixed':
386b8e80941Smrg                    args.append(str(field.fractional_size))
387b8e80941Smrg                    convert = "__gen_unpack_sfixed"
388b8e80941Smrg                else:
389b8e80941Smrg                    print("/* unhandled field %s, type %s */\n" % (field.name, field.type))
390b8e80941Smrg                    s = None
391b8e80941Smrg
392b8e80941Smrg                plusone = ""
393b8e80941Smrg                if field.minus_one:
394b8e80941Smrg                    plusone = " + 1"
395b8e80941Smrg                print("   values->%s = %s(%s)%s;" % \
396b8e80941Smrg                      (field.name, convert, ', '.join(args), plusone))
397b8e80941Smrg
398b8e80941Smrgclass Value(object):
399b8e80941Smrg    def __init__(self, attrs):
400b8e80941Smrg        self.name = attrs["name"]
401b8e80941Smrg        self.value = int(attrs["value"])
402b8e80941Smrg
403b8e80941Smrgclass Parser(object):
404b8e80941Smrg    def __init__(self, ver):
405b8e80941Smrg        self.parser = xml.parsers.expat.ParserCreate()
406b8e80941Smrg        self.parser.StartElementHandler = self.start_element
407b8e80941Smrg        self.parser.EndElementHandler = self.end_element
408b8e80941Smrg
409b8e80941Smrg        self.packet = None
410b8e80941Smrg        self.struct = None
411b8e80941Smrg        self.structs = {}
412b8e80941Smrg        # Set of enum names we've seen.
413b8e80941Smrg        self.enums = set()
414b8e80941Smrg        self.registers = {}
415b8e80941Smrg        self.ver = ver
416b8e80941Smrg
417b8e80941Smrg    def gen_prefix(self, name):
418b8e80941Smrg        if name[0] == "_":
419b8e80941Smrg            return 'V3D%s%s' % (self.ver, name)
420b8e80941Smrg        else:
421b8e80941Smrg            return 'V3D%s_%s' % (self.ver, name)
422b8e80941Smrg
423b8e80941Smrg    def gen_guard(self):
424b8e80941Smrg        return self.gen_prefix("PACK_H")
425b8e80941Smrg
426b8e80941Smrg    def attrs_version_valid(self, attrs):
427b8e80941Smrg        if "min_ver" in attrs and self.ver < attrs["min_ver"]:
428b8e80941Smrg            return False
429b8e80941Smrg
430b8e80941Smrg        if "max_ver" in attrs and self.ver > attrs["max_ver"]:
431b8e80941Smrg            return False
432b8e80941Smrg
433b8e80941Smrg        return True
434b8e80941Smrg
435b8e80941Smrg    def group_enabled(self):
436b8e80941Smrg        if self.group.min_ver != 0 and self.ver < self.group.min_ver:
437b8e80941Smrg            return False
438b8e80941Smrg
439b8e80941Smrg        if self.group.max_ver != 0 and self.ver > self.group.max_ver:
440b8e80941Smrg            return False
441b8e80941Smrg
442b8e80941Smrg        return True
443b8e80941Smrg
444b8e80941Smrg    def start_element(self, name, attrs):
445b8e80941Smrg        if name == "vcxml":
446b8e80941Smrg            self.platform = "V3D {}.{}".format(self.ver[0], self.ver[1])
447b8e80941Smrg            print(pack_header % {'license': license, 'platform': self.platform, 'guard': self.gen_guard()})
448b8e80941Smrg        elif name in ("packet", "struct", "register"):
449b8e80941Smrg            default_field = None
450b8e80941Smrg
451b8e80941Smrg            object_name = self.gen_prefix(safe_name(attrs["name"].upper()))
452b8e80941Smrg            if name == "packet":
453b8e80941Smrg                self.packet = object_name
454b8e80941Smrg
455b8e80941Smrg                # Add a fixed Field for the opcode.  We only make <field>s in
456b8e80941Smrg                # the XML for the fields listed in the spec, and all of those
457b8e80941Smrg                # start from bit 0 after of the opcode.
458b8e80941Smrg                default_field = {
459b8e80941Smrg                    "name" : "opcode",
460b8e80941Smrg                    "default" : attrs["code"],
461b8e80941Smrg                    "type" : "uint",
462b8e80941Smrg                    "start" : -8,
463b8e80941Smrg                    "size" : 8,
464b8e80941Smrg                }
465b8e80941Smrg            elif name == "struct":
466b8e80941Smrg                self.struct = object_name
467b8e80941Smrg                self.structs[attrs["name"]] = 1
468b8e80941Smrg            elif name == "register":
469b8e80941Smrg                self.register = object_name
470b8e80941Smrg                self.reg_num = num_from_str(attrs["num"])
471b8e80941Smrg                self.registers[attrs["name"]] = 1
472b8e80941Smrg
473b8e80941Smrg            self.group = Group(self, None, 0, 1)
474b8e80941Smrg            if default_field:
475b8e80941Smrg                field = Field(self, default_field)
476b8e80941Smrg                field.values = []
477b8e80941Smrg                self.group.fields.append(field)
478b8e80941Smrg
479b8e80941Smrg            if "min_ver" in attrs:
480b8e80941Smrg                self.group.min_ver = attrs["min_ver"]
481b8e80941Smrg            if "max_ver" in attrs:
482b8e80941Smrg                self.group.max_ver = attrs["max_ver"]
483b8e80941Smrg
484b8e80941Smrg        elif name == "field":
485b8e80941Smrg            self.group.fields.append(Field(self, attrs))
486b8e80941Smrg            self.values = []
487b8e80941Smrg        elif name == "enum":
488b8e80941Smrg            self.values = []
489b8e80941Smrg            self.enum = safe_name(attrs["name"])
490b8e80941Smrg            self.enums.add(attrs["name"])
491b8e80941Smrg            self.enum_enabled = self.attrs_version_valid(attrs)
492b8e80941Smrg            if "prefix" in attrs:
493b8e80941Smrg                self.prefix = attrs["prefix"]
494b8e80941Smrg            else:
495b8e80941Smrg                self.prefix= None
496b8e80941Smrg        elif name == "value":
497b8e80941Smrg            if self.attrs_version_valid(attrs):
498b8e80941Smrg                self.values.append(Value(attrs))
499b8e80941Smrg
500b8e80941Smrg    def end_element(self, name):
501b8e80941Smrg        if name  == "packet":
502b8e80941Smrg            self.emit_packet()
503b8e80941Smrg            self.packet = None
504b8e80941Smrg            self.group = None
505b8e80941Smrg        elif name == "struct":
506b8e80941Smrg            self.emit_struct()
507b8e80941Smrg            self.struct = None
508b8e80941Smrg            self.group = None
509b8e80941Smrg        elif name == "register":
510b8e80941Smrg            self.emit_register()
511b8e80941Smrg            self.register = None
512b8e80941Smrg            self.reg_num = None
513b8e80941Smrg            self.group = None
514b8e80941Smrg        elif name  == "field":
515b8e80941Smrg            self.group.fields[-1].values = self.values
516b8e80941Smrg        elif name  == "enum":
517b8e80941Smrg            if self.enum_enabled:
518b8e80941Smrg                self.emit_enum()
519b8e80941Smrg            self.enum = None
520b8e80941Smrg        elif name == "vcxml":
521b8e80941Smrg            print('#endif /* %s */' % self.gen_guard())
522b8e80941Smrg
523b8e80941Smrg    def emit_template_struct(self, name, group):
524b8e80941Smrg        print("struct %s {" % name)
525b8e80941Smrg        group.emit_template_struct("")
526b8e80941Smrg        print("};\n")
527b8e80941Smrg
528b8e80941Smrg    def emit_pack_function(self, name, group):
529b8e80941Smrg        print("static inline void\n%s_pack(__gen_user_data *data, uint8_t * restrict cl,\n%sconst struct %s * restrict values)\n{" %
530b8e80941Smrg              (name, ' ' * (len(name) + 6), name))
531b8e80941Smrg
532b8e80941Smrg        group.emit_pack_function(0)
533b8e80941Smrg
534b8e80941Smrg        print("}\n")
535b8e80941Smrg
536b8e80941Smrg        print('#define %-33s %6d' %
537b8e80941Smrg              (name + "_length", self.group.length))
538b8e80941Smrg
539b8e80941Smrg    def emit_unpack_function(self, name, group):
540b8e80941Smrg        print("#ifdef __gen_unpack_address")
541b8e80941Smrg        print("static inline void")
542b8e80941Smrg        print("%s_unpack(const uint8_t * restrict cl,\n%sstruct %s * restrict values)\n{" %
543b8e80941Smrg              (name, ' ' * (len(name) + 8), name))
544b8e80941Smrg
545b8e80941Smrg        group.emit_unpack_function(0)
546b8e80941Smrg
547b8e80941Smrg        print("}\n#endif\n")
548b8e80941Smrg
549b8e80941Smrg    def emit_header(self, name):
550b8e80941Smrg        default_fields = []
551b8e80941Smrg        for field in self.group.fields:
552b8e80941Smrg            if not type(field) is Field:
553b8e80941Smrg                continue
554b8e80941Smrg            if field.default == None:
555b8e80941Smrg                continue
556b8e80941Smrg            default_fields.append("   .%-35s = %6d" % (field.name, field.default))
557b8e80941Smrg
558b8e80941Smrg        print('#define %-40s\\' % (name + '_header'))
559b8e80941Smrg        print(",  \\\n".join(default_fields))
560b8e80941Smrg        print('')
561b8e80941Smrg
562b8e80941Smrg    def emit_packet(self):
563b8e80941Smrg        if not self.group_enabled():
564b8e80941Smrg            return
565b8e80941Smrg
566b8e80941Smrg        name = self.packet
567b8e80941Smrg
568b8e80941Smrg        assert(self.group.fields[0].name == "opcode")
569b8e80941Smrg        print('#define %-33s %6d' %
570b8e80941Smrg              (name + "_opcode", self.group.fields[0].default))
571b8e80941Smrg
572b8e80941Smrg        self.emit_header(name)
573b8e80941Smrg        self.emit_template_struct(self.packet, self.group)
574b8e80941Smrg        self.emit_pack_function(self.packet, self.group)
575b8e80941Smrg        self.emit_unpack_function(self.packet, self.group)
576b8e80941Smrg
577b8e80941Smrg        print('')
578b8e80941Smrg
579b8e80941Smrg    def emit_register(self):
580b8e80941Smrg        if not self.group_enabled():
581b8e80941Smrg            return
582b8e80941Smrg
583b8e80941Smrg        name = self.register
584b8e80941Smrg        if not self.reg_num == None:
585b8e80941Smrg            print('#define %-33s 0x%04x' %
586b8e80941Smrg                  (self.gen_prefix(name + "_num"), self.reg_num))
587b8e80941Smrg
588b8e80941Smrg        self.emit_template_struct(self.register, self.group)
589b8e80941Smrg        self.emit_pack_function(self.register, self.group)
590b8e80941Smrg        self.emit_unpack_function(self.register, self.group)
591b8e80941Smrg
592b8e80941Smrg    def emit_struct(self):
593b8e80941Smrg        if not self.group_enabled():
594b8e80941Smrg            return
595b8e80941Smrg
596b8e80941Smrg        name = self.struct
597b8e80941Smrg
598b8e80941Smrg        self.emit_header(name)
599b8e80941Smrg        self.emit_template_struct(self.struct, self.group)
600b8e80941Smrg        self.emit_pack_function(self.struct, self.group)
601b8e80941Smrg        self.emit_unpack_function(self.struct, self.group)
602b8e80941Smrg
603b8e80941Smrg        print('')
604b8e80941Smrg
605b8e80941Smrg    def emit_enum(self):
606b8e80941Smrg        print('enum %s {' % self.gen_prefix(self.enum))
607b8e80941Smrg        for value in self.values:
608b8e80941Smrg            name = value.name
609b8e80941Smrg            if self.prefix:
610b8e80941Smrg                name = self.prefix + "_" + name
611b8e80941Smrg            name = safe_name(name).upper()
612b8e80941Smrg            print('        % -36s = %6d,' % (name, value.value))
613b8e80941Smrg        print('};\n')
614b8e80941Smrg
615b8e80941Smrg    def parse(self, filename):
616b8e80941Smrg        file = open(filename, "rb")
617b8e80941Smrg        self.parser.ParseFile(file)
618b8e80941Smrg        file.close()
619b8e80941Smrg
620b8e80941Smrgif len(sys.argv) < 2:
621b8e80941Smrg    print("No input xml file specified")
622b8e80941Smrg    sys.exit(1)
623b8e80941Smrg
624b8e80941Smrginput_file = sys.argv[1]
625b8e80941Smrg
626b8e80941Smrgp = Parser(sys.argv[2])
627b8e80941Smrgp.parse(input_file)
628