broadcom/clif: Print out the contents of the generic tile list.
[mesa.git] / src / broadcom / clif / clif_dump.c
1 /*
2 * Copyright © 2016 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 <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include "clif_dump.h"
28 #include "util/list.h"
29 #include "util/ralloc.h"
30
31 #include "broadcom/cle/v3d_decoder.h"
32
33 #define __gen_user_data void
34 #define __gen_address_type uint32_t
35 #define __gen_address_offset(reloc) (*reloc)
36 #define __gen_emit_reloc(cl, reloc)
37 #define __gen_unpack_address(cl, s, e) (__gen_unpack_uint(cl, s, e) << (31 - (e - s)))
38
39 enum reloc_worklist_type {
40 reloc_gl_shader_state,
41 reloc_generic_tile_list,
42 };
43
44 struct reloc_worklist_entry {
45 struct list_head link;
46
47 enum reloc_worklist_type type;
48 uint32_t addr;
49
50 union {
51 struct {
52 uint32_t num_attrs;
53 } shader_state;
54 struct {
55 uint32_t end;
56 } generic_tile_list;
57 };
58 };
59
60 struct clif_dump {
61 const struct v3d_device_info *devinfo;
62 bool (*lookup_vaddr)(void *data, uint32_t addr, void **vaddr);
63 FILE *out;
64 /* Opaque data from the caller that is passed to the callbacks. */
65 void *data;
66
67 struct v3d_spec *spec;
68
69 /* List of struct reloc_worklist_entry */
70 struct list_head worklist;
71 };
72
73 static void
74 out(struct clif_dump *clif, const char *fmt, ...)
75 {
76 va_list args;
77
78 va_start(args, fmt);
79 vfprintf(clif->out, fmt, args);
80 va_end(args);
81 }
82
83 #include "broadcom/cle/v3d_packet_v33_pack.h"
84
85 static struct reloc_worklist_entry *
86 clif_dump_add_address_to_worklist(struct clif_dump *clif,
87 enum reloc_worklist_type type,
88 uint32_t addr)
89 {
90 struct reloc_worklist_entry *entry =
91 rzalloc(clif, struct reloc_worklist_entry);
92 if (!entry)
93 return NULL;
94
95 entry->type = type;
96 entry->addr = addr;
97
98 list_addtail(&entry->link, &clif->worklist);
99
100 return entry;
101 }
102
103 struct clif_dump *
104 clif_dump_init(const struct v3d_device_info *devinfo,
105 FILE *out,
106 bool (*lookup_vaddr)(void *data, uint32_t addr, void **vaddr),
107 void *data)
108 {
109 struct clif_dump *clif = rzalloc(NULL, struct clif_dump);
110
111 clif->devinfo = devinfo;
112 clif->lookup_vaddr = lookup_vaddr;
113 clif->out = out;
114 clif->data = data;
115 clif->spec = v3d_spec_load(devinfo);
116
117 list_inithead(&clif->worklist);
118
119 return clif;
120 }
121
122 void
123 clif_dump_destroy(struct clif_dump *clif)
124 {
125 ralloc_free(clif);
126 }
127
128 #define out_uint(_clif, field) out(_clif, " /* %s = */ %u\n", \
129 #field, values-> field);
130
131 static bool
132 clif_dump_packet(struct clif_dump *clif, uint32_t offset, const uint8_t *cl,
133 uint32_t *size)
134 {
135 struct v3d_group *inst = v3d_spec_find_instruction(clif->spec, cl);
136 if (!inst) {
137 out(clif, "0x%08x: Unknown packet %d!\n", offset, *cl);
138 return false;
139 }
140
141 *size = v3d_group_get_length(inst);
142
143 out(clif, "%s\n", v3d_group_get_name(inst));
144 v3d_print_group(clif->out, inst, 0, cl, "");
145
146 switch (*cl) {
147 case V3D33_GL_SHADER_STATE_opcode: {
148 struct V3D33_GL_SHADER_STATE values;
149 V3D33_GL_SHADER_STATE_unpack(cl, &values);
150
151 struct reloc_worklist_entry *reloc =
152 clif_dump_add_address_to_worklist(clif,
153 reloc_gl_shader_state,
154 values.address);
155 if (reloc) {
156 reloc->shader_state.num_attrs =
157 values.number_of_attribute_arrays;
158 }
159 return true;
160 }
161
162 case V3D33_STORE_MULTI_SAMPLE_RESOLVED_TILE_COLOR_BUFFER_EXTENDED_opcode: {
163 struct V3D33_STORE_MULTI_SAMPLE_RESOLVED_TILE_COLOR_BUFFER_EXTENDED values;
164 V3D33_STORE_MULTI_SAMPLE_RESOLVED_TILE_COLOR_BUFFER_EXTENDED_unpack(cl, &values);
165
166 if (values.last_tile_of_frame)
167 return false;
168 break;
169 }
170
171 case V3D33_TRANSFORM_FEEDBACK_ENABLE_opcode: {
172 struct V3D33_TRANSFORM_FEEDBACK_ENABLE values;
173 V3D33_TRANSFORM_FEEDBACK_ENABLE_unpack(cl, &values);
174 struct v3d_group *spec = v3d_spec_find_struct(clif->spec,
175 "Transform Feedback Output Data Spec");
176 struct v3d_group *addr = v3d_spec_find_struct(clif->spec,
177 "Transform Feedback Output Address");
178 assert(spec);
179 assert(addr);
180
181 cl += *size;
182
183 for (int i = 0; i < values.number_of_16_bit_output_data_specs_following; i++) {
184 v3d_print_group(clif->out, spec, 0, cl, "");
185 cl += v3d_group_get_length(spec);
186 *size += v3d_group_get_length(spec);
187 }
188
189 for (int i = 0; i < values.number_of_32_bit_output_buffer_address_following; i++) {
190 v3d_print_group(clif->out, addr, 0, cl, "");
191 cl += v3d_group_get_length(addr);
192 *size += v3d_group_get_length(addr);
193 }
194 break;
195 }
196
197 case V3D33_START_ADDRESS_OF_GENERIC_TILE_LIST_opcode: {
198 struct V3D33_START_ADDRESS_OF_GENERIC_TILE_LIST values;
199 V3D33_START_ADDRESS_OF_GENERIC_TILE_LIST_unpack(cl, &values);
200 struct reloc_worklist_entry *reloc =
201 clif_dump_add_address_to_worklist(clif,
202 reloc_generic_tile_list,
203 values.start);
204 reloc->generic_tile_list.end = values.end;
205 break;
206 }
207
208 case V3D33_HALT_opcode:
209 return false;
210 }
211
212 return true;
213 }
214
215 static void
216 clif_dump_gl_shader_state_record(struct clif_dump *clif,
217 struct reloc_worklist_entry *reloc, void *vaddr)
218 {
219 struct v3d_group *state = v3d_spec_find_struct(clif->spec,
220 "GL Shader State Record");
221 struct v3d_group *attr = v3d_spec_find_struct(clif->spec,
222 "GL Shader State Attribute Record");
223 assert(state);
224 assert(attr);
225
226 out(clif, "GL Shader State Record at 0x%08x\n", reloc->addr);
227 v3d_print_group(clif->out, state, 0, vaddr, "");
228 vaddr += v3d_group_get_length(state);
229
230 for (int i = 0; i < reloc->shader_state.num_attrs; i++) {
231 out(clif, " Attribute %d\n", i);
232 v3d_print_group(clif->out, attr, 0, vaddr, "");
233 vaddr += v3d_group_get_length(attr);
234 }
235 }
236
237 static void
238 clif_dump_cl(struct clif_dump *clif, uint32_t start, uint32_t end)
239 {
240 void *start_vaddr;
241 if (!clif->lookup_vaddr(clif->data, start, &start_vaddr)) {
242 out(clif, "Failed to look up address 0x%08x\n",
243 start);
244 return;
245 }
246
247 /* The end address is optional (for example, a BRANCH instruction
248 * won't set an end), but is used for BCL/RCL termination.
249 */
250 void *end_vaddr = NULL;
251 if (end && !clif->lookup_vaddr(clif->data, end, &end_vaddr)) {
252 out(clif, "Failed to look up address 0x%08x\n",
253 end);
254 return;
255 }
256
257 uint32_t size;
258 uint8_t *cl = start_vaddr;
259 while (clif_dump_packet(clif, start, cl, &size)) {
260 cl += size;
261 start += size;
262
263 if (cl == end_vaddr)
264 break;
265 }
266 }
267
268 static void
269 clif_process_worklist(struct clif_dump *clif)
270 {
271 while (!list_empty(&clif->worklist)) {
272 struct reloc_worklist_entry *reloc =
273 list_first_entry(&clif->worklist,
274 struct reloc_worklist_entry, link);
275 list_del(&reloc->link);
276
277 void *vaddr;
278 if (!clif->lookup_vaddr(clif->data, reloc->addr, &vaddr)) {
279 out(clif, "Failed to look up address 0x%08x\n",
280 reloc->addr);
281 continue;
282 }
283
284 switch (reloc->type) {
285 case reloc_gl_shader_state:
286 clif_dump_gl_shader_state_record(clif, reloc, vaddr);
287 break;
288 case reloc_generic_tile_list:
289 clif_dump_cl(clif, reloc->addr,
290 reloc->generic_tile_list.end);
291 break;
292 }
293 out(clif, "\n");
294 }
295 }
296
297 void
298 clif_dump_add_cl(struct clif_dump *clif, uint32_t start, uint32_t end)
299 {
300 clif_dump_cl(clif, start, end);
301 out(clif, "\n");
302
303 clif_process_worklist(clif);
304 }