17ec681f3Smrg/* 27ec681f3Smrg * Copyright © 2021 Google, Inc. 37ec681f3Smrg * 47ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a 57ec681f3Smrg * copy of this software and associated documentation files (the "Software"), 67ec681f3Smrg * to deal in the Software without restriction, including without limitation 77ec681f3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 87ec681f3Smrg * and/or sell copies of the Software, and to permit persons to whom the 97ec681f3Smrg * Software is furnished to do so, subject to the following conditions: 107ec681f3Smrg * 117ec681f3Smrg * The above copyright notice and this permission notice (including the next 127ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the 137ec681f3Smrg * Software. 147ec681f3Smrg * 157ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 167ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 177ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 187ec681f3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 197ec681f3Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 207ec681f3Smrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 217ec681f3Smrg * SOFTWARE. 227ec681f3Smrg */ 237ec681f3Smrg 247ec681f3Smrg#include <err.h> 257ec681f3Smrg#include <stdarg.h> 267ec681f3Smrg#include <stdio.h> 277ec681f3Smrg#include <string.h> 287ec681f3Smrg 297ec681f3Smrg#include "rnn.h" 307ec681f3Smrg#include "rnndec.h" 317ec681f3Smrg 327ec681f3Smrg#include "afuc.h" 337ec681f3Smrg#include "util.h" 347ec681f3Smrg 357ec681f3Smrgstatic struct rnndeccontext *ctx; 367ec681f3Smrgstatic struct rnndb *db; 377ec681f3Smrgstatic struct rnndomain *control_regs; 387ec681f3Smrgstatic struct rnndomain *pipe_regs; 397ec681f3Smrgstruct rnndomain *dom[2]; 407ec681f3Smrgstatic struct rnnenum *pm4_packets; 417ec681f3Smrg 427ec681f3Smrgstatic int 437ec681f3Smrgfind_reg(struct rnndomain *dom, const char *name) 447ec681f3Smrg{ 457ec681f3Smrg for (int i = 0; i < dom->subelemsnum; i++) 467ec681f3Smrg if (!strcmp(name, dom->subelems[i]->name)) 477ec681f3Smrg return dom->subelems[i]->offset; 487ec681f3Smrg 497ec681f3Smrg return -1; 507ec681f3Smrg} 517ec681f3Smrg 527ec681f3Smrgstatic unsigned 537ec681f3Smrgreg(struct rnndomain *dom, const char *type, const char *name) 547ec681f3Smrg{ 557ec681f3Smrg int val = find_reg(dom, name); 567ec681f3Smrg if (val < 0) { 577ec681f3Smrg char *endptr = NULL; 587ec681f3Smrg val = strtol(name, &endptr, 0); 597ec681f3Smrg if (endptr && *endptr) { 607ec681f3Smrg printf("invalid %s reg: %s\n", type, name); 617ec681f3Smrg exit(2); 627ec681f3Smrg } 637ec681f3Smrg } 647ec681f3Smrg return (unsigned)val; 657ec681f3Smrg} 667ec681f3Smrg 677ec681f3Smrgstatic char * 687ec681f3Smrgreg_name(struct rnndomain *dom, unsigned id) 697ec681f3Smrg{ 707ec681f3Smrg if (rnndec_checkaddr(ctx, dom, id, 0)) { 717ec681f3Smrg struct rnndecaddrinfo *info = rnndec_decodeaddr(ctx, dom, id, 0); 727ec681f3Smrg char *name = info->name; 737ec681f3Smrg free(info); 747ec681f3Smrg return name; 757ec681f3Smrg } else { 767ec681f3Smrg return NULL; 777ec681f3Smrg } 787ec681f3Smrg} 797ec681f3Smrg 807ec681f3Smrg/** 817ec681f3Smrg * Map control reg name to offset. 827ec681f3Smrg */ 837ec681f3Smrgunsigned 847ec681f3Smrgafuc_control_reg(const char *name) 857ec681f3Smrg{ 867ec681f3Smrg return reg(control_regs, "control", name); 877ec681f3Smrg} 887ec681f3Smrg 897ec681f3Smrg/** 907ec681f3Smrg * Map offset to control reg name (or NULL), caller frees 917ec681f3Smrg */ 927ec681f3Smrgchar * 937ec681f3Smrgafuc_control_reg_name(unsigned id) 947ec681f3Smrg{ 957ec681f3Smrg return reg_name(control_regs, id); 967ec681f3Smrg} 977ec681f3Smrg 987ec681f3Smrg/** 997ec681f3Smrg * Map pipe reg name to offset. 1007ec681f3Smrg */ 1017ec681f3Smrgunsigned 1027ec681f3Smrgafuc_pipe_reg(const char *name) 1037ec681f3Smrg{ 1047ec681f3Smrg return reg(pipe_regs, "pipe", name); 1057ec681f3Smrg} 1067ec681f3Smrg 1077ec681f3Smrg/** 1087ec681f3Smrg * "void" pipe regs don't have a value written, the $addr right is 1097ec681f3Smrg * enough to trigger what they do 1107ec681f3Smrg */ 1117ec681f3Smrgbool 1127ec681f3Smrgafuc_pipe_reg_is_void(unsigned id) 1137ec681f3Smrg{ 1147ec681f3Smrg if (rnndec_checkaddr(ctx, pipe_regs, id, 0)) { 1157ec681f3Smrg struct rnndecaddrinfo *info = rnndec_decodeaddr(ctx, pipe_regs, id, 0); 1167ec681f3Smrg free(info->name); 1177ec681f3Smrg bool ret = !strcmp(info->typeinfo->name, "void"); 1187ec681f3Smrg free(info); 1197ec681f3Smrg return ret; 1207ec681f3Smrg } else { 1217ec681f3Smrg return false; 1227ec681f3Smrg } 1237ec681f3Smrg} 1247ec681f3Smrg 1257ec681f3Smrg/** 1267ec681f3Smrg * Map offset to pipe reg name (or NULL), caller frees 1277ec681f3Smrg */ 1287ec681f3Smrgchar * 1297ec681f3Smrgafuc_pipe_reg_name(unsigned id) 1307ec681f3Smrg{ 1317ec681f3Smrg return reg_name(pipe_regs, id); 1327ec681f3Smrg} 1337ec681f3Smrg 1347ec681f3Smrg/** 1357ec681f3Smrg * Map GPU reg name to offset. 1367ec681f3Smrg */ 1377ec681f3Smrgunsigned 1387ec681f3Smrgafuc_gpu_reg(const char *name) 1397ec681f3Smrg{ 1407ec681f3Smrg int val = find_reg(dom[0], name); 1417ec681f3Smrg if (val < 0) 1427ec681f3Smrg val = find_reg(dom[1], name); 1437ec681f3Smrg if (val < 0) { 1447ec681f3Smrg char *endptr = NULL; 1457ec681f3Smrg val = strtol(name, &endptr, 0); 1467ec681f3Smrg if (endptr && *endptr) { 1477ec681f3Smrg printf("invalid control reg: %s\n", name); 1487ec681f3Smrg exit(2); 1497ec681f3Smrg } 1507ec681f3Smrg } 1517ec681f3Smrg return (unsigned)val; 1527ec681f3Smrg} 1537ec681f3Smrg 1547ec681f3Smrg/** 1557ec681f3Smrg * Map offset to gpu reg name (or NULL), caller frees 1567ec681f3Smrg */ 1577ec681f3Smrgchar * 1587ec681f3Smrgafuc_gpu_reg_name(unsigned id) 1597ec681f3Smrg{ 1607ec681f3Smrg struct rnndomain *d = NULL; 1617ec681f3Smrg 1627ec681f3Smrg if (rnndec_checkaddr(ctx, dom[0], id, 0)) { 1637ec681f3Smrg d = dom[0]; 1647ec681f3Smrg } else if (rnndec_checkaddr(ctx, dom[1], id, 0)) { 1657ec681f3Smrg d = dom[1]; 1667ec681f3Smrg } 1677ec681f3Smrg 1687ec681f3Smrg if (d) { 1697ec681f3Smrg struct rnndecaddrinfo *info = rnndec_decodeaddr(ctx, d, id, 0); 1707ec681f3Smrg if (info) { 1717ec681f3Smrg char *name = info->name; 1727ec681f3Smrg free(info); 1737ec681f3Smrg return name; 1747ec681f3Smrg } 1757ec681f3Smrg } 1767ec681f3Smrg 1777ec681f3Smrg return NULL; 1787ec681f3Smrg} 1797ec681f3Smrg 1807ec681f3Smrgunsigned 1817ec681f3Smrgafuc_gpr_reg(const char *name) 1827ec681f3Smrg{ 1837ec681f3Smrg /* If it starts with '$' just swallow it: */ 1847ec681f3Smrg if (name[0] == '$') 1857ec681f3Smrg name++; 1867ec681f3Smrg 1877ec681f3Smrg /* handle aliases: */ 1887ec681f3Smrg if (!strcmp(name, "rem")) { 1897ec681f3Smrg return REG_REM; 1907ec681f3Smrg } else if (!strcmp(name, "memdata")) { 1917ec681f3Smrg return REG_MEMDATA; 1927ec681f3Smrg } else if (!strcmp(name, "addr")) { 1937ec681f3Smrg return REG_ADDR; 1947ec681f3Smrg } else if (!strcmp(name, "regdata")) { 1957ec681f3Smrg return REG_REGDATA; 1967ec681f3Smrg } else if (!strcmp(name, "usraddr")) { 1977ec681f3Smrg return REG_USRADDR; 1987ec681f3Smrg } else if (!strcmp(name, "data")) { 1997ec681f3Smrg return REG_DATA; 2007ec681f3Smrg } else { 2017ec681f3Smrg char *endptr = NULL; 2027ec681f3Smrg unsigned val = strtol(name, &endptr, 16); 2037ec681f3Smrg if (endptr && *endptr) { 2047ec681f3Smrg printf("invalid gpr reg: %s\n", name); 2057ec681f3Smrg exit(2); 2067ec681f3Smrg } 2077ec681f3Smrg return val; 2087ec681f3Smrg } 2097ec681f3Smrg} 2107ec681f3Smrg 2117ec681f3Smrgstatic int 2127ec681f3Smrgfind_enum_val(struct rnnenum *en, const char *name) 2137ec681f3Smrg{ 2147ec681f3Smrg int i; 2157ec681f3Smrg 2167ec681f3Smrg for (i = 0; i < en->valsnum; i++) 2177ec681f3Smrg if (en->vals[i]->valvalid && !strcmp(name, en->vals[i]->name)) 2187ec681f3Smrg return en->vals[i]->value; 2197ec681f3Smrg 2207ec681f3Smrg return -1; 2217ec681f3Smrg} 2227ec681f3Smrg 2237ec681f3Smrg/** 2247ec681f3Smrg * Map pm4 packet name to id 2257ec681f3Smrg */ 2267ec681f3Smrgint 2277ec681f3Smrgafuc_pm4_id(const char *name) 2287ec681f3Smrg{ 2297ec681f3Smrg return find_enum_val(pm4_packets, name); 2307ec681f3Smrg} 2317ec681f3Smrg 2327ec681f3Smrgconst char * 2337ec681f3Smrgafuc_pm_id_name(unsigned id) 2347ec681f3Smrg{ 2357ec681f3Smrg return rnndec_decode_enum(ctx, "adreno_pm4_type3_packets", id); 2367ec681f3Smrg} 2377ec681f3Smrg 2387ec681f3Smrgvoid 2397ec681f3Smrgafuc_printc(enum afuc_color c, const char *fmt, ...) 2407ec681f3Smrg{ 2417ec681f3Smrg va_list args; 2427ec681f3Smrg if (c == AFUC_ERR) { 2437ec681f3Smrg printf("%s", ctx->colors->err); 2447ec681f3Smrg } else if (c == AFUC_LBL) { 2457ec681f3Smrg printf("%s", ctx->colors->btarg); 2467ec681f3Smrg } 2477ec681f3Smrg va_start(args, fmt); 2487ec681f3Smrg vprintf(fmt, args); 2497ec681f3Smrg va_end(args); 2507ec681f3Smrg printf("%s", ctx->colors->reset); 2517ec681f3Smrg} 2527ec681f3Smrg 2537ec681f3Smrgint afuc_util_init(int gpuver, bool colors) 2547ec681f3Smrg{ 2557ec681f3Smrg char *name, *control_reg_name; 2567ec681f3Smrg char *pipe_reg_name = NULL; 2577ec681f3Smrg 2587ec681f3Smrg switch (gpuver) { 2597ec681f3Smrg case 6: 2607ec681f3Smrg name = "A6XX"; 2617ec681f3Smrg control_reg_name = "A6XX_CONTROL_REG"; 2627ec681f3Smrg pipe_reg_name = "A6XX_PIPE_REG"; 2637ec681f3Smrg break; 2647ec681f3Smrg case 5: 2657ec681f3Smrg name = "A5XX"; 2667ec681f3Smrg control_reg_name = "A5XX_CONTROL_REG"; 2677ec681f3Smrg pipe_reg_name = "A5XX_PIPE_REG"; 2687ec681f3Smrg break; 2697ec681f3Smrg default: 2707ec681f3Smrg fprintf(stderr, "unknown GPU version!\n"); 2717ec681f3Smrg return -1; 2727ec681f3Smrg } 2737ec681f3Smrg 2747ec681f3Smrg rnn_init(); 2757ec681f3Smrg db = rnn_newdb(); 2767ec681f3Smrg 2777ec681f3Smrg ctx = rnndec_newcontext(db); 2787ec681f3Smrg ctx->colors = colors ? &envy_def_colors : &envy_null_colors; 2797ec681f3Smrg 2807ec681f3Smrg rnn_parsefile(db, "adreno.xml"); 2817ec681f3Smrg rnn_prepdb(db); 2827ec681f3Smrg if (db->estatus) 2837ec681f3Smrg errx(db->estatus, "failed to parse register database"); 2847ec681f3Smrg dom[0] = rnn_finddomain(db, name); 2857ec681f3Smrg dom[1] = rnn_finddomain(db, "AXXX"); 2867ec681f3Smrg control_regs = rnn_finddomain(db, control_reg_name); 2877ec681f3Smrg pipe_regs = rnn_finddomain(db, pipe_reg_name); 2887ec681f3Smrg 2897ec681f3Smrg rnndec_varadd(ctx, "chip", name); 2907ec681f3Smrg 2917ec681f3Smrg pm4_packets = rnn_findenum(ctx->db, "adreno_pm4_type3_packets"); 2927ec681f3Smrg 2937ec681f3Smrg return 0; 2947ec681f3Smrg} 2957ec681f3Smrg 296