1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright © 2021 Google, Inc.
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
13bf215546Sopenharmony_ci * Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20bf215546Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21bf215546Sopenharmony_ci * SOFTWARE.
22bf215546Sopenharmony_ci */
23bf215546Sopenharmony_ci
24bf215546Sopenharmony_ci#include <err.h>
25bf215546Sopenharmony_ci#include <stdarg.h>
26bf215546Sopenharmony_ci#include <stdio.h>
27bf215546Sopenharmony_ci#include <string.h>
28bf215546Sopenharmony_ci
29bf215546Sopenharmony_ci#include "rnn.h"
30bf215546Sopenharmony_ci#include "rnndec.h"
31bf215546Sopenharmony_ci
32bf215546Sopenharmony_ci#include "afuc.h"
33bf215546Sopenharmony_ci#include "util.h"
34bf215546Sopenharmony_ci
35bf215546Sopenharmony_cistatic struct rnndeccontext *ctx;
36bf215546Sopenharmony_cistatic struct rnndb *db;
37bf215546Sopenharmony_cistatic struct rnndomain *control_regs;
38bf215546Sopenharmony_cistatic struct rnndomain *pipe_regs;
39bf215546Sopenharmony_cistruct rnndomain *dom[2];
40bf215546Sopenharmony_cistatic struct rnnenum *pm4_packets;
41bf215546Sopenharmony_ci
42bf215546Sopenharmony_cistatic int
43bf215546Sopenharmony_cifind_reg(struct rnndomain *dom, const char *name)
44bf215546Sopenharmony_ci{
45bf215546Sopenharmony_ci   for (int i = 0; i < dom->subelemsnum; i++)
46bf215546Sopenharmony_ci      if (!strcmp(name, dom->subelems[i]->name))
47bf215546Sopenharmony_ci         return dom->subelems[i]->offset;
48bf215546Sopenharmony_ci
49bf215546Sopenharmony_ci   return -1;
50bf215546Sopenharmony_ci}
51bf215546Sopenharmony_ci
52bf215546Sopenharmony_cistatic unsigned
53bf215546Sopenharmony_cireg(struct rnndomain *dom, const char *type, const char *name)
54bf215546Sopenharmony_ci{
55bf215546Sopenharmony_ci   int val = find_reg(dom, name);
56bf215546Sopenharmony_ci   if (val < 0) {
57bf215546Sopenharmony_ci      char *endptr = NULL;
58bf215546Sopenharmony_ci      val = strtol(name, &endptr, 0);
59bf215546Sopenharmony_ci      if (endptr && *endptr) {
60bf215546Sopenharmony_ci         printf("invalid %s reg: %s\n", type, name);
61bf215546Sopenharmony_ci         exit(2);
62bf215546Sopenharmony_ci      }
63bf215546Sopenharmony_ci   }
64bf215546Sopenharmony_ci   return (unsigned)val;
65bf215546Sopenharmony_ci}
66bf215546Sopenharmony_ci
67bf215546Sopenharmony_cistatic char *
68bf215546Sopenharmony_cireg_name(struct rnndomain *dom, unsigned id)
69bf215546Sopenharmony_ci{
70bf215546Sopenharmony_ci   if (rnndec_checkaddr(ctx, dom, id, 0)) {
71bf215546Sopenharmony_ci      struct rnndecaddrinfo *info = rnndec_decodeaddr(ctx, dom, id, 0);
72bf215546Sopenharmony_ci      char *name = info->name;
73bf215546Sopenharmony_ci      free(info);
74bf215546Sopenharmony_ci      return name;
75bf215546Sopenharmony_ci   } else {
76bf215546Sopenharmony_ci      return NULL;
77bf215546Sopenharmony_ci   }
78bf215546Sopenharmony_ci}
79bf215546Sopenharmony_ci
80bf215546Sopenharmony_ci/**
81bf215546Sopenharmony_ci * Map control reg name to offset.
82bf215546Sopenharmony_ci */
83bf215546Sopenharmony_ciunsigned
84bf215546Sopenharmony_ciafuc_control_reg(const char *name)
85bf215546Sopenharmony_ci{
86bf215546Sopenharmony_ci   return reg(control_regs, "control", name);
87bf215546Sopenharmony_ci}
88bf215546Sopenharmony_ci
89bf215546Sopenharmony_ci/**
90bf215546Sopenharmony_ci * Map offset to control reg name (or NULL), caller frees
91bf215546Sopenharmony_ci */
92bf215546Sopenharmony_cichar *
93bf215546Sopenharmony_ciafuc_control_reg_name(unsigned id)
94bf215546Sopenharmony_ci{
95bf215546Sopenharmony_ci   return reg_name(control_regs, id);
96bf215546Sopenharmony_ci}
97bf215546Sopenharmony_ci
98bf215546Sopenharmony_ci/**
99bf215546Sopenharmony_ci * Map pipe reg name to offset.
100bf215546Sopenharmony_ci */
101bf215546Sopenharmony_ciunsigned
102bf215546Sopenharmony_ciafuc_pipe_reg(const char *name)
103bf215546Sopenharmony_ci{
104bf215546Sopenharmony_ci   return reg(pipe_regs, "pipe", name);
105bf215546Sopenharmony_ci}
106bf215546Sopenharmony_ci
107bf215546Sopenharmony_ci/**
108bf215546Sopenharmony_ci * "void" pipe regs don't have a value written, the $addr right is
109bf215546Sopenharmony_ci * enough to trigger what they do
110bf215546Sopenharmony_ci */
111bf215546Sopenharmony_cibool
112bf215546Sopenharmony_ciafuc_pipe_reg_is_void(unsigned id)
113bf215546Sopenharmony_ci{
114bf215546Sopenharmony_ci   if (rnndec_checkaddr(ctx, pipe_regs, id, 0)) {
115bf215546Sopenharmony_ci      struct rnndecaddrinfo *info = rnndec_decodeaddr(ctx, pipe_regs, id, 0);
116bf215546Sopenharmony_ci      free(info->name);
117bf215546Sopenharmony_ci      bool ret = !strcmp(info->typeinfo->name, "void");
118bf215546Sopenharmony_ci      free(info);
119bf215546Sopenharmony_ci      return ret;
120bf215546Sopenharmony_ci   } else {
121bf215546Sopenharmony_ci      return false;
122bf215546Sopenharmony_ci   }
123bf215546Sopenharmony_ci}
124bf215546Sopenharmony_ci
125bf215546Sopenharmony_ci/**
126bf215546Sopenharmony_ci * Map offset to pipe reg name (or NULL), caller frees
127bf215546Sopenharmony_ci */
128bf215546Sopenharmony_cichar *
129bf215546Sopenharmony_ciafuc_pipe_reg_name(unsigned id)
130bf215546Sopenharmony_ci{
131bf215546Sopenharmony_ci   return reg_name(pipe_regs, id);
132bf215546Sopenharmony_ci}
133bf215546Sopenharmony_ci
134bf215546Sopenharmony_ci/**
135bf215546Sopenharmony_ci * Map GPU reg name to offset.
136bf215546Sopenharmony_ci */
137bf215546Sopenharmony_ciunsigned
138bf215546Sopenharmony_ciafuc_gpu_reg(const char *name)
139bf215546Sopenharmony_ci{
140bf215546Sopenharmony_ci   int val = find_reg(dom[0], name);
141bf215546Sopenharmony_ci   if (val < 0)
142bf215546Sopenharmony_ci      val = find_reg(dom[1], name);
143bf215546Sopenharmony_ci   if (val < 0) {
144bf215546Sopenharmony_ci      char *endptr = NULL;
145bf215546Sopenharmony_ci      val = strtol(name, &endptr, 0);
146bf215546Sopenharmony_ci      if (endptr && *endptr) {
147bf215546Sopenharmony_ci         printf("invalid control reg: %s\n", name);
148bf215546Sopenharmony_ci         exit(2);
149bf215546Sopenharmony_ci      }
150bf215546Sopenharmony_ci   }
151bf215546Sopenharmony_ci   return (unsigned)val;
152bf215546Sopenharmony_ci}
153bf215546Sopenharmony_ci
154bf215546Sopenharmony_ci/**
155bf215546Sopenharmony_ci * Map offset to gpu reg name (or NULL), caller frees
156bf215546Sopenharmony_ci */
157bf215546Sopenharmony_cichar *
158bf215546Sopenharmony_ciafuc_gpu_reg_name(unsigned id)
159bf215546Sopenharmony_ci{
160bf215546Sopenharmony_ci   struct rnndomain *d = NULL;
161bf215546Sopenharmony_ci
162bf215546Sopenharmony_ci   if (rnndec_checkaddr(ctx, dom[0], id, 0)) {
163bf215546Sopenharmony_ci      d = dom[0];
164bf215546Sopenharmony_ci   } else if (rnndec_checkaddr(ctx, dom[1], id, 0)) {
165bf215546Sopenharmony_ci      d = dom[1];
166bf215546Sopenharmony_ci   }
167bf215546Sopenharmony_ci
168bf215546Sopenharmony_ci   if (d) {
169bf215546Sopenharmony_ci      struct rnndecaddrinfo *info = rnndec_decodeaddr(ctx, d, id, 0);
170bf215546Sopenharmony_ci      if (info) {
171bf215546Sopenharmony_ci         char *name = info->name;
172bf215546Sopenharmony_ci         free(info);
173bf215546Sopenharmony_ci         return name;
174bf215546Sopenharmony_ci      }
175bf215546Sopenharmony_ci   }
176bf215546Sopenharmony_ci
177bf215546Sopenharmony_ci   return NULL;
178bf215546Sopenharmony_ci}
179bf215546Sopenharmony_ci
180bf215546Sopenharmony_ciunsigned
181bf215546Sopenharmony_ciafuc_gpr_reg(const char *name)
182bf215546Sopenharmony_ci{
183bf215546Sopenharmony_ci   /* If it starts with '$' just swallow it: */
184bf215546Sopenharmony_ci   if (name[0] == '$')
185bf215546Sopenharmony_ci      name++;
186bf215546Sopenharmony_ci
187bf215546Sopenharmony_ci   /* handle aliases: */
188bf215546Sopenharmony_ci   if (!strcmp(name, "rem")) {
189bf215546Sopenharmony_ci      return REG_REM;
190bf215546Sopenharmony_ci   } else if (!strcmp(name, "memdata")) {
191bf215546Sopenharmony_ci      return REG_MEMDATA;
192bf215546Sopenharmony_ci   } else if (!strcmp(name, "addr")) {
193bf215546Sopenharmony_ci      return REG_ADDR;
194bf215546Sopenharmony_ci   } else if (!strcmp(name, "regdata")) {
195bf215546Sopenharmony_ci      return REG_REGDATA;
196bf215546Sopenharmony_ci   } else if (!strcmp(name, "usraddr")) {
197bf215546Sopenharmony_ci      return REG_USRADDR;
198bf215546Sopenharmony_ci   } else if (!strcmp(name, "data")) {
199bf215546Sopenharmony_ci      return REG_DATA;
200bf215546Sopenharmony_ci   } else {
201bf215546Sopenharmony_ci      char *endptr = NULL;
202bf215546Sopenharmony_ci      unsigned val = strtol(name, &endptr, 16);
203bf215546Sopenharmony_ci      if (endptr && *endptr) {
204bf215546Sopenharmony_ci         printf("invalid gpr reg: %s\n", name);
205bf215546Sopenharmony_ci         exit(2);
206bf215546Sopenharmony_ci      }
207bf215546Sopenharmony_ci      return val;
208bf215546Sopenharmony_ci   }
209bf215546Sopenharmony_ci}
210bf215546Sopenharmony_ci
211bf215546Sopenharmony_cistatic int
212bf215546Sopenharmony_cifind_enum_val(struct rnnenum *en, const char *name)
213bf215546Sopenharmony_ci{
214bf215546Sopenharmony_ci   int i;
215bf215546Sopenharmony_ci
216bf215546Sopenharmony_ci   for (i = 0; i < en->valsnum; i++)
217bf215546Sopenharmony_ci      if (en->vals[i]->valvalid && !strcmp(name, en->vals[i]->name))
218bf215546Sopenharmony_ci         return en->vals[i]->value;
219bf215546Sopenharmony_ci
220bf215546Sopenharmony_ci   return -1;
221bf215546Sopenharmony_ci}
222bf215546Sopenharmony_ci
223bf215546Sopenharmony_ci/**
224bf215546Sopenharmony_ci * Map pm4 packet name to id
225bf215546Sopenharmony_ci */
226bf215546Sopenharmony_ciint
227bf215546Sopenharmony_ciafuc_pm4_id(const char *name)
228bf215546Sopenharmony_ci{
229bf215546Sopenharmony_ci   return find_enum_val(pm4_packets, name);
230bf215546Sopenharmony_ci}
231bf215546Sopenharmony_ci
232bf215546Sopenharmony_ciconst char *
233bf215546Sopenharmony_ciafuc_pm_id_name(unsigned id)
234bf215546Sopenharmony_ci{
235bf215546Sopenharmony_ci   return rnndec_decode_enum(ctx, "adreno_pm4_type3_packets", id);
236bf215546Sopenharmony_ci}
237bf215546Sopenharmony_ci
238bf215546Sopenharmony_civoid
239bf215546Sopenharmony_ciafuc_printc(enum afuc_color c, const char *fmt, ...)
240bf215546Sopenharmony_ci{
241bf215546Sopenharmony_ci   va_list args;
242bf215546Sopenharmony_ci   if (c == AFUC_ERR) {
243bf215546Sopenharmony_ci      printf("%s", ctx->colors->err);
244bf215546Sopenharmony_ci   } else if (c == AFUC_LBL) {
245bf215546Sopenharmony_ci      printf("%s", ctx->colors->btarg);
246bf215546Sopenharmony_ci   }
247bf215546Sopenharmony_ci   va_start(args, fmt);
248bf215546Sopenharmony_ci   vprintf(fmt, args);
249bf215546Sopenharmony_ci   va_end(args);
250bf215546Sopenharmony_ci   printf("%s", ctx->colors->reset);
251bf215546Sopenharmony_ci}
252bf215546Sopenharmony_ci
253bf215546Sopenharmony_ciint afuc_util_init(int gpuver, bool colors)
254bf215546Sopenharmony_ci{
255bf215546Sopenharmony_ci   char *name, *control_reg_name;
256bf215546Sopenharmony_ci   char *pipe_reg_name = NULL;
257bf215546Sopenharmony_ci
258bf215546Sopenharmony_ci   switch (gpuver) {
259bf215546Sopenharmony_ci   case 6:
260bf215546Sopenharmony_ci      name = "A6XX";
261bf215546Sopenharmony_ci      control_reg_name = "A6XX_CONTROL_REG";
262bf215546Sopenharmony_ci      pipe_reg_name = "A6XX_PIPE_REG";
263bf215546Sopenharmony_ci      break;
264bf215546Sopenharmony_ci   case 5:
265bf215546Sopenharmony_ci      name = "A5XX";
266bf215546Sopenharmony_ci      control_reg_name = "A5XX_CONTROL_REG";
267bf215546Sopenharmony_ci      pipe_reg_name = "A5XX_PIPE_REG";
268bf215546Sopenharmony_ci      break;
269bf215546Sopenharmony_ci   default:
270bf215546Sopenharmony_ci      fprintf(stderr, "unknown GPU version!\n");
271bf215546Sopenharmony_ci      return -1;
272bf215546Sopenharmony_ci   }
273bf215546Sopenharmony_ci
274bf215546Sopenharmony_ci   rnn_init();
275bf215546Sopenharmony_ci   db = rnn_newdb();
276bf215546Sopenharmony_ci
277bf215546Sopenharmony_ci   ctx = rnndec_newcontext(db);
278bf215546Sopenharmony_ci   ctx->colors = colors ? &envy_def_colors : &envy_null_colors;
279bf215546Sopenharmony_ci
280bf215546Sopenharmony_ci   rnn_parsefile(db, "adreno.xml");
281bf215546Sopenharmony_ci   rnn_prepdb(db);
282bf215546Sopenharmony_ci   if (db->estatus)
283bf215546Sopenharmony_ci      errx(db->estatus, "failed to parse register database");
284bf215546Sopenharmony_ci   dom[0] = rnn_finddomain(db, name);
285bf215546Sopenharmony_ci   dom[1] = rnn_finddomain(db, "AXXX");
286bf215546Sopenharmony_ci   control_regs = rnn_finddomain(db, control_reg_name);
287bf215546Sopenharmony_ci   pipe_regs = rnn_finddomain(db, pipe_reg_name);
288bf215546Sopenharmony_ci
289bf215546Sopenharmony_ci   rnndec_varadd(ctx, "chip", name);
290bf215546Sopenharmony_ci
291bf215546Sopenharmony_ci   pm4_packets = rnn_findenum(ctx->db, "adreno_pm4_type3_packets");
292bf215546Sopenharmony_ci
293bf215546Sopenharmony_ci   return 0;
294bf215546Sopenharmony_ci}
295bf215546Sopenharmony_ci
296