• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 static void
vir_print_reg(struct v3d_compile * c,struct qreg reg)28 vir_print_reg(struct v3d_compile *c, struct qreg reg)
29 {
30         static const char *files[] = {
31                 [QFILE_TEMP] = "t",
32                 [QFILE_UNIF] = "u",
33                 [QFILE_TLB] = "tlb",
34                 [QFILE_TLBU] = "tlbu",
35         };
36         static const char *quniform_names[] = {
37                 [QUNIFORM_VIEWPORT_X_SCALE] = "vp_x_scale",
38                 [QUNIFORM_VIEWPORT_Y_SCALE] = "vp_y_scale",
39                 [QUNIFORM_VIEWPORT_Z_OFFSET] = "vp_z_offset",
40                 [QUNIFORM_VIEWPORT_Z_SCALE] = "vp_z_scale",
41         };
42 
43         switch (reg.file) {
44 
45         case QFILE_NULL:
46                 fprintf(stderr, "null");
47                 break;
48 
49         case QFILE_LOAD_IMM:
50                 fprintf(stderr, "0x%08x (%f)", reg.index, uif(reg.index));
51                 break;
52 
53         case QFILE_REG:
54                 fprintf(stderr, "rf%d", reg.index);
55                 break;
56 
57         case QFILE_MAGIC:
58                 fprintf(stderr, "%s", v3d_qpu_magic_waddr_name(reg.index));
59                 break;
60 
61         case QFILE_SMALL_IMM:
62                 if ((int)reg.index >= -16 && (int)reg.index <= 15)
63                         fprintf(stderr, "%d", reg.index);
64                 else
65                         fprintf(stderr, "%f", uif(reg.index));
66                 break;
67 
68         case QFILE_VPM:
69                 fprintf(stderr, "vpm%d.%d",
70                         reg.index / 4, reg.index % 4);
71                 break;
72 
73         case QFILE_TLB:
74                 fprintf(stderr, "%s", files[reg.file]);
75                 break;
76 
77         case QFILE_UNIF: {
78                 enum quniform_contents contents = c->uniform_contents[reg.index];
79 
80                 fprintf(stderr, "%s%d", files[reg.file], reg.index);
81 
82                 switch (contents) {
83                 case QUNIFORM_CONSTANT:
84                         fprintf(stderr, " (0x%08x / %f)",
85                                 c->uniform_data[reg.index],
86                                 uif(c->uniform_data[reg.index]));
87                         break;
88 
89                 case QUNIFORM_UNIFORM:
90                         fprintf(stderr, " (push[%d])",
91                                 c->uniform_data[reg.index]);
92                         break;
93 
94                 case QUNIFORM_TEXTURE_CONFIG_P1:
95                         fprintf(stderr, " (tex[%d].p1)",
96                                 c->uniform_data[reg.index]);
97                         break;
98 
99                 case QUNIFORM_TEXTURE_WIDTH:
100                         fprintf(stderr, " (tex[%d].width)",
101                                 c->uniform_data[reg.index]);
102                         break;
103                 case QUNIFORM_TEXTURE_HEIGHT:
104                         fprintf(stderr, " (tex[%d].height)",
105                                 c->uniform_data[reg.index]);
106                         break;
107                 case QUNIFORM_TEXTURE_DEPTH:
108                         fprintf(stderr, " (tex[%d].depth)",
109                                 c->uniform_data[reg.index]);
110                         break;
111                 case QUNIFORM_TEXTURE_ARRAY_SIZE:
112                         fprintf(stderr, " (tex[%d].array_size)",
113                                 c->uniform_data[reg.index]);
114                         break;
115                 case QUNIFORM_TEXTURE_LEVELS:
116                         fprintf(stderr, " (tex[%d].levels)",
117                                 c->uniform_data[reg.index]);
118                         break;
119 
120                 case QUNIFORM_UBO_ADDR:
121                         fprintf(stderr, " (ubo[%d])",
122                                 c->uniform_data[reg.index]);
123                         break;
124 
125                 default:
126                         if (quniform_contents_is_texture_p0(contents)) {
127                                 fprintf(stderr, " (tex[%d].p0: 0x%08x)",
128                                         contents - QUNIFORM_TEXTURE_CONFIG_P0_0,
129                                         c->uniform_data[reg.index]);
130                         } else if (contents < ARRAY_SIZE(quniform_names)) {
131                                 fprintf(stderr, " (%s)",
132                                         quniform_names[contents]);
133                         } else {
134                                 fprintf(stderr, " (%d / 0x%08x)", contents,
135                                         c->uniform_data[reg.index]);
136                         }
137                 }
138 
139                 break;
140         }
141 
142         default:
143                 fprintf(stderr, "%s%d", files[reg.file], reg.index);
144                 break;
145         }
146 }
147 
148 static void
vir_dump_sig_addr(const struct v3d_device_info * devinfo,const struct v3d_qpu_instr * instr)149 vir_dump_sig_addr(const struct v3d_device_info *devinfo,
150                   const struct v3d_qpu_instr *instr)
151 {
152         if (devinfo->ver < 41)
153                 return;
154 
155         if (!instr->sig_magic)
156                 fprintf(stderr, ".rf%d", instr->sig_addr);
157         else {
158                 const char *name = v3d_qpu_magic_waddr_name(instr->sig_addr);
159                 if (name)
160                         fprintf(stderr, ".%s", name);
161                 else
162                         fprintf(stderr, ".UNKNOWN%d", instr->sig_addr);
163         }
164 }
165 
166 static void
vir_dump_sig(struct v3d_compile * c,struct qinst * inst)167 vir_dump_sig(struct v3d_compile *c, struct qinst *inst)
168 {
169         struct v3d_qpu_sig *sig = &inst->qpu.sig;
170 
171         if (sig->thrsw)
172                 fprintf(stderr, "; thrsw");
173         if (sig->ldvary) {
174                 fprintf(stderr, "; ldvary");
175                 vir_dump_sig_addr(c->devinfo, &inst->qpu);
176         }
177         if (sig->ldvpm)
178                 fprintf(stderr, "; ldvpm");
179         if (sig->ldtmu) {
180                 fprintf(stderr, "; ldtmu");
181                 vir_dump_sig_addr(c->devinfo, &inst->qpu);
182         }
183         if (sig->ldtlb) {
184                 fprintf(stderr, "; ldtlb");
185                 vir_dump_sig_addr(c->devinfo, &inst->qpu);
186         }
187         if (sig->ldtlbu) {
188                 fprintf(stderr, "; ldtlbu");
189                 vir_dump_sig_addr(c->devinfo, &inst->qpu);
190         }
191         if (sig->ldunif)
192                 fprintf(stderr, "; ldunif");
193         if (sig->ldunifrf) {
194                 fprintf(stderr, "; ldunifrf");
195                 vir_dump_sig_addr(c->devinfo, &inst->qpu);
196         }
197         if (sig->ldunifa)
198                 fprintf(stderr, "; ldunifa");
199         if (sig->ldunifarf) {
200                 fprintf(stderr, "; ldunifarf");
201                 vir_dump_sig_addr(c->devinfo, &inst->qpu);
202         }
203         if (sig->wrtmuc)
204                 fprintf(stderr, "; wrtmuc");
205 }
206 
207 static void
vir_dump_alu(struct v3d_compile * c,struct qinst * inst)208 vir_dump_alu(struct v3d_compile *c, struct qinst *inst)
209 {
210         struct v3d_qpu_instr *instr = &inst->qpu;
211         int nsrc = vir_get_non_sideband_nsrc(inst);
212         int sideband_nsrc = vir_get_nsrc(inst);
213         enum v3d_qpu_input_unpack unpack[2];
214 
215         if (inst->qpu.alu.add.op != V3D_QPU_A_NOP) {
216                 fprintf(stderr, "%s", v3d_qpu_add_op_name(instr->alu.add.op));
217                 fprintf(stderr, "%s", v3d_qpu_cond_name(instr->flags.ac));
218                 fprintf(stderr, "%s", v3d_qpu_pf_name(instr->flags.apf));
219                 fprintf(stderr, "%s", v3d_qpu_uf_name(instr->flags.auf));
220                 fprintf(stderr, " ");
221 
222                 vir_print_reg(c, inst->dst);
223                 fprintf(stderr, "%s", v3d_qpu_pack_name(instr->alu.add.output_pack));
224 
225                 unpack[0] = instr->alu.add.a_unpack;
226                 unpack[1] = instr->alu.add.b_unpack;
227         } else {
228                 fprintf(stderr, "%s", v3d_qpu_mul_op_name(instr->alu.mul.op));
229                 fprintf(stderr, "%s", v3d_qpu_cond_name(instr->flags.mc));
230                 fprintf(stderr, "%s", v3d_qpu_pf_name(instr->flags.mpf));
231                 fprintf(stderr, "%s", v3d_qpu_uf_name(instr->flags.muf));
232                 fprintf(stderr, " ");
233 
234                 vir_print_reg(c, inst->dst);
235                 fprintf(stderr, "%s", v3d_qpu_pack_name(instr->alu.mul.output_pack));
236 
237                 unpack[0] = instr->alu.mul.a_unpack;
238                 unpack[1] = instr->alu.mul.b_unpack;
239         }
240 
241         for (int i = 0; i < sideband_nsrc; i++) {
242                 fprintf(stderr, ", ");
243                 vir_print_reg(c, inst->src[i]);
244                 if (i < nsrc)
245                         fprintf(stderr, "%s", v3d_qpu_unpack_name(unpack[i]));
246         }
247 
248         vir_dump_sig(c, inst);
249 }
250 
251 void
vir_dump_inst(struct v3d_compile * c,struct qinst * inst)252 vir_dump_inst(struct v3d_compile *c, struct qinst *inst)
253 {
254         struct v3d_qpu_instr *instr = &inst->qpu;
255 
256         switch (inst->qpu.type) {
257         case V3D_QPU_INSTR_TYPE_ALU:
258                 vir_dump_alu(c, inst);
259                 break;
260         case V3D_QPU_INSTR_TYPE_BRANCH:
261                 fprintf(stderr, "b");
262                 if (instr->branch.ub)
263                         fprintf(stderr, "u");
264 
265                 fprintf(stderr, "%s",
266                         v3d_qpu_branch_cond_name(instr->branch.cond));
267                 fprintf(stderr, "%s", v3d_qpu_msfign_name(instr->branch.msfign));
268 
269                 switch (instr->branch.bdi) {
270                 case V3D_QPU_BRANCH_DEST_ABS:
271                         fprintf(stderr, "  zero_addr+0x%08x", instr->branch.offset);
272                         break;
273 
274                 case V3D_QPU_BRANCH_DEST_REL:
275                         fprintf(stderr, "  %d", instr->branch.offset);
276                         break;
277 
278                 case V3D_QPU_BRANCH_DEST_LINK_REG:
279                         fprintf(stderr, "  lri");
280                         break;
281 
282                 case V3D_QPU_BRANCH_DEST_REGFILE:
283                         fprintf(stderr, "  rf%d", instr->branch.raddr_a);
284                         break;
285                 }
286 
287                 if (instr->branch.ub) {
288                         switch (instr->branch.bdu) {
289                         case V3D_QPU_BRANCH_DEST_ABS:
290                                 fprintf(stderr, ", a:unif");
291                                 break;
292 
293                         case V3D_QPU_BRANCH_DEST_REL:
294                                 fprintf(stderr, ", r:unif");
295                                 break;
296 
297                         case V3D_QPU_BRANCH_DEST_LINK_REG:
298                                 fprintf(stderr, ", lri");
299                                 break;
300 
301                         case V3D_QPU_BRANCH_DEST_REGFILE:
302                                 fprintf(stderr, ", rf%d", instr->branch.raddr_a);
303                                 break;
304                         }
305                 }
306 
307                 if (vir_has_implicit_uniform(inst)) {
308                         fprintf(stderr, " ");
309                         vir_print_reg(c, inst->src[vir_get_implicit_uniform_src(inst)]);
310                 }
311 
312                 break;
313         }
314 }
315 
316 void
vir_dump(struct v3d_compile * c)317 vir_dump(struct v3d_compile *c)
318 {
319         int ip = 0;
320 
321         vir_for_each_block(block, c) {
322                 fprintf(stderr, "BLOCK %d:\n", block->index);
323                 vir_for_each_inst(inst, block) {
324                         if (c->temp_start) {
325                                 bool first = true;
326 
327                                 for (int i = 0; i < c->num_temps; i++) {
328                                         if (c->temp_start[i] != ip)
329                                                 continue;
330 
331                                         if (first) {
332                                                 first = false;
333                                         } else {
334                                                 fprintf(stderr, ", ");
335                                         }
336                                         fprintf(stderr, "S%4d", i);
337                                 }
338 
339                                 if (first)
340                                         fprintf(stderr, "      ");
341                                 else
342                                         fprintf(stderr, " ");
343                         }
344 
345                         if (c->temp_end) {
346                                 bool first = true;
347 
348                                 for (int i = 0; i < c->num_temps; i++) {
349                                         if (c->temp_end[i] != ip)
350                                                 continue;
351 
352                                         if (first) {
353                                                 first = false;
354                                         } else {
355                                                 fprintf(stderr, ", ");
356                                         }
357                                         fprintf(stderr, "E%4d", i);
358                                 }
359 
360                                 if (first)
361                                         fprintf(stderr, "      ");
362                                 else
363                                         fprintf(stderr, " ");
364                         }
365 
366                         vir_dump_inst(c, inst);
367                         fprintf(stderr, "\n");
368                         ip++;
369                 }
370                 if (block->successors[1]) {
371                         fprintf(stderr, "-> BLOCK %d, %d\n",
372                                 block->successors[0]->index,
373                                 block->successors[1]->index);
374                 } else if (block->successors[0]) {
375                         fprintf(stderr, "-> BLOCK %d\n",
376                                 block->successors[0]->index);
377                 }
378         }
379 }
380