broadcom/genxml: Stop manually scrubbing 'α' -> "alpha"
[mesa.git] / src / broadcom / cle / gen_pack_header.py
index 528ff8fa4399a7203cc4f44bcbdca4555ac9044f..cc9e4a03ec27443089dc3cf743eceda50a418716 100644 (file)
@@ -30,7 +30,7 @@ import re
 import sys
 import copy
 
-license =  """/* Generated code, see packets.xml and gen_packet_header.py */
+license =  """/* Generated code, see v3d_packet_v21.xml, v3d_packet_v33.xml and gen_pack_header.py */
 """
 
 pack_header = """%(license)s
@@ -43,7 +43,7 @@ pack_header = """%(license)s
 #ifndef %(guard)s
 #define %(guard)s
 
-#include "v3d_packet_helpers.h"
+#include "cle/v3d_packet_helpers.h"
 
 """
 
@@ -62,7 +62,6 @@ def to_alphanum(name):
         '=': '',
         '>': '',
         '#': '',
-        'α': 'alpha',
         '&': '',
         '*': '',
         '"': '',
@@ -82,6 +81,11 @@ def safe_name(name):
 
     return name
 
+def prefixed_upper_name(prefix, name):
+    if prefix:
+        name = prefix + "_" + name
+    return safe_name(name).upper()
+
 def num_from_str(num_str):
     if num_str.lower().startswith('0x'):
         return int(num_str, base=16)
@@ -111,6 +115,9 @@ class Field(object):
         self.end = self.start + int(attrs["size"]) - 1
         self.type = attrs["type"]
 
+        if self.type == 'bool' and self.start != self.end:
+            print("#error Field {} has bool type but more than one bit of size".format(self.name));
+
         if "prefix" in attrs:
             self.prefix = safe_name(attrs["prefix"]).upper()
         else:
@@ -121,6 +128,12 @@ class Field(object):
         else:
             self.default = None
 
+        if "minus_one" in attrs:
+            assert(attrs["minus_one"] == "true")
+            self.minus_one = True
+        else:
+            self.minus_one = False
+
         ufixed_match = Field.ufixed_pattern.match(self.type)
         if ufixed_match:
             self.type = 'ufixed'
@@ -138,6 +151,8 @@ class Field(object):
             type = 'bool'
         elif self.type == 'float':
             type = 'float'
+        elif self.type == 'f187':
+            type = 'float'
         elif self.type == 'ufixed':
             type = 'float'
         elif self.type == 'sfixed':
@@ -152,22 +167,19 @@ class Field(object):
             type = 'uint32_t'
         elif self.type in self.parser.structs:
             type = 'struct ' + self.parser.gen_prefix(safe_name(self.type))
+        elif self.type in self.parser.enums:
+            type = 'enum ' + self.parser.gen_prefix(safe_name(self.type))
         elif self.type == 'mbo':
             return
         else:
             print("#error unhandled type: %s" % self.type)
+            type = "uint32_t"
 
         print("   %-36s %s%s;" % (type, self.name, dim))
 
-        if len(self.values) > 0 and self.default == None:
-            if self.prefix:
-                prefix = self.prefix + "_"
-            else:
-                prefix = ""
-
         for value in self.values:
-            print("#define %-40s %d" % ((prefix + value.name).replace("__", "_"),
-                                        value.value))
+            name = prefixed_upper_name(self.prefix, value.name)
+            print("#define %-40s %d" % (name, value.value))
 
     def overlaps(self, field):
         return self != field and max(self.start, field.start) <= min(self.end, field.end)
@@ -181,6 +193,8 @@ class Group(object):
         self.count = count
         self.size = 0
         self.fields = []
+        self.min_ver = 0
+        self.max_ver = 0
 
     def emit_template_struct(self, dim):
         if self.count == 0:
@@ -203,7 +217,7 @@ class Group(object):
             first_byte = field.start // 8
             last_byte = field.end // 8
 
-            for b in xrange(first_byte, last_byte + 1):
+            for b in range(first_byte, last_byte + 1):
                 if not b in bytes:
                     bytes[b] = self.Byte()
 
@@ -223,6 +237,10 @@ class Group(object):
         relocs_emitted = set()
         memcpy_fields = set()
 
+        for field in self.fields:
+            if field.minus_one:
+                print("   assert(values->%s >= 1);" % field.name)
+
         for index in range(self.length):
             # Handle MBZ bytes
             if not index in bytes:
@@ -247,7 +265,7 @@ class Group(object):
             # uints/ints with no merged fields.
             if len(byte.fields) == 1:
                 field = byte.fields[0]
-                if field.type in ["float", "uint", "int"] and field.start % 8 == 0 and field.end - field.start == 31:
+                if field.type in ["float", "uint", "int"] and field.start % 8 == 0 and field.end - field.start == 31 and not field.minus_one:
                     if field in memcpy_fields:
                         continue
 
@@ -274,32 +292,44 @@ class Group(object):
                 field_byte_start = (field.start // 8) * 8
                 start -= field_byte_start
                 end -= field_byte_start
+                extra_shift = 0
+
+                value = "values->%s" % name
+                if field.minus_one:
+                    value = "%s - 1" % value
 
                 if field.type == "mbo":
                     s = "__gen_mbo(%d, %d)" % \
                         (start, end)
                 elif field.type == "address":
+                    extra_shift = (31 - (end - start)) // 8 * 8
                     s = "__gen_address_offset(&values->%s)" % byte.address.name
                 elif field.type == "uint":
-                    s = "__gen_uint(values->%s, %d, %d)" % \
-                        (name, start, end)
+                    s = "__gen_uint(%s, %d, %d)" % \
+                        (value, start, end)
+                elif field.type in self.parser.enums:
+                    s = "__gen_uint(%s, %d, %d)" % \
+                        (value, start, end)
                 elif field.type == "int":
-                    s = "__gen_sint(values->%s, %d, %d)" % \
-                        (name, start, end)
+                    s = "__gen_sint(%s, %d, %d)" % \
+                        (value, start, end)
                 elif field.type == "bool":
-                    s = "__gen_uint(values->%s, %d, %d)" % \
-                        (name, start, end)
+                    s = "__gen_uint(%s, %d, %d)" % \
+                        (value, start, end)
                 elif field.type == "float":
                     s = "#error %s float value mixed in with other fields" % name
+                elif field.type == "f187":
+                    s = "__gen_uint(fui(%s) >> 16, %d, %d)" % \
+                        (value, start, end)
                 elif field.type == "offset":
-                    s = "__gen_offset(values->%s, %d, %d)" % \
-                        (name, start, end)
+                    s = "__gen_offset(%s, %d, %d)" % \
+                        (value, start, end)
                 elif field.type == 'ufixed':
-                    s = "__gen_ufixed(values->%s, %d, %d, %d)" % \
-                        (name, start, end, field.fractional_size)
+                    s = "__gen_ufixed(%s, %d, %d, %d)" % \
+                        (value, start, end, field.fractional_size)
                 elif field.type == 'sfixed':
-                    s = "__gen_sfixed(values->%s, %d, %d, %d)" % \
-                        (name, start, end, field.fractional_size)
+                    s = "__gen_sfixed(%s, %d, %d, %d)" % \
+                        (value, start, end, field.fractional_size)
                 elif field.type in self.parser.structs:
                     s = "__gen_uint(v%d_%d, %d, %d)" % \
                         (index, field_index, start, end)
@@ -309,8 +339,9 @@ class Group(object):
                     s = None
 
                 if not s == None:
-                    if byte_start - field_byte_start != 0:
-                        s = "%s >> %d" % (s, byte_start - field_byte_start)
+                    shift = byte_start - field_byte_start + extra_shift
+                    if shift:
+                        s = "%s >> %d" % (s, shift)
 
                     if field == byte.fields[-1]:
                         print("%s %s;" % (prefix, s))
@@ -335,12 +366,16 @@ class Group(object):
                     convert = "__gen_unpack_address"
                 elif field.type == "uint":
                     convert = "__gen_unpack_uint"
+                elif field.type in self.parser.enums:
+                    convert = "__gen_unpack_uint"
                 elif field.type == "int":
                     convert = "__gen_unpack_sint"
                 elif field.type == "bool":
                     convert = "__gen_unpack_uint"
                 elif field.type == "float":
                     convert = "__gen_unpack_float"
+                elif field.type == "f187":
+                    convert = "__gen_unpack_f187"
                 elif field.type == "offset":
                     convert = "__gen_unpack_offset"
                 elif field.type == 'ufixed':
@@ -350,19 +385,22 @@ class Group(object):
                     args.append(str(field.fractional_size))
                     convert = "__gen_unpack_sfixed"
                 else:
-                    print("/* unhandled field %s, type %s */\n" % (name, field.type))
+                    print("/* unhandled field %s, type %s */\n" % (field.name, field.type))
                     s = None
 
-                print("   values->%s = %s(%s);" % \
-                      (field.name, convert, ', '.join(args)))
+                plusone = ""
+                if field.minus_one:
+                    plusone = " + 1"
+                print("   values->%s = %s(%s)%s;" % \
+                      (field.name, convert, ', '.join(args), plusone))
 
 class Value(object):
     def __init__(self, attrs):
-        self.name = safe_name(attrs["name"]).upper()
+        self.name = attrs["name"]
         self.value = int(attrs["value"])
 
 class Parser(object):
-    def __init__(self):
+    def __init__(self, ver):
         self.parser = xml.parsers.expat.ParserCreate()
         self.parser.StartElementHandler = self.start_element
         self.parser.EndElementHandler = self.end_element
@@ -370,7 +408,10 @@ class Parser(object):
         self.packet = None
         self.struct = None
         self.structs = {}
+        # Set of enum names we've seen.
+        self.enums = set()
         self.registers = {}
+        self.ver = ver
 
     def gen_prefix(self, name):
         if name[0] == "_":
@@ -381,10 +422,27 @@ class Parser(object):
     def gen_guard(self):
         return self.gen_prefix("PACK_H")
 
+    def attrs_version_valid(self, attrs):
+        if "min_ver" in attrs and self.ver < attrs["min_ver"]:
+            return False
+
+        if "max_ver" in attrs and self.ver > attrs["max_ver"]:
+            return False
+
+        return True
+
+    def group_enabled(self):
+        if self.group.min_ver != 0 and self.ver < self.group.min_ver:
+            return False
+
+        if self.group.max_ver != 0 and self.ver > self.group.max_ver:
+            return False
+
+        return True
+
     def start_element(self, name, attrs):
         if name == "vcxml":
-            self.platform = "V3D {}".format(attrs["ver"])
-            self.ver = attrs["ver"].replace('.', '')
+            self.platform = "V3D {}.{}".format(self.ver[0], self.ver[1])
             print(pack_header % {'license': license, 'platform': self.platform, 'guard': self.gen_guard()})
         elif name in ("packet", "struct", "register"):
             default_field = None
@@ -417,18 +475,26 @@ class Parser(object):
                 field.values = []
                 self.group.fields.append(field)
 
+            if "min_ver" in attrs:
+                self.group.min_ver = attrs["min_ver"]
+            if "max_ver" in attrs:
+                self.group.max_ver = attrs["max_ver"]
+
         elif name == "field":
             self.group.fields.append(Field(self, attrs))
             self.values = []
         elif name == "enum":
             self.values = []
             self.enum = safe_name(attrs["name"])
+            self.enums.add(attrs["name"])
+            self.enum_enabled = self.attrs_version_valid(attrs)
             if "prefix" in attrs:
-                self.prefix = safe_name(attrs["prefix"])
+                self.prefix = attrs["prefix"]
             else:
                 self.prefix= None
         elif name == "value":
-            self.values.append(Value(attrs))
+            if self.attrs_version_valid(attrs):
+                self.values.append(Value(attrs))
 
     def end_element(self, name):
         if name  == "packet":
@@ -447,7 +513,8 @@ class Parser(object):
         elif name  == "field":
             self.group.fields[-1].values = self.values
         elif name  == "enum":
-            self.emit_enum()
+            if self.enum_enabled:
+                self.emit_enum()
             self.enum = None
         elif name == "vcxml":
             print('#endif /* %s */' % self.gen_guard())
@@ -478,13 +545,7 @@ class Parser(object):
 
         print("}\n#endif\n")
 
-    def emit_packet(self):
-        name = self.packet
-
-        assert(self.group.fields[0].name == "opcode")
-        print('#define %-33s %6d' %
-              (name + "_opcode", self.group.fields[0].default))
-
+    def emit_header(self, name):
         default_fields = []
         for field in self.group.fields:
             if not type(field) is Field:
@@ -493,11 +554,21 @@ class Parser(object):
                 continue
             default_fields.append("   .%-35s = %6d" % (field.name, field.default))
 
-        if default_fields:
-            print('#define %-40s\\' % (name + '_header'))
-            print(",  \\\n".join(default_fields))
-            print('')
+        print('#define %-40s\\' % (name + '_header'))
+        print(",  \\\n".join(default_fields))
+        print('')
+
+    def emit_packet(self):
+        if not self.group_enabled():
+            return
+
+        name = self.packet
 
+        assert(self.group.fields[0].name == "opcode")
+        print('#define %-33s %6d' %
+              (name + "_opcode", self.group.fields[0].default))
+
+        self.emit_header(name)
         self.emit_template_struct(self.packet, self.group)
         self.emit_pack_function(self.packet, self.group)
         self.emit_unpack_function(self.packet, self.group)
@@ -505,6 +576,9 @@ class Parser(object):
         print('')
 
     def emit_register(self):
+        if not self.group_enabled():
+            return
+
         name = self.register
         if not self.reg_num == None:
             print('#define %-33s 0x%04x' %
@@ -515,11 +589,12 @@ class Parser(object):
         self.emit_unpack_function(self.register, self.group)
 
     def emit_struct(self):
+        if not self.group_enabled():
+            return
+
         name = self.struct
-        # Emit an empty header define so that we can use the CL pack functions
-        # with structs.
-        print('#define ' + name + '_header')
 
+        self.emit_header(name)
         self.emit_template_struct(self.struct, self.group)
         self.emit_pack_function(self.struct, self.group)
         self.emit_unpack_function(self.struct, self.group)
@@ -527,14 +602,14 @@ class Parser(object):
         print('')
 
     def emit_enum(self):
-        print('/* enum %s */' % self.gen_prefix(self.enum))
+        print('enum %s {' % self.gen_prefix(self.enum))
         for value in self.values:
+            name = value.name
             if self.prefix:
-                name = self.prefix + "_" + value.name
-            else:
-                name = value.name
-                print('#define %-36s %6d' % (name.upper(), value.value))
-        print('')
+                name = self.prefix + "_" + name
+            name = safe_name(name).upper()
+            print('        % -36s = %6d,' % (name, value.value))
+        print('};\n')
 
     def parse(self, filename):
         file = open(filename, "rb")
@@ -547,5 +622,5 @@ if len(sys.argv) < 2:
 
 input_file = sys.argv[1]
 
-p = Parser()
+p = Parser(sys.argv[2])
 p.parse(input_file)