v3d: Add pack/unpack/decode support for fields with a "- 1" modifier.
authorEric Anholt <eric@anholt.net>
Tue, 26 Jun 2018 22:53:26 +0000 (15:53 -0700)
committerEric Anholt <eric@anholt.net>
Wed, 27 Jun 2018 16:13:48 +0000 (09:13 -0700)
Right now, we name these fields as "field name minus one" so that your C
code obviously states what the value should be.  However, it's easy enough
to handle at the codegen level with another little XML attribute, meaning
less C code and easier-to-read values in CLIF dumping and gdb as well.

(The actual CLIF format for simulator and FPGA replay takes in
pre-minus-one values, so we need it there too).

src/broadcom/cle/gen_pack_header.py
src/broadcom/cle/v3d_decoder.c
src/broadcom/cle/v3d_decoder.h

index 310e0a7c7a02290aad7ca111de1ed8342479e018..5fde7bb07ade99f40d220aad9d158359b05150e1 100644 (file)
@@ -129,6 +129,12 @@ class Field(object):
         else:
             self.default = None
 
         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'
         ufixed_match = Field.ufixed_pattern.match(self.type)
         if ufixed_match:
             self.type = 'ufixed'
@@ -228,6 +234,10 @@ class Group(object):
         relocs_emitted = set()
         memcpy_fields = set()
 
         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:
         for index in range(self.length):
             # Handle MBZ bytes
             if not index in bytes:
@@ -252,7 +262,7 @@ class Group(object):
             # uints/ints with no merged fields.
             if len(byte.fields) == 1:
                 field = byte.fields[0]
             # 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
 
                     if field in memcpy_fields:
                         continue
 
@@ -281,6 +291,10 @@ class Group(object):
                 end -= field_byte_start
                 extra_shift = 0
 
                 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)
                 if field.type == "mbo":
                     s = "__gen_mbo(%d, %d)" % \
                         (start, end)
@@ -288,28 +302,28 @@ class Group(object):
                     extra_shift = (31 - (end - start)) // 8 * 8
                     s = "__gen_address_offset(&values->%s)" % byte.address.name
                 elif field.type == "uint":
                     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:
                 elif field.type in self.parser.enums:
-                    s = "__gen_uint(values->%s, %d, %d)" % \
-                        (name, start, end)
+                    s = "__gen_uint(%s, %d, %d)" % \
+                        (value, start, end)
                 elif field.type == "int":
                 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":
                 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 == "offset":
                 elif field.type == "float":
                     s = "#error %s float value mixed in with other fields" % name
                 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':
                 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':
                 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)
                 elif field.type in self.parser.structs:
                     s = "__gen_uint(v%d_%d, %d, %d)" % \
                         (index, field_index, start, end)
@@ -366,8 +380,11 @@ class Group(object):
                     print("/* unhandled field %s, type %s */\n" % (field.name, field.type))
                     s = None
 
                     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):
 
 class Value(object):
     def __init__(self, attrs):
index 9c457b76068154e90b8016791bfa213ed35af717..ed9cb7dd43889c77e6d96d774c3150fab325ed8f 100644 (file)
@@ -359,6 +359,9 @@ create_field(struct parser_context *ctx, const char **atts)
                 else if (strcmp(atts[i], "default") == 0) {
                         field->has_default = true;
                         field->default_value = strtoul(atts[i + 1], &p, 0);
                 else if (strcmp(atts[i], "default") == 0) {
                         field->has_default = true;
                         field->default_value = strtoul(atts[i + 1], &p, 0);
+                } else if (strcmp(atts[i], "minus_one") == 0) {
+                        assert(strcmp(atts[i + 1], "true") == 0);
+                        field->minus_one = true;
                 }
         }
 
                 }
         }
 
@@ -786,16 +789,24 @@ v3d_field_iterator_next(struct v3d_field_iterator *iter)
         int s = group_member_offset + iter->field->start;
         int e = group_member_offset + iter->field->end;
 
         int s = group_member_offset + iter->field->start;
         int e = group_member_offset + iter->field->end;
 
+        assert(!iter->field->minus_one ||
+               iter->field->type.kind == V3D_TYPE_INT ||
+               iter->field->type.kind == V3D_TYPE_UINT);
+
         switch (iter->field->type.kind) {
         case V3D_TYPE_UNKNOWN:
         case V3D_TYPE_INT: {
                 uint32_t value = __gen_unpack_sint(iter->p, s, e);
         switch (iter->field->type.kind) {
         case V3D_TYPE_UNKNOWN:
         case V3D_TYPE_INT: {
                 uint32_t value = __gen_unpack_sint(iter->p, s, e);
+                if (iter->field->minus_one)
+                        value++;
                 snprintf(iter->value, sizeof(iter->value), "%d", value);
                 enum_name = v3d_get_enum_name(&iter->field->inline_enum, value);
                 break;
         }
         case V3D_TYPE_UINT: {
                 uint32_t value = __gen_unpack_uint(iter->p, s, e);
                 snprintf(iter->value, sizeof(iter->value), "%d", value);
                 enum_name = v3d_get_enum_name(&iter->field->inline_enum, value);
                 break;
         }
         case V3D_TYPE_UINT: {
                 uint32_t value = __gen_unpack_uint(iter->p, s, e);
+                if (iter->field->minus_one)
+                        value++;
                 snprintf(iter->value, sizeof(iter->value), "%u", value);
                 enum_name = v3d_get_enum_name(&iter->field->inline_enum, value);
                 break;
                 snprintf(iter->value, sizeof(iter->value), "%u", value);
                 enum_name = v3d_get_enum_name(&iter->field->inline_enum, value);
                 break;
index 541d877a9a74c808d0effcd8907b531f5c1844ee..cca1d6fa64cdae099eb6b678b298189a3e20e27f 100644 (file)
@@ -125,6 +125,7 @@ struct v3d_field {
         char *name;
         int start, end;
         struct v3d_type type;
         char *name;
         int start, end;
         struct v3d_type type;
+        bool minus_one;
         bool has_default;
         uint32_t default_value;
 
         bool has_default;
         uint32_t default_value;