xref: /aosp_15_r20/external/mesa3d/src/freedreno/afuc/emu-ui.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright © 2021 Google, Inc.
3*61046927SAndroid Build Coastguard Worker  * SPDX-License-Identifier: MIT
4*61046927SAndroid Build Coastguard Worker  */
5*61046927SAndroid Build Coastguard Worker 
6*61046927SAndroid Build Coastguard Worker #include <assert.h>
7*61046927SAndroid Build Coastguard Worker #include <ctype.h>
8*61046927SAndroid Build Coastguard Worker #include <inttypes.h>
9*61046927SAndroid Build Coastguard Worker #include <stdio.h>
10*61046927SAndroid Build Coastguard Worker #include <stdlib.h>
11*61046927SAndroid Build Coastguard Worker #include <termios.h>
12*61046927SAndroid Build Coastguard Worker #include <unistd.h>
13*61046927SAndroid Build Coastguard Worker 
14*61046927SAndroid Build Coastguard Worker #include "freedreno_pm4.h"
15*61046927SAndroid Build Coastguard Worker 
16*61046927SAndroid Build Coastguard Worker #include "emu.h"
17*61046927SAndroid Build Coastguard Worker #include "util.h"
18*61046927SAndroid Build Coastguard Worker 
19*61046927SAndroid Build Coastguard Worker /*
20*61046927SAndroid Build Coastguard Worker  * Emulator User Interface:
21*61046927SAndroid Build Coastguard Worker  *
22*61046927SAndroid Build Coastguard Worker  * Handles the user prompts and input parsing.
23*61046927SAndroid Build Coastguard Worker  */
24*61046927SAndroid Build Coastguard Worker 
25*61046927SAndroid Build Coastguard Worker static void
clear_line(void)26*61046927SAndroid Build Coastguard Worker clear_line(void)
27*61046927SAndroid Build Coastguard Worker {
28*61046927SAndroid Build Coastguard Worker    if (!isatty(STDOUT_FILENO))
29*61046927SAndroid Build Coastguard Worker       return;
30*61046927SAndroid Build Coastguard Worker    printf("\r                                                           \r");
31*61046927SAndroid Build Coastguard Worker }
32*61046927SAndroid Build Coastguard Worker 
33*61046927SAndroid Build Coastguard Worker static int
readchar(void)34*61046927SAndroid Build Coastguard Worker readchar(void)
35*61046927SAndroid Build Coastguard Worker {
36*61046927SAndroid Build Coastguard Worker    static struct termios saved_termios, unbuffered_termios;
37*61046927SAndroid Build Coastguard Worker    int c;
38*61046927SAndroid Build Coastguard Worker 
39*61046927SAndroid Build Coastguard Worker    fflush(stdout);
40*61046927SAndroid Build Coastguard Worker 
41*61046927SAndroid Build Coastguard Worker    tcgetattr(STDIN_FILENO, &saved_termios);
42*61046927SAndroid Build Coastguard Worker    unbuffered_termios = saved_termios;
43*61046927SAndroid Build Coastguard Worker    cfmakeraw(&unbuffered_termios);
44*61046927SAndroid Build Coastguard Worker 
45*61046927SAndroid Build Coastguard Worker    tcsetattr(STDIN_FILENO, TCSANOW, &unbuffered_termios);
46*61046927SAndroid Build Coastguard Worker    do {
47*61046927SAndroid Build Coastguard Worker       c = getchar();
48*61046927SAndroid Build Coastguard Worker    } while (isspace(c));
49*61046927SAndroid Build Coastguard Worker    tcsetattr(STDIN_FILENO, TCSANOW, &saved_termios);
50*61046927SAndroid Build Coastguard Worker 
51*61046927SAndroid Build Coastguard Worker    /* TODO, read from script until EOF and then read from stdin: */
52*61046927SAndroid Build Coastguard Worker    if (c == -1)
53*61046927SAndroid Build Coastguard Worker       exit(0);
54*61046927SAndroid Build Coastguard Worker 
55*61046927SAndroid Build Coastguard Worker    return c;
56*61046927SAndroid Build Coastguard Worker }
57*61046927SAndroid Build Coastguard Worker 
58*61046927SAndroid Build Coastguard Worker static const char *
extract_string(char ** buf)59*61046927SAndroid Build Coastguard Worker extract_string(char **buf)
60*61046927SAndroid Build Coastguard Worker {
61*61046927SAndroid Build Coastguard Worker    char *p = *buf;
62*61046927SAndroid Build Coastguard Worker 
63*61046927SAndroid Build Coastguard Worker    /* eat any leading whitespace: */
64*61046927SAndroid Build Coastguard Worker    while (*p && isspace(*p))
65*61046927SAndroid Build Coastguard Worker       p++;
66*61046927SAndroid Build Coastguard Worker 
67*61046927SAndroid Build Coastguard Worker    if (!*p)
68*61046927SAndroid Build Coastguard Worker       return NULL;
69*61046927SAndroid Build Coastguard Worker 
70*61046927SAndroid Build Coastguard Worker    char *ret = p;
71*61046927SAndroid Build Coastguard Worker 
72*61046927SAndroid Build Coastguard Worker    /* skip to next whitespace: */
73*61046927SAndroid Build Coastguard Worker    while (*p && !isspace(*p))
74*61046927SAndroid Build Coastguard Worker       p++;
75*61046927SAndroid Build Coastguard Worker 
76*61046927SAndroid Build Coastguard Worker    if (*p)
77*61046927SAndroid Build Coastguard Worker       *p = '\0';
78*61046927SAndroid Build Coastguard Worker 
79*61046927SAndroid Build Coastguard Worker    *buf = ++p;
80*61046927SAndroid Build Coastguard Worker 
81*61046927SAndroid Build Coastguard Worker    return ret;
82*61046927SAndroid Build Coastguard Worker }
83*61046927SAndroid Build Coastguard Worker 
84*61046927SAndroid Build Coastguard Worker static size_t
readline(char ** p)85*61046927SAndroid Build Coastguard Worker readline(char **p)
86*61046927SAndroid Build Coastguard Worker {
87*61046927SAndroid Build Coastguard Worker    static char *buf;
88*61046927SAndroid Build Coastguard Worker    static size_t n;
89*61046927SAndroid Build Coastguard Worker 
90*61046927SAndroid Build Coastguard Worker    ssize_t ret = getline(&buf, &n, stdin);
91*61046927SAndroid Build Coastguard Worker    if (ret < 0)
92*61046927SAndroid Build Coastguard Worker       return ret;
93*61046927SAndroid Build Coastguard Worker 
94*61046927SAndroid Build Coastguard Worker    *p = buf;
95*61046927SAndroid Build Coastguard Worker    return 0;
96*61046927SAndroid Build Coastguard Worker }
97*61046927SAndroid Build Coastguard Worker 
98*61046927SAndroid Build Coastguard Worker static ssize_t
read_two_values(const char ** val1,const char ** val2)99*61046927SAndroid Build Coastguard Worker read_two_values(const char **val1, const char **val2)
100*61046927SAndroid Build Coastguard Worker {
101*61046927SAndroid Build Coastguard Worker    char *p;
102*61046927SAndroid Build Coastguard Worker 
103*61046927SAndroid Build Coastguard Worker    ssize_t ret = readline(&p);
104*61046927SAndroid Build Coastguard Worker    if (ret < 0)
105*61046927SAndroid Build Coastguard Worker       return ret;
106*61046927SAndroid Build Coastguard Worker 
107*61046927SAndroid Build Coastguard Worker    *val1 = extract_string(&p);
108*61046927SAndroid Build Coastguard Worker    *val2 = extract_string(&p);
109*61046927SAndroid Build Coastguard Worker 
110*61046927SAndroid Build Coastguard Worker    return 0;
111*61046927SAndroid Build Coastguard Worker }
112*61046927SAndroid Build Coastguard Worker 
113*61046927SAndroid Build Coastguard Worker static ssize_t
read_one_value(const char ** val)114*61046927SAndroid Build Coastguard Worker read_one_value(const char **val)
115*61046927SAndroid Build Coastguard Worker {
116*61046927SAndroid Build Coastguard Worker    char *p;
117*61046927SAndroid Build Coastguard Worker 
118*61046927SAndroid Build Coastguard Worker    ssize_t ret = readline(&p);
119*61046927SAndroid Build Coastguard Worker    if (ret < 0)
120*61046927SAndroid Build Coastguard Worker       return ret;
121*61046927SAndroid Build Coastguard Worker 
122*61046927SAndroid Build Coastguard Worker    *val = extract_string(&p);
123*61046927SAndroid Build Coastguard Worker 
124*61046927SAndroid Build Coastguard Worker    return 0;
125*61046927SAndroid Build Coastguard Worker }
126*61046927SAndroid Build Coastguard Worker 
127*61046927SAndroid Build Coastguard Worker static void
print_dst(unsigned reg)128*61046927SAndroid Build Coastguard Worker print_dst(unsigned reg)
129*61046927SAndroid Build Coastguard Worker {
130*61046927SAndroid Build Coastguard Worker    if (reg == REG_REM)
131*61046927SAndroid Build Coastguard Worker       printf("$rem"); /* remainding dwords in packet */
132*61046927SAndroid Build Coastguard Worker    else if (reg == REG_ADDR)
133*61046927SAndroid Build Coastguard Worker       printf("$addr");
134*61046927SAndroid Build Coastguard Worker    else if (reg == REG_USRADDR)
135*61046927SAndroid Build Coastguard Worker       printf("$usraddr");
136*61046927SAndroid Build Coastguard Worker    else if (reg == REG_DATA)
137*61046927SAndroid Build Coastguard Worker       printf("$data");
138*61046927SAndroid Build Coastguard Worker    else
139*61046927SAndroid Build Coastguard Worker       printf("$%02x", reg);
140*61046927SAndroid Build Coastguard Worker }
141*61046927SAndroid Build Coastguard Worker 
142*61046927SAndroid Build Coastguard Worker static void
dump_gpr_register(struct emu * emu,unsigned n)143*61046927SAndroid Build Coastguard Worker dump_gpr_register(struct emu *emu, unsigned n)
144*61046927SAndroid Build Coastguard Worker {
145*61046927SAndroid Build Coastguard Worker    printf("              GPR:  ");
146*61046927SAndroid Build Coastguard Worker    print_dst(n);
147*61046927SAndroid Build Coastguard Worker    printf(": ");
148*61046927SAndroid Build Coastguard Worker    if (BITSET_TEST(emu->gpr_regs.written, n)) {
149*61046927SAndroid Build Coastguard Worker       printdelta("%08x\n", emu->gpr_regs.val[n]);
150*61046927SAndroid Build Coastguard Worker    } else {
151*61046927SAndroid Build Coastguard Worker       printf("%08x\n", emu->gpr_regs.val[n]);
152*61046927SAndroid Build Coastguard Worker    }
153*61046927SAndroid Build Coastguard Worker }
154*61046927SAndroid Build Coastguard Worker 
155*61046927SAndroid Build Coastguard Worker static void
dump_gpr_registers(struct emu * emu)156*61046927SAndroid Build Coastguard Worker dump_gpr_registers(struct emu *emu)
157*61046927SAndroid Build Coastguard Worker {
158*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < ARRAY_SIZE(emu->gpr_regs.val); i++) {
159*61046927SAndroid Build Coastguard Worker       dump_gpr_register(emu, i);
160*61046927SAndroid Build Coastguard Worker    }
161*61046927SAndroid Build Coastguard Worker }
162*61046927SAndroid Build Coastguard Worker 
163*61046927SAndroid Build Coastguard Worker static void
dump_gpu_register(struct emu * emu,unsigned n)164*61046927SAndroid Build Coastguard Worker dump_gpu_register(struct emu *emu, unsigned n)
165*61046927SAndroid Build Coastguard Worker {
166*61046927SAndroid Build Coastguard Worker    printf("              GPU:  ");
167*61046927SAndroid Build Coastguard Worker    char *name = afuc_gpu_reg_name(n);
168*61046927SAndroid Build Coastguard Worker    if (name) {
169*61046927SAndroid Build Coastguard Worker       printf("%s", name);
170*61046927SAndroid Build Coastguard Worker       free(name);
171*61046927SAndroid Build Coastguard Worker    } else {
172*61046927SAndroid Build Coastguard Worker       printf("0x%04x", n);
173*61046927SAndroid Build Coastguard Worker    }
174*61046927SAndroid Build Coastguard Worker    printf(": ");
175*61046927SAndroid Build Coastguard Worker    if (BITSET_TEST(emu->gpu_regs.written, n)) {
176*61046927SAndroid Build Coastguard Worker       printdelta("%08x\n", emu->gpu_regs.val[n]);
177*61046927SAndroid Build Coastguard Worker    } else {
178*61046927SAndroid Build Coastguard Worker       printf("%08x\n", emu->gpu_regs.val[n]);
179*61046927SAndroid Build Coastguard Worker    }
180*61046927SAndroid Build Coastguard Worker }
181*61046927SAndroid Build Coastguard Worker 
182*61046927SAndroid Build Coastguard Worker static void
dump_pipe_register(struct emu * emu,unsigned n)183*61046927SAndroid Build Coastguard Worker dump_pipe_register(struct emu *emu, unsigned n)
184*61046927SAndroid Build Coastguard Worker {
185*61046927SAndroid Build Coastguard Worker    printf("              PIPE: ");
186*61046927SAndroid Build Coastguard Worker    print_pipe_reg(n);
187*61046927SAndroid Build Coastguard Worker    printf(": ");
188*61046927SAndroid Build Coastguard Worker    if (BITSET_TEST(emu->pipe_regs.written, n)) {
189*61046927SAndroid Build Coastguard Worker       printdelta("%08x\n", emu->pipe_regs.val[n]);
190*61046927SAndroid Build Coastguard Worker    } else {
191*61046927SAndroid Build Coastguard Worker       printf("%08x\n", emu->pipe_regs.val[n]);
192*61046927SAndroid Build Coastguard Worker    }
193*61046927SAndroid Build Coastguard Worker }
194*61046927SAndroid Build Coastguard Worker 
195*61046927SAndroid Build Coastguard Worker static void
dump_control_register(struct emu * emu,unsigned n)196*61046927SAndroid Build Coastguard Worker dump_control_register(struct emu *emu, unsigned n)
197*61046927SAndroid Build Coastguard Worker {
198*61046927SAndroid Build Coastguard Worker    printf("              CTRL: ");
199*61046927SAndroid Build Coastguard Worker    print_control_reg(n);
200*61046927SAndroid Build Coastguard Worker    printf(": ");
201*61046927SAndroid Build Coastguard Worker    if (BITSET_TEST(emu->control_regs.written, n)) {
202*61046927SAndroid Build Coastguard Worker       printdelta("%08x\n", emu->control_regs.val[n]);
203*61046927SAndroid Build Coastguard Worker    } else {
204*61046927SAndroid Build Coastguard Worker       printf("%08x\n", emu->control_regs.val[n]);
205*61046927SAndroid Build Coastguard Worker    }
206*61046927SAndroid Build Coastguard Worker }
207*61046927SAndroid Build Coastguard Worker 
208*61046927SAndroid Build Coastguard Worker static void
dump_sqe_register(struct emu * emu,unsigned n)209*61046927SAndroid Build Coastguard Worker dump_sqe_register(struct emu *emu, unsigned n)
210*61046927SAndroid Build Coastguard Worker {
211*61046927SAndroid Build Coastguard Worker    printf("              SQE: ");
212*61046927SAndroid Build Coastguard Worker    print_sqe_reg(n);
213*61046927SAndroid Build Coastguard Worker    printf(": ");
214*61046927SAndroid Build Coastguard Worker    if (BITSET_TEST(emu->sqe_regs.written, n)) {
215*61046927SAndroid Build Coastguard Worker       printdelta("%08x\n", emu->sqe_regs.val[n]);
216*61046927SAndroid Build Coastguard Worker    } else {
217*61046927SAndroid Build Coastguard Worker       printf("%08x\n", emu->sqe_regs.val[n]);
218*61046927SAndroid Build Coastguard Worker    }
219*61046927SAndroid Build Coastguard Worker }
220*61046927SAndroid Build Coastguard Worker 
221*61046927SAndroid Build Coastguard Worker static void
dump_sqe_registers(struct emu * emu)222*61046927SAndroid Build Coastguard Worker dump_sqe_registers(struct emu *emu)
223*61046927SAndroid Build Coastguard Worker {
224*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < ARRAY_SIZE(emu->sqe_regs.val); i++) {
225*61046927SAndroid Build Coastguard Worker       dump_sqe_register(emu, i);
226*61046927SAndroid Build Coastguard Worker    }
227*61046927SAndroid Build Coastguard Worker }
228*61046927SAndroid Build Coastguard Worker 
229*61046927SAndroid Build Coastguard Worker 
230*61046927SAndroid Build Coastguard Worker static void
dump_gpumem(struct emu * emu,uintptr_t addr)231*61046927SAndroid Build Coastguard Worker dump_gpumem(struct emu *emu, uintptr_t addr)
232*61046927SAndroid Build Coastguard Worker {
233*61046927SAndroid Build Coastguard Worker    uint32_t val = emu_mem_read_dword(emu, addr);
234*61046927SAndroid Build Coastguard Worker 
235*61046927SAndroid Build Coastguard Worker    printf("              MEM:  0x%016"PRIxPTR": ", addr);
236*61046927SAndroid Build Coastguard Worker    if (addr == emu->gpumem_written) {
237*61046927SAndroid Build Coastguard Worker       printdelta("0x%08x\n", val);
238*61046927SAndroid Build Coastguard Worker    } else {
239*61046927SAndroid Build Coastguard Worker       printf("0x%08x\n", val);
240*61046927SAndroid Build Coastguard Worker    }
241*61046927SAndroid Build Coastguard Worker }
242*61046927SAndroid Build Coastguard Worker 
243*61046927SAndroid Build Coastguard Worker static void
emu_write_gpr_prompt(struct emu * emu)244*61046927SAndroid Build Coastguard Worker emu_write_gpr_prompt(struct emu *emu)
245*61046927SAndroid Build Coastguard Worker {
246*61046927SAndroid Build Coastguard Worker    clear_line();
247*61046927SAndroid Build Coastguard Worker    printf("    GPR register (name or offset) and value: ");
248*61046927SAndroid Build Coastguard Worker 
249*61046927SAndroid Build Coastguard Worker    const char *name;
250*61046927SAndroid Build Coastguard Worker    const char *value;
251*61046927SAndroid Build Coastguard Worker 
252*61046927SAndroid Build Coastguard Worker    if (read_two_values(&name, &value))
253*61046927SAndroid Build Coastguard Worker       return;
254*61046927SAndroid Build Coastguard Worker 
255*61046927SAndroid Build Coastguard Worker    unsigned offset = afuc_gpr_reg(name);
256*61046927SAndroid Build Coastguard Worker    uint32_t val = strtoul(value, NULL, 0);
257*61046927SAndroid Build Coastguard Worker 
258*61046927SAndroid Build Coastguard Worker    emu_set_gpr_reg(emu, offset, val);
259*61046927SAndroid Build Coastguard Worker }
260*61046927SAndroid Build Coastguard Worker 
261*61046927SAndroid Build Coastguard Worker static void
emu_write_control_prompt(struct emu * emu)262*61046927SAndroid Build Coastguard Worker emu_write_control_prompt(struct emu *emu)
263*61046927SAndroid Build Coastguard Worker {
264*61046927SAndroid Build Coastguard Worker    clear_line();
265*61046927SAndroid Build Coastguard Worker    printf("    Control register (name or offset) and value: ");
266*61046927SAndroid Build Coastguard Worker 
267*61046927SAndroid Build Coastguard Worker    const char *name;
268*61046927SAndroid Build Coastguard Worker    const char *value;
269*61046927SAndroid Build Coastguard Worker 
270*61046927SAndroid Build Coastguard Worker    if (read_two_values(&name, &value))
271*61046927SAndroid Build Coastguard Worker       return;
272*61046927SAndroid Build Coastguard Worker 
273*61046927SAndroid Build Coastguard Worker    unsigned offset = afuc_control_reg(name);
274*61046927SAndroid Build Coastguard Worker    uint32_t val = strtoul(value, NULL, 0);
275*61046927SAndroid Build Coastguard Worker 
276*61046927SAndroid Build Coastguard Worker    emu_set_control_reg(emu, offset, val);
277*61046927SAndroid Build Coastguard Worker }
278*61046927SAndroid Build Coastguard Worker 
279*61046927SAndroid Build Coastguard Worker static void
emu_dump_control_prompt(struct emu * emu)280*61046927SAndroid Build Coastguard Worker emu_dump_control_prompt(struct emu *emu)
281*61046927SAndroid Build Coastguard Worker {
282*61046927SAndroid Build Coastguard Worker    clear_line();
283*61046927SAndroid Build Coastguard Worker    printf("    Control register (name or offset): ");
284*61046927SAndroid Build Coastguard Worker 
285*61046927SAndroid Build Coastguard Worker    const char *name;
286*61046927SAndroid Build Coastguard Worker 
287*61046927SAndroid Build Coastguard Worker    if (read_one_value(&name))
288*61046927SAndroid Build Coastguard Worker       return;
289*61046927SAndroid Build Coastguard Worker 
290*61046927SAndroid Build Coastguard Worker    printf("\n");
291*61046927SAndroid Build Coastguard Worker 
292*61046927SAndroid Build Coastguard Worker    unsigned offset = afuc_control_reg(name);
293*61046927SAndroid Build Coastguard Worker    dump_control_register(emu, offset);
294*61046927SAndroid Build Coastguard Worker }
295*61046927SAndroid Build Coastguard Worker 
296*61046927SAndroid Build Coastguard Worker static void
emu_write_sqe_prompt(struct emu * emu)297*61046927SAndroid Build Coastguard Worker emu_write_sqe_prompt(struct emu *emu)
298*61046927SAndroid Build Coastguard Worker {
299*61046927SAndroid Build Coastguard Worker    clear_line();
300*61046927SAndroid Build Coastguard Worker    printf("    SQE register (name or offset) and value: ");
301*61046927SAndroid Build Coastguard Worker 
302*61046927SAndroid Build Coastguard Worker    const char *name;
303*61046927SAndroid Build Coastguard Worker    const char *value;
304*61046927SAndroid Build Coastguard Worker 
305*61046927SAndroid Build Coastguard Worker    if (read_two_values(&name, &value))
306*61046927SAndroid Build Coastguard Worker       return;
307*61046927SAndroid Build Coastguard Worker 
308*61046927SAndroid Build Coastguard Worker    unsigned offset = afuc_sqe_reg(name);
309*61046927SAndroid Build Coastguard Worker    uint32_t val = strtoul(value, NULL, 0);
310*61046927SAndroid Build Coastguard Worker 
311*61046927SAndroid Build Coastguard Worker    emu_set_sqe_reg(emu, offset, val);
312*61046927SAndroid Build Coastguard Worker }
313*61046927SAndroid Build Coastguard Worker 
314*61046927SAndroid Build Coastguard Worker static void
emu_write_gpu_prompt(struct emu * emu)315*61046927SAndroid Build Coastguard Worker emu_write_gpu_prompt(struct emu *emu)
316*61046927SAndroid Build Coastguard Worker {
317*61046927SAndroid Build Coastguard Worker    clear_line();
318*61046927SAndroid Build Coastguard Worker    printf("    GPU register (name or offset) and value: ");
319*61046927SAndroid Build Coastguard Worker 
320*61046927SAndroid Build Coastguard Worker    const char *name;
321*61046927SAndroid Build Coastguard Worker    const char *value;
322*61046927SAndroid Build Coastguard Worker 
323*61046927SAndroid Build Coastguard Worker    if (read_two_values(&name, &value))
324*61046927SAndroid Build Coastguard Worker       return;
325*61046927SAndroid Build Coastguard Worker 
326*61046927SAndroid Build Coastguard Worker    unsigned offset = afuc_gpu_reg(name);
327*61046927SAndroid Build Coastguard Worker    uint32_t val = strtoul(value, NULL, 0);
328*61046927SAndroid Build Coastguard Worker 
329*61046927SAndroid Build Coastguard Worker    emu_set_gpu_reg(emu, offset, val);
330*61046927SAndroid Build Coastguard Worker }
331*61046927SAndroid Build Coastguard Worker 
332*61046927SAndroid Build Coastguard Worker static void
emu_dump_gpu_prompt(struct emu * emu)333*61046927SAndroid Build Coastguard Worker emu_dump_gpu_prompt(struct emu *emu)
334*61046927SAndroid Build Coastguard Worker {
335*61046927SAndroid Build Coastguard Worker    clear_line();
336*61046927SAndroid Build Coastguard Worker    printf("    GPU register (name or offset): ");
337*61046927SAndroid Build Coastguard Worker 
338*61046927SAndroid Build Coastguard Worker    const char *name;
339*61046927SAndroid Build Coastguard Worker 
340*61046927SAndroid Build Coastguard Worker    if (read_one_value(&name))
341*61046927SAndroid Build Coastguard Worker       return;
342*61046927SAndroid Build Coastguard Worker 
343*61046927SAndroid Build Coastguard Worker    printf("\n");
344*61046927SAndroid Build Coastguard Worker 
345*61046927SAndroid Build Coastguard Worker    unsigned offset = afuc_gpu_reg(name);
346*61046927SAndroid Build Coastguard Worker    dump_gpu_register(emu, offset);
347*61046927SAndroid Build Coastguard Worker }
348*61046927SAndroid Build Coastguard Worker 
349*61046927SAndroid Build Coastguard Worker static void
emu_write_mem_prompt(struct emu * emu)350*61046927SAndroid Build Coastguard Worker emu_write_mem_prompt(struct emu *emu)
351*61046927SAndroid Build Coastguard Worker {
352*61046927SAndroid Build Coastguard Worker    clear_line();
353*61046927SAndroid Build Coastguard Worker    printf("    GPU memory offset and value: ");
354*61046927SAndroid Build Coastguard Worker 
355*61046927SAndroid Build Coastguard Worker    const char *offset;
356*61046927SAndroid Build Coastguard Worker    const char *value;
357*61046927SAndroid Build Coastguard Worker 
358*61046927SAndroid Build Coastguard Worker    if (read_two_values(&offset, &value))
359*61046927SAndroid Build Coastguard Worker       return;
360*61046927SAndroid Build Coastguard Worker 
361*61046927SAndroid Build Coastguard Worker    uintptr_t addr = strtoull(offset, NULL, 0);
362*61046927SAndroid Build Coastguard Worker    uint32_t val = strtoul(value, NULL, 0);
363*61046927SAndroid Build Coastguard Worker 
364*61046927SAndroid Build Coastguard Worker    emu_mem_write_dword(emu, addr, val);
365*61046927SAndroid Build Coastguard Worker }
366*61046927SAndroid Build Coastguard Worker 
367*61046927SAndroid Build Coastguard Worker static void
emu_dump_mem_prompt(struct emu * emu)368*61046927SAndroid Build Coastguard Worker emu_dump_mem_prompt(struct emu *emu)
369*61046927SAndroid Build Coastguard Worker {
370*61046927SAndroid Build Coastguard Worker    clear_line();
371*61046927SAndroid Build Coastguard Worker    printf("    GPU memory offset: ");
372*61046927SAndroid Build Coastguard Worker 
373*61046927SAndroid Build Coastguard Worker    const char *offset;
374*61046927SAndroid Build Coastguard Worker 
375*61046927SAndroid Build Coastguard Worker    if (read_one_value(&offset))
376*61046927SAndroid Build Coastguard Worker       return;
377*61046927SAndroid Build Coastguard Worker 
378*61046927SAndroid Build Coastguard Worker    printf("\n");
379*61046927SAndroid Build Coastguard Worker 
380*61046927SAndroid Build Coastguard Worker    uintptr_t addr = strtoull(offset, NULL, 0);
381*61046927SAndroid Build Coastguard Worker    dump_gpumem(emu, addr);
382*61046927SAndroid Build Coastguard Worker }
383*61046927SAndroid Build Coastguard Worker 
384*61046927SAndroid Build Coastguard Worker static void
emu_dump_prompt(struct emu * emu)385*61046927SAndroid Build Coastguard Worker emu_dump_prompt(struct emu *emu)
386*61046927SAndroid Build Coastguard Worker {
387*61046927SAndroid Build Coastguard Worker    do {
388*61046927SAndroid Build Coastguard Worker       clear_line();
389*61046927SAndroid Build Coastguard Worker       printf("  dump: GPR (r)egisters, (c)ontrol register, (s)qe registers, (g)pu register, (m)emory: ");
390*61046927SAndroid Build Coastguard Worker 
391*61046927SAndroid Build Coastguard Worker       int c = readchar();
392*61046927SAndroid Build Coastguard Worker       printf("%c\n", c);
393*61046927SAndroid Build Coastguard Worker 
394*61046927SAndroid Build Coastguard Worker       if (c == 'r') {
395*61046927SAndroid Build Coastguard Worker          /* Since there aren't too many GPR registers, just dump
396*61046927SAndroid Build Coastguard Worker           * them all:
397*61046927SAndroid Build Coastguard Worker           */
398*61046927SAndroid Build Coastguard Worker          dump_gpr_registers(emu);
399*61046927SAndroid Build Coastguard Worker          break;
400*61046927SAndroid Build Coastguard Worker       } else if (c == 's') {
401*61046927SAndroid Build Coastguard Worker          /* Similarly, just dump all the SQE registers */
402*61046927SAndroid Build Coastguard Worker          dump_sqe_registers(emu);
403*61046927SAndroid Build Coastguard Worker          break;
404*61046927SAndroid Build Coastguard Worker       } else if (c == 'c') {
405*61046927SAndroid Build Coastguard Worker          emu_dump_control_prompt(emu);
406*61046927SAndroid Build Coastguard Worker          break;
407*61046927SAndroid Build Coastguard Worker       } else if (c == 'g') {
408*61046927SAndroid Build Coastguard Worker          emu_dump_gpu_prompt(emu);
409*61046927SAndroid Build Coastguard Worker          break;
410*61046927SAndroid Build Coastguard Worker       } else if (c == 'm') {
411*61046927SAndroid Build Coastguard Worker          emu_dump_mem_prompt(emu);
412*61046927SAndroid Build Coastguard Worker          break;
413*61046927SAndroid Build Coastguard Worker       } else {
414*61046927SAndroid Build Coastguard Worker          printf("invalid option: '%c'\n", c);
415*61046927SAndroid Build Coastguard Worker          break;
416*61046927SAndroid Build Coastguard Worker       }
417*61046927SAndroid Build Coastguard Worker    } while (true);
418*61046927SAndroid Build Coastguard Worker }
419*61046927SAndroid Build Coastguard Worker 
420*61046927SAndroid Build Coastguard Worker static void
emu_write_prompt(struct emu * emu)421*61046927SAndroid Build Coastguard Worker emu_write_prompt(struct emu *emu)
422*61046927SAndroid Build Coastguard Worker {
423*61046927SAndroid Build Coastguard Worker    do {
424*61046927SAndroid Build Coastguard Worker       clear_line();
425*61046927SAndroid Build Coastguard Worker       printf("  write: GPR (r)egister, (c)ontrol register, (s)sqe register, (g)pu register, (m)emory: ");
426*61046927SAndroid Build Coastguard Worker 
427*61046927SAndroid Build Coastguard Worker       int c = readchar();
428*61046927SAndroid Build Coastguard Worker       printf("%c\n", c);
429*61046927SAndroid Build Coastguard Worker 
430*61046927SAndroid Build Coastguard Worker       if (c == 'r') {
431*61046927SAndroid Build Coastguard Worker          emu_write_gpr_prompt(emu);
432*61046927SAndroid Build Coastguard Worker          break;
433*61046927SAndroid Build Coastguard Worker       } else if (c == 's') {
434*61046927SAndroid Build Coastguard Worker          emu_write_sqe_prompt(emu);
435*61046927SAndroid Build Coastguard Worker          break;
436*61046927SAndroid Build Coastguard Worker       } else if (c == 'c') {
437*61046927SAndroid Build Coastguard Worker          emu_write_control_prompt(emu);
438*61046927SAndroid Build Coastguard Worker          break;
439*61046927SAndroid Build Coastguard Worker       } else if (c == 'g') {
440*61046927SAndroid Build Coastguard Worker          emu_write_gpu_prompt(emu);
441*61046927SAndroid Build Coastguard Worker          break;
442*61046927SAndroid Build Coastguard Worker       } else if (c == 'm') {
443*61046927SAndroid Build Coastguard Worker          emu_write_mem_prompt(emu);
444*61046927SAndroid Build Coastguard Worker          break;
445*61046927SAndroid Build Coastguard Worker       } else {
446*61046927SAndroid Build Coastguard Worker          printf("invalid option: '%c'\n", c);
447*61046927SAndroid Build Coastguard Worker          break;
448*61046927SAndroid Build Coastguard Worker       }
449*61046927SAndroid Build Coastguard Worker    } while (true);
450*61046927SAndroid Build Coastguard Worker }
451*61046927SAndroid Build Coastguard Worker 
452*61046927SAndroid Build Coastguard Worker static void
emu_packet_prompt(struct emu * emu)453*61046927SAndroid Build Coastguard Worker emu_packet_prompt(struct emu *emu)
454*61046927SAndroid Build Coastguard Worker {
455*61046927SAndroid Build Coastguard Worker    clear_line();
456*61046927SAndroid Build Coastguard Worker    printf("  Enter packet (opc or register name), followed by payload: ");
457*61046927SAndroid Build Coastguard Worker    fflush(stdout);
458*61046927SAndroid Build Coastguard Worker 
459*61046927SAndroid Build Coastguard Worker    char *p;
460*61046927SAndroid Build Coastguard Worker    if (readline(&p) < 0)
461*61046927SAndroid Build Coastguard Worker       return;
462*61046927SAndroid Build Coastguard Worker 
463*61046927SAndroid Build Coastguard Worker    printf("\n");
464*61046927SAndroid Build Coastguard Worker 
465*61046927SAndroid Build Coastguard Worker    const char *name = extract_string(&p);
466*61046927SAndroid Build Coastguard Worker 
467*61046927SAndroid Build Coastguard Worker    /* Read the payload, so we can know the size to generate correct header: */
468*61046927SAndroid Build Coastguard Worker    uint32_t payload[0x7f];
469*61046927SAndroid Build Coastguard Worker    unsigned cnt = 0;
470*61046927SAndroid Build Coastguard Worker 
471*61046927SAndroid Build Coastguard Worker    do {
472*61046927SAndroid Build Coastguard Worker       const char *val = extract_string(&p);
473*61046927SAndroid Build Coastguard Worker       if (!val)
474*61046927SAndroid Build Coastguard Worker          break;
475*61046927SAndroid Build Coastguard Worker 
476*61046927SAndroid Build Coastguard Worker       assert(cnt < ARRAY_SIZE(payload));
477*61046927SAndroid Build Coastguard Worker       payload[cnt++] = strtoul(val, NULL, 0);
478*61046927SAndroid Build Coastguard Worker    } while (true);
479*61046927SAndroid Build Coastguard Worker 
480*61046927SAndroid Build Coastguard Worker    uint32_t hdr;
481*61046927SAndroid Build Coastguard Worker    if (afuc_pm4_id(name) >= 0) {
482*61046927SAndroid Build Coastguard Worker       unsigned opcode = afuc_pm4_id(name);
483*61046927SAndroid Build Coastguard Worker       hdr = pm4_pkt7_hdr(opcode, cnt);
484*61046927SAndroid Build Coastguard Worker    } else {
485*61046927SAndroid Build Coastguard Worker       unsigned regindx = afuc_gpu_reg(name);
486*61046927SAndroid Build Coastguard Worker       hdr = pm4_pkt4_hdr(regindx, cnt);
487*61046927SAndroid Build Coastguard Worker    }
488*61046927SAndroid Build Coastguard Worker 
489*61046927SAndroid Build Coastguard Worker    ASSERTED bool ret = emu_queue_push(&emu->roq, hdr);
490*61046927SAndroid Build Coastguard Worker    assert(ret);
491*61046927SAndroid Build Coastguard Worker 
492*61046927SAndroid Build Coastguard Worker    for (unsigned i = 0; i < cnt; i++) {
493*61046927SAndroid Build Coastguard Worker       ASSERTED bool ret = emu_queue_push(&emu->roq, payload[i]);
494*61046927SAndroid Build Coastguard Worker       assert(ret);
495*61046927SAndroid Build Coastguard Worker    }
496*61046927SAndroid Build Coastguard Worker }
497*61046927SAndroid Build Coastguard Worker 
498*61046927SAndroid Build Coastguard Worker void
emu_main_prompt(struct emu * emu)499*61046927SAndroid Build Coastguard Worker emu_main_prompt(struct emu *emu)
500*61046927SAndroid Build Coastguard Worker {
501*61046927SAndroid Build Coastguard Worker    if (emu->run_mode)
502*61046927SAndroid Build Coastguard Worker       return;
503*61046927SAndroid Build Coastguard Worker 
504*61046927SAndroid Build Coastguard Worker    do {
505*61046927SAndroid Build Coastguard Worker       clear_line();
506*61046927SAndroid Build Coastguard Worker       printf("(s)tep, (r)un, (d)ump, (w)rite, (p)acket, (h)elp, (q)uit: ");
507*61046927SAndroid Build Coastguard Worker 
508*61046927SAndroid Build Coastguard Worker       int c = readchar();
509*61046927SAndroid Build Coastguard Worker 
510*61046927SAndroid Build Coastguard Worker       printf("%c\n", c);
511*61046927SAndroid Build Coastguard Worker 
512*61046927SAndroid Build Coastguard Worker       if (c == 's') {
513*61046927SAndroid Build Coastguard Worker          break;
514*61046927SAndroid Build Coastguard Worker       } else if (c == 'r') {
515*61046927SAndroid Build Coastguard Worker          emu->run_mode = true;
516*61046927SAndroid Build Coastguard Worker          break;
517*61046927SAndroid Build Coastguard Worker       } else if (c == 'd') {
518*61046927SAndroid Build Coastguard Worker          emu_dump_prompt(emu);
519*61046927SAndroid Build Coastguard Worker       } else if (c == 'w') {
520*61046927SAndroid Build Coastguard Worker          emu_write_prompt(emu);
521*61046927SAndroid Build Coastguard Worker       } else if (c == 'p') {
522*61046927SAndroid Build Coastguard Worker          emu_packet_prompt(emu);
523*61046927SAndroid Build Coastguard Worker       } else if (c == 'h') {
524*61046927SAndroid Build Coastguard Worker          printf("  (s)tep   - single step to next instruction\n");
525*61046927SAndroid Build Coastguard Worker          printf("  (r)un    - run until next waitin\n");
526*61046927SAndroid Build Coastguard Worker          printf("  (d)ump   - dump memory/register menu\n");
527*61046927SAndroid Build Coastguard Worker          printf("  (w)rite  - write memory/register menu\n");
528*61046927SAndroid Build Coastguard Worker          printf("  (p)acket - inject a pm4 packet\n");
529*61046927SAndroid Build Coastguard Worker          printf("  (h)elp   - show this usage message\n");
530*61046927SAndroid Build Coastguard Worker          printf("  (q)uit   - exit emulator\n");
531*61046927SAndroid Build Coastguard Worker       } else if (c == 'q') {
532*61046927SAndroid Build Coastguard Worker          printf("\n");
533*61046927SAndroid Build Coastguard Worker          exit(0);
534*61046927SAndroid Build Coastguard Worker       } else {
535*61046927SAndroid Build Coastguard Worker          printf("invalid option: '%c'\n", c);
536*61046927SAndroid Build Coastguard Worker       }
537*61046927SAndroid Build Coastguard Worker    } while (true);
538*61046927SAndroid Build Coastguard Worker }
539*61046927SAndroid Build Coastguard Worker 
540*61046927SAndroid Build Coastguard Worker void
emu_clear_state_change(struct emu * emu)541*61046927SAndroid Build Coastguard Worker emu_clear_state_change(struct emu *emu)
542*61046927SAndroid Build Coastguard Worker {
543*61046927SAndroid Build Coastguard Worker    memset(emu->control_regs.written, 0, sizeof(emu->control_regs.written));
544*61046927SAndroid Build Coastguard Worker    memset(emu->sqe_regs.written,     0, sizeof(emu->sqe_regs.written));
545*61046927SAndroid Build Coastguard Worker    memset(emu->pipe_regs.written,    0, sizeof(emu->pipe_regs.written));
546*61046927SAndroid Build Coastguard Worker    memset(emu->gpu_regs.written,     0, sizeof(emu->gpu_regs.written));
547*61046927SAndroid Build Coastguard Worker    memset(emu->gpr_regs.written,     0, sizeof(emu->gpr_regs.written));
548*61046927SAndroid Build Coastguard Worker    emu->gpumem_written = ~0;
549*61046927SAndroid Build Coastguard Worker }
550*61046927SAndroid Build Coastguard Worker 
551*61046927SAndroid Build Coastguard Worker void
emu_dump_state_change(struct emu * emu)552*61046927SAndroid Build Coastguard Worker emu_dump_state_change(struct emu *emu)
553*61046927SAndroid Build Coastguard Worker {
554*61046927SAndroid Build Coastguard Worker    unsigned i;
555*61046927SAndroid Build Coastguard Worker 
556*61046927SAndroid Build Coastguard Worker    if (emu->quiet)
557*61046927SAndroid Build Coastguard Worker       return;
558*61046927SAndroid Build Coastguard Worker 
559*61046927SAndroid Build Coastguard Worker    /* Print the GPRs that changed: */
560*61046927SAndroid Build Coastguard Worker    BITSET_FOREACH_SET (i, emu->gpr_regs.written, EMU_NUM_GPR_REGS) {
561*61046927SAndroid Build Coastguard Worker       dump_gpr_register(emu, i);
562*61046927SAndroid Build Coastguard Worker    }
563*61046927SAndroid Build Coastguard Worker 
564*61046927SAndroid Build Coastguard Worker    BITSET_FOREACH_SET (i, emu->gpu_regs.written, EMU_NUM_GPU_REGS) {
565*61046927SAndroid Build Coastguard Worker       dump_gpu_register(emu, i);
566*61046927SAndroid Build Coastguard Worker    }
567*61046927SAndroid Build Coastguard Worker 
568*61046927SAndroid Build Coastguard Worker    BITSET_FOREACH_SET (i, emu->pipe_regs.written, EMU_NUM_PIPE_REGS) {
569*61046927SAndroid Build Coastguard Worker       dump_pipe_register(emu, i);
570*61046927SAndroid Build Coastguard Worker    }
571*61046927SAndroid Build Coastguard Worker 
572*61046927SAndroid Build Coastguard Worker    BITSET_FOREACH_SET (i, emu->control_regs.written, EMU_NUM_CONTROL_REGS) {
573*61046927SAndroid Build Coastguard Worker       dump_control_register(emu, i);
574*61046927SAndroid Build Coastguard Worker    }
575*61046927SAndroid Build Coastguard Worker 
576*61046927SAndroid Build Coastguard Worker    BITSET_FOREACH_SET (i, emu->sqe_regs.written, EMU_NUM_SQE_REGS) {
577*61046927SAndroid Build Coastguard Worker       dump_sqe_register(emu, i);
578*61046927SAndroid Build Coastguard Worker    }
579*61046927SAndroid Build Coastguard Worker 
580*61046927SAndroid Build Coastguard Worker    if (emu->gpumem_written != ~0) {
581*61046927SAndroid Build Coastguard Worker       dump_gpumem(emu, emu->gpumem_written);
582*61046927SAndroid Build Coastguard Worker    }
583*61046927SAndroid Build Coastguard Worker }
584