[Mesa-dev] [RFC PATCH 2/2] intel/i965: teach command streamer parsers about debug messages

Lionel Landwerlin lionel.g.landwerlin at intel.com
Tue Jun 20 20:25:25 UTC 2017


We introduce a gen_decoder_context structure that holds state spanning
multiple instructions. That way we can print debug messages that span
multiple MI_NOOPs.

Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin at intel.com>
---
 src/intel/common/gen_decoder.c                | 98 +++++++++++++++++++++++----
 src/intel/common/gen_decoder.h                | 17 +++++
 src/intel/tools/aubinator.c                   |  6 +-
 src/intel/tools/aubinator_error_decode.c      | 14 ++--
 src/mesa/drivers/dri/i965/brw_context.h       |  5 ++
 src/mesa/drivers/dri/i965/intel_batchbuffer.c | 18 +++--
 6 files changed, 135 insertions(+), 23 deletions(-)

diff --git a/src/intel/common/gen_decoder.c b/src/intel/common/gen_decoder.c
index ba3a5139aec..65a98862f19 100644
--- a/src/intel/common/gen_decoder.c
+++ b/src/intel/common/gen_decoder.c
@@ -29,6 +29,7 @@
 #include <expat.h>
 #include <inttypes.h>
 #include <zlib.h>
+#include <ctype.h>

 #include <util/macros.h>
 #include <util/ralloc.h>
@@ -767,16 +768,76 @@ gen_group_get_length(struct gen_group *group, const uint32_t *p)
 }

 void
+gen_decoder_context_init(struct gen_decoder_context *ctx)
+{
+   memset(ctx, 0, sizeof(*ctx));
+}
+
+static void
+reset_debug_status(struct gen_decoder_context *ctx)
+{
+   ctx->debug.is_debug = false;
+   ctx->debug.ready = false;
+   ctx->debug.message_length = 0;
+   ctx->debug.last_pointer = NULL;
+}
+
+static void
+update_debug_status(struct gen_field_iterator *iter)
+{
+   struct gen_decoder_context *ctx = iter->ctx;
+
+   if (ctx == NULL)
+      return;
+
+   /* Drop any non compliant instruction. */
+   if (strcmp(iter->group->name, "MI_NOOP") != 0 ||
+       (1UL << 22) & iter->p[0]) {
+      reset_debug_status(iter->ctx);
+      return;
+   }
+
+   if (ctx->debug.last_pointer != iter->p - 1)
+      reset_debug_status(iter->ctx);
+
+   ctx->debug.last_pointer = iter->p;
+   ctx->debug.is_debug = true;
+
+   for (int i = 0; i < 3; i++) {
+      ctx->debug.message[ctx->debug.message_length++] =
+         (iter->p[0] >> ((2 - i) * 7)) & 0x7f;
+
+      if ((ctx->debug.message_length == 1 && ctx->debug.message[0] == 0) ||
+          (!isprint(ctx->debug.message[ctx->debug.message_length - 1]) &&
+           ctx->debug.message[ctx->debug.message_length - 1] != 0)) {
+
+         reset_debug_status(iter->ctx);
+         return;
+      }
+
+      if (ctx->debug.message[ctx->debug.message_length - 1] == 0 &&
+          ctx->debug.message_length > 1) {
+         ctx->debug.ready = true;
+         return;
+      }
+   }
+}
+
+void
 gen_field_iterator_init(struct gen_field_iterator *iter,
+                        struct gen_decoder_context *ctx,
                         struct gen_group *group,
                         const uint32_t *p,
                         bool print_colors)
 {
    memset(iter, 0, sizeof(*iter));

+   iter->ctx = ctx;
    iter->group = group;
    iter->p = p;
    iter->print_colors = print_colors;
+
+   update_debug_status(iter);
 }

 static const char *
@@ -967,24 +1028,37 @@ is_header_field(struct gen_group *group, struct gen_field *field)
 }

 void
-gen_print_group(FILE *outfile, struct gen_group *group,
+gen_print_group(FILE *outfile,
+                struct gen_decoder_context *ctx,
+                struct gen_group *group,
                 uint64_t offset, const uint32_t *p, bool color)
 {
    struct gen_field_iterator iter;
    int last_dword = 0;

-   gen_field_iterator_init(&iter, group, p, color);
+   gen_field_iterator_init(&iter, ctx, group, p, color);
    while (gen_field_iterator_next(&iter)) {
-      if (last_dword != iter.dword) {
-         print_dword_header(outfile, &iter, offset);
-         last_dword = iter.dword;
-      }
-      if (!is_header_field(group, iter.field)) {
-         fprintf(outfile, "    %s: %s\n", iter.name, iter.value);
-         if (iter.struct_desc) {
-            uint64_t struct_offset = offset + 4 * iter.dword;
-            gen_print_group(outfile, iter.struct_desc, struct_offset,
-                            &p[iter.dword], color);
+      if (ctx && ctx->debug.is_debug) {
+         if (ctx->debug.ready) {
+            fprintf(outfile, "%sDEBUG: (%i) : %s%s\n",
+                    color ? "\e[0;35m" : "",
+                    ctx->debug.message_length, ctx->debug.message,
+                    "\e[0m");
+            reset_debug_status(ctx);
+            break;
+         }
+      } else {
+         if (last_dword != iter.dword) {
+            print_dword_header(outfile, &iter, offset);
+            last_dword = iter.dword;
+         }
+         if (!is_header_field(group, iter.field)) {
+            fprintf(outfile, "    %s: %s\n", iter.name, iter.value);
+            if (iter.struct_desc) {
+               uint64_t struct_offset = offset + 4 * iter.dword;
+               gen_print_group(outfile, ctx, iter.struct_desc, struct_offset,
+                               &p[iter.dword], color);
+            }
          }
       }
    }
diff --git a/src/intel/common/gen_decoder.h b/src/intel/common/gen_decoder.h
index cfc9f2e3f15..25476d03140 100644
--- a/src/intel/common/gen_decoder.h
+++ b/src/intel/common/gen_decoder.h
@@ -51,7 +51,20 @@ const char *gen_group_get_name(struct gen_group *group);
 uint32_t gen_group_get_opcode(struct gen_group *group);
 struct gen_enum *gen_spec_find_enum(struct gen_spec *spec, const char *name);

+struct gen_decoder_context {
+   /* State for identifying debug messages in the stream of commands. */
+   struct {
+      bool is_debug;
+      bool ready;
+
+      char message[1024];
+      int message_length;
+      const uint32_t *last_pointer;
+   } debug;
+};
+
 struct gen_field_iterator {
+   struct gen_decoder_context *ctx;
    struct gen_group *group;
    char name[128];
    char value[128];
@@ -136,7 +149,10 @@ struct gen_field {
    struct gen_enum inline_enum;
 };

+void gen_decoder_context_init(struct gen_decoder_context *ctx);
+
 void gen_field_iterator_init(struct gen_field_iterator *iter,
+                             struct gen_decoder_context *ctx,
                              struct gen_group *group,
                              const uint32_t *p,
                              bool print_colors);
@@ -144,6 +160,7 @@ void gen_field_iterator_init(struct gen_field_iterator *iter,
 bool gen_field_iterator_next(struct gen_field_iterator *iter);

 void gen_print_group(FILE *out,
+                     struct gen_decoder_context *ctx,
                      struct gen_group *group,
                      uint64_t offset, const uint32_t *p,
                      bool color);
diff --git a/src/intel/tools/aubinator.c b/src/intel/tools/aubinator.c
index 4d74fe964d0..fa52835ea59 100644
--- a/src/intel/tools/aubinator.c
+++ b/src/intel/tools/aubinator.c
@@ -66,6 +66,7 @@ uint16_t pci_id = 0;
 char *input_file = NULL, *xml_path = NULL;
 struct gen_spec *spec;
 struct gen_disasm *disasm;
+static struct gen_decoder_context decoder_context;

 uint64_t gtt_size, gtt_end;
 void *gtt;
@@ -100,7 +101,8 @@ decode_group(struct gen_group *strct, const uint32_t *p, int starting_dword)
 {
    uint64_t offset = option_print_offsets ? (void *) p - gtt : 0;

-   gen_print_group(outfile, strct, offset, p, option_color == COLOR_ALWAYS);
+   gen_print_group(outfile, &decoder_context, strct, offset,
+                   p, option_color == COLOR_ALWAYS);
 }

 static void
@@ -686,6 +688,8 @@ parse_commands(struct gen_spec *spec, uint32_t *cmds, int size, int engine)
    int length, i;
    struct gen_group *inst;

+   gen_decoder_context_init(&decoder_context);
+
    for (p = cmds; p < end; p += length) {
       inst = gen_spec_find_instruction(spec, p);
       length = gen_group_get_length(inst, p);
diff --git a/src/intel/tools/aubinator_error_decode.c b/src/intel/tools/aubinator_error_decode.c
index 636f56a3365..6be73854d34 100644
--- a/src/intel/tools/aubinator_error_decode.c
+++ b/src/intel/tools/aubinator_error_decode.c
@@ -67,7 +67,8 @@ print_register(struct gen_spec *spec, const char *name, uint32_t reg)
    struct gen_group *reg_spec = gen_spec_find_register_by_name(spec, name);

    if (reg_spec)
-      gen_print_group(stdout, reg_spec, 0, &reg, option_color == COLOR_ALWAYS);
+      gen_print_group(stdout, NULL, reg_spec, 0, &reg,
+                      option_color == COLOR_ALWAYS);
 }

 struct ring_register_mapping {
@@ -233,6 +234,9 @@ static void decode(struct gen_spec *spec,
    int length;
    struct gen_group *inst;
    uint64_t current_instruction_base_address = 0;
+   struct gen_decoder_context decoder_ctx;
+
+   gen_decoder_context_init(&decoder_ctx);

    for (p = data; p < end; p += length) {
       const char *color = option_full_decode ? BLUE_HEADER : NORMAL,
@@ -255,7 +259,7 @@ static void decode(struct gen_spec *spec,
       printf("%s0x%08"PRIx64":  0x%08x:  %-80s%s\n",
              color, offset, p[0], gen_group_get_name(inst), reset_color);

-      gen_print_group(stdout, inst, offset, p,
+      gen_print_group(stdout, &decoder_ctx, inst, offset, p,
                       option_color == COLOR_ALWAYS);

       if (strcmp(inst->name, "MI_BATCH_BUFFER_END") == 0)
@@ -263,7 +267,7 @@ static void decode(struct gen_spec *spec,

       if (strcmp(inst->name, "STATE_BASE_ADDRESS") == 0) {
          struct gen_field_iterator iter;
-         gen_field_iterator_init(&iter, inst, p, false);
+         gen_field_iterator_init(&iter, &decoder_ctx, inst, p, false);

          while (gen_field_iterator_next(&iter)) {
             if (strcmp(iter.name, "Instruction Base Address") == 0) {
@@ -274,7 +278,7 @@ static void decode(struct gen_spec *spec,
                  strcmp(inst->name, "3DSTATE_PS") == 0 ||
                  strcmp(inst->name, "3DSTATE_WM") == 0) {
          struct gen_field_iterator iter;
-         gen_field_iterator_init(&iter, inst, p, false);
+         gen_field_iterator_init(&iter, &decoder_ctx, inst, p, false);
          uint64_t ksp[3] = {0, 0, 0};
          bool enabled[3] = {false, false, false};

@@ -346,7 +350,7 @@ static void decode(struct gen_spec *spec,
                  strcmp(inst->name, "3DSTATE_GS") == 0 ||
                  strcmp(inst->name, "3DSTATE_VS") == 0) {
          struct gen_field_iterator iter;
-         gen_field_iterator_init(&iter, inst, p, false);
+         gen_field_iterator_init(&iter, &decoder_ctx, inst, p, false);
          uint64_t ksp = 0;
          bool is_simd8 = false; /* vertex shaders on Gen8+ only */
          bool is_enabled = true;
diff --git a/src/mesa/drivers/dri/i965/brw_context.h b/src/mesa/drivers/dri/i965/brw_context.h
index 10313e49041..4f746bb3740 100644
--- a/src/mesa/drivers/dri/i965/brw_context.h
+++ b/src/mesa/drivers/dri/i965/brw_context.h
@@ -143,6 +143,8 @@ struct brw_wm_prog_data;
 struct brw_cs_prog_key;
 struct brw_cs_prog_data;

+struct gen_decoder_context;
+
 enum brw_pipeline {
    BRW_RENDER_PIPELINE,
    BRW_COMPUTE_PIPELINE,
@@ -472,6 +474,9 @@ struct intel_batchbuffer {

    /** Map from batch offset to brw_state_batch data (with DEBUG_BATCH) */
    struct hash_table *state_batch_sizes;
+
+   /** Decoder context tracking */
+   struct gen_decoder_context *decoder_context;
 };

 #define BRW_MAX_XFB_STREAMS 4
diff --git a/src/mesa/drivers/dri/i965/intel_batchbuffer.c b/src/mesa/drivers/dri/i965/intel_batchbuffer.c
index 62d2fe8ef35..736cc3433e6 100644
--- a/src/mesa/drivers/dri/i965/intel_batchbuffer.c
+++ b/src/mesa/drivers/dri/i965/intel_batchbuffer.c
@@ -84,6 +84,8 @@ intel_batchbuffer_init(struct intel_batchbuffer *batch,
    if (INTEL_DEBUG & DEBUG_BATCH) {
       batch->state_batch_sizes =
          _mesa_hash_table_create(NULL, uint_key_hash, uint_key_compare);
+      batch->decoder_context = malloc(sizeof(*batch->decoder_context));
+      gen_decoder_context_init(batch->decoder_context);
    }
 }

@@ -116,6 +118,8 @@ intel_batchbuffer_reset(struct intel_batchbuffer *batch,

    if (batch->state_batch_sizes)
       _mesa_hash_table_clear(batch->state_batch_sizes, NULL);
+   if (batch->decoder_context)
+      gen_decoder_context_init(batch->decoder_context);
 }

 static void
@@ -168,6 +172,8 @@ intel_batchbuffer_free(struct intel_batchbuffer *batch)
    brw_bo_unreference(batch->bo);
    if (batch->state_batch_sizes)
       _mesa_hash_table_destroy(batch->state_batch_sizes, NULL);
+   if (batch->decoder_context)
+      free(batch->decoder_context);
 }

 void
@@ -208,8 +214,8 @@ decode_struct(struct brw_context *brw, struct gen_spec *spec,
       return;

    fprintf(stderr, "%s\n", struct_name);
-   gen_print_group(stderr, group, gtt_offset + offset,
-                   &data[offset / 4], color);
+   gen_print_group(stderr, brw->batch.decoder_context, group,
+                   gtt_offset + offset, &data[offset / 4], color);
 }

 static void
@@ -225,7 +231,8 @@ decode_structs(struct brw_context *brw, struct gen_spec *spec,
    int entries = brw_state_batch_size(brw, offset) / struct_size;
    for (int i = 0; i < entries; i++) {
       fprintf(stderr, "%s %d\n", struct_name, i);
-      gen_print_group(stderr, group, gtt_offset + offset,
+      gen_print_group(stderr, brw->batch.decoder_context, group,
+                      gtt_offset + offset,
                       &data[(offset + i * struct_size) / 4], color);
    }
 }
@@ -270,7 +277,7 @@ do_batch_dump(struct brw_context *brw)
       fprintf(stderr, "%s0x%08"PRIx64":  0x%08x:  %-80s%s\n", header_color,
               offset, p[0], gen_group_get_name(inst), reset_color);

-      gen_print_group(stderr, inst, offset, p, color);
+      gen_print_group(stderr, batch->decoder_context, inst, offset, p, color);

       switch (gen_group_get_opcode(inst) >> 16) {
       case _3DSTATE_PIPELINED_POINTERS:
@@ -311,7 +318,8 @@ do_batch_dump(struct brw_context *brw)
          uint32_t *bt_pointers = &data[bt_offset / 4];
          for (int i = 0; i < bt_entries; i++) {
             fprintf(stderr, "SURFACE_STATE - BTI = %d\n", i);
-            gen_print_group(stderr, group, gtt_offset + bt_pointers[i],
+            gen_print_group(stderr, batch->decoder_context, group,
+                            gtt_offset + bt_pointers[i],
                             &data[bt_pointers[i] / 4], color);
          }
          break;
--
2.11.0


More information about the mesa-dev mailing list