xref: /aosp_15_r20/external/mesa3d/src/amd/common/ac_parse_ib.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright 2015 Advanced Micro Devices, Inc.
3  *
4  * SPDX-License-Identifier: MIT
5  */
6 
7 #include "ac_debug.h"
8 #include "sid.h"
9 #include "sid_tables.h"
10 
11 #include "util/compiler.h"
12 #include "util/hash_table.h"
13 #include "util/u_debug.h"
14 #include "util/u_math.h"
15 #include "util/memstream.h"
16 #include "util/u_string.h"
17 
18 #include <stdlib.h>
19 
20 #ifdef HAVE_VALGRIND
21 #include <memcheck.h>
22 #include <valgrind.h>
23 #endif
24 
25 DEBUG_GET_ONCE_BOOL_OPTION(color, "AMD_COLOR", true);
26 
27 /* Parsed IBs are difficult to read without colors. Use "less -R file" to
28  * read them, or use "aha -b -f file" to convert them to html.
29  */
30 #define COLOR_RESET  "\033[0m"
31 #define COLOR_RED    "\033[31m"
32 #define COLOR_GREEN  "\033[1;32m"
33 #define COLOR_YELLOW "\033[1;33m"
34 #define COLOR_CYAN   "\033[1;36m"
35 #define COLOR_PURPLE "\033[1;35m"
36 
37 #define O_COLOR_RESET  (debug_get_option_color() ? COLOR_RESET : "")
38 #define O_COLOR_RED    (debug_get_option_color() ? COLOR_RED : "")
39 #define O_COLOR_GREEN  (debug_get_option_color() ? COLOR_GREEN : "")
40 #define O_COLOR_YELLOW (debug_get_option_color() ? COLOR_YELLOW : "")
41 #define O_COLOR_CYAN   (debug_get_option_color() ? COLOR_CYAN : "")
42 #define O_COLOR_PURPLE (debug_get_option_color() ? COLOR_PURPLE : "")
43 
44 #define INDENT_PKT 8
45 
46 static void parse_gfx_compute_ib(FILE *f, struct ac_ib_parser *ib);
47 
print_spaces(FILE * f,unsigned num)48 static void print_spaces(FILE *f, unsigned num)
49 {
50    fprintf(f, "%*s", num, "");
51 }
52 
print_value(FILE * file,uint32_t value,int bits)53 static void print_value(FILE *file, uint32_t value, int bits)
54 {
55    /* Guess if it's int or float */
56    if (value <= (1 << 15)) {
57       if (value <= 9)
58          fprintf(file, "%u\n", value);
59       else
60          fprintf(file, "%u (0x%0*x)\n", value, bits / 4, value);
61    } else {
62       float f = uif(value);
63 
64       if (fabs(f) < 100000 && f * 10 == floor(f * 10))
65          fprintf(file, "%.1ff (0x%0*x)\n", f, bits / 4, value);
66       else
67          /* Don't print more leading zeros than there are bits. */
68          fprintf(file, "0x%0*x\n", bits / 4, value);
69    }
70 }
71 
print_data_dword(FILE * file,uint32_t value,const char * comment)72 static void print_data_dword(FILE *file, uint32_t value, const char *comment)
73 {
74    print_spaces(file, INDENT_PKT);
75    fprintf(file, "(%s)\n", comment);
76 }
77 
print_named_value(FILE * file,const char * name,uint32_t value,int bits)78 static void print_named_value(FILE *file, const char *name, uint32_t value, int bits)
79 {
80    print_spaces(file, INDENT_PKT);
81    fprintf(file, "%s%s%s <- ",
82            O_COLOR_YELLOW, name,
83            O_COLOR_RESET);
84    print_value(file, value, bits);
85 }
86 
print_string_value(FILE * file,const char * name,const char * value)87 static void print_string_value(FILE *file, const char *name, const char *value)
88 {
89    print_spaces(file, INDENT_PKT);
90    fprintf(file, "%s%s%s <- ",
91            O_COLOR_YELLOW, name,
92            O_COLOR_RESET);
93    fprintf(file, "%s\n", value);
94 }
95 
ac_dump_reg(FILE * file,enum amd_gfx_level gfx_level,enum radeon_family family,unsigned offset,uint32_t value,uint32_t field_mask)96 void ac_dump_reg(FILE *file, enum amd_gfx_level gfx_level, enum radeon_family family,
97                  unsigned offset, uint32_t value, uint32_t field_mask)
98 {
99    const struct si_reg *reg = ac_find_register(gfx_level, family, offset);
100 
101    if (reg) {
102       const char *reg_name = sid_strings + reg->name_offset;
103 
104       print_spaces(file, INDENT_PKT);
105       fprintf(file, "%s%s%s <- ",
106               O_COLOR_YELLOW, reg_name,
107               O_COLOR_RESET);
108 
109       print_value(file, value, 32);
110 
111       for (unsigned f = 0; f < reg->num_fields; f++) {
112          const struct si_field *field = sid_fields_table + reg->fields_offset + f;
113          const int *values_offsets = sid_strings_offsets + field->values_offset;
114          uint32_t val = (value & field->mask) >> (ffs(field->mask) - 1);
115 
116          if (!(field->mask & field_mask))
117             continue;
118 
119          /* Indent the field. */
120          print_spaces(file, INDENT_PKT + strlen(reg_name) + 4);
121 
122          /* Print the field. */
123          fprintf(file, "%s = ", sid_strings + field->name_offset);
124 
125          if (val < field->num_values && values_offsets[val] >= 0)
126             fprintf(file, "%s\n", sid_strings + values_offsets[val]);
127          else
128             print_value(file, val, util_bitcount(field->mask));
129       }
130       return;
131    }
132 
133    print_spaces(file, INDENT_PKT);
134    fprintf(file, "%s0x%05x%s <- 0x%08x\n",
135            O_COLOR_YELLOW, offset,
136            O_COLOR_RESET, value);
137 }
138 
ac_ib_get(struct ac_ib_parser * ib)139 static uint32_t ac_ib_get(struct ac_ib_parser *ib)
140 {
141    uint32_t v = 0;
142 
143    if (ib->cur_dw < ib->num_dw) {
144       v = ib->ib[ib->cur_dw];
145 #ifdef HAVE_VALGRIND
146       /* Help figure out where garbage data is written to IBs.
147        *
148        * Arguably we should do this already when the IBs are written,
149        * see RADEON_VALGRIND. The problem is that client-requests to
150        * Valgrind have an overhead even when Valgrind isn't running,
151        * and radeon_emit is performance sensitive...
152        */
153       if (VALGRIND_CHECK_VALUE_IS_DEFINED(v))
154          fprintf(ib->f, "%sValgrind: The next DWORD is garbage%s\n",
155                  debug_get_option_color() ? COLOR_RED : "", O_COLOR_RESET);
156 #endif
157       fprintf(ib->f, "\n\035#%08x ", v);
158    } else {
159       fprintf(ib->f, "\n\035#???????? ");
160    }
161 
162    ib->cur_dw++;
163    return v;
164 }
165 
ac_ib_get64(struct ac_ib_parser * ib)166 static uint64_t ac_ib_get64(struct ac_ib_parser *ib)
167 {
168    uint32_t lo = ac_ib_get(ib);
169    uint32_t hi = ac_ib_get(ib);
170    return ((uint64_t)hi << 32) | lo;
171 }
172 
ac_sext_addr48(uint64_t addr)173 static uint64_t ac_sext_addr48(uint64_t addr)
174 {
175    if (addr & (1llu << 47))
176       return addr | (0xFFFFllu << 48);
177    else
178       return addr & (~(0xFFFFllu << 48));
179 }
180 
ac_parse_set_reg_packet(FILE * f,unsigned count,unsigned reg_offset,struct ac_ib_parser * ib)181 static void ac_parse_set_reg_packet(FILE *f, unsigned count, unsigned reg_offset,
182                                     struct ac_ib_parser *ib)
183 {
184    unsigned reg_dw = ac_ib_get(ib);
185    unsigned reg = ((reg_dw & 0xFFFF) << 2) + reg_offset;
186    unsigned index = reg_dw >> 28;
187    int i;
188 
189    if (index != 0)
190       print_named_value(f, "INDEX", index, 32);
191 
192    for (i = 0; i < count; i++)
193       ac_dump_reg(f, ib->gfx_level, ib->family, reg + i * 4, ac_ib_get(ib), ~0);
194 }
195 
ac_parse_set_reg_pairs_packet(FILE * f,unsigned count,unsigned reg_base,struct ac_ib_parser * ib)196 static void ac_parse_set_reg_pairs_packet(FILE *f, unsigned count, unsigned reg_base,
197                                           struct ac_ib_parser *ib)
198 {
199    for (unsigned i = 0; i < (count + 1) / 2; i++) {
200       unsigned reg_offset = (ac_ib_get(ib) << 2) + reg_base;
201       ac_dump_reg(f, ib->gfx_level, ib->family, reg_offset, ac_ib_get(ib), ~0);
202    }
203 }
204 
ac_parse_set_reg_pairs_packed_packet(FILE * f,unsigned count,unsigned reg_base,struct ac_ib_parser * ib)205 static void ac_parse_set_reg_pairs_packed_packet(FILE *f, unsigned count, unsigned reg_base,
206                                                  struct ac_ib_parser *ib)
207 {
208    unsigned reg_offset0 = 0, reg_offset1 = 0;
209 
210    print_named_value(f, "REG_COUNT", ac_ib_get(ib), 32);
211 
212    for (unsigned i = 0; i < count; i++) {
213       if (i % 3 == 0) {
214          unsigned tmp = ac_ib_get(ib);
215          reg_offset0 = ((tmp & 0xffff) << 2) + reg_base;
216          reg_offset1 = ((tmp >> 16) << 2) + reg_base;
217       } else if (i % 3 == 1) {
218          ac_dump_reg(f, ib->gfx_level, ib->family, reg_offset0, ac_ib_get(ib), ~0);
219       } else {
220          ac_dump_reg(f, ib->gfx_level, ib->family, reg_offset1, ac_ib_get(ib), ~0);
221       }
222    }
223 }
224 
225 #define AC_ADDR_SIZE_NOT_MEMORY 0xFFFFFFFF
226 
print_addr(struct ac_ib_parser * ib,const char * name,uint64_t addr,uint32_t size)227 static void print_addr(struct ac_ib_parser *ib, const char *name, uint64_t addr, uint32_t size)
228 {
229    FILE *f = ib->f;
230 
231    print_spaces(f, INDENT_PKT);
232    fprintf(f, "%s%s%s <- ",
233            O_COLOR_YELLOW, name,
234            O_COLOR_RESET);
235 
236    fprintf(f, "0x%llx", (unsigned long long)addr);
237 
238    if (ib->addr_callback && size != AC_ADDR_SIZE_NOT_MEMORY) {
239       struct ac_addr_info addr_info;
240       ib->addr_callback(ib->addr_callback_data, addr, &addr_info);
241 
242       struct ac_addr_info addr_info2 = addr_info;
243       if (size)
244          ib->addr_callback(ib->addr_callback_data, addr + size - 1, &addr_info2);
245 
246       uint32_t invalid_count = !addr_info.valid + !addr_info2.valid;
247 
248       if (addr_info.use_after_free && addr_info2.use_after_free)
249          fprintf(f, " used after free");
250       else if (invalid_count == 2)
251          fprintf(f, " invalid");
252       else if (invalid_count == 1)
253          fprintf(f, " out of bounds");
254    }
255 
256    fprintf(f, "\n");
257 }
258 
ac_parse_packet3(FILE * f,uint32_t header,struct ac_ib_parser * ib,int * current_trace_id)259 static void ac_parse_packet3(FILE *f, uint32_t header, struct ac_ib_parser *ib,
260                              int *current_trace_id)
261 {
262    unsigned first_dw = ib->cur_dw;
263    int count = PKT_COUNT_G(header);
264    unsigned op = PKT3_IT_OPCODE_G(header);
265    const char *shader_type = PKT3_SHADER_TYPE_G(header) ? "(shader_type=compute)" : "";
266    const char *predicated = PKT3_PREDICATE(header) ? "(predicated)" : "";
267    const char *reset_filter_cam = PKT3_RESET_FILTER_CAM_G(header) ? "(reset_filter_cam)" : "";
268    int i;
269    unsigned tmp;
270 
271    /* Print the name first. */
272    for (i = 0; i < ARRAY_SIZE(packet3_table); i++)
273       if (packet3_table[i].op == op)
274          break;
275 
276    char unknown_name[32];
277    const char *pkt_name;
278 
279    if (i < ARRAY_SIZE(packet3_table)) {
280       pkt_name = sid_strings + packet3_table[i].name_offset;
281    } else {
282       snprintf(unknown_name, sizeof(unknown_name), "UNKNOWN(0x%02X)", op);
283       pkt_name = unknown_name;
284    }
285    const char *color;
286 
287    if (strstr(pkt_name, "DRAW") || strstr(pkt_name, "DISPATCH"))
288       color = O_COLOR_PURPLE;
289    else if (strstr(pkt_name, "SET") == pkt_name && strstr(pkt_name, "REG"))
290       color = O_COLOR_CYAN;
291    else if (i >= ARRAY_SIZE(packet3_table))
292       color = O_COLOR_RED;
293    else
294       color = O_COLOR_GREEN;
295 
296    fprintf(f, "%s%s%s%s%s%s:\n", color, pkt_name, O_COLOR_RESET,
297            shader_type, predicated, reset_filter_cam);
298 
299    /* Print the contents. */
300    switch (op) {
301    case PKT3_SET_CONTEXT_REG:
302       ac_parse_set_reg_packet(f, count, SI_CONTEXT_REG_OFFSET, ib);
303       break;
304    case PKT3_SET_CONFIG_REG:
305       ac_parse_set_reg_packet(f, count, SI_CONFIG_REG_OFFSET, ib);
306       break;
307    case PKT3_SET_UCONFIG_REG:
308    case PKT3_SET_UCONFIG_REG_INDEX:
309       ac_parse_set_reg_packet(f, count, CIK_UCONFIG_REG_OFFSET, ib);
310       break;
311    case PKT3_SET_SH_REG:
312    case PKT3_SET_SH_REG_INDEX:
313       ac_parse_set_reg_packet(f, count, SI_SH_REG_OFFSET, ib);
314       break;
315    case PKT3_SET_UCONFIG_REG_PAIRS:
316       ac_parse_set_reg_pairs_packet(f, count, CIK_UCONFIG_REG_OFFSET, ib);
317       break;
318    case PKT3_SET_CONTEXT_REG_PAIRS:
319       ac_parse_set_reg_pairs_packet(f, count, SI_CONTEXT_REG_OFFSET, ib);
320       break;
321    case PKT3_SET_SH_REG_PAIRS:
322       ac_parse_set_reg_pairs_packet(f, count, SI_SH_REG_OFFSET, ib);
323       break;
324    case PKT3_SET_CONTEXT_REG_PAIRS_PACKED:
325       ac_parse_set_reg_pairs_packed_packet(f, count, SI_CONTEXT_REG_OFFSET, ib);
326       break;
327    case PKT3_SET_SH_REG_PAIRS_PACKED:
328    case PKT3_SET_SH_REG_PAIRS_PACKED_N:
329       ac_parse_set_reg_pairs_packed_packet(f, count, SI_SH_REG_OFFSET, ib);
330       break;
331    case PKT3_ACQUIRE_MEM:
332       if (ib->gfx_level >= GFX11) {
333          if (G_585_PWS_ENA(ib->ib[ib->cur_dw + 5])) {
334             ac_dump_reg(f, ib->gfx_level, ib->family, R_580_ACQUIRE_MEM_PWS_2, ac_ib_get(ib), ~0);
335             print_named_value(f, "GCR_SIZE", ac_ib_get(ib), 32);
336             print_named_value(f, "GCR_SIZE_HI", ac_ib_get(ib), 25);
337             print_named_value(f, "GCR_BASE_LO", ac_ib_get(ib), 32);
338             print_named_value(f, "GCR_BASE_HI", ac_ib_get(ib), 32);
339             ac_dump_reg(f, ib->gfx_level, ib->family, R_585_ACQUIRE_MEM_PWS_7, ac_ib_get(ib), ~0);
340             ac_dump_reg(f, ib->gfx_level, ib->family, R_586_GCR_CNTL, ac_ib_get(ib), ~0);
341          } else {
342             print_string_value(f, "ENGINE_SEL", ac_ib_get(ib) & 0x80000000 ? "ME" : "PFP");
343             print_named_value(f, "GCR_SIZE", ac_ib_get(ib), 32);
344             print_named_value(f, "GCR_SIZE_HI", ac_ib_get(ib), 25);
345             print_named_value(f, "GCR_BASE_LO", ac_ib_get(ib), 32);
346             print_named_value(f, "GCR_BASE_HI", ac_ib_get(ib), 32);
347             print_named_value(f, "POLL_INTERVAL", ac_ib_get(ib), 16);
348             ac_dump_reg(f, ib->gfx_level, ib->family, R_586_GCR_CNTL, ac_ib_get(ib), ~0);
349          }
350       } else {
351          tmp = ac_ib_get(ib);
352          ac_dump_reg(f, ib->gfx_level, ib->family, R_0301F0_CP_COHER_CNTL, tmp, 0x7fffffff);
353          print_string_value(f, "ENGINE_SEL", tmp & 0x80000000 ? "ME" : "PFP");
354          ac_dump_reg(f, ib->gfx_level, ib->family, R_0301F4_CP_COHER_SIZE, ac_ib_get(ib), ~0);
355          ac_dump_reg(f, ib->gfx_level, ib->family, R_030230_CP_COHER_SIZE_HI, ac_ib_get(ib), ~0);
356          ac_dump_reg(f, ib->gfx_level, ib->family, R_0301F8_CP_COHER_BASE, ac_ib_get(ib), ~0);
357          ac_dump_reg(f, ib->gfx_level, ib->family, R_0301E4_CP_COHER_BASE_HI, ac_ib_get(ib), ~0);
358          print_named_value(f, "POLL_INTERVAL", ac_ib_get(ib), 16);
359          if (ib->gfx_level >= GFX10)
360             ac_dump_reg(f, ib->gfx_level, ib->family, R_586_GCR_CNTL, ac_ib_get(ib), ~0);
361       }
362       break;
363    case PKT3_SURFACE_SYNC:
364       if (ib->gfx_level >= GFX7) {
365          ac_dump_reg(f, ib->gfx_level, ib->family, R_0301F0_CP_COHER_CNTL, ac_ib_get(ib), ~0);
366          ac_dump_reg(f, ib->gfx_level, ib->family, R_0301F4_CP_COHER_SIZE, ac_ib_get(ib), ~0);
367          ac_dump_reg(f, ib->gfx_level, ib->family, R_0301F8_CP_COHER_BASE, ac_ib_get(ib), ~0);
368       } else {
369          ac_dump_reg(f, ib->gfx_level, ib->family, R_0085F0_CP_COHER_CNTL, ac_ib_get(ib), ~0);
370          ac_dump_reg(f, ib->gfx_level, ib->family, R_0085F4_CP_COHER_SIZE, ac_ib_get(ib), ~0);
371          ac_dump_reg(f, ib->gfx_level, ib->family, R_0085F8_CP_COHER_BASE, ac_ib_get(ib), ~0);
372       }
373       print_named_value(f, "POLL_INTERVAL", ac_ib_get(ib), 16);
374       break;
375    case PKT3_EVENT_WRITE: {
376       uint32_t event_dw = ac_ib_get(ib);
377       ac_dump_reg(f, ib->gfx_level, ib->family, R_028A90_VGT_EVENT_INITIATOR, event_dw,
378                   S_028A90_EVENT_TYPE(~0));
379       print_named_value(f, "EVENT_INDEX", (event_dw >> 8) & 0xf, 4);
380       print_named_value(f, "INV_L2", (event_dw >> 20) & 0x1, 1);
381       if (count > 0)
382          print_addr(ib, "ADDR", ac_ib_get64(ib), 0);
383 
384       break;
385    }
386    case PKT3_EVENT_WRITE_EOP: {
387       uint32_t event_dw = ac_ib_get(ib);
388       ac_dump_reg(f, ib->gfx_level, ib->family, R_028A90_VGT_EVENT_INITIATOR, event_dw,
389                   S_028A90_EVENT_TYPE(~0));
390       print_named_value(f, "EVENT_INDEX", (event_dw >> 8) & 0xf, 4);
391       print_named_value(f, "TCL1_VOL_ACTION_ENA", (event_dw >> 12) & 0x1, 1);
392       print_named_value(f, "TC_VOL_ACTION_ENA", (event_dw >> 13) & 0x1, 1);
393       print_named_value(f, "TC_WB_ACTION_ENA", (event_dw >> 15) & 0x1, 1);
394       print_named_value(f, "TCL1_ACTION_ENA", (event_dw >> 16) & 0x1, 1);
395       print_named_value(f, "TC_ACTION_ENA", (event_dw >> 17) & 0x1, 1);
396       uint64_t addr = ac_ib_get64(ib);
397       uint32_t data_sel = addr >> 61;
398       uint32_t data_size;
399       switch (data_sel) {
400       case EOP_DATA_SEL_VALUE_32BIT:
401          data_size = 4;
402          break;
403       case EOP_DATA_SEL_VALUE_64BIT:
404       case EOP_DATA_SEL_TIMESTAMP:
405          data_size = 8;
406          break;
407       default:
408          data_size = AC_ADDR_SIZE_NOT_MEMORY;
409          break;
410       }
411       print_addr(ib, "ADDR", ac_sext_addr48(addr), data_size);
412       print_named_value(f, "DST_SEL", (addr >> 48) & 0x3, 2);
413       print_named_value(f, "INT_SEL", (addr >> 56) & 0x7, 3);
414       print_named_value(f, "DATA_SEL", data_sel, 3);
415       print_named_value(f, "DATA_LO", ac_ib_get(ib), 32);
416       print_named_value(f, "DATA_HI", ac_ib_get(ib), 32);
417       break;
418    }
419    case PKT3_RELEASE_MEM: {
420       uint32_t event_dw = ac_ib_get(ib);
421       if (ib->gfx_level >= GFX10) {
422          ac_dump_reg(f, ib->gfx_level, ib->family, R_490_RELEASE_MEM_OP, event_dw, ~0u);
423       } else {
424          ac_dump_reg(f, ib->gfx_level, ib->family, R_028A90_VGT_EVENT_INITIATOR, event_dw,
425                      S_028A90_EVENT_TYPE(~0));
426          print_named_value(f, "EVENT_INDEX", (event_dw >> 8) & 0xf, 4);
427          print_named_value(f, "TCL1_VOL_ACTION_ENA", (event_dw >> 12) & 0x1, 1);
428          print_named_value(f, "TC_VOL_ACTION_ENA", (event_dw >> 13) & 0x1, 1);
429          print_named_value(f, "TC_WB_ACTION_ENA", (event_dw >> 15) & 0x1, 1);
430          print_named_value(f, "TCL1_ACTION_ENA", (event_dw >> 16) & 0x1, 1);
431          print_named_value(f, "TC_ACTION_ENA", (event_dw >> 17) & 0x1, 1);
432          print_named_value(f, "TC_NC_ACTION_ENA", (event_dw >> 19) & 0x1, 1);
433          print_named_value(f, "TC_WC_ACTION_ENA", (event_dw >> 20) & 0x1, 1);
434          print_named_value(f, "TC_MD_ACTION_ENA", (event_dw >> 21) & 0x1, 1);
435       }
436       uint32_t sel_dw = ac_ib_get(ib);
437       print_named_value(f, "DST_SEL", (sel_dw >> 16) & 0x3, 2);
438       print_named_value(f, "INT_SEL", (sel_dw >> 24) & 0x7, 3);
439       print_named_value(f, "DATA_SEL", sel_dw >> 29, 3);
440       print_named_value(f, "ADDRESS_LO", ac_ib_get(ib), 32);
441       print_named_value(f, "ADDRESS_HI", ac_ib_get(ib), 32);
442       print_named_value(f, "DATA_LO", ac_ib_get(ib), 32);
443       print_named_value(f, "DATA_HI", ac_ib_get(ib), 32);
444       print_named_value(f, "CTXID", ac_ib_get(ib), 32);
445       break;
446    }
447    case PKT3_WAIT_REG_MEM:
448       print_named_value(f, "OP", ac_ib_get(ib), 32);
449       print_named_value(f, "ADDRESS_LO", ac_ib_get(ib), 32);
450       print_named_value(f, "ADDRESS_HI", ac_ib_get(ib), 32);
451       print_named_value(f, "REF", ac_ib_get(ib), 32);
452       print_named_value(f, "MASK", ac_ib_get(ib), 32);
453       print_named_value(f, "POLL_INTERVAL", ac_ib_get(ib), 16);
454       break;
455    case PKT3_DRAW_INDEX_AUTO:
456       ac_dump_reg(f, ib->gfx_level, ib->family, R_030930_VGT_NUM_INDICES, ac_ib_get(ib), ~0);
457       ac_dump_reg(f, ib->gfx_level, ib->family, R_0287F0_VGT_DRAW_INITIATOR, ac_ib_get(ib), ~0);
458       break;
459    case PKT3_DRAW_INDEX_2:
460       ac_dump_reg(f, ib->gfx_level, ib->family, R_028A78_VGT_DMA_MAX_SIZE, ac_ib_get(ib), ~0);
461       print_addr(ib, "INDEX_ADDR", ac_ib_get64(ib), 0);
462       ac_dump_reg(f, ib->gfx_level, ib->family, R_030930_VGT_NUM_INDICES, ac_ib_get(ib), ~0);
463       ac_dump_reg(f, ib->gfx_level, ib->family, R_0287F0_VGT_DRAW_INITIATOR, ac_ib_get(ib), ~0);
464       break;
465    case PKT3_DRAW_INDIRECT:
466    case PKT3_DRAW_INDEX_INDIRECT:
467       print_named_value(f, "OFFSET", ac_ib_get(ib), 32);
468       print_named_value(f, "VERTEX_OFFSET_REG", ac_ib_get(ib), 32);
469       print_named_value(f, "START_INSTANCE_REG", ac_ib_get(ib), 32);
470       ac_dump_reg(f, ib->gfx_level, ib->family, R_0287F0_VGT_DRAW_INITIATOR, ac_ib_get(ib), ~0);
471       break;
472    case PKT3_DRAW_INDIRECT_MULTI:
473    case PKT3_DRAW_INDEX_INDIRECT_MULTI:
474       print_named_value(f, "OFFSET", ac_ib_get(ib), 32);
475       print_named_value(f, "VERTEX_OFFSET_REG", ac_ib_get(ib), 32);
476       print_named_value(f, "START_INSTANCE_REG", ac_ib_get(ib), 32);
477       tmp = ac_ib_get(ib);
478       print_named_value(f, "DRAW_ID_REG", tmp & 0xFFFF, 16);
479       print_named_value(f, "DRAW_ID_ENABLE", tmp >> 31, 1);
480       print_named_value(f, "COUNT_INDIRECT_ENABLE", (tmp >> 30) & 1, 1);
481       print_named_value(f, "DRAW_COUNT", ac_ib_get(ib), 32);
482       print_addr(ib, "COUNT_ADDR", ac_ib_get64(ib), 0);
483       print_named_value(f, "STRIDE", ac_ib_get(ib), 32);
484       ac_dump_reg(f, ib->gfx_level, ib->family, R_0287F0_VGT_DRAW_INITIATOR, ac_ib_get(ib), ~0);
485       break;
486    case PKT3_INDEX_BASE:
487       print_addr(ib, "ADDR", ac_ib_get64(ib), 0);
488       break;
489    case PKT3_INDEX_TYPE:
490       ac_dump_reg(f, ib->gfx_level, ib->family, R_028A7C_VGT_DMA_INDEX_TYPE, ac_ib_get(ib), ~0);
491       break;
492    case PKT3_NUM_INSTANCES:
493       ac_dump_reg(f, ib->gfx_level, ib->family, R_030934_VGT_NUM_INSTANCES, ac_ib_get(ib), ~0);
494       break;
495    case PKT3_WRITE_DATA: {
496       uint32_t control = ac_ib_get(ib);
497       ac_dump_reg(f, ib->gfx_level, ib->family, R_370_CONTROL, control, ~0);
498       uint32_t dst_sel = G_370_DST_SEL(control);
499       uint64_t addr = ac_ib_get64(ib);
500       uint32_t dword_count = first_dw + count + 1 - ib->cur_dw;
501       bool writes_memory = dst_sel == V_370_MEM_GRBM || dst_sel == V_370_TC_L2 || dst_sel == V_370_MEM;
502       print_addr(ib, "DST_ADDR", addr, writes_memory ? dword_count * 4 : AC_ADDR_SIZE_NOT_MEMORY);
503       for (uint32_t i = 0; i < dword_count; i++)
504           print_data_dword(f, ac_ib_get(ib), "data");
505       break;
506    }
507    case PKT3_CP_DMA:
508       ac_dump_reg(f, ib->gfx_level, ib->family, R_410_CP_DMA_WORD0, ac_ib_get(ib), ~0);
509       ac_dump_reg(f, ib->gfx_level, ib->family, R_411_CP_DMA_WORD1, ac_ib_get(ib), ~0);
510       ac_dump_reg(f, ib->gfx_level, ib->family, R_412_CP_DMA_WORD2, ac_ib_get(ib), ~0);
511       ac_dump_reg(f, ib->gfx_level, ib->family, R_413_CP_DMA_WORD3, ac_ib_get(ib), ~0);
512       ac_dump_reg(f, ib->gfx_level, ib->family, R_415_COMMAND, ac_ib_get(ib), ~0);
513       break;
514    case PKT3_DMA_DATA: {
515       uint32_t header = ac_ib_get(ib);
516       ac_dump_reg(f, ib->gfx_level, ib->family, R_501_DMA_DATA_WORD0, header, ~0);
517 
518       uint64_t src_addr = ac_ib_get64(ib);
519       uint64_t dst_addr = ac_ib_get64(ib);
520 
521       uint32_t command = ac_ib_get(ib);
522       uint32_t size = ib->gfx_level >= GFX9 ? G_415_BYTE_COUNT_GFX9(command)
523                                             : G_415_BYTE_COUNT_GFX6(command);
524 
525       uint32_t src_sel = G_501_SRC_SEL(header);
526       bool src_mem = (src_sel == V_501_SRC_ADDR && G_415_SAS(command) == V_415_MEMORY) ||
527                       src_sel == V_411_SRC_ADDR_TC_L2;
528 
529       uint32_t dst_sel = G_501_DST_SEL(header);
530       bool dst_mem = (dst_sel == V_501_DST_ADDR && G_415_DAS(command) == V_415_MEMORY) ||
531                       dst_sel == V_411_DST_ADDR_TC_L2;
532 
533       print_addr(ib, "SRC_ADDR", src_addr, src_mem ? size : AC_ADDR_SIZE_NOT_MEMORY);
534       print_addr(ib, "DST_ADDR", dst_addr, dst_mem ? size : AC_ADDR_SIZE_NOT_MEMORY);
535       ac_dump_reg(f, ib->gfx_level, ib->family, R_415_COMMAND, command, ~0);
536       break;
537    }
538    case PKT3_INDIRECT_BUFFER_SI:
539    case PKT3_INDIRECT_BUFFER_CONST:
540    case PKT3_INDIRECT_BUFFER: {
541       uint32_t base_lo_dw = ac_ib_get(ib);
542       ac_dump_reg(f, ib->gfx_level, ib->family, R_3F0_IB_BASE_LO, base_lo_dw, ~0);
543       uint32_t base_hi_dw = ac_ib_get(ib);
544       ac_dump_reg(f, ib->gfx_level, ib->family, R_3F1_IB_BASE_HI, base_hi_dw, ~0);
545       uint32_t control_dw = ac_ib_get(ib);
546       ac_dump_reg(f, ib->gfx_level, ib->family, R_3F2_IB_CONTROL, control_dw, ~0);
547 
548       if (!ib->addr_callback)
549          break;
550 
551       uint64_t addr = ((uint64_t)base_hi_dw << 32) | base_lo_dw;
552       struct ac_addr_info addr_info;
553       ib->addr_callback(ib->addr_callback_data, addr, &addr_info);
554       void *data = addr_info.cpu_addr;
555       if (!data)
556          break;
557 
558       if (G_3F2_CHAIN(control_dw)) {
559          ib->ib = data;
560          ib->num_dw = G_3F2_IB_SIZE(control_dw);
561          ib->cur_dw = 0;
562          return;
563       }
564 
565       struct ac_ib_parser ib_recurse;
566       memcpy(&ib_recurse, ib, sizeof(ib_recurse));
567       ib_recurse.ib = data;
568       ib_recurse.num_dw = G_3F2_IB_SIZE(control_dw);
569       ib_recurse.cur_dw = 0;
570       if (ib_recurse.trace_id_count) {
571          if (*current_trace_id == *ib->trace_ids) {
572             ++ib_recurse.trace_ids;
573             --ib_recurse.trace_id_count;
574          } else {
575             ib_recurse.trace_id_count = 0;
576          }
577       }
578 
579       fprintf(f, "\n\035>------------------ nested begin ------------------\n");
580       parse_gfx_compute_ib(f, &ib_recurse);
581       fprintf(f, "\n\035<------------------- nested end -------------------\n");
582       break;
583    }
584    case PKT3_CLEAR_STATE:
585    case PKT3_INCREMENT_DE_COUNTER:
586    case PKT3_PFP_SYNC_ME:
587       print_data_dword(f, ac_ib_get(ib), "reserved");
588       break;
589    case PKT3_NOP:
590       if (header == PKT3_NOP_PAD) {
591          count = -1; /* One dword NOP. */
592       } else if (count == 0 && ib->cur_dw < ib->num_dw && AC_IS_TRACE_POINT(ib->ib[ib->cur_dw])) {
593          unsigned packet_id = AC_GET_TRACE_POINT_ID(ib->ib[ib->cur_dw]);
594 
595          print_spaces(f, INDENT_PKT);
596          fprintf(f, "%sTrace point ID: %u%s\n", O_COLOR_RED, packet_id, O_COLOR_RESET);
597 
598          if (!ib->trace_id_count)
599             break; /* tracing was disabled */
600 
601          *current_trace_id = packet_id;
602 
603          print_spaces(f, INDENT_PKT);
604          if (packet_id < *ib->trace_ids) {
605             fprintf(f, "%sThis trace point was reached by the CP.%s\n",
606                     O_COLOR_RED, O_COLOR_RESET);
607          } else if (packet_id == *ib->trace_ids) {
608             fprintf(f, "%s!!!!! This is the last trace point that "
609                                  "was reached by the CP !!!!!%s\n",
610                     O_COLOR_RED, O_COLOR_RESET);
611          } else if (packet_id + 1 == *ib->trace_ids) {
612             fprintf(f, "%s!!!!! This is the first trace point that "
613                                  "was NOT been reached by the CP !!!!!%s\n",
614                     O_COLOR_RED, O_COLOR_RESET);
615          } else {
616             fprintf(f, "%s!!!!! This trace point was NOT reached "
617                                  "by the CP !!!!!%s\n",
618                     O_COLOR_RED, O_COLOR_RESET);
619          }
620       } else {
621          while (ib->cur_dw <= first_dw + count)
622              print_data_dword(f, ac_ib_get(ib), "unused");
623       }
624       break;
625    case PKT3_DISPATCH_DIRECT:
626    case PKT3_DISPATCH_DIRECT_INTERLEAVED:
627       ac_dump_reg(f, ib->gfx_level, ib->family, R_00B804_COMPUTE_DIM_X, ac_ib_get(ib), ~0);
628       ac_dump_reg(f, ib->gfx_level, ib->family, R_00B808_COMPUTE_DIM_Y, ac_ib_get(ib), ~0);
629       ac_dump_reg(f, ib->gfx_level, ib->family, R_00B80C_COMPUTE_DIM_Z, ac_ib_get(ib), ~0);
630       ac_dump_reg(f, ib->gfx_level, ib->family, R_00B800_COMPUTE_DISPATCH_INITIATOR,
631                   ac_ib_get(ib), ~0);
632       break;
633    case PKT3_DISPATCH_INDIRECT:
634    case PKT3_DISPATCH_INDIRECT_INTERLEAVED:
635       if (count > 1)
636          print_addr(ib, "ADDR", ac_ib_get64(ib), 12);
637       else
638          print_named_value(f, "DATA_OFFSET", ac_ib_get(ib), 32);
639 
640       ac_dump_reg(f, ib->gfx_level, ib->family, R_00B800_COMPUTE_DISPATCH_INITIATOR,
641                   ac_ib_get(ib), ~0);
642       break;
643    case PKT3_SET_BASE:
644       tmp = ac_ib_get(ib);
645       print_string_value(f, "BASE_INDEX", tmp == 1 ? "INDIRECT_BASE" : COLOR_RED "UNKNOWN" COLOR_RESET);
646       print_addr(ib, "ADDR", ac_ib_get64(ib), 0);
647       break;
648    case PKT3_PRIME_UTCL2:
649       tmp = ac_ib_get(ib);
650       print_named_value(f, "CACHE_PERM[rwx]", tmp & 0x7, 3);
651       print_string_value(f, "PRIME_MODE", tmp & 0x8 ? "WAIT_FOR_XACK" : "DONT_WAIT_FOR_XACK");
652       print_named_value(f, "ENGINE_SEL", tmp >> 30, 2);
653       print_addr(ib, "ADDR", ac_ib_get64(ib), 0);
654       print_named_value(f, "REQUESTED_PAGES", ac_ib_get(ib), 14);
655       break;
656    case PKT3_ATOMIC_MEM:
657       tmp = ac_ib_get(ib);
658       print_named_value(f, "ATOMIC", tmp & 0x7f, 7);
659       print_named_value(f, "COMMAND", (tmp >> 8) & 0xf, 4);
660       print_named_value(f, "CACHE_POLICY", (tmp >> 25) & 0x3, 2);
661       print_named_value(f, "ENGINE_SEL", tmp >> 30, 2);
662       print_addr(ib, "ADDR", ac_ib_get64(ib), 8);
663       print_named_value(f, "SRC_DATA_LO", ac_ib_get(ib), 32);
664       print_named_value(f, "SRC_DATA_HI", ac_ib_get(ib), 32);
665       print_named_value(f, "CMP_DATA_LO", ac_ib_get(ib), 32);
666       print_named_value(f, "CMP_DATA_HI", ac_ib_get(ib), 32);
667       print_named_value(f, "LOOP_INTERVAL", ac_ib_get(ib) & 0x1fff, 13);
668       break;
669    case PKT3_INDEX_BUFFER_SIZE:
670       print_named_value(f, "COUNT", ac_ib_get(ib), 32);
671       break;
672    case PKT3_COND_EXEC: {
673       uint32_t size = ac_ib_get(ib) * 4;
674       print_addr(ib, "ADDR", ac_ib_get64(ib), size);
675       print_named_value(f, "SIZE", size, 32);
676       break;
677    }
678    case PKT3_DISPATCH_TASKMESH_GFX:
679       tmp = ac_ib_get(ib);
680       print_named_value(f, "RING_ENTRY_REG", (tmp >> 16) & 0xffff, 16);
681       print_named_value(f, "XYZ_DIM_REG", (tmp & 0xffff), 16);
682       tmp = ac_ib_get(ib);
683       print_named_value(f, "THREAD_TRACE_MARKER_ENABLE", (tmp >> 31) & 0x1, 1);
684       if (ib->gfx_level >= GFX11) {
685          print_named_value(f, "XYZ_DIM_ENABLE", (tmp >> 30) & 0x1, 1);
686          print_named_value(f, "MODE1_ENABLE", (tmp >> 29) & 0x1, 1);
687          print_named_value(f, "LINEAR_DISPATCH_ENABLED", (tmp >> 28) & 0x1, 1);
688       }
689       print_named_value(f, "DI_SRC_SEL_AUTO_INDEX", ac_ib_get(ib), ~0);
690       break;
691    case PKT3_DISPATCH_TASKMESH_DIRECT_ACE:
692       print_named_value(f, "X_DIM", ac_ib_get(ib), ~0);
693       print_named_value(f, "Y_DIM", ac_ib_get(ib), ~0);
694       print_named_value(f, "Z_DIM", ac_ib_get(ib), ~0);
695       ac_dump_reg(f, ib->gfx_level, ib->family, R_00B800_COMPUTE_DISPATCH_INITIATOR,
696                   ac_ib_get(ib), ~0);
697       print_named_value(f, "RING_ENTRY_REG", ac_ib_get(ib), 16);
698       break;
699    }
700 
701    /* print additional dwords */
702    while (ib->cur_dw <= first_dw + count)
703       ac_ib_get(ib);
704 
705    if (ib->cur_dw > first_dw + count + 1)
706       fprintf(f, "%s !!!!! count in header too low !!!!!%s\n",
707               O_COLOR_RED, O_COLOR_RESET);
708 }
709 
710 /**
711  * Parse and print an IB into a file.
712  */
parse_gfx_compute_ib(FILE * f,struct ac_ib_parser * ib)713 static void parse_gfx_compute_ib(FILE *f, struct ac_ib_parser *ib)
714 {
715    int current_trace_id = -1;
716 
717    while (ib->cur_dw < ib->num_dw) {
718       if (ib->annotations) {
719          struct hash_entry *marker = _mesa_hash_table_search(ib->annotations, ib->ib + ib->cur_dw);
720          if (marker)
721             fprintf(f, "\n%s:", (char *)marker->data);
722       }
723 
724       uint32_t header = ac_ib_get(ib);
725       unsigned type = PKT_TYPE_G(header);
726 
727       switch (type) {
728       case 3:
729          ac_parse_packet3(f, header, ib, &current_trace_id);
730          break;
731       case 2:
732          /* type-2 nop */
733          if (header == 0x80000000) {
734             fprintf(f, "%sNOP (type 2)%s\n",
735                     O_COLOR_GREEN, O_COLOR_RESET);
736             break;
737          }
738          FALLTHROUGH;
739       default:
740          fprintf(f, "Unknown packet type %i\n", type);
741          break;
742       }
743    }
744 }
745 
format_ib_output(FILE * f,char * out)746 static void format_ib_output(FILE *f, char *out)
747 {
748    unsigned depth = 0;
749 
750    for (;;) {
751       char op = 0;
752 
753       if (out[0] == '\n' && out[1] == '\035')
754          out++;
755       if (out[0] == '\035') {
756          op = out[1];
757          out += 2;
758       }
759 
760       if (op == '<')
761          depth--;
762 
763       unsigned indent = 4 * depth;
764       if (op != '#')
765          indent += 9;
766 
767       if (indent)
768          print_spaces(f, indent);
769 
770       char *end = strchrnul(out, '\n');
771       fwrite(out, end - out, 1, f);
772       fputc('\n', f); /* always end with a new line */
773       if (!*end)
774          break;
775 
776       out = end + 1;
777 
778       if (op == '>')
779          depth++;
780    }
781 }
782 
parse_sdma_ib(FILE * f,struct ac_ib_parser * ib)783 static void parse_sdma_ib(FILE *f, struct ac_ib_parser *ib)
784 {
785    while (ib->cur_dw < ib->num_dw) {
786       const uint32_t header = ac_ib_get(ib);
787       const uint32_t opcode = header & 0xff;
788       const uint32_t sub_op = (header >> 8) & 0xff;
789 
790       switch (opcode) {
791       case SDMA_OPCODE_NOP: {
792          fprintf(f, "NOP\n");
793 
794          const uint32_t count = header >> 16;
795          for (unsigned i = 0; i < count; ++i) {
796             ac_ib_get(ib);
797             fprintf(f, "\n");
798          }
799          break;
800       }
801       case SDMA_OPCODE_CONSTANT_FILL: {
802          fprintf(f, "CONSTANT_FILL\n");
803          ac_ib_get(ib);
804          fprintf(f, "\n");
805          ac_ib_get(ib);
806          fprintf(f, "\n");
807          uint32_t value = ac_ib_get(ib);
808          fprintf(f, "    fill value = %u\n", value);
809          uint32_t byte_count = ac_ib_get(ib) + 1;
810          fprintf(f, "    fill byte count = %u\n", byte_count);
811 
812          unsigned dwords = byte_count / 4;
813          for (unsigned i = 0; i < dwords; ++i) {
814             ac_ib_get(ib);
815             fprintf(f, "\n");
816          }
817 
818          break;
819       }
820       case SDMA_OPCODE_WRITE: {
821          fprintf(f, "WRITE\n");
822 
823          /* VA */
824          ac_ib_get(ib);
825          fprintf(f, "\n");
826          ac_ib_get(ib);
827          fprintf(f, "\n");
828 
829          uint32_t dwords = ac_ib_get(ib) + 1;
830          fprintf(f, "    written dword count = %u\n", dwords);
831 
832          for (unsigned i = 0; i < dwords; ++i) {
833             ac_ib_get(ib);
834             fprintf(f, "\n");
835          }
836 
837          break;
838       }
839       case SDMA_OPCODE_COPY: {
840          switch (sub_op) {
841          case SDMA_COPY_SUB_OPCODE_LINEAR: {
842             fprintf(f, "COPY LINEAR\n");
843 
844             uint32_t copy_bytes = ac_ib_get(ib) + (ib->gfx_level >= GFX9 ? 1 : 0);
845             fprintf(f, "    copy bytes: %u\n", copy_bytes);
846             ac_ib_get(ib);
847             fprintf(f, "\n");
848             ac_ib_get(ib);
849             fprintf(f, "    src VA low\n");
850             ac_ib_get(ib);
851             fprintf(f, "    src VA high\n");
852             ac_ib_get(ib);
853             fprintf(f, "    dst VA low\n");
854             ac_ib_get(ib);
855             fprintf(f, "    dst VA high\n");
856 
857             break;
858          }
859          case SDMA_COPY_SUB_OPCODE_LINEAR_SUB_WINDOW: {
860             fprintf(f, "COPY LINEAR_SUB_WINDOW\n");
861 
862             for (unsigned i = 0; i < 12; ++i) {
863                ac_ib_get(ib);
864                fprintf(f, "\n");
865             }
866             break;
867          }
868          case SDMA_COPY_SUB_OPCODE_TILED_SUB_WINDOW: {
869             fprintf(f, "COPY TILED_SUB_WINDOW %s\n", header >> 31 ? "t2l" : "l2t");
870             uint32_t dcc = (header >> 19) & 1;
871 
872             /* Tiled VA */
873             ac_ib_get(ib);
874             fprintf(f, "    tiled VA low\n");
875             ac_ib_get(ib);
876             fprintf(f, "    tiled VA high\n");
877 
878             uint32_t dw3 = ac_ib_get(ib);
879             fprintf(f, "    tiled offset x = %u, y=%u\n", dw3 & 0xffff, dw3 >> 16);
880             uint32_t dw4 = ac_ib_get(ib);
881             fprintf(f, "    tiled offset z = %u, tiled width = %u\n", dw4 & 0xffff, (dw4 >> 16) + 1);
882             uint32_t dw5 = ac_ib_get(ib);
883             fprintf(f, "    tiled height = %u, tiled depth = %u\n", (dw5 & 0xffff) + 1, (dw5 >> 16) + 1);
884 
885             /* Tiled image info */
886             ac_ib_get(ib);
887             fprintf(f, "    (tiled image info)\n");
888 
889             /* Linear VA */
890             ac_ib_get(ib);
891             fprintf(f, "    linear VA low\n");
892             ac_ib_get(ib);
893             fprintf(f, "    linear VA high\n");
894 
895             uint32_t dw9 = ac_ib_get(ib);
896             fprintf(f, "    linear offset x = %u, y=%u\n", dw9 & 0xffff, dw9 >> 16);
897             uint32_t dw10 = ac_ib_get(ib);
898             fprintf(f, "    linear offset z = %u, linear pitch = %u\n", dw10 & 0xffff, (dw10 >> 16) + 1);
899             uint32_t dw11 = ac_ib_get(ib);
900             fprintf(f, "    linear slice pitch = %u\n", dw11 + 1);
901             uint32_t dw12 = ac_ib_get(ib);
902             fprintf(f, "    copy width = %u, copy height = %u\n", (dw12 & 0xffff) + 1, (dw12 >> 16) + 1);
903             uint32_t dw13 = ac_ib_get(ib);
904             fprintf(f, "    copy depth = %u\n", dw13 + 1);
905 
906             if (dcc) {
907                ac_ib_get(ib);
908                fprintf(f, "    metadata VA low\n");
909                ac_ib_get(ib);
910                fprintf(f, "    metadata VA high\n");
911                ac_ib_get(ib);
912                fprintf(f, "    (metadata config)\n");
913             }
914             break;
915          }
916          case SDMA_COPY_SUB_OPCODE_T2T_SUB_WINDOW: {
917             fprintf(f, "COPY T2T_SUB_WINDOW\n");
918             uint32_t dcc = (header >> 19) & 1;
919 
920             for (unsigned i = 0; i < 14; ++i) {
921                ac_ib_get(ib);
922                fprintf(f, "\n");
923             }
924 
925             if (dcc) {
926                ac_ib_get(ib);
927                fprintf(f, "    metadata VA low\n");
928                ac_ib_get(ib);
929                fprintf(f, "    metadata VA high\n");
930                ac_ib_get(ib);
931                fprintf(f, "    (metadata config)\n");
932             }
933             break;
934          }
935          default:
936             fprintf(f, "(unrecognized COPY sub op)\n");
937             break;
938          }
939          break;
940       }
941       default:
942          fprintf(f, " (unrecognized opcode)\n");
943          break;
944       }
945    }
946 }
947 
948 /**
949  * Parse and print an IB into a file.
950  *
951  * \param f            file
952  * \param ib_ptr       IB
953  * \param num_dw       size of the IB
954  * \param gfx_level   gfx level
955  * \param family	chip family
956  * \param ip_type IP type
957  * \param trace_ids	the last trace IDs that are known to have been reached
958  *			and executed by the CP, typically read from a buffer
959  * \param trace_id_count The number of entries in the trace_ids array.
960  * \param addr_callback Get a mapped pointer of the IB at a given address. Can
961  *                      be NULL.
962  * \param addr_callback_data user data for addr_callback
963  */
ac_parse_ib_chunk(struct ac_ib_parser * ib)964 void ac_parse_ib_chunk(struct ac_ib_parser *ib)
965 {
966    struct ac_ib_parser tmp_ib = *ib;
967 
968    char *out;
969    size_t outsize;
970    struct u_memstream mem;
971    u_memstream_open(&mem, &out, &outsize);
972    FILE *const memf = u_memstream_get(&mem);
973    tmp_ib.f = memf;
974 
975    if (ib->ip_type == AMD_IP_GFX || ib->ip_type == AMD_IP_COMPUTE)
976       parse_gfx_compute_ib(memf, &tmp_ib);
977    else if (ib->ip_type == AMD_IP_SDMA)
978       parse_sdma_ib(memf, &tmp_ib);
979    else
980       unreachable("unsupported IP type");
981 
982    u_memstream_close(&mem);
983 
984    if (out) {
985       format_ib_output(ib->f, out);
986       free(out);
987    }
988 
989    if (tmp_ib.cur_dw > tmp_ib.num_dw) {
990       printf("\nPacket ends after the end of IB.\n");
991       exit(1);
992    }
993 }
994 
995 /**
996  * Parse and print an IB into a file.
997  *
998  * \param f		file
999  * \param ib		IB
1000  * \param num_dw	size of the IB
1001  * \param gfx_level	gfx level
1002  * \param family	chip family
1003  * \param ip_type IP type
1004  * \param trace_ids	the last trace IDs that are known to have been reached
1005  *			and executed by the CP, typically read from a buffer
1006  * \param trace_id_count The number of entries in the trace_ids array.
1007  * \param addr_callback Get a mapped pointer of the IB at a given address. Can
1008  *                      be NULL.
1009  * \param addr_callback_data user data for addr_callback
1010  */
ac_parse_ib(struct ac_ib_parser * ib,const char * name)1011 void ac_parse_ib(struct ac_ib_parser *ib, const char *name)
1012 {
1013    fprintf(ib->f, "------------------ %s begin - %s ------------------\n", name,
1014            ac_get_ip_type_string(NULL, ib->ip_type));
1015 
1016    ac_parse_ib_chunk(ib);
1017 
1018    fprintf(ib->f, "------------------- %s end - %s -------------------\n\n", name,
1019            ac_get_ip_type_string(NULL, ib->ip_type));
1020 }
1021