xref: /aosp_15_r20/external/mesa3d/src/freedreno/afuc/emu.h (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 #ifndef _EMU_H_
7*61046927SAndroid Build Coastguard Worker #define _EMU_H_
8*61046927SAndroid Build Coastguard Worker 
9*61046927SAndroid Build Coastguard Worker #include <stdbool.h>
10*61046927SAndroid Build Coastguard Worker #include <stdint.h>
11*61046927SAndroid Build Coastguard Worker 
12*61046927SAndroid Build Coastguard Worker #include "util/bitset.h"
13*61046927SAndroid Build Coastguard Worker 
14*61046927SAndroid Build Coastguard Worker #include "afuc.h"
15*61046927SAndroid Build Coastguard Worker 
16*61046927SAndroid Build Coastguard Worker extern int gpuver;
17*61046927SAndroid Build Coastguard Worker 
18*61046927SAndroid Build Coastguard Worker #define EMU_NUM_GPR_REGS 32
19*61046927SAndroid Build Coastguard Worker 
20*61046927SAndroid Build Coastguard Worker struct emu_gpr_regs {
21*61046927SAndroid Build Coastguard Worker    BITSET_DECLARE(written, EMU_NUM_GPR_REGS);
22*61046927SAndroid Build Coastguard Worker    uint32_t pc;
23*61046927SAndroid Build Coastguard Worker    uint32_t val[EMU_NUM_GPR_REGS];
24*61046927SAndroid Build Coastguard Worker };
25*61046927SAndroid Build Coastguard Worker 
26*61046927SAndroid Build Coastguard Worker #define EMU_NUM_CONTROL_REGS 0x1000
27*61046927SAndroid Build Coastguard Worker 
28*61046927SAndroid Build Coastguard Worker struct emu_control_regs {
29*61046927SAndroid Build Coastguard Worker    BITSET_DECLARE(written, EMU_NUM_CONTROL_REGS);
30*61046927SAndroid Build Coastguard Worker    uint32_t val[EMU_NUM_CONTROL_REGS];
31*61046927SAndroid Build Coastguard Worker };
32*61046927SAndroid Build Coastguard Worker 
33*61046927SAndroid Build Coastguard Worker #define EMU_NUM_SQE_REGS 0x10
34*61046927SAndroid Build Coastguard Worker 
35*61046927SAndroid Build Coastguard Worker struct emu_sqe_regs {
36*61046927SAndroid Build Coastguard Worker    BITSET_DECLARE(written, EMU_NUM_SQE_REGS);
37*61046927SAndroid Build Coastguard Worker    uint32_t val[EMU_NUM_SQE_REGS];
38*61046927SAndroid Build Coastguard Worker };
39*61046927SAndroid Build Coastguard Worker 
40*61046927SAndroid Build Coastguard Worker #define EMU_NUM_GPU_REGS 0x10000
41*61046927SAndroid Build Coastguard Worker 
42*61046927SAndroid Build Coastguard Worker struct emu_gpu_regs {
43*61046927SAndroid Build Coastguard Worker    BITSET_DECLARE(written, EMU_NUM_GPU_REGS);
44*61046927SAndroid Build Coastguard Worker    uint32_t val[EMU_NUM_GPU_REGS];
45*61046927SAndroid Build Coastguard Worker };
46*61046927SAndroid Build Coastguard Worker 
47*61046927SAndroid Build Coastguard Worker #define EMU_NUM_PIPE_REGS 0x100
48*61046927SAndroid Build Coastguard Worker 
49*61046927SAndroid Build Coastguard Worker struct emu_pipe_regs {
50*61046927SAndroid Build Coastguard Worker    BITSET_DECLARE(written, EMU_NUM_PIPE_REGS);
51*61046927SAndroid Build Coastguard Worker    uint32_t val[EMU_NUM_PIPE_REGS];
52*61046927SAndroid Build Coastguard Worker };
53*61046927SAndroid Build Coastguard Worker 
54*61046927SAndroid Build Coastguard Worker /**
55*61046927SAndroid Build Coastguard Worker  * A simple queue implementation to buffer up cmdstream for the
56*61046927SAndroid Build Coastguard Worker  * emulated firmware to consume
57*61046927SAndroid Build Coastguard Worker  */
58*61046927SAndroid Build Coastguard Worker struct emu_queue {
59*61046927SAndroid Build Coastguard Worker    unsigned head, tail, count;
60*61046927SAndroid Build Coastguard Worker    uint32_t fifo[0x100];
61*61046927SAndroid Build Coastguard Worker };
62*61046927SAndroid Build Coastguard Worker 
63*61046927SAndroid Build Coastguard Worker static inline bool
emu_queue_push(struct emu_queue * q,uint32_t val)64*61046927SAndroid Build Coastguard Worker emu_queue_push(struct emu_queue *q, uint32_t val)
65*61046927SAndroid Build Coastguard Worker {
66*61046927SAndroid Build Coastguard Worker    if (q->count >= ARRAY_SIZE(q->fifo))
67*61046927SAndroid Build Coastguard Worker       return false;
68*61046927SAndroid Build Coastguard Worker 
69*61046927SAndroid Build Coastguard Worker    q->count++;
70*61046927SAndroid Build Coastguard Worker    q->head++;
71*61046927SAndroid Build Coastguard Worker    q->head %= ARRAY_SIZE(q->fifo);
72*61046927SAndroid Build Coastguard Worker 
73*61046927SAndroid Build Coastguard Worker    q->fifo[q->head] = val;
74*61046927SAndroid Build Coastguard Worker 
75*61046927SAndroid Build Coastguard Worker    return true;
76*61046927SAndroid Build Coastguard Worker }
77*61046927SAndroid Build Coastguard Worker 
78*61046927SAndroid Build Coastguard Worker static inline bool
emu_queue_pop(struct emu_queue * q,uint32_t * val)79*61046927SAndroid Build Coastguard Worker emu_queue_pop(struct emu_queue *q, uint32_t *val)
80*61046927SAndroid Build Coastguard Worker {
81*61046927SAndroid Build Coastguard Worker    if (!q->count)
82*61046927SAndroid Build Coastguard Worker       return false;
83*61046927SAndroid Build Coastguard Worker 
84*61046927SAndroid Build Coastguard Worker    q->count--;
85*61046927SAndroid Build Coastguard Worker    q->tail++;
86*61046927SAndroid Build Coastguard Worker    q->tail %= ARRAY_SIZE(q->fifo);
87*61046927SAndroid Build Coastguard Worker 
88*61046927SAndroid Build Coastguard Worker    *val = q->fifo[q->tail];
89*61046927SAndroid Build Coastguard Worker 
90*61046927SAndroid Build Coastguard Worker    return true;
91*61046927SAndroid Build Coastguard Worker }
92*61046927SAndroid Build Coastguard Worker 
93*61046927SAndroid Build Coastguard Worker static inline bool
emu_queue_peek(struct emu_queue * q,uint32_t * val)94*61046927SAndroid Build Coastguard Worker emu_queue_peek(struct emu_queue *q, uint32_t *val)
95*61046927SAndroid Build Coastguard Worker {
96*61046927SAndroid Build Coastguard Worker    if (!q->count)
97*61046927SAndroid Build Coastguard Worker       return false;
98*61046927SAndroid Build Coastguard Worker 
99*61046927SAndroid Build Coastguard Worker    *val = q->fifo[q->tail];
100*61046927SAndroid Build Coastguard Worker 
101*61046927SAndroid Build Coastguard Worker    return true;
102*61046927SAndroid Build Coastguard Worker }
103*61046927SAndroid Build Coastguard Worker 
104*61046927SAndroid Build Coastguard Worker /**
105*61046927SAndroid Build Coastguard Worker  * Draw-state (ie. CP_SET_DRAW_STATE) related emulation
106*61046927SAndroid Build Coastguard Worker  */
107*61046927SAndroid Build Coastguard Worker struct emu_draw_state {
108*61046927SAndroid Build Coastguard Worker    unsigned prev_draw_state_sel;
109*61046927SAndroid Build Coastguard Worker    struct {
110*61046927SAndroid Build Coastguard Worker       union {
111*61046927SAndroid Build Coastguard Worker          uint32_t hdr;
112*61046927SAndroid Build Coastguard Worker          struct {
113*61046927SAndroid Build Coastguard Worker             uint16_t count;       /* # of dwords */
114*61046927SAndroid Build Coastguard Worker             uint16_t mode_mask;
115*61046927SAndroid Build Coastguard Worker          };
116*61046927SAndroid Build Coastguard Worker       };
117*61046927SAndroid Build Coastguard Worker       union {
118*61046927SAndroid Build Coastguard Worker          uint32_t base_lohi[2];
119*61046927SAndroid Build Coastguard Worker          uint64_t base;
120*61046927SAndroid Build Coastguard Worker       };
121*61046927SAndroid Build Coastguard Worker       uint64_t sds_base;
122*61046927SAndroid Build Coastguard Worker       uint32_t sds_dwords;
123*61046927SAndroid Build Coastguard Worker    } state[32];
124*61046927SAndroid Build Coastguard Worker };
125*61046927SAndroid Build Coastguard Worker 
126*61046927SAndroid Build Coastguard Worker /**
127*61046927SAndroid Build Coastguard Worker  * The GPU memory size:
128*61046927SAndroid Build Coastguard Worker  *
129*61046927SAndroid Build Coastguard Worker  * The size is a bit arbitrary, and could be increased.  The backing
130*61046927SAndroid Build Coastguard Worker  * storage is a MAP_ANONYMOUS mapping so untouched pages should not
131*61046927SAndroid Build Coastguard Worker  * have a cost other than consuming virtual address space.
132*61046927SAndroid Build Coastguard Worker  *
133*61046927SAndroid Build Coastguard Worker  * Use something >4gb so we can test that anything doing GPU pointer
134*61046927SAndroid Build Coastguard Worker  * math correctly handles rollover
135*61046927SAndroid Build Coastguard Worker  */
136*61046927SAndroid Build Coastguard Worker #define EMU_MEMORY_SIZE 0x200000000
137*61046927SAndroid Build Coastguard Worker 
138*61046927SAndroid Build Coastguard Worker /**
139*61046927SAndroid Build Coastguard Worker  * The GPU "address" of the instructions themselves:
140*61046927SAndroid Build Coastguard Worker  *
141*61046927SAndroid Build Coastguard Worker  * Note address is kind of arbitrary, but should be something non-
142*61046927SAndroid Build Coastguard Worker  * zero to sanity check the bootstrap process and packet-table
143*61046927SAndroid Build Coastguard Worker  * loading
144*61046927SAndroid Build Coastguard Worker  */
145*61046927SAndroid Build Coastguard Worker #define EMU_INSTR_BASE 0x1000
146*61046927SAndroid Build Coastguard Worker 
147*61046927SAndroid Build Coastguard Worker /**
148*61046927SAndroid Build Coastguard Worker  * Emulated hw state.
149*61046927SAndroid Build Coastguard Worker  */
150*61046927SAndroid Build Coastguard Worker struct emu {
151*61046927SAndroid Build Coastguard Worker    /**
152*61046927SAndroid Build Coastguard Worker     * In bootstrap mode, execute bootstrap without outputting anything.
153*61046927SAndroid Build Coastguard Worker     * Useful to (for example) extract packet-table.
154*61046927SAndroid Build Coastguard Worker     */
155*61046927SAndroid Build Coastguard Worker    bool quiet;
156*61046927SAndroid Build Coastguard Worker 
157*61046927SAndroid Build Coastguard Worker    enum {
158*61046927SAndroid Build Coastguard Worker       EMU_PROC_SQE,
159*61046927SAndroid Build Coastguard Worker       EMU_PROC_BV,
160*61046927SAndroid Build Coastguard Worker       EMU_PROC_LPAC,
161*61046927SAndroid Build Coastguard Worker    } processor;
162*61046927SAndroid Build Coastguard Worker 
163*61046927SAndroid Build Coastguard Worker    uint32_t *instrs;
164*61046927SAndroid Build Coastguard Worker    unsigned sizedwords;
165*61046927SAndroid Build Coastguard Worker    unsigned fw_id;
166*61046927SAndroid Build Coastguard Worker 
167*61046927SAndroid Build Coastguard Worker    struct emu_control_regs control_regs;
168*61046927SAndroid Build Coastguard Worker    struct emu_sqe_regs     sqe_regs;
169*61046927SAndroid Build Coastguard Worker    struct emu_pipe_regs    pipe_regs;
170*61046927SAndroid Build Coastguard Worker    struct emu_gpu_regs     gpu_regs;
171*61046927SAndroid Build Coastguard Worker    struct emu_gpr_regs     gpr_regs;
172*61046927SAndroid Build Coastguard Worker 
173*61046927SAndroid Build Coastguard Worker    struct emu_draw_state   draw_state;
174*61046927SAndroid Build Coastguard Worker 
175*61046927SAndroid Build Coastguard Worker    /* branch target to jump to after next instruction (ie. after delay-
176*61046927SAndroid Build Coastguard Worker     * slot):
177*61046927SAndroid Build Coastguard Worker     */
178*61046927SAndroid Build Coastguard Worker    uint32_t branch_target;
179*61046927SAndroid Build Coastguard Worker 
180*61046927SAndroid Build Coastguard Worker    /* executed waitin, jump to handler after next instruction (ie. after
181*61046927SAndroid Build Coastguard Worker     * delay-slot):
182*61046927SAndroid Build Coastguard Worker     */
183*61046927SAndroid Build Coastguard Worker    bool waitin;
184*61046927SAndroid Build Coastguard Worker 
185*61046927SAndroid Build Coastguard Worker    /* (r)un mode, don't stop for input until next waitin: */
186*61046927SAndroid Build Coastguard Worker    bool run_mode;
187*61046927SAndroid Build Coastguard Worker 
188*61046927SAndroid Build Coastguard Worker    /* Don't prompt on a read from $data with an empty queue and instead assume
189*61046927SAndroid Build Coastguard Worker     * the bootstrap routine has finished and return a dummy value while
190*61046927SAndroid Build Coastguard Worker     * setting bootstrap_finished.
191*61046927SAndroid Build Coastguard Worker     */
192*61046927SAndroid Build Coastguard Worker    bool bootstrap_mode;
193*61046927SAndroid Build Coastguard Worker 
194*61046927SAndroid Build Coastguard Worker    bool bootstrap_finished;
195*61046927SAndroid Build Coastguard Worker 
196*61046927SAndroid Build Coastguard Worker    /* carry-bits for add/sub for addhi/subhi
197*61046927SAndroid Build Coastguard Worker     * TODO: this is probably in a SQE register somewhere
198*61046927SAndroid Build Coastguard Worker     */
199*61046927SAndroid Build Coastguard Worker    uint32_t carry;
200*61046927SAndroid Build Coastguard Worker 
201*61046927SAndroid Build Coastguard Worker    /* packet table (aka jmptable) has offsets for pm4 packet handlers: */
202*61046927SAndroid Build Coastguard Worker    uint32_t jmptbl[0x80];
203*61046927SAndroid Build Coastguard Worker 
204*61046927SAndroid Build Coastguard Worker    /* In reality ROQ is actually multiple queues, but we don't try
205*61046927SAndroid Build Coastguard Worker     * to model the hw that exactly (but instead only model the behavior)
206*61046927SAndroid Build Coastguard Worker     * so we just use this to buffer up cmdstream input
207*61046927SAndroid Build Coastguard Worker     */
208*61046927SAndroid Build Coastguard Worker    struct emu_queue roq;
209*61046927SAndroid Build Coastguard Worker 
210*61046927SAndroid Build Coastguard Worker    /* Mode for writes to $data: */
211*61046927SAndroid Build Coastguard Worker    enum {
212*61046927SAndroid Build Coastguard Worker       DATA_ADDR,
213*61046927SAndroid Build Coastguard Worker       DATA_USRADDR,
214*61046927SAndroid Build Coastguard Worker       DATA_PIPE,
215*61046927SAndroid Build Coastguard Worker    } data_mode;
216*61046927SAndroid Build Coastguard Worker 
217*61046927SAndroid Build Coastguard Worker    /* GPU address space: */
218*61046927SAndroid Build Coastguard Worker    void *gpumem;
219*61046927SAndroid Build Coastguard Worker 
220*61046927SAndroid Build Coastguard Worker    /* A bitset would be prohibitively large to track memory writes, to
221*61046927SAndroid Build Coastguard Worker     * show in the state-change dump.  But we can only write a single
222*61046927SAndroid Build Coastguard Worker     * dword per instruction (given that for (rep) and/or (xmov) we
223*61046927SAndroid Build Coastguard Worker     * dump state change at each "step" of the instruction.
224*61046927SAndroid Build Coastguard Worker     *
225*61046927SAndroid Build Coastguard Worker     * ~0 means no memory write
226*61046927SAndroid Build Coastguard Worker     */
227*61046927SAndroid Build Coastguard Worker    uintptr_t gpumem_written;
228*61046927SAndroid Build Coastguard Worker };
229*61046927SAndroid Build Coastguard Worker 
230*61046927SAndroid Build Coastguard Worker /*
231*61046927SAndroid Build Coastguard Worker  * API for disasm to use:
232*61046927SAndroid Build Coastguard Worker  */
233*61046927SAndroid Build Coastguard Worker void emu_step(struct emu *emu);
234*61046927SAndroid Build Coastguard Worker void emu_run_bootstrap(struct emu *emu);
235*61046927SAndroid Build Coastguard Worker void emu_init(struct emu *emu);
236*61046927SAndroid Build Coastguard Worker void emu_fini(struct emu *emu);
237*61046927SAndroid Build Coastguard Worker 
238*61046927SAndroid Build Coastguard Worker /*
239*61046927SAndroid Build Coastguard Worker  * Internal APIs
240*61046927SAndroid Build Coastguard Worker  */
241*61046927SAndroid Build Coastguard Worker 
242*61046927SAndroid Build Coastguard Worker uint32_t emu_mem_read_dword(struct emu *emu, uintptr_t gpuaddr);
243*61046927SAndroid Build Coastguard Worker void emu_mem_write_dword(struct emu *emu, uintptr_t gpuaddr, uint32_t val);
244*61046927SAndroid Build Coastguard Worker 
245*61046927SAndroid Build Coastguard Worker /* UI: */
246*61046927SAndroid Build Coastguard Worker void emu_main_prompt(struct emu *emu);
247*61046927SAndroid Build Coastguard Worker void emu_clear_state_change(struct emu *emu);
248*61046927SAndroid Build Coastguard Worker void emu_dump_state_change(struct emu *emu);
249*61046927SAndroid Build Coastguard Worker 
250*61046927SAndroid Build Coastguard Worker /* Registers: */
251*61046927SAndroid Build Coastguard Worker uint32_t emu_get_gpr_reg(struct emu *emu, unsigned n);
252*61046927SAndroid Build Coastguard Worker void emu_set_gpr_reg(struct emu *emu, unsigned n, uint32_t val);
253*61046927SAndroid Build Coastguard Worker uint32_t emu_get_gpr_reg_alu(struct emu *emu, unsigned n, bool peek);
254*61046927SAndroid Build Coastguard Worker 
255*61046927SAndroid Build Coastguard Worker void emu_set_gpu_reg(struct emu *emu, unsigned n, uint32_t val);
256*61046927SAndroid Build Coastguard Worker 
257*61046927SAndroid Build Coastguard Worker uint32_t emu_get_control_reg(struct emu *emu, unsigned n);
258*61046927SAndroid Build Coastguard Worker void emu_set_control_reg(struct emu *emu, unsigned n, uint32_t val);
259*61046927SAndroid Build Coastguard Worker 
260*61046927SAndroid Build Coastguard Worker uint32_t emu_get_sqe_reg(struct emu *emu, unsigned n);
261*61046927SAndroid Build Coastguard Worker void emu_set_sqe_reg(struct emu *emu, unsigned n, uint32_t val);
262*61046927SAndroid Build Coastguard Worker 
263*61046927SAndroid Build Coastguard Worker /* Register helpers for fixed fxn emulation, to avoid lots of boilerplate
264*61046927SAndroid Build Coastguard Worker  * for accessing other pipe/control registers.
265*61046927SAndroid Build Coastguard Worker  *
266*61046927SAndroid Build Coastguard Worker  * Example:
267*61046927SAndroid Build Coastguard Worker  *    EMU_CONTROL_REG(REG_NAME);
268*61046927SAndroid Build Coastguard Worker  *    val = emu_get_reg32(emu, &SOME_REG);
269*61046927SAndroid Build Coastguard Worker  */
270*61046927SAndroid Build Coastguard Worker 
271*61046927SAndroid Build Coastguard Worker struct emu_reg_accessor;
272*61046927SAndroid Build Coastguard Worker 
273*61046927SAndroid Build Coastguard Worker struct emu_reg {
274*61046927SAndroid Build Coastguard Worker    const char *name;
275*61046927SAndroid Build Coastguard Worker    const struct emu_reg_accessor *accessor;
276*61046927SAndroid Build Coastguard Worker    unsigned offset;
277*61046927SAndroid Build Coastguard Worker };
278*61046927SAndroid Build Coastguard Worker 
279*61046927SAndroid Build Coastguard Worker extern const struct emu_reg_accessor emu_control_accessor;
280*61046927SAndroid Build Coastguard Worker extern const struct emu_reg_accessor emu_sqe_accessor;
281*61046927SAndroid Build Coastguard Worker extern const struct emu_reg_accessor emu_pipe_accessor;
282*61046927SAndroid Build Coastguard Worker extern const struct emu_reg_accessor emu_gpu_accessor;
283*61046927SAndroid Build Coastguard Worker 
284*61046927SAndroid Build Coastguard Worker #define EMU_CONTROL_REG(name) static struct emu_reg name = { #name, &emu_control_accessor, ~0 }
285*61046927SAndroid Build Coastguard Worker #define EMU_SQE_REG(name) static struct emu_reg name = { #name, &emu_sqe_accessor, ~0 }
286*61046927SAndroid Build Coastguard Worker #define EMU_PIPE_REG(name)    static struct emu_reg name = { #name, &emu_pipe_accessor, ~0 }
287*61046927SAndroid Build Coastguard Worker #define EMU_GPU_REG(name)     static struct emu_reg name = { #name, &emu_gpu_accessor, ~0 }
288*61046927SAndroid Build Coastguard Worker 
289*61046927SAndroid Build Coastguard Worker unsigned emu_reg_offset(struct emu_reg *reg);
290*61046927SAndroid Build Coastguard Worker uint32_t emu_get_reg32(struct emu *emu, struct emu_reg *reg);
291*61046927SAndroid Build Coastguard Worker uint64_t emu_get_reg64(struct emu *emu, struct emu_reg *reg);
292*61046927SAndroid Build Coastguard Worker void emu_set_reg32(struct emu *emu, struct emu_reg *reg, uint32_t val);
293*61046927SAndroid Build Coastguard Worker void emu_set_reg64(struct emu *emu, struct emu_reg *reg, uint64_t val);
294*61046927SAndroid Build Coastguard Worker 
295*61046927SAndroid Build Coastguard Worker /* Draw-state control reg emulation: */
296*61046927SAndroid Build Coastguard Worker uint32_t emu_get_draw_state_reg(struct emu *emu, unsigned n);
297*61046927SAndroid Build Coastguard Worker void emu_set_draw_state_reg(struct emu *emu, unsigned n, uint32_t val);
298*61046927SAndroid Build Coastguard Worker void emu_set_draw_state_base(struct emu *emu, unsigned n, uint32_t val);
299*61046927SAndroid Build Coastguard Worker 
300*61046927SAndroid Build Coastguard Worker /* Helpers: */
301*61046927SAndroid Build Coastguard Worker #define printdelta(fmt, ...) afuc_printc(AFUC_ERR, fmt, ##__VA_ARGS__)
302*61046927SAndroid Build Coastguard Worker 
303*61046927SAndroid Build Coastguard Worker #endif /* _ASM_H_ */
304