diff --git a/src/intel/decoder/intel_decoder.c b/src/intel/decoder/intel_decoder.c index 08c70bc89e7..f6436b6c363 100644 --- a/src/intel/decoder/intel_decoder.c +++ b/src/intel/decoder/intel_decoder.c @@ -147,6 +147,11 @@ static void get_array_offset_count(const char **atts, uint32_t *offset, uint32_t *count, uint32_t *size, bool *variable) { + bool is_old_format = false; + bool is_new_format = false; + + *offset = 0; + for (int i = 0; atts[i]; i += 2) { char *p; @@ -155,12 +160,21 @@ get_array_offset_count(const char **atts, uint32_t *offset, uint32_t *count, if (*count == 0) *variable = true; } else if (strcmp(atts[i], "start") == 0) { + assert(!is_new_format); + is_old_format = true; *offset = strtoul(atts[i + 1], &p, 0); + } else if (strcmp(atts[i], "dword") == 0) { + assert(!is_old_format); + is_new_format = true; + *offset += 32 * strtoul(atts[i + 1], &p, 0); + } else if (strcmp(atts[i], "offset_bits") == 0) { + assert(!is_old_format); + is_new_format = true; + *offset += strtoul(atts[i + 1], &p, 0); } else if (strcmp(atts[i], "size") == 0) { *size = strtoul(atts[i + 1], &p, 0); } } - return; } static struct intel_group * @@ -336,6 +350,16 @@ create_field(struct parser_context *ctx, const char **atts) field = rzalloc(ctx->group, struct intel_field); field->parent = ctx->group; + bool is_old_format = false; + bool is_new_format = false; + + uint32_t dword = 0; + uint32_t bits_start = 0; + uint32_t bits_end = 0; + + bool has_default = false; + uint32_t default_value = 0; + for (int i = 0; atts[i]; i += 2) { char *p; @@ -345,18 +369,41 @@ create_field(struct parser_context *ctx, const char **atts) field->parent->dword_length_field = field; } } else if (strcmp(atts[i], "start") == 0) { - field->start = strtoul(atts[i + 1], &p, 0); + assert(!is_new_format); + is_old_format = true; + bits_start = strtoul(atts[i + 1], &p, 0); } else if (strcmp(atts[i], "end") == 0) { - field->end = strtoul(atts[i + 1], &p, 0); + assert(!is_new_format); + is_old_format = true; + bits_end = strtoul(atts[i + 1], &p, 0); + } else if (strcmp(atts[i], "dword") == 0) { + assert(!is_old_format); + is_new_format = true; + dword = strtoul(atts[i + 1], &p, 10); + } else if (strcmp(atts[i], "bits") == 0) { + assert(!is_old_format); + is_new_format = true; + const char *bits_str = atts[i + 1]; + const char *colon = strchr(bits_str, ':'); + assert(colon); + bits_end = strtoul(bits_str, NULL, 10); + bits_start = strtoul(colon+1, NULL, 10); } else if (strcmp(atts[i], "type") == 0) { field->type = string_to_type(ctx, atts[i + 1]); - } else if (strcmp(atts[i], "default") == 0 && - field->start >= 16 && field->end <= 31) { - field->has_default = true; - field->default_value = strtoul(atts[i + 1], &p, 0); + } else if (strcmp(atts[i], "default") == 0) { + has_default = true; + default_value = strtoul(atts[i + 1], &p, 0); } } + field->start = dword * 32 + bits_start; + field->end = dword * 32 + bits_end; + + if (has_default && field->start >= 16 && field->end <= 31) { + field->has_default = true; + field->default_value = default_value; + } + return field; } diff --git a/src/intel/decoder/tests/gentest.xml b/src/intel/decoder/tests/gentest.xml index 2b4af514a7a..60bbe0b3c4c 100644 --- a/src/intel/decoder/tests/gentest.xml +++ b/src/intel/decoder/tests/gentest.xml @@ -7,6 +7,18 @@ + + + + + + + + + + + + diff --git a/src/intel/decoder/tests/genxml_test.c b/src/intel/decoder/tests/genxml_test.c index 10b78f0cc63..3d17e92c421 100644 --- a/src/intel/decoder/tests/genxml_test.c +++ b/src/intel/decoder/tests/genxml_test.c @@ -127,6 +127,86 @@ test_two_levels(struct intel_spec *spec) { } } +static void +test_dword_fields(struct intel_spec *spec) { + struct GFX9_TEST_DWORD_FIELDS test = { + .value_dw0 = 0x1234, + .value_dw1 = 0xABCDEF00, + .value_dw2 = 0x5678, + .single_bit = true, + }; + + uint32_t dw[GFX9_TEST_DWORD_FIELDS_length]; + GFX9_TEST_DWORD_FIELDS_pack(NULL, dw, &test); + + struct intel_group *group; + group = intel_spec_find_struct(spec, "TEST_DWORD_FIELDS"); + + assert(group != NULL); + + if (!quiet) { + printf("\nTEST_DWORD_FIELDS:\n"); + intel_print_group(stdout, group, 0, dw, 0, false); + } + + struct intel_field_iterator iter; + intel_field_iterator_init(&iter, group, dw, 0, false); + + while (intel_field_iterator_next(&iter)) { + if (strcmp(iter.name, "value_dw0") == 0) { + uint16_t value = iter.raw_value; + assert(value == test.value_dw0); + } else if (strcmp(iter.name, "value_dw1") == 0) { + uint32_t value = iter.raw_value; + assert(value == test.value_dw1); + } else if (strcmp(iter.name, "value_dw2") == 0) { + uint16_t value = iter.raw_value; + assert(value == test.value_dw2); + } else if (strcmp(iter.name, "single_bit") == 0) { + bool value = iter.raw_value; + assert(value == test.single_bit); + } + } +} + +static void +test_offset_bits(struct intel_spec *spec) { + struct GFX9_TEST_OFFSET_BITS test = { + .header = 0x12345678, + }; + + for (int i = 0; i < 3; i++) { + test.data[i] = 0x1000 + i; + } + + uint32_t dw[GFX9_TEST_OFFSET_BITS_length]; + GFX9_TEST_OFFSET_BITS_pack(NULL, dw, &test); + + struct intel_group *group; + group = intel_spec_find_struct(spec, "TEST_OFFSET_BITS"); + + assert(group != NULL); + + if (!quiet) { + printf("\nTEST_OFFSET_BITS:\n"); + intel_print_group(stdout, group, 0, dw, 0, false); + } + + struct intel_field_iterator iter; + intel_field_iterator_init(&iter, group, dw, 0, false); + + while (intel_field_iterator_next(&iter)) { + int idx; + if (strcmp(iter.name, "header") == 0) { + uint32_t value = iter.raw_value; + assert(value == test.header); + } else if (sscanf(iter.name, "data[%d]", &idx) == 1) { + uint16_t value = iter.raw_value; + assert(value == test.data[idx]); + } + } +} + int main(int argc, char **argv) { struct intel_spec *spec = intel_spec_load_filename(GENXML_DIR, GENXML_FILE); @@ -136,6 +216,8 @@ int main(int argc, char **argv) test_struct(spec); test_two_levels(spec); + test_dword_fields(spec); + test_offset_bits(spec); intel_spec_destroy(spec); diff --git a/src/intel/genxml/gen_bits_header.py b/src/intel/genxml/gen_bits_header.py index 9399a09ad15..e1d05c5f9b5 100644 --- a/src/intel/genxml/gen_bits_header.py +++ b/src/intel/genxml/gen_bits_header.py @@ -213,9 +213,16 @@ class Field(object): def add_gen(self, gen, xml_attrs): assert isinstance(gen, Gen) - start = int(xml_attrs['start']) - end = int(xml_attrs['end']) - self.start_by_gen[gen] = start + + if 'start' in xml_attrs: + dword = 0 + start = int(xml_attrs['start']) + end = int(xml_attrs['end']) + else: + dword = int(xml_attrs['dword']) + end, start = map(int, xml_attrs['bits'].split(':')) + + self.start_by_gen[gen] = dword * 32 + start self.bits_by_gen[gen] = 1 + end - start def has_prop(self, prop): diff --git a/src/intel/genxml/gen_pack_header.py b/src/intel/genxml/gen_pack_header.py index 8790bdd98e3..edf807d08c1 100644 --- a/src/intel/genxml/gen_pack_header.py +++ b/src/intel/genxml/gen_pack_header.py @@ -72,8 +72,17 @@ class Field(object): self.parser = parser if "name" in attrs: self.name = safe_name(attrs["name"]) - self.start = int(attrs["start"]) - self.end = int(attrs["end"]) + + if "start" in attrs: + self.start = int(attrs["start"]) + self.end = int(attrs["end"]) + else: + dword = int(attrs["dword"]) + end_bit, start_bit = map(int, attrs["bits"].split(":")) + + self.start = dword * 32 + start_bit + self.end = dword * 32 + end_bit + self.type = attrs["type"] self.nonzero = bool_from_str(attrs.get("nonzero", "false")) self.prefix = attrs["prefix"] if "prefix" in attrs else None @@ -458,8 +467,15 @@ class Parser(object): self.group = Group(self, None, 0, 1, size) elif name == "group": + if "start" in attrs: + start = int(attrs["start"]) + else: + dword = int(attrs["dword"]) + offset_bits = int(attrs.get("offset_bits", 0)) + start = dword * 32 + offset_bits + group = Group(self, self.group, - int(attrs["start"]), int(attrs["count"]), int(attrs["size"])) + start, int(attrs["count"]), int(attrs["size"])) self.group.fields.append(group) self.group = group elif name == "field":