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.landwer...@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 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev