[Mesa-dev] [PATCH 2/2] aubinator: Fix the tool to correctly decode the DWords
Jason Ekstrand
jason at jlekstrand.net
Wed Aug 10 21:22:29 UTC 2016
On Tue, Aug 9, 2016 at 4:52 PM, Sirisha Gandikota <
sirisha.gandikota at intel.com> wrote:
> From: Sirisha Gandikota <Sirisha.Gandikota at intel.com>
>
> Several fixes have been added as part of this as listed below:
>
> 1) Fix the mask and add disassembler handling for STATE_DS, STATE_HS
> as the mask returned wrong values of the fields.
>
> 2) Fix the GEN_TYPE_ADDRESS/GEN_TYPE_OFFSET decoding - the address/
> offset were handled the same way as the other fields and that gives
> the wrong values for the address/offset.
>
> 3) Decode nested/recurssive structures - Many packets contain nested
> structures, ex: 3DSATE_SO_BUFFER, STATE_BASE_ADDRESS, etc contain MOC
> structures. Previously, the aubinator printed 1 if there was a MOC
> structure. Now we decode the entire structure and print out its fields.
>
> 4) Print out the DWord address along with its hex value - For a better
> clarity of information, it is helpful to print both the address and
> hex value of the DWord along with the DWord count. Since the DWord0
> contains the instruction code and the instruction length, it is
> unnecessary to print the decoded values for DWord0. This information
> is already available from the DWord hex value.
>
> 5) Decode the <group> and the corresponding fields in the group- The
> <group> tag can have fields of several types including structures. A
> group can contain one or more number of fields and this has be correctly
> decoded. Previously, aubinator did not decode the groups or the
> fields/structures inside them. Now we decode the <group> in the
> instructions and structures where the fields in it repeat for any number
> of times specified.
>
One comment for now: Usually, when making a bunch of changes like this, we
try and split each functional change into its own patch. That way it's
more clear what's going on. This is brand new code, so a couple giant
patches may be ok, but having it split up would be nicer. :) Git has some
tools that make this less painful than it might look and I'm available to
help if you'd like.
I'll try and get around to actually playing with it soon.
--Jason
>
> Signed-off-by: Sirisha Gandikota <Sirisha.Gandikota at intel.com>
> ---
> src/intel/tools/aubinator.c | 115 ++++++++++++++++++++++++++++++
> +++++++++++---
> src/intel/tools/decoder.c | 95 +++++++++++++++++-------------------
> src/intel/tools/decoder.h | 39 +++++++++++++++
> 3 files changed, 192 insertions(+), 57 deletions(-)
>
> diff --git a/src/intel/tools/aubinator.c b/src/intel/tools/aubinator.c
> index 99d67a1..d2f9d13 100644
> --- a/src/intel/tools/aubinator.c
> +++ b/src/intel/tools/aubinator.c
> @@ -84,17 +84,80 @@ valid_offset(uint32_t offset)
> }
>
> static void
> +print_dword_val(struct gen_field_iterator *iter, uint64_t offset, int
> *dword_num)
> +{
> + struct gen_field *f;
> + union {
> + uint32_t dw;
> + float f;
> + } v;
> +
> + f = iter->group->fields[iter->i-1];
> + v.dw = iter->p[f->start / 32];
> +
> + if (*dword_num != (f->start/32)) {
> + printf("0x%08lx: 0x%08x : Dword %d\n",(offset+4*(f->start/32)),
> v.dw, f->start/32);
> + *dword_num = (f->start/32);
> + }
> +}
> +
> +static char *
> +print_iterator_values(struct gen_field_iterator *iter, int *idx)
> +{
> + char *token = NULL;
> + if (strstr(iter->value,"struct") == NULL) {
> + printf(" %s: %s\n", iter->name, iter->value);
> + } else {
> + token = strtok(iter->value, " ");
> + if (token != NULL) {
> + token = strtok(NULL, " ");
> + *idx = atoi(strtok(NULL, ">"));
> + } else {
> + token = NULL;
> + }
> + printf(" %s:<struct %s>\n", iter->name, token);
> + }
> + return token;
> +
> +}
> +
> +static void
> decode_structure(struct gen_spec *spec, struct gen_group *strct, const
> uint32_t *p)
> {
> struct gen_field_iterator iter;
> + char *token = NULL;
> + int idx = 0, dword_num = 0;
> + uint64_t offset = 0;
> +
> + if (option_print_offsets)
> + offset = (void *) p - gtt;
> + else
> + offset = 0;
>
> gen_field_iterator_init(&iter, strct, p);
> while (gen_field_iterator_next(&iter)) {
> - printf(" %s: %s\n", iter.name, iter.value);
> + idx = 0;
> + print_dword_val(&iter, offset, &dword_num);
> + token = print_iterator_values(&iter, &idx);
> + if (token != NULL) {
> + struct gen_group *struct_val = gen_spec_find_struct(spec, token);
> + decode_structure(spec, struct_val, &p[idx]);
> + token = NULL;
> + }
> }
> }
>
> static void
> +handle_struct_decode(struct gen_spec *spec, char *struct_name, uint32_t
> *p)
> +{
> + if (struct_name == NULL)
> + return;
> + struct gen_group *struct_val = gen_spec_find_struct(spec,
> struct_name);
> + decode_structure(spec, struct_val, p);
> +
> +}
> +
> +static void
> dump_binding_table(struct gen_spec *spec, uint32_t offset)
> {
> uint32_t *pointers, i;
> @@ -248,7 +311,8 @@ handle_media_interface_descriptor_load(struct
> gen_spec *spec, uint32_t *p)
> }
>
> /* Heuristic to determine whether a uint32_t is probably actually a float
> - * (http://stackoverflow.com/a/2953466) */
> + * (http://stackoverflow.com/a/2953466)
> + */
>
> static bool
> probably_float(uint32_t bits)
> @@ -256,15 +320,15 @@ probably_float(uint32_t bits)
> int exp = ((bits & 0x7f800000U) >> 23) - 127;
> uint32_t mant = bits & 0x007fffff;
>
> - // +- 0.0
> + /* +- 0.0 */
> if (exp == -127 && mant == 0)
> return true;
>
> - // +- 1 billionth to 1 billion
> + /* +- 1 billionth to 1 billion */
> if (-30 <= exp && exp <= 30)
> return true;
>
> - // some value with only a few binary digits
> + /* some value with only a few binary digits */
> if ((mant & 0x0000ffff) == 0)
> return true;
>
> @@ -342,6 +406,30 @@ handle_3dstate_vs(struct gen_spec *spec, uint32_t *p)
> }
>
> static void
> +handle_3dstate_hs(struct gen_spec *spec, uint32_t *p)
> +{
> + uint64_t start;
> + struct brw_instruction *insns;
> + int hs_enable;
> +
> + if (gen_spec_get_gen(spec) >= gen_make_gen(8, 0)) {
> + start = get_qword(&p[4]);
> + } else {
> + start = p[4];
> + }
> +
> + hs_enable = p[2] & 0x80000000;
> +
> + if (hs_enable) {
> + printf("instruction_base %08lx, start %08lx\n",
> + instruction_base, start);
> +
> + insns = (struct brw_instruction *) (gtt + instruction_base + start);
> + gen_disasm_disassemble(disasm, insns, 0, 8192, stdout);
> + }
> +}
> +
> +static void
> handle_3dstate_constant(struct gen_spec *spec, uint32_t *p)
> {
> int i, j, length;
> @@ -537,6 +625,8 @@ handle_3dstate_scissor_state_pointers(struct gen_spec
> *spec, uint32_t *p)
>
> #define _3DSTATE_VS 0x78100000
> #define _3DSTATE_GS 0x78110000
> +#define _3DSTATE_HS 0x781b0000
> +#define _3DSTATE_DS 0x781d0000
>
> #define _3DSTATE_CONSTANT_VS 0x78150000
> #define _3DSTATE_CONSTANT_GS 0x78160000
> @@ -572,7 +662,8 @@ struct custom_handler {
> { _3DSTATE_INDEX_BUFFER, handle_3dstate_index_buffer },
> { _3DSTATE_VS, handle_3dstate_vs },
> { _3DSTATE_GS, handle_3dstate_vs },
> - /* FIXME: Handle disassmbing for 3DSTATE_HS and 3DSTATE_DS. */
> + { _3DSTATE_DS, handle_3dstate_vs },
> + { _3DSTATE_HS, handle_3dstate_hs },
> { _3DSTATE_CONSTANT_VS, handle_3dstate_constant },
> { _3DSTATE_CONSTANT_GS, handle_3dstate_constant },
> { _3DSTATE_CONSTANT_PS, handle_3dstate_constant },
> @@ -637,9 +728,19 @@ parse_commands(struct gen_spec *spec, uint32_t *cmds,
> int size, int engine)
>
> if (option_full_decode) {
> struct gen_field_iterator iter;
> + char *token = NULL;
> + int idx = 0, dword_num = 0;
> gen_field_iterator_init(&iter, inst, p);
> while (gen_field_iterator_next(&iter)) {
> - printf(" %s: %s\n", iter.name, iter.value);
> + idx = 0;
> + print_dword_val(&iter, offset, &dword_num);
> + if (dword_num > 0)
> + token = print_iterator_values(&iter, &idx);
> + if (token != NULL) {
> + printf("0x%08lx: 0x%08x : Dword %d\n",(offset+4*idx),
> p[idx], idx);
> + handle_struct_decode(spec,token, &p[idx]);
> + token = NULL;
> + }
> }
>
> for (i = 0; i < ARRAY_LENGTH(custom_handlers); i++) {
> diff --git a/src/intel/tools/decoder.c b/src/intel/tools/decoder.c
> index 7ab3696..060d4ed 100644
> --- a/src/intel/tools/decoder.c
> +++ b/src/intel/tools/decoder.c
> @@ -49,45 +49,6 @@ struct gen_spec {
> struct gen_group *registers[256];
> };
>
> -struct gen_group {
> - char *name;
> - int nfields;
> - struct gen_field **fields;
> -
> - uint32_t opcode_mask;
> - uint32_t opcode;
> -};
> -
> -struct gen_type {
> - enum {
> - GEN_TYPE_UNKNOWN,
> - GEN_TYPE_INT,
> - GEN_TYPE_UINT,
> - GEN_TYPE_BOOL,
> - GEN_TYPE_FLOAT,
> - GEN_TYPE_ADDRESS,
> - GEN_TYPE_OFFSET,
> - GEN_TYPE_STRUCT,
> - GEN_TYPE_UFIXED,
> - GEN_TYPE_SFIXED,
> - GEN_TYPE_MBO
> - } kind;
> -
> - /* Struct definition for GEN_TYPE_STRUCT*/
> - struct gen_group *gen_struct;
> -
> - /* Integer and fractional sizes for GEN_TYPE_UFIXED and
> GEN_TYPE_SFIXED */
> - int i, f;
> -};
> -
> -struct gen_field {
> - char *name;
> - int start, end;
> - struct gen_type type;
> - bool has_default;
> - uint32_t default_value;
> -};
> -
> struct location {
> const char *filename;
> int line_number;
> @@ -187,23 +148,48 @@ create_group(struct parser_context *ctx, const char
> *name, const char **atts)
> if (name)
> group->name = xstrdup(name);
>
> + group->group_offset = 0;
> + group->group_count = 0;
> +
> return group;
> }
>
> +static void
> +get_group_offset_count(struct parser_context *ctx, const char *name,
> const char **atts, uint32_t *offset, uint32_t *count)
> +{
> + char *p;
> + int i;
> +
> + for (i = 0; atts[i]; i += 2) {
> + if (strcmp(atts[i], "count") == 0)
> + *count = strtoul(atts[i + 1], &p, 0);
> + else if (strcmp(atts[i], "start") == 0)
> + *offset = strtoul(atts[i + 1], &p, 0);
> + }
> + return;
> +}
> +
> static inline uint64_t
> mask(int start, int end)
> {
> uint64_t v;
>
> - v = ~0ULL >> (63 - end + start);
> + v = ~0ULL >> (63 - (end%32) + (start%32));
>
> - return v << start;
> + return v << (start%32);
> }
>
> static inline uint64_t
> field(uint64_t value, int start, int end)
> {
> - return (value & mask(start, end)) >> start;
> + return (value & mask(start, end)) >> (start%32);
> +}
> +
> +static inline uint64_t
> +field_address(uint64_t value, int start, int end)
> +{
> + /* no need to right shift for address/offset */
> + return (value & mask(start, end));
> }
>
> static struct gen_type
> @@ -249,10 +235,12 @@ create_field(struct parser_context *ctx, const char
> **atts)
> if (strcmp(atts[i], "name") == 0)
> field->name = xstrdup(atts[i + 1]);
> else if (strcmp(atts[i], "start") == 0)
> - field->start = strtoul(atts[i + 1], &p, 0);
> - else if (strcmp(atts[i], "end") == 0)
> - field->end = strtoul(atts[i + 1], &p, 0);
> - else if (strcmp(atts[i], "type") == 0)
> + field->start = ctx->group->group_offset+strtoul(atts[i + 1],
> &p, 0);
> + else if (strcmp(atts[i], "end") == 0) {
> + field->end = ctx->group->group_offset+strtoul(atts[i + 1], &p,
> 0);
> + if (ctx->group->group_offset)
> + ctx->group->group_offset = field->end+1;
> + } 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) {
> @@ -301,8 +289,13 @@ start_element(void *data, const char *element_name,
> const char **atts)
> strcmp(element_name, "register") == 0) {
> ctx->group = create_group(ctx, name, atts);
> } else if (strcmp(element_name, "group") == 0) {
> + get_group_offset_count(ctx, name, atts,&ctx->group->group_
> offset,&ctx->group->group_count);
> } else if (strcmp(element_name, "field") == 0) {
> - ctx->fields[ctx->nfields++] = create_field(ctx, atts);
> + do {
> + ctx->fields[ctx->nfields++] = create_field(ctx, atts);
> + if (ctx->group->group_count)
> + ctx->group->group_count--;
> + } while (ctx->group->group_count > 0);
> } else if (strcmp(element_name, "enum") == 0) {
> } else if (strcmp(element_name, "value") == 0) {
> }
> @@ -343,6 +336,9 @@ end_element(void *data, const char *name)
> spec->structs[spec->nstructs++] = group;
> else if (strcmp(name, "register") == 0)
> spec->registers[spec->nregisters++] = group;
> + } else if (strcmp(name, "group") == 0) {
> + ctx->group->group_offset = 0;
> + ctx->group->group_count = 0;
> }
> }
>
> @@ -497,12 +493,11 @@ gen_field_iterator_next(struct gen_field_iterator
> *iter)
> case GEN_TYPE_ADDRESS:
> case GEN_TYPE_OFFSET:
> snprintf(iter->value, sizeof(iter->value),
> - "0x%08lx", field(v.dw, f->start, f->end));
> + "0x%08lx", field_address(v.dw, f->start, f->end));
> break;
> case GEN_TYPE_STRUCT:
> - /* FIXME: Make iterator decode the struct recursively */
> snprintf(iter->value, sizeof(iter->value),
> - "<struct %s>", f->type.gen_struct->name);
> + "<struct %s %d>", f->type.gen_struct->name, (f->start /
> 32));
> break;
> case GEN_TYPE_UFIXED:
> snprintf(iter->value, sizeof(iter->value),
> diff --git a/src/intel/tools/decoder.h b/src/intel/tools/decoder.h
> index af9e075..09667ef 100644
> --- a/src/intel/tools/decoder.h
> +++ b/src/intel/tools/decoder.h
> @@ -51,6 +51,45 @@ struct gen_field_iterator {
> int i;
> };
>
> +struct gen_group {
> + char *name;
> + int nfields;
> + struct gen_field **fields;
> + uint32_t group_offset, group_count;
> +
> + uint32_t opcode_mask;
> + uint32_t opcode;
> +};
> +struct gen_type {
> + enum {
> + GEN_TYPE_UNKNOWN,
> + GEN_TYPE_INT,
> + GEN_TYPE_UINT,
> + GEN_TYPE_BOOL,
> + GEN_TYPE_FLOAT,
> + GEN_TYPE_ADDRESS,
> + GEN_TYPE_OFFSET,
> + GEN_TYPE_STRUCT,
> + GEN_TYPE_UFIXED,
> + GEN_TYPE_SFIXED,
> + GEN_TYPE_MBO
> + } kind;
> +
> + /* Struct definition for GEN_TYPE_STRUCT*/
> + struct gen_group *gen_struct;
> +
> + /* Integer and fractional sizes for GEN_TYPE_UFIXED and
> GEN_TYPE_SFIXED */
> + int i, f;
> +};
> +
> +struct gen_field {
> + char *name;
> + int start, end;
> + struct gen_type type;
> + bool has_default;
> + uint32_t default_value;
> +};
> +
> void gen_field_iterator_init(struct gen_field_iterator *iter,
> struct gen_group *group, const uint32_t *p);
>
> --
> 2.7.4
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/mesa-dev/attachments/20160810/a92fc833/attachment-0001.html>
More information about the mesa-dev
mailing list