1/* 2 * Copyright © 2016-2017 Broadcom 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 * IN THE SOFTWARE. 22 */ 23 24#include "broadcom/common/v3d_device_info.h" 25#include "v3d_compiler.h" 26 27/* Prints a human-readable description of the uniform reference. */ 28void 29vir_dump_uniform(enum quniform_contents contents, 30 uint32_t data) 31{ 32 static const char *quniform_names[] = { 33 [QUNIFORM_ALPHA_REF] = "alpha_ref", 34 [QUNIFORM_VIEWPORT_X_SCALE] = "vp_x_scale", 35 [QUNIFORM_VIEWPORT_Y_SCALE] = "vp_y_scale", 36 [QUNIFORM_VIEWPORT_Z_OFFSET] = "vp_z_offset", 37 [QUNIFORM_VIEWPORT_Z_SCALE] = "vp_z_scale", 38 [QUNIFORM_SHARED_OFFSET] = "shared_offset", 39 }; 40 41 switch (contents) { 42 case QUNIFORM_CONSTANT: 43 fprintf(stderr, "0x%08x / %f", data, uif(data)); 44 break; 45 46 case QUNIFORM_UNIFORM: 47 fprintf(stderr, "push[%d]", data); 48 break; 49 50 case QUNIFORM_TEXTURE_CONFIG_P1: 51 fprintf(stderr, "tex[%d].p1", data); 52 break; 53 54 case QUNIFORM_TMU_CONFIG_P0: 55 fprintf(stderr, "tex[%d].p0 | 0x%x", 56 v3d_unit_data_get_unit(data), 57 v3d_unit_data_get_offset(data)); 58 break; 59 60 case QUNIFORM_TMU_CONFIG_P1: 61 fprintf(stderr, "tex[%d].p1 | 0x%x", 62 v3d_unit_data_get_unit(data), 63 v3d_unit_data_get_offset(data)); 64 break; 65 66 case QUNIFORM_IMAGE_TMU_CONFIG_P0: 67 fprintf(stderr, "img[%d].p0 | 0x%x", 68 v3d_unit_data_get_unit(data), 69 v3d_unit_data_get_offset(data)); 70 break; 71 72 case QUNIFORM_TEXTURE_WIDTH: 73 fprintf(stderr, "tex[%d].width", data); 74 break; 75 case QUNIFORM_TEXTURE_HEIGHT: 76 fprintf(stderr, "tex[%d].height", data); 77 break; 78 case QUNIFORM_TEXTURE_DEPTH: 79 fprintf(stderr, "tex[%d].depth", data); 80 break; 81 case QUNIFORM_TEXTURE_ARRAY_SIZE: 82 fprintf(stderr, "tex[%d].array_size", data); 83 break; 84 case QUNIFORM_TEXTURE_LEVELS: 85 fprintf(stderr, "tex[%d].levels", data); 86 break; 87 88 case QUNIFORM_IMAGE_WIDTH: 89 fprintf(stderr, "img[%d].width", data); 90 break; 91 case QUNIFORM_IMAGE_HEIGHT: 92 fprintf(stderr, "img[%d].height", data); 93 break; 94 case QUNIFORM_IMAGE_DEPTH: 95 fprintf(stderr, "img[%d].depth", data); 96 break; 97 case QUNIFORM_IMAGE_ARRAY_SIZE: 98 fprintf(stderr, "img[%d].array_size", data); 99 break; 100 101 case QUNIFORM_SPILL_OFFSET: 102 fprintf(stderr, "spill_offset"); 103 break; 104 105 case QUNIFORM_SPILL_SIZE_PER_THREAD: 106 fprintf(stderr, "spill_size_per_thread"); 107 break; 108 109 case QUNIFORM_UBO_ADDR: 110 fprintf(stderr, "ubo[%d]+0x%x", 111 v3d_unit_data_get_unit(data), 112 v3d_unit_data_get_offset(data)); 113 break; 114 115 case QUNIFORM_SSBO_OFFSET: 116 fprintf(stderr, "ssbo[%d]", data); 117 break; 118 119 case QUNIFORM_GET_BUFFER_SIZE: 120 fprintf(stderr, "ssbo_size[%d]", data); 121 break; 122 123 case QUNIFORM_NUM_WORK_GROUPS: 124 fprintf(stderr, "num_wg.%c", data < 3 ? "xyz"[data] : '?'); 125 break; 126 127 default: 128 if (quniform_contents_is_texture_p0(contents)) { 129 fprintf(stderr, "tex[%d].p0: 0x%08x", 130 contents - QUNIFORM_TEXTURE_CONFIG_P0_0, 131 data); 132 } else if (contents < ARRAY_SIZE(quniform_names) && 133 quniform_names[contents]) { 134 fprintf(stderr, "%s", 135 quniform_names[contents]); 136 } else { 137 fprintf(stderr, "%d / 0x%08x", contents, data); 138 } 139 } 140} 141 142static void 143vir_print_reg(struct v3d_compile *c, const struct qinst *inst, 144 struct qreg reg) 145{ 146 switch (reg.file) { 147 148 case QFILE_NULL: 149 fprintf(stderr, "null"); 150 break; 151 152 case QFILE_LOAD_IMM: 153 fprintf(stderr, "0x%08x (%f)", reg.index, uif(reg.index)); 154 break; 155 156 case QFILE_REG: 157 fprintf(stderr, "rf%d", reg.index); 158 break; 159 160 case QFILE_MAGIC: 161 fprintf(stderr, "%s", v3d_qpu_magic_waddr_name(reg.index)); 162 break; 163 164 case QFILE_SMALL_IMM: { 165 uint32_t unpacked; 166 bool ok = v3d_qpu_small_imm_unpack(c->devinfo, 167 inst->qpu.raddr_b, 168 &unpacked); 169 assert(ok); (void) ok; 170 171 if ((int)inst->qpu.raddr_b >= -16 && 172 (int)inst->qpu.raddr_b <= 15) 173 fprintf(stderr, "%d", unpacked); 174 else 175 fprintf(stderr, "%f", uif(unpacked)); 176 break; 177 } 178 179 case QFILE_VPM: 180 fprintf(stderr, "vpm%d.%d", 181 reg.index / 4, reg.index % 4); 182 break; 183 184 case QFILE_TEMP: 185 fprintf(stderr, "t%d", reg.index); 186 break; 187 } 188} 189 190static void 191vir_dump_sig_addr(const struct v3d_device_info *devinfo, 192 const struct v3d_qpu_instr *instr) 193{ 194 if (devinfo->ver < 41) 195 return; 196 197 if (!instr->sig_magic) 198 fprintf(stderr, ".rf%d", instr->sig_addr); 199 else { 200 const char *name = v3d_qpu_magic_waddr_name(instr->sig_addr); 201 if (name) 202 fprintf(stderr, ".%s", name); 203 else 204 fprintf(stderr, ".UNKNOWN%d", instr->sig_addr); 205 } 206} 207 208static void 209vir_dump_sig(struct v3d_compile *c, struct qinst *inst) 210{ 211 struct v3d_qpu_sig *sig = &inst->qpu.sig; 212 213 if (sig->thrsw) 214 fprintf(stderr, "; thrsw"); 215 if (sig->ldvary) { 216 fprintf(stderr, "; ldvary"); 217 vir_dump_sig_addr(c->devinfo, &inst->qpu); 218 } 219 if (sig->ldvpm) 220 fprintf(stderr, "; ldvpm"); 221 if (sig->ldtmu) { 222 fprintf(stderr, "; ldtmu"); 223 vir_dump_sig_addr(c->devinfo, &inst->qpu); 224 } 225 if (sig->ldtlb) { 226 fprintf(stderr, "; ldtlb"); 227 vir_dump_sig_addr(c->devinfo, &inst->qpu); 228 } 229 if (sig->ldtlbu) { 230 fprintf(stderr, "; ldtlbu"); 231 vir_dump_sig_addr(c->devinfo, &inst->qpu); 232 } 233 if (sig->ldunif) 234 fprintf(stderr, "; ldunif"); 235 if (sig->ldunifrf) { 236 fprintf(stderr, "; ldunifrf"); 237 vir_dump_sig_addr(c->devinfo, &inst->qpu); 238 } 239 if (sig->ldunifa) 240 fprintf(stderr, "; ldunifa"); 241 if (sig->ldunifarf) { 242 fprintf(stderr, "; ldunifarf"); 243 vir_dump_sig_addr(c->devinfo, &inst->qpu); 244 } 245 if (sig->wrtmuc) 246 fprintf(stderr, "; wrtmuc"); 247} 248 249static void 250vir_dump_alu(struct v3d_compile *c, struct qinst *inst) 251{ 252 struct v3d_qpu_instr *instr = &inst->qpu; 253 int nsrc = vir_get_nsrc(inst); 254 enum v3d_qpu_input_unpack unpack[2]; 255 256 if (inst->qpu.alu.add.op != V3D_QPU_A_NOP) { 257 fprintf(stderr, "%s", v3d_qpu_add_op_name(instr->alu.add.op)); 258 fprintf(stderr, "%s", v3d_qpu_cond_name(instr->flags.ac)); 259 fprintf(stderr, "%s", v3d_qpu_pf_name(instr->flags.apf)); 260 fprintf(stderr, "%s", v3d_qpu_uf_name(instr->flags.auf)); 261 fprintf(stderr, " "); 262 263 vir_print_reg(c, inst, inst->dst); 264 fprintf(stderr, "%s", v3d_qpu_pack_name(instr->alu.add.output_pack)); 265 266 unpack[0] = instr->alu.add.a_unpack; 267 unpack[1] = instr->alu.add.b_unpack; 268 } else { 269 fprintf(stderr, "%s", v3d_qpu_mul_op_name(instr->alu.mul.op)); 270 fprintf(stderr, "%s", v3d_qpu_cond_name(instr->flags.mc)); 271 fprintf(stderr, "%s", v3d_qpu_pf_name(instr->flags.mpf)); 272 fprintf(stderr, "%s", v3d_qpu_uf_name(instr->flags.muf)); 273 fprintf(stderr, " "); 274 275 vir_print_reg(c, inst, inst->dst); 276 fprintf(stderr, "%s", v3d_qpu_pack_name(instr->alu.mul.output_pack)); 277 278 unpack[0] = instr->alu.mul.a_unpack; 279 unpack[1] = instr->alu.mul.b_unpack; 280 } 281 282 for (int i = 0; i < nsrc; i++) { 283 fprintf(stderr, ", "); 284 vir_print_reg(c, inst, inst->src[i]); 285 fprintf(stderr, "%s", v3d_qpu_unpack_name(unpack[i])); 286 } 287 288 vir_dump_sig(c, inst); 289} 290 291void 292vir_dump_inst(struct v3d_compile *c, struct qinst *inst) 293{ 294 struct v3d_qpu_instr *instr = &inst->qpu; 295 296 switch (inst->qpu.type) { 297 case V3D_QPU_INSTR_TYPE_ALU: 298 vir_dump_alu(c, inst); 299 break; 300 case V3D_QPU_INSTR_TYPE_BRANCH: 301 fprintf(stderr, "b"); 302 if (instr->branch.ub) 303 fprintf(stderr, "u"); 304 305 fprintf(stderr, "%s", 306 v3d_qpu_branch_cond_name(instr->branch.cond)); 307 fprintf(stderr, "%s", v3d_qpu_msfign_name(instr->branch.msfign)); 308 309 switch (instr->branch.bdi) { 310 case V3D_QPU_BRANCH_DEST_ABS: 311 fprintf(stderr, " zero_addr+0x%08x", instr->branch.offset); 312 break; 313 314 case V3D_QPU_BRANCH_DEST_REL: 315 fprintf(stderr, " %d", instr->branch.offset); 316 break; 317 318 case V3D_QPU_BRANCH_DEST_LINK_REG: 319 fprintf(stderr, " lri"); 320 break; 321 322 case V3D_QPU_BRANCH_DEST_REGFILE: 323 fprintf(stderr, " rf%d", instr->branch.raddr_a); 324 break; 325 } 326 327 if (instr->branch.ub) { 328 switch (instr->branch.bdu) { 329 case V3D_QPU_BRANCH_DEST_ABS: 330 fprintf(stderr, ", a:unif"); 331 break; 332 333 case V3D_QPU_BRANCH_DEST_REL: 334 fprintf(stderr, ", r:unif"); 335 break; 336 337 case V3D_QPU_BRANCH_DEST_LINK_REG: 338 fprintf(stderr, ", lri"); 339 break; 340 341 case V3D_QPU_BRANCH_DEST_REGFILE: 342 fprintf(stderr, ", rf%d", instr->branch.raddr_a); 343 break; 344 } 345 } 346 break; 347 } 348 349 if (vir_has_uniform(inst)) { 350 fprintf(stderr, " ("); 351 vir_dump_uniform(c->uniform_contents[inst->uniform], 352 c->uniform_data[inst->uniform]); 353 fprintf(stderr, ")"); 354 } 355} 356 357void 358vir_dump(struct v3d_compile *c) 359{ 360 int ip = 0; 361 int pressure = 0; 362 363 vir_for_each_block(block, c) { 364 fprintf(stderr, "BLOCK %d:\n", block->index); 365 vir_for_each_inst(inst, block) { 366 if (c->live_intervals_valid) { 367 for (int i = 0; i < c->num_temps; i++) { 368 if (c->temp_start[i] == ip) 369 pressure++; 370 } 371 372 fprintf(stderr, "P%4d ", pressure); 373 374 bool first = true; 375 376 for (int i = 0; i < c->num_temps; i++) { 377 if (c->temp_start[i] != ip) 378 continue; 379 380 if (first) { 381 first = false; 382 } else { 383 fprintf(stderr, ", "); 384 } 385 if (BITSET_TEST(c->spillable, i)) 386 fprintf(stderr, "S%4d", i); 387 else 388 fprintf(stderr, "U%4d", i); 389 } 390 391 if (first) 392 fprintf(stderr, " "); 393 else 394 fprintf(stderr, " "); 395 } 396 397 if (c->live_intervals_valid) { 398 bool first = true; 399 400 for (int i = 0; i < c->num_temps; i++) { 401 if (c->temp_end[i] != ip) 402 continue; 403 404 if (first) { 405 first = false; 406 } else { 407 fprintf(stderr, ", "); 408 } 409 fprintf(stderr, "E%4d", i); 410 pressure--; 411 } 412 413 if (first) 414 fprintf(stderr, " "); 415 else 416 fprintf(stderr, " "); 417 } 418 419 vir_dump_inst(c, inst); 420 fprintf(stderr, "\n"); 421 ip++; 422 } 423 if (block->successors[1]) { 424 fprintf(stderr, "-> BLOCK %d, %d\n", 425 block->successors[0]->index, 426 block->successors[1]->index); 427 } else if (block->successors[0]) { 428 fprintf(stderr, "-> BLOCK %d\n", 429 block->successors[0]->index); 430 } 431 } 432} 433