xref: /aosp_15_r20/external/mesa3d/src/freedreno/afuc/util.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2021 Google, Inc.
3  * SPDX-License-Identifier: MIT
4  */
5 
6 #include <err.h>
7 #include <stdarg.h>
8 #include <stdio.h>
9 #include <string.h>
10 
11 #include "rnn.h"
12 #include "rnndec.h"
13 
14 #include "afuc.h"
15 #include "util.h"
16 
17 static struct rnndeccontext *ctx;
18 static struct rnndb *db;
19 static struct rnndomain *control_regs;
20 static struct rnndomain *sqe_regs;
21 static struct rnndomain *pipe_regs;
22 struct rnndomain *dom[2];
23 static struct rnnenum *pm4_packets;
24 
25 static int
find_reg(struct rnndomain * dom,const char * name)26 find_reg(struct rnndomain *dom, const char *name)
27 {
28    for (int i = 0; i < dom->subelemsnum; i++)
29       if (!strcmp(name, dom->subelems[i]->name))
30          return dom->subelems[i]->offset;
31 
32    return -1;
33 }
34 
35 static unsigned
reg(struct rnndomain * dom,const char * type,const char * name)36 reg(struct rnndomain *dom, const char *type, const char *name)
37 {
38    int val = find_reg(dom, name);
39    if (val < 0) {
40       char *endptr = NULL;
41       val = strtol(name, &endptr, 0);
42       if (endptr && *endptr) {
43          printf("invalid %s reg: %s\n", type, name);
44          exit(2);
45       }
46    }
47    return (unsigned)val;
48 }
49 
50 static char *
reg_name(struct rnndomain * dom,unsigned id)51 reg_name(struct rnndomain *dom, unsigned id)
52 {
53    if (rnndec_checkaddr(ctx, dom, id, 0)) {
54       struct rnndecaddrinfo *info = rnndec_decodeaddr(ctx, dom, id, 0);
55       char *name = info->name;
56       free(info);
57       return name;
58    } else {
59       return NULL;
60    }
61 }
62 
63 /**
64  * Map control reg name to offset.
65  */
66 unsigned
afuc_control_reg(const char * name)67 afuc_control_reg(const char *name)
68 {
69    return reg(control_regs, "control", name);
70 }
71 
72 /**
73  * Map offset to SQE reg name (or NULL), caller frees
74  */
75 char *
afuc_sqe_reg_name(unsigned id)76 afuc_sqe_reg_name(unsigned id)
77 {
78    return reg_name(sqe_regs, id);
79 }
80 
81 /**
82  * Map SQE reg name to offset.
83  */
84 unsigned
afuc_sqe_reg(const char * name)85 afuc_sqe_reg(const char *name)
86 {
87    return reg(sqe_regs, "SQE", name);
88 }
89 
90 /**
91  * Map offset to control reg name (or NULL), caller frees
92  */
93 char *
afuc_control_reg_name(unsigned id)94 afuc_control_reg_name(unsigned id)
95 {
96    return reg_name(control_regs, id);
97 }
98 
99 /**
100  * Map pipe reg name to offset.
101  */
102 unsigned
afuc_pipe_reg(const char * name)103 afuc_pipe_reg(const char *name)
104 {
105    return reg(pipe_regs, "pipe", name);
106 }
107 
108 /**
109  * "void" pipe regs don't have a value written, the $addr right is
110  * enough to trigger what they do
111  */
112 bool
afuc_pipe_reg_is_void(unsigned id)113 afuc_pipe_reg_is_void(unsigned id)
114 {
115    if (rnndec_checkaddr(ctx, pipe_regs, id, 0)) {
116       struct rnndecaddrinfo *info = rnndec_decodeaddr(ctx, pipe_regs, id, 0);
117       free(info->name);
118       bool ret = !strcmp(info->typeinfo->name, "void");
119       free(info);
120       return ret;
121    } else {
122       return false;
123    }
124 }
125 
126 /**
127  * Map offset to pipe reg name (or NULL), caller frees
128  */
129 char *
afuc_pipe_reg_name(unsigned id)130 afuc_pipe_reg_name(unsigned id)
131 {
132    return reg_name(pipe_regs, id);
133 }
134 
135 /**
136  * Map GPU reg name to offset.
137  */
138 unsigned
afuc_gpu_reg(const char * name)139 afuc_gpu_reg(const char *name)
140 {
141    int val = find_reg(dom[0], name);
142    if (val < 0)
143       val = find_reg(dom[1], name);
144    if (val < 0) {
145       char *endptr = NULL;
146       val = strtol(name, &endptr, 0);
147       if (endptr && *endptr) {
148          printf("invalid control reg: %s\n", name);
149          exit(2);
150       }
151    }
152    return (unsigned)val;
153 }
154 
155 /**
156  * Map offset to gpu reg name (or NULL), caller frees
157  */
158 char *
afuc_gpu_reg_name(unsigned id)159 afuc_gpu_reg_name(unsigned id)
160 {
161    struct rnndomain *d = NULL;
162 
163    if (rnndec_checkaddr(ctx, dom[0], id, 0)) {
164       d = dom[0];
165    } else if (rnndec_checkaddr(ctx, dom[1], id, 0)) {
166       d = dom[1];
167    }
168 
169    if (d) {
170       struct rnndecaddrinfo *info = rnndec_decodeaddr(ctx, d, id, 0);
171       if (info) {
172          char *name = info->name;
173          free(info);
174          return name;
175       }
176    }
177 
178    return NULL;
179 }
180 
181 unsigned
afuc_gpr_reg(const char * name)182 afuc_gpr_reg(const char *name)
183 {
184    /* If it starts with '$' just swallow it: */
185    if (name[0] == '$')
186       name++;
187 
188    /* handle aliases: */
189    if (!strcmp(name, "rem")) {
190       return REG_REM;
191    } else if (!strcmp(name, "memdata")) {
192       return REG_MEMDATA;
193    } else if (!strcmp(name, "addr")) {
194       return REG_ADDR;
195    } else if (!strcmp(name, "regdata")) {
196       return REG_REGDATA;
197    } else if (!strcmp(name, "usraddr")) {
198       return REG_USRADDR;
199    } else if (!strcmp(name, "data")) {
200       return REG_DATA;
201    } else {
202       char *endptr = NULL;
203       unsigned val = strtol(name, &endptr, 16);
204       if (endptr && *endptr) {
205          printf("invalid gpr reg: %s\n", name);
206          exit(2);
207       }
208       return val;
209    }
210 }
211 
212 static int
find_enum_val(struct rnnenum * en,const char * name)213 find_enum_val(struct rnnenum *en, const char *name)
214 {
215    int i;
216 
217    for (i = 0; i < en->valsnum; i++)
218       if (en->vals[i]->valvalid && !strcmp(name, en->vals[i]->name))
219          return en->vals[i]->value;
220 
221    return -1;
222 }
223 
224 /**
225  * Map pm4 packet name to id
226  */
227 int
afuc_pm4_id(const char * name)228 afuc_pm4_id(const char *name)
229 {
230    return find_enum_val(pm4_packets, name);
231 }
232 
233 const char *
afuc_pm_id_name(unsigned id)234 afuc_pm_id_name(unsigned id)
235 {
236    return rnndec_decode_enum(ctx, "adreno_pm4_type3_packets", id);
237 }
238 
239 void
afuc_printc(enum afuc_color c,const char * fmt,...)240 afuc_printc(enum afuc_color c, const char *fmt, ...)
241 {
242    va_list args;
243    if (c == AFUC_ERR) {
244       printf("%s", ctx->colors->err);
245    } else if (c == AFUC_LBL) {
246       printf("%s", ctx->colors->btarg);
247    }
248    va_start(args, fmt);
249    vprintf(fmt, args);
250    va_end(args);
251    printf("%s", ctx->colors->reset);
252 }
253 
afuc_util_init(enum afuc_fwid fw_id,int * gpuver_out,bool colors)254 int afuc_util_init(enum afuc_fwid fw_id, int *gpuver_out, bool colors)
255 {
256    char *name, *control_reg_name, *variant;
257    char *pipe_reg_name = NULL;
258 
259    switch (fw_id) {
260    case AFUC_A750:
261       name = "A6XX";
262       variant = "A7XX";
263       control_reg_name = "A7XX_GEN3_CONTROL_REG";
264       pipe_reg_name = "A7XX_PIPE_REG";
265       *gpuver_out = 7;
266       break;
267    case AFUC_A730:
268    case AFUC_A740:
269       name = "A6XX";
270       variant = "A7XX";
271       control_reg_name = "A7XX_CONTROL_REG";
272       pipe_reg_name = "A7XX_PIPE_REG";
273       *gpuver_out = 7;
274       break;
275    case AFUC_A630:
276    case AFUC_A650:
277    case AFUC_A660:
278       name = "A6XX";
279       variant = "A6XX";
280       control_reg_name = "A6XX_CONTROL_REG";
281       pipe_reg_name = "A6XX_PIPE_REG";
282       *gpuver_out = 6;
283       break;
284    case AFUC_A530:
285       name = "A5XX";
286       variant = "A5XX";
287       control_reg_name = "A5XX_CONTROL_REG";
288       pipe_reg_name = "A5XX_PIPE_REG";
289       *gpuver_out = 5;
290       break;
291    default:
292       fprintf(stderr, "unknown GPU version %03x!\n", fw_id);
293       return -1;
294    }
295 
296    rnn_init();
297    db = rnn_newdb();
298 
299    ctx = rnndec_newcontext(db);
300    ctx->colors = colors ? &envy_def_colors : &envy_null_colors;
301 
302    rnn_parsefile(db, "adreno.xml");
303    rnn_prepdb(db);
304    if (db->estatus)
305       errx(db->estatus, "failed to parse register database");
306    dom[0] = rnn_finddomain(db, name);
307    dom[1] = rnn_finddomain(db, "AXXX");
308    control_regs = rnn_finddomain(db, control_reg_name);
309    sqe_regs = rnn_finddomain(db, "A6XX_SQE_REG");
310    pipe_regs = rnn_finddomain(db, pipe_reg_name);
311 
312    rnndec_varadd(ctx, "chip", variant);
313 
314    pm4_packets = rnn_findenum(ctx->db, "adreno_pm4_type3_packets");
315 
316    return 0;
317 }
318 
319