From 18b1bb0b63f3e5b726458523bc3eecb688f9d3cb Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 26 Jun 2018 15:53:26 -0700 Subject: [PATCH] v3d: Add pack/unpack/decode support for fields with a "- 1" modifier. 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 | 51 +++++++++++++++++++---------- src/broadcom/cle/v3d_decoder.c | 11 +++++++ src/broadcom/cle/v3d_decoder.h | 1 + 3 files changed, 46 insertions(+), 17 deletions(-) diff --git a/src/broadcom/cle/gen_pack_header.py b/src/broadcom/cle/gen_pack_header.py index 310e0a7c7a0..5fde7bb07ad 100644 --- a/src/broadcom/cle/gen_pack_header.py +++ b/src/broadcom/cle/gen_pack_header.py @@ -129,6 +129,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' @@ -228,6 +234,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: @@ -252,7 +262,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 @@ -281,6 +291,10 @@ class Group(object): 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) @@ -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": - 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(values->%s, %d, %d)" % \ - (name, start, end) + 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 == "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) @@ -366,8 +380,11 @@ class Group(object): 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): diff --git a/src/broadcom/cle/v3d_decoder.c b/src/broadcom/cle/v3d_decoder.c index 9c457b76068..ed9cb7dd438 100644 --- a/src/broadcom/cle/v3d_decoder.c +++ b/src/broadcom/cle/v3d_decoder.c @@ -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], "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; + 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); + 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); + 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; diff --git a/src/broadcom/cle/v3d_decoder.h b/src/broadcom/cle/v3d_decoder.h index 541d877a9a7..cca1d6fa64c 100644 --- a/src/broadcom/cle/v3d_decoder.h +++ b/src/broadcom/cle/v3d_decoder.h @@ -125,6 +125,7 @@ struct v3d_field { char *name; int start, end; struct v3d_type type; + bool minus_one; bool has_default; uint32_t default_value; -- 2.30.2