intel/genxml: Add support for dword/bits in fields to rest of the code

Change code to temporarily support both the start/end old format and the
dword/bits new format.

Acked-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Acked-by: José Roberto de Souza <jose.souza@intel.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/36138>
This commit is contained in:
Caio Oliveira
2025-07-21 22:43:38 -07:00
committed by Marge Bot
parent 001f207ee0
commit fb8f14820a
5 changed files with 177 additions and 13 deletions

View File

@@ -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;
}

View File

@@ -7,6 +7,18 @@
</group>
</group>
</struct>
<struct name="TEST_DWORD_FIELDS" length="4">
<field name="value_dw0" start="0" end="15" type="uint" />
<field name="value_dw1" start="32" end="63" type="uint" />
<field name="value_dw2" start="72" end="87" type="uint" />
<field name="single_bit" start="101" end="101" type="bool" />
</struct>
<struct name="TEST_OFFSET_BITS" length="6">
<field name="header" start="0" end="31" type="uint" />
<group count="3" start="48" size="16">
<field name="data" start="0" end="15" type="uint" />
</group>
</struct>
<struct name="TEST_STRUCT" length="2">
<field name="number1" start="0" end="15" type="uint" />
<field name="number2" start="16" end="31" type="uint" />

View File

@@ -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);

View File

@@ -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):

View File

@@ -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":