[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, ®, option_color == COLOR_ALWAYS);
+ gen_print_group(stdout, NULL, reg_spec, 0, ®,
+ 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