101e04c3fSmrg#encoding=utf-8
201e04c3fSmrg
301e04c3fSmrg# Copyright (C) 2016 Intel Corporation
401e04c3fSmrg# Copyright (C) 2016 Broadcom
501e04c3fSmrg#
601e04c3fSmrg# Permission is hereby granted, free of charge, to any person obtaining a
701e04c3fSmrg# copy of this software and associated documentation files (the "Software"),
801e04c3fSmrg# to deal in the Software without restriction, including without limitation
901e04c3fSmrg# the rights to use, copy, modify, merge, publish, distribute, sublicense,
1001e04c3fSmrg# and/or sell copies of the Software, and to permit persons to whom the
1101e04c3fSmrg# Software is furnished to do so, subject to the following conditions:
1201e04c3fSmrg#
1301e04c3fSmrg# The above copyright notice and this permission notice (including the next
1401e04c3fSmrg# paragraph) shall be included in all copies or substantial portions of the
1501e04c3fSmrg# Software.
1601e04c3fSmrg#
1701e04c3fSmrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1801e04c3fSmrg# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1901e04c3fSmrg# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
2001e04c3fSmrg# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2101e04c3fSmrg# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2201e04c3fSmrg# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
2301e04c3fSmrg# IN THE SOFTWARE.
2401e04c3fSmrg
2501e04c3fSmrgimport xml.parsers.expat
2601e04c3fSmrgimport re
2701e04c3fSmrgimport sys
2801e04c3fSmrgimport copy
2901e04c3fSmrg
307ec681f3Smrglicense =  """/* Generated code, see v3d_packet_v21.xml, v3d_packet_v33.xml and gen_pack_header.py */
3101e04c3fSmrg"""
3201e04c3fSmrg
3301e04c3fSmrgpack_header = """%(license)s
3401e04c3fSmrg
3501e04c3fSmrg/* Packets, enums and structures for %(platform)s.
3601e04c3fSmrg *
3701e04c3fSmrg * This file has been generated, do not hand edit.
3801e04c3fSmrg */
3901e04c3fSmrg
4001e04c3fSmrg#ifndef %(guard)s
4101e04c3fSmrg#define %(guard)s
4201e04c3fSmrg
4301e04c3fSmrg#include "cle/v3d_packet_helpers.h"
4401e04c3fSmrg
4501e04c3fSmrg"""
4601e04c3fSmrg
4701e04c3fSmrgdef to_alphanum(name):
4801e04c3fSmrg    substitutions = {
4901e04c3fSmrg        ' ': '_',
5001e04c3fSmrg        '/': '_',
5101e04c3fSmrg        '[': '',
5201e04c3fSmrg        ']': '',
5301e04c3fSmrg        '(': '',
5401e04c3fSmrg        ')': '',
5501e04c3fSmrg        '-': '_',
5601e04c3fSmrg        ':': '',
5701e04c3fSmrg        '.': '',
5801e04c3fSmrg        ',': '',
5901e04c3fSmrg        '=': '',
6001e04c3fSmrg        '>': '',
6101e04c3fSmrg        '#': '',
6201e04c3fSmrg        '&': '',
6301e04c3fSmrg        '*': '',
6401e04c3fSmrg        '"': '',
6501e04c3fSmrg        '+': '',
6601e04c3fSmrg        '\'': '',
6701e04c3fSmrg    }
6801e04c3fSmrg
6901e04c3fSmrg    for i, j in substitutions.items():
7001e04c3fSmrg        name = name.replace(i, j)
7101e04c3fSmrg
7201e04c3fSmrg    return name
7301e04c3fSmrg
7401e04c3fSmrgdef safe_name(name):
7501e04c3fSmrg    name = to_alphanum(name)
7601e04c3fSmrg    if not name[0].isalpha():
7701e04c3fSmrg        name = '_' + name
7801e04c3fSmrg
7901e04c3fSmrg    return name
8001e04c3fSmrg
8101e04c3fSmrgdef prefixed_upper_name(prefix, name):
8201e04c3fSmrg    if prefix:
8301e04c3fSmrg        name = prefix + "_" + name
8401e04c3fSmrg    return safe_name(name).upper()
8501e04c3fSmrg
8601e04c3fSmrgdef num_from_str(num_str):
8701e04c3fSmrg    if num_str.lower().startswith('0x'):
8801e04c3fSmrg        return int(num_str, base=16)
8901e04c3fSmrg    else:
9001e04c3fSmrg        assert(not num_str.startswith('0') and 'octals numbers not allowed')
9101e04c3fSmrg        return int(num_str)
9201e04c3fSmrg
9301e04c3fSmrgclass Field(object):
9401e04c3fSmrg    ufixed_pattern = re.compile(r"u(\d+)\.(\d+)")
9501e04c3fSmrg    sfixed_pattern = re.compile(r"s(\d+)\.(\d+)")
9601e04c3fSmrg
9701e04c3fSmrg    def __init__(self, parser, attrs):
9801e04c3fSmrg        self.parser = parser
9901e04c3fSmrg        if "name" in attrs:
10001e04c3fSmrg            self.name = safe_name(attrs["name"]).lower()
10101e04c3fSmrg
10201e04c3fSmrg        if str(attrs["start"]).endswith("b"):
10301e04c3fSmrg            self.start = int(attrs["start"][:-1]) * 8
10401e04c3fSmrg        else:
10501e04c3fSmrg            self.start = int(attrs["start"])
10601e04c3fSmrg        # packet <field> entries in XML start from the bit after the
10701e04c3fSmrg        # opcode, so shift everything up by 8 since we'll also have a
10801e04c3fSmrg        # Field for the opcode.
10901e04c3fSmrg        if not parser.struct:
11001e04c3fSmrg            self.start += 8
11101e04c3fSmrg
11201e04c3fSmrg        self.end = self.start + int(attrs["size"]) - 1
11301e04c3fSmrg        self.type = attrs["type"]
11401e04c3fSmrg
11501e04c3fSmrg        if self.type == 'bool' and self.start != self.end:
11601e04c3fSmrg            print("#error Field {} has bool type but more than one bit of size".format(self.name));
11701e04c3fSmrg
11801e04c3fSmrg        if "prefix" in attrs:
11901e04c3fSmrg            self.prefix = safe_name(attrs["prefix"]).upper()
12001e04c3fSmrg        else:
12101e04c3fSmrg            self.prefix = None
12201e04c3fSmrg
12301e04c3fSmrg        if "default" in attrs:
12401e04c3fSmrg            self.default = int(attrs["default"])
12501e04c3fSmrg        else:
12601e04c3fSmrg            self.default = None
12701e04c3fSmrg
12801e04c3fSmrg        if "minus_one" in attrs:
12901e04c3fSmrg            assert(attrs["minus_one"] == "true")
13001e04c3fSmrg            self.minus_one = True
13101e04c3fSmrg        else:
13201e04c3fSmrg            self.minus_one = False
13301e04c3fSmrg
13401e04c3fSmrg        ufixed_match = Field.ufixed_pattern.match(self.type)
13501e04c3fSmrg        if ufixed_match:
13601e04c3fSmrg            self.type = 'ufixed'
13701e04c3fSmrg            self.fractional_size = int(ufixed_match.group(2))
13801e04c3fSmrg
13901e04c3fSmrg        sfixed_match = Field.sfixed_pattern.match(self.type)
14001e04c3fSmrg        if sfixed_match:
14101e04c3fSmrg            self.type = 'sfixed'
14201e04c3fSmrg            self.fractional_size = int(sfixed_match.group(2))
14301e04c3fSmrg
14401e04c3fSmrg    def emit_template_struct(self, dim):
14501e04c3fSmrg        if self.type == 'address':
14601e04c3fSmrg            type = '__gen_address_type'
14701e04c3fSmrg        elif self.type == 'bool':
14801e04c3fSmrg            type = 'bool'
14901e04c3fSmrg        elif self.type == 'float':
15001e04c3fSmrg            type = 'float'
15101e04c3fSmrg        elif self.type == 'f187':
15201e04c3fSmrg            type = 'float'
15301e04c3fSmrg        elif self.type == 'ufixed':
15401e04c3fSmrg            type = 'float'
15501e04c3fSmrg        elif self.type == 'sfixed':
15601e04c3fSmrg            type = 'float'
15701e04c3fSmrg        elif self.type == 'uint' and self.end - self.start > 32:
15801e04c3fSmrg            type = 'uint64_t'
15901e04c3fSmrg        elif self.type == 'offset':
16001e04c3fSmrg            type = 'uint64_t'
16101e04c3fSmrg        elif self.type == 'int':
16201e04c3fSmrg            type = 'int32_t'
16301e04c3fSmrg        elif self.type == 'uint':
16401e04c3fSmrg            type = 'uint32_t'
16501e04c3fSmrg        elif self.type in self.parser.structs:
16601e04c3fSmrg            type = 'struct ' + self.parser.gen_prefix(safe_name(self.type))
16701e04c3fSmrg        elif self.type in self.parser.enums:
16801e04c3fSmrg            type = 'enum ' + self.parser.gen_prefix(safe_name(self.type))
16901e04c3fSmrg        elif self.type == 'mbo':
17001e04c3fSmrg            return
17101e04c3fSmrg        else:
17201e04c3fSmrg            print("#error unhandled type: %s" % self.type)
17301e04c3fSmrg            type = "uint32_t"
17401e04c3fSmrg
17501e04c3fSmrg        print("   %-36s %s%s;" % (type, self.name, dim))
17601e04c3fSmrg
17701e04c3fSmrg        for value in self.values:
17801e04c3fSmrg            name = prefixed_upper_name(self.prefix, value.name)
17901e04c3fSmrg            print("#define %-40s %d" % (name, value.value))
18001e04c3fSmrg
18101e04c3fSmrg    def overlaps(self, field):
18201e04c3fSmrg        return self != field and max(self.start, field.start) <= min(self.end, field.end)
18301e04c3fSmrg
18401e04c3fSmrg
18501e04c3fSmrgclass Group(object):
18601e04c3fSmrg    def __init__(self, parser, parent, start, count):
18701e04c3fSmrg        self.parser = parser
18801e04c3fSmrg        self.parent = parent
18901e04c3fSmrg        self.start = start
19001e04c3fSmrg        self.count = count
19101e04c3fSmrg        self.size = 0
19201e04c3fSmrg        self.fields = []
19301e04c3fSmrg        self.min_ver = 0
19401e04c3fSmrg        self.max_ver = 0
19501e04c3fSmrg
19601e04c3fSmrg    def emit_template_struct(self, dim):
19701e04c3fSmrg        if self.count == 0:
19801e04c3fSmrg            print("   /* variable length fields follow */")
19901e04c3fSmrg        else:
20001e04c3fSmrg            if self.count > 1:
20101e04c3fSmrg                dim = "%s[%d]" % (dim, self.count)
20201e04c3fSmrg
20301e04c3fSmrg            for field in self.fields:
20401e04c3fSmrg                field.emit_template_struct(dim)
20501e04c3fSmrg
20601e04c3fSmrg    class Byte:
20701e04c3fSmrg        def __init__(self):
20801e04c3fSmrg            self.size = 8
20901e04c3fSmrg            self.fields = []
21001e04c3fSmrg            self.address = None
21101e04c3fSmrg
21201e04c3fSmrg    def collect_bytes(self, bytes):
21301e04c3fSmrg        for field in self.fields:
21401e04c3fSmrg            first_byte = field.start // 8
21501e04c3fSmrg            last_byte = field.end // 8
21601e04c3fSmrg
21701e04c3fSmrg            for b in range(first_byte, last_byte + 1):
21801e04c3fSmrg                if not b in bytes:
21901e04c3fSmrg                    bytes[b] = self.Byte()
22001e04c3fSmrg
22101e04c3fSmrg                bytes[b].fields.append(field)
22201e04c3fSmrg
22301e04c3fSmrg                if field.type == "address":
22401e04c3fSmrg                    # assert bytes[index].address == None
22501e04c3fSmrg                    bytes[b].address = field
22601e04c3fSmrg
22701e04c3fSmrg    def emit_pack_function(self, start):
22801e04c3fSmrg        # Determine number of bytes in this group.
22901e04c3fSmrg        self.length = max(field.end // 8 for field in self.fields) + 1
23001e04c3fSmrg
23101e04c3fSmrg        bytes = {}
23201e04c3fSmrg        self.collect_bytes(bytes)
23301e04c3fSmrg
23401e04c3fSmrg        relocs_emitted = set()
23501e04c3fSmrg        memcpy_fields = set()
23601e04c3fSmrg
23701e04c3fSmrg        for field in self.fields:
23801e04c3fSmrg            if field.minus_one:
23901e04c3fSmrg                print("   assert(values->%s >= 1);" % field.name)
24001e04c3fSmrg
24101e04c3fSmrg        for index in range(self.length):
24201e04c3fSmrg            # Handle MBZ bytes
24301e04c3fSmrg            if not index in bytes:
24401e04c3fSmrg                print("   cl[%2d] = 0;" % index)
24501e04c3fSmrg                continue
24601e04c3fSmrg            byte = bytes[index]
24701e04c3fSmrg
24801e04c3fSmrg            # Call out to the driver to note our relocations.  Inside of the
24901e04c3fSmrg            # packet we only store offsets within the BOs, and we store the
25001e04c3fSmrg            # handle to the packet outside.  Unlike Intel genxml, we don't
25101e04c3fSmrg            # need to have the other bits that will be stored together with
25201e04c3fSmrg            # the address during the reloc process, so there's no need for the
25301e04c3fSmrg            # complicated combine_address() function.
25401e04c3fSmrg            if byte.address and byte.address not in relocs_emitted:
25501e04c3fSmrg                print("   __gen_emit_reloc(data, &values->%s);" % byte.address.name)
25601e04c3fSmrg                relocs_emitted.add(byte.address)
25701e04c3fSmrg
25801e04c3fSmrg            # Special case: floats can't have any other fields packed into
25901e04c3fSmrg            # them (since they'd change the meaning of the float), and the
26001e04c3fSmrg            # per-byte bitshifting math below bloats the pack code for floats,
26101e04c3fSmrg            # so just copy them directly here.  Also handle 16/32-bit
26201e04c3fSmrg            # uints/ints with no merged fields.
26301e04c3fSmrg            if len(byte.fields) == 1:
26401e04c3fSmrg                field = byte.fields[0]
26501e04c3fSmrg                if field.type in ["float", "uint", "int"] and field.start % 8 == 0 and field.end - field.start == 31 and not field.minus_one:
26601e04c3fSmrg                    if field in memcpy_fields:
26701e04c3fSmrg                        continue
26801e04c3fSmrg
26901e04c3fSmrg                    if not any(field.overlaps(scan_field) for scan_field in self.fields):
27001e04c3fSmrg                        assert(field.start == index * 8)
27101e04c3fSmrg                        print("")
27201e04c3fSmrg                        print("   memcpy(&cl[%d], &values->%s, sizeof(values->%s));" %
27301e04c3fSmrg                                (index, field.name, field.name))
27401e04c3fSmrg                        memcpy_fields.add(field)
27501e04c3fSmrg                        continue
27601e04c3fSmrg
27701e04c3fSmrg            byte_start = index * 8
27801e04c3fSmrg
27901e04c3fSmrg            v = None
28001e04c3fSmrg            prefix = "   cl[%2d] =" % index
28101e04c3fSmrg
28201e04c3fSmrg            field_index = 0
28301e04c3fSmrg            for field in byte.fields:
28401e04c3fSmrg                if field.type != "mbo":
28501e04c3fSmrg                    name = field.name
28601e04c3fSmrg
28701e04c3fSmrg                start = field.start
28801e04c3fSmrg                end = field.end
28901e04c3fSmrg                field_byte_start = (field.start // 8) * 8
29001e04c3fSmrg                start -= field_byte_start
29101e04c3fSmrg                end -= field_byte_start
29201e04c3fSmrg                extra_shift = 0
29301e04c3fSmrg
29401e04c3fSmrg                value = "values->%s" % name
29501e04c3fSmrg                if field.minus_one:
29601e04c3fSmrg                    value = "%s - 1" % value
29701e04c3fSmrg
29801e04c3fSmrg                if field.type == "mbo":
29901e04c3fSmrg                    s = "__gen_mbo(%d, %d)" % \
30001e04c3fSmrg                        (start, end)
30101e04c3fSmrg                elif field.type == "address":
30201e04c3fSmrg                    extra_shift = (31 - (end - start)) // 8 * 8
30301e04c3fSmrg                    s = "__gen_address_offset(&values->%s)" % byte.address.name
30401e04c3fSmrg                elif field.type == "uint":
30501e04c3fSmrg                    s = "__gen_uint(%s, %d, %d)" % \
30601e04c3fSmrg                        (value, start, end)
30701e04c3fSmrg                elif field.type in self.parser.enums:
30801e04c3fSmrg                    s = "__gen_uint(%s, %d, %d)" % \
30901e04c3fSmrg                        (value, start, end)
31001e04c3fSmrg                elif field.type == "int":
31101e04c3fSmrg                    s = "__gen_sint(%s, %d, %d)" % \
31201e04c3fSmrg                        (value, start, end)
31301e04c3fSmrg                elif field.type == "bool":
31401e04c3fSmrg                    s = "__gen_uint(%s, %d, %d)" % \
31501e04c3fSmrg                        (value, start, end)
31601e04c3fSmrg                elif field.type == "float":
31701e04c3fSmrg                    s = "#error %s float value mixed in with other fields" % name
31801e04c3fSmrg                elif field.type == "f187":
31901e04c3fSmrg                    s = "__gen_uint(fui(%s) >> 16, %d, %d)" % \
32001e04c3fSmrg                        (value, start, end)
32101e04c3fSmrg                elif field.type == "offset":
32201e04c3fSmrg                    s = "__gen_offset(%s, %d, %d)" % \
32301e04c3fSmrg                        (value, start, end)
32401e04c3fSmrg                elif field.type == 'ufixed':
32501e04c3fSmrg                    s = "__gen_ufixed(%s, %d, %d, %d)" % \
32601e04c3fSmrg                        (value, start, end, field.fractional_size)
32701e04c3fSmrg                elif field.type == 'sfixed':
32801e04c3fSmrg                    s = "__gen_sfixed(%s, %d, %d, %d)" % \
32901e04c3fSmrg                        (value, start, end, field.fractional_size)
33001e04c3fSmrg                elif field.type in self.parser.structs:
33101e04c3fSmrg                    s = "__gen_uint(v%d_%d, %d, %d)" % \
33201e04c3fSmrg                        (index, field_index, start, end)
33301e04c3fSmrg                    field_index = field_index + 1
33401e04c3fSmrg                else:
33501e04c3fSmrg                    print("/* unhandled field %s, type %s */\n" % (name, field.type))
33601e04c3fSmrg                    s = None
33701e04c3fSmrg
33801e04c3fSmrg                if not s == None:
33901e04c3fSmrg                    shift = byte_start - field_byte_start + extra_shift
34001e04c3fSmrg                    if shift:
34101e04c3fSmrg                        s = "%s >> %d" % (s, shift)
34201e04c3fSmrg
34301e04c3fSmrg                    if field == byte.fields[-1]:
34401e04c3fSmrg                        print("%s %s;" % (prefix, s))
34501e04c3fSmrg                    else:
34601e04c3fSmrg                        print("%s %s |" % (prefix, s))
34701e04c3fSmrg                    prefix = "           "
34801e04c3fSmrg
34901e04c3fSmrg            print("")
35001e04c3fSmrg            continue
35101e04c3fSmrg
35201e04c3fSmrg    def emit_unpack_function(self, start):
35301e04c3fSmrg        for field in self.fields:
35401e04c3fSmrg            if field.type != "mbo":
35501e04c3fSmrg                convert = None
35601e04c3fSmrg
35701e04c3fSmrg                args = []
35801e04c3fSmrg                args.append('cl')
35901e04c3fSmrg                args.append(str(start + field.start))
36001e04c3fSmrg                args.append(str(start + field.end))
36101e04c3fSmrg
36201e04c3fSmrg                if field.type == "address":
36301e04c3fSmrg                    convert = "__gen_unpack_address"
36401e04c3fSmrg                elif field.type == "uint":
36501e04c3fSmrg                    convert = "__gen_unpack_uint"
36601e04c3fSmrg                elif field.type in self.parser.enums:
36701e04c3fSmrg                    convert = "__gen_unpack_uint"
36801e04c3fSmrg                elif field.type == "int":
36901e04c3fSmrg                    convert = "__gen_unpack_sint"
37001e04c3fSmrg                elif field.type == "bool":
37101e04c3fSmrg                    convert = "__gen_unpack_uint"
37201e04c3fSmrg                elif field.type == "float":
37301e04c3fSmrg                    convert = "__gen_unpack_float"
37401e04c3fSmrg                elif field.type == "f187":
37501e04c3fSmrg                    convert = "__gen_unpack_f187"
37601e04c3fSmrg                elif field.type == "offset":
37701e04c3fSmrg                    convert = "__gen_unpack_offset"
37801e04c3fSmrg                elif field.type == 'ufixed':
37901e04c3fSmrg                    args.append(str(field.fractional_size))
38001e04c3fSmrg                    convert = "__gen_unpack_ufixed"
38101e04c3fSmrg                elif field.type == 'sfixed':
38201e04c3fSmrg                    args.append(str(field.fractional_size))
38301e04c3fSmrg                    convert = "__gen_unpack_sfixed"
38401e04c3fSmrg                else:
38501e04c3fSmrg                    print("/* unhandled field %s, type %s */\n" % (field.name, field.type))
38601e04c3fSmrg                    s = None
38701e04c3fSmrg
38801e04c3fSmrg                plusone = ""
38901e04c3fSmrg                if field.minus_one:
39001e04c3fSmrg                    plusone = " + 1"
39101e04c3fSmrg                print("   values->%s = %s(%s)%s;" % \
39201e04c3fSmrg                      (field.name, convert, ', '.join(args), plusone))
39301e04c3fSmrg
39401e04c3fSmrgclass Value(object):
39501e04c3fSmrg    def __init__(self, attrs):
39601e04c3fSmrg        self.name = attrs["name"]
39701e04c3fSmrg        self.value = int(attrs["value"])
39801e04c3fSmrg
39901e04c3fSmrgclass Parser(object):
40001e04c3fSmrg    def __init__(self, ver):
40101e04c3fSmrg        self.parser = xml.parsers.expat.ParserCreate()
40201e04c3fSmrg        self.parser.StartElementHandler = self.start_element
40301e04c3fSmrg        self.parser.EndElementHandler = self.end_element
40401e04c3fSmrg
40501e04c3fSmrg        self.packet = None
40601e04c3fSmrg        self.struct = None
40701e04c3fSmrg        self.structs = {}
40801e04c3fSmrg        # Set of enum names we've seen.
40901e04c3fSmrg        self.enums = set()
41001e04c3fSmrg        self.registers = {}
41101e04c3fSmrg        self.ver = ver
41201e04c3fSmrg
41301e04c3fSmrg    def gen_prefix(self, name):
41401e04c3fSmrg        if name[0] == "_":
41501e04c3fSmrg            return 'V3D%s%s' % (self.ver, name)
41601e04c3fSmrg        else:
41701e04c3fSmrg            return 'V3D%s_%s' % (self.ver, name)
41801e04c3fSmrg
41901e04c3fSmrg    def gen_guard(self):
42001e04c3fSmrg        return self.gen_prefix("PACK_H")
42101e04c3fSmrg
42201e04c3fSmrg    def attrs_version_valid(self, attrs):
42301e04c3fSmrg        if "min_ver" in attrs and self.ver < attrs["min_ver"]:
42401e04c3fSmrg            return False
42501e04c3fSmrg
42601e04c3fSmrg        if "max_ver" in attrs and self.ver > attrs["max_ver"]:
42701e04c3fSmrg            return False
42801e04c3fSmrg
42901e04c3fSmrg        return True
43001e04c3fSmrg
43101e04c3fSmrg    def group_enabled(self):
43201e04c3fSmrg        if self.group.min_ver != 0 and self.ver < self.group.min_ver:
43301e04c3fSmrg            return False
43401e04c3fSmrg
43501e04c3fSmrg        if self.group.max_ver != 0 and self.ver > self.group.max_ver:
43601e04c3fSmrg            return False
43701e04c3fSmrg
43801e04c3fSmrg        return True
43901e04c3fSmrg
44001e04c3fSmrg    def start_element(self, name, attrs):
44101e04c3fSmrg        if name == "vcxml":
44201e04c3fSmrg            self.platform = "V3D {}.{}".format(self.ver[0], self.ver[1])
44301e04c3fSmrg            print(pack_header % {'license': license, 'platform': self.platform, 'guard': self.gen_guard()})
44401e04c3fSmrg        elif name in ("packet", "struct", "register"):
44501e04c3fSmrg            default_field = None
44601e04c3fSmrg
44701e04c3fSmrg            object_name = self.gen_prefix(safe_name(attrs["name"].upper()))
44801e04c3fSmrg            if name == "packet":
44901e04c3fSmrg                self.packet = object_name
45001e04c3fSmrg
45101e04c3fSmrg                # Add a fixed Field for the opcode.  We only make <field>s in
45201e04c3fSmrg                # the XML for the fields listed in the spec, and all of those
45301e04c3fSmrg                # start from bit 0 after of the opcode.
45401e04c3fSmrg                default_field = {
45501e04c3fSmrg                    "name" : "opcode",
45601e04c3fSmrg                    "default" : attrs["code"],
45701e04c3fSmrg                    "type" : "uint",
45801e04c3fSmrg                    "start" : -8,
45901e04c3fSmrg                    "size" : 8,
46001e04c3fSmrg                }
46101e04c3fSmrg            elif name == "struct":
46201e04c3fSmrg                self.struct = object_name
46301e04c3fSmrg                self.structs[attrs["name"]] = 1
46401e04c3fSmrg            elif name == "register":
46501e04c3fSmrg                self.register = object_name
46601e04c3fSmrg                self.reg_num = num_from_str(attrs["num"])
46701e04c3fSmrg                self.registers[attrs["name"]] = 1
46801e04c3fSmrg
46901e04c3fSmrg            self.group = Group(self, None, 0, 1)
47001e04c3fSmrg            if default_field:
47101e04c3fSmrg                field = Field(self, default_field)
47201e04c3fSmrg                field.values = []
47301e04c3fSmrg                self.group.fields.append(field)
47401e04c3fSmrg
47501e04c3fSmrg            if "min_ver" in attrs:
47601e04c3fSmrg                self.group.min_ver = attrs["min_ver"]
47701e04c3fSmrg            if "max_ver" in attrs:
47801e04c3fSmrg                self.group.max_ver = attrs["max_ver"]
47901e04c3fSmrg
48001e04c3fSmrg        elif name == "field":
48101e04c3fSmrg            self.group.fields.append(Field(self, attrs))
48201e04c3fSmrg            self.values = []
48301e04c3fSmrg        elif name == "enum":
48401e04c3fSmrg            self.values = []
48501e04c3fSmrg            self.enum = safe_name(attrs["name"])
48601e04c3fSmrg            self.enums.add(attrs["name"])
48701e04c3fSmrg            self.enum_enabled = self.attrs_version_valid(attrs)
48801e04c3fSmrg            if "prefix" in attrs:
48901e04c3fSmrg                self.prefix = attrs["prefix"]
49001e04c3fSmrg            else:
49101e04c3fSmrg                self.prefix= None
49201e04c3fSmrg        elif name == "value":
49301e04c3fSmrg            if self.attrs_version_valid(attrs):
49401e04c3fSmrg                self.values.append(Value(attrs))
49501e04c3fSmrg
49601e04c3fSmrg    def end_element(self, name):
49701e04c3fSmrg        if name  == "packet":
49801e04c3fSmrg            self.emit_packet()
49901e04c3fSmrg            self.packet = None
50001e04c3fSmrg            self.group = None
50101e04c3fSmrg        elif name == "struct":
50201e04c3fSmrg            self.emit_struct()
50301e04c3fSmrg            self.struct = None
50401e04c3fSmrg            self.group = None
50501e04c3fSmrg        elif name == "register":
50601e04c3fSmrg            self.emit_register()
50701e04c3fSmrg            self.register = None
50801e04c3fSmrg            self.reg_num = None
50901e04c3fSmrg            self.group = None
51001e04c3fSmrg        elif name  == "field":
51101e04c3fSmrg            self.group.fields[-1].values = self.values
51201e04c3fSmrg        elif name  == "enum":
51301e04c3fSmrg            if self.enum_enabled:
51401e04c3fSmrg                self.emit_enum()
51501e04c3fSmrg            self.enum = None
51601e04c3fSmrg        elif name == "vcxml":
51701e04c3fSmrg            print('#endif /* %s */' % self.gen_guard())
51801e04c3fSmrg
51901e04c3fSmrg    def emit_template_struct(self, name, group):
52001e04c3fSmrg        print("struct %s {" % name)
52101e04c3fSmrg        group.emit_template_struct("")
52201e04c3fSmrg        print("};\n")
52301e04c3fSmrg
52401e04c3fSmrg    def emit_pack_function(self, name, group):
52501e04c3fSmrg        print("static inline void\n%s_pack(__gen_user_data *data, uint8_t * restrict cl,\n%sconst struct %s * restrict values)\n{" %
52601e04c3fSmrg              (name, ' ' * (len(name) + 6), name))
52701e04c3fSmrg
52801e04c3fSmrg        group.emit_pack_function(0)
52901e04c3fSmrg
53001e04c3fSmrg        print("}\n")
53101e04c3fSmrg
53201e04c3fSmrg        print('#define %-33s %6d' %
53301e04c3fSmrg              (name + "_length", self.group.length))
53401e04c3fSmrg
53501e04c3fSmrg    def emit_unpack_function(self, name, group):
53601e04c3fSmrg        print("#ifdef __gen_unpack_address")
53701e04c3fSmrg        print("static inline void")
53801e04c3fSmrg        print("%s_unpack(const uint8_t * restrict cl,\n%sstruct %s * restrict values)\n{" %
53901e04c3fSmrg              (name, ' ' * (len(name) + 8), name))
54001e04c3fSmrg
54101e04c3fSmrg        group.emit_unpack_function(0)
54201e04c3fSmrg
54301e04c3fSmrg        print("}\n#endif\n")
54401e04c3fSmrg
54501e04c3fSmrg    def emit_header(self, name):
54601e04c3fSmrg        default_fields = []
54701e04c3fSmrg        for field in self.group.fields:
54801e04c3fSmrg            if not type(field) is Field:
54901e04c3fSmrg                continue
55001e04c3fSmrg            if field.default == None:
55101e04c3fSmrg                continue
55201e04c3fSmrg            default_fields.append("   .%-35s = %6d" % (field.name, field.default))
55301e04c3fSmrg
55401e04c3fSmrg        print('#define %-40s\\' % (name + '_header'))
55501e04c3fSmrg        print(",  \\\n".join(default_fields))
55601e04c3fSmrg        print('')
55701e04c3fSmrg
55801e04c3fSmrg    def emit_packet(self):
55901e04c3fSmrg        if not self.group_enabled():
56001e04c3fSmrg            return
56101e04c3fSmrg
56201e04c3fSmrg        name = self.packet
56301e04c3fSmrg
56401e04c3fSmrg        assert(self.group.fields[0].name == "opcode")
56501e04c3fSmrg        print('#define %-33s %6d' %
56601e04c3fSmrg              (name + "_opcode", self.group.fields[0].default))
56701e04c3fSmrg
56801e04c3fSmrg        self.emit_header(name)
56901e04c3fSmrg        self.emit_template_struct(self.packet, self.group)
57001e04c3fSmrg        self.emit_pack_function(self.packet, self.group)
57101e04c3fSmrg        self.emit_unpack_function(self.packet, self.group)
57201e04c3fSmrg
57301e04c3fSmrg        print('')
57401e04c3fSmrg
57501e04c3fSmrg    def emit_register(self):
57601e04c3fSmrg        if not self.group_enabled():
57701e04c3fSmrg            return
57801e04c3fSmrg
57901e04c3fSmrg        name = self.register
58001e04c3fSmrg        if not self.reg_num == None:
58101e04c3fSmrg            print('#define %-33s 0x%04x' %
58201e04c3fSmrg                  (self.gen_prefix(name + "_num"), self.reg_num))
58301e04c3fSmrg
58401e04c3fSmrg        self.emit_template_struct(self.register, self.group)
58501e04c3fSmrg        self.emit_pack_function(self.register, self.group)
58601e04c3fSmrg        self.emit_unpack_function(self.register, self.group)
58701e04c3fSmrg
58801e04c3fSmrg    def emit_struct(self):
58901e04c3fSmrg        if not self.group_enabled():
59001e04c3fSmrg            return
59101e04c3fSmrg
59201e04c3fSmrg        name = self.struct
59301e04c3fSmrg
59401e04c3fSmrg        self.emit_header(name)
59501e04c3fSmrg        self.emit_template_struct(self.struct, self.group)
59601e04c3fSmrg        self.emit_pack_function(self.struct, self.group)
59701e04c3fSmrg        self.emit_unpack_function(self.struct, self.group)
59801e04c3fSmrg
59901e04c3fSmrg        print('')
60001e04c3fSmrg
60101e04c3fSmrg    def emit_enum(self):
60201e04c3fSmrg        print('enum %s {' % self.gen_prefix(self.enum))
60301e04c3fSmrg        for value in self.values:
60401e04c3fSmrg            name = value.name
60501e04c3fSmrg            if self.prefix:
60601e04c3fSmrg                name = self.prefix + "_" + name
60701e04c3fSmrg            name = safe_name(name).upper()
60801e04c3fSmrg            print('        % -36s = %6d,' % (name, value.value))
60901e04c3fSmrg        print('};\n')
61001e04c3fSmrg
61101e04c3fSmrg    def parse(self, filename):
61201e04c3fSmrg        file = open(filename, "rb")
61301e04c3fSmrg        self.parser.ParseFile(file)
61401e04c3fSmrg        file.close()
61501e04c3fSmrg
61601e04c3fSmrgif len(sys.argv) < 2:
61701e04c3fSmrg    print("No input xml file specified")
61801e04c3fSmrg    sys.exit(1)
61901e04c3fSmrg
62001e04c3fSmrginput_file = sys.argv[1]
62101e04c3fSmrg
62201e04c3fSmrgp = Parser(sys.argv[2])
62301e04c3fSmrgp.parse(input_file)
624