aubinator: Fix the tool to correctly decode the DWords
authorSirisha Gandikota <Sirisha.Gandikota@intel.com>
Fri, 19 Aug 2016 19:13:25 +0000 (12:13 -0700)
committerKenneth Graunke <kenneth@whitecape.org>
Wed, 24 Aug 2016 04:19:55 +0000 (21:19 -0700)
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.

v2: Fix the formatting (per Matt)
Make the start and end pos calculation to extract fields from a DWord
more appropriate by moving %32 away from mask() method

Signed-off-by: Sirisha Gandikota <Sirisha.Gandikota@intel.com>
Acked-by: Kenneth Graunke <kenneth@whitecape.org>
Acked-by: Ben Widawsky <ben@bwidawsk.net>
src/intel/tools/aubinator.c
src/intel/tools/decoder.c
src/intel/tools/decoder.h

index 250a2e1ecbfb4080b86021eb22b2c6c61198bcdc..11e1b9dc72fcdf44e4bfd1c326373360bb57547f 100644 (file)
@@ -87,17 +87,78 @@ valid_offset(uint32_t offset)
    return offset < gtt_end;
 }
 
+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)
 {
@@ -346,6 +407,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)
 {
@@ -543,6 +628,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
@@ -578,7 +665,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 },
@@ -643,9 +731,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++) {
index 02944dd0062104c9a763127c99287c6ab3e8ed0e..f57be979038f030fa0703680997b6e5ec76b995a 100644 (file)
@@ -47,45 +47,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;
@@ -185,9 +146,27 @@ 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)
 {
@@ -201,7 +180,18 @@ mask(int start, int end)
 static inline uint64_t
 field(uint64_t value, int start, int end)
 {
-   return (value & mask(start, end)) >> start;
+   /* The field values are obtained from the DWord,
+    * Hence, get the relative start and end positions
+    * by doing a %32 on the start and end positions
+    */
+   return (value & mask(start % 32, end % 32)) >> (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 % 32, end % 32));
 }
 
 static struct gen_type
@@ -247,10 +237,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) {
@@ -299,8 +291,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) {
    }
@@ -328,7 +325,7 @@ end_element(void *data, const char *name)
             group->fields[i]->end <= 31 &&
             group->fields[i]->has_default) {
             group->opcode_mask |=
-               mask(group->fields[i]->start, group->fields[i]->end);
+               mask(group->fields[i]->start % 32, group->fields[i]->end % 32);
             group->opcode |=
                group->fields[i]->default_value << group->fields[i]->start;
          }
@@ -341,6 +338,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;
    }
 }
 
@@ -407,7 +407,6 @@ gen_spec_load(const char *filename)
 struct gen_group *
 gen_spec_find_instruction(struct gen_spec *spec, const uint32_t *p)
 {
-   /* FIXME: Make sure the opcodes put out are correct */
    for (int i = 0; i < spec->ncommands; i++) {
       uint32_t opcode = *p & spec->commands[i]->opcode_mask;
       if (opcode == spec->commands[i]->opcode)
@@ -495,12 +494,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),
index af9e075f00e78543c4adef05bba4db72cb83f3d0..b46e451652fe63176d43f351939f5899f7e6f577 100644 (file)
@@ -51,6 +51,46 @@ 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);