script.c revision 7ec681f3
17ec681f3Smrg/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
27ec681f3Smrg
37ec681f3Smrg/*
47ec681f3Smrg * Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
57ec681f3Smrg *
67ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a
77ec681f3Smrg * copy of this software and associated documentation files (the "Software"),
87ec681f3Smrg * to deal in the Software without restriction, including without limitation
97ec681f3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
107ec681f3Smrg * and/or sell copies of the Software, and to permit persons to whom the
117ec681f3Smrg * Software is furnished to do so, subject to the following conditions:
127ec681f3Smrg *
137ec681f3Smrg * The above copyright notice and this permission notice (including the next
147ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the
157ec681f3Smrg * Software.
167ec681f3Smrg *
177ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
187ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
197ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
207ec681f3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
217ec681f3Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
227ec681f3Smrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
237ec681f3Smrg * SOFTWARE.
247ec681f3Smrg *
257ec681f3Smrg * Authors:
267ec681f3Smrg *    Rob Clark <robclark@freedesktop.org>
277ec681f3Smrg */
287ec681f3Smrg
297ec681f3Smrg#define LUA_COMPAT_APIINTCASTS
307ec681f3Smrg
317ec681f3Smrg#include <assert.h>
327ec681f3Smrg#include <lauxlib.h>
337ec681f3Smrg#include <lua.h>
347ec681f3Smrg#include <lualib.h>
357ec681f3Smrg#include <stdio.h>
367ec681f3Smrg#include <stdlib.h>
377ec681f3Smrg#include <string.h>
387ec681f3Smrg
397ec681f3Smrg#include "cffdec.h"
407ec681f3Smrg#include "rnnutil.h"
417ec681f3Smrg#include "script.h"
427ec681f3Smrg
437ec681f3Smrgstatic lua_State *L;
447ec681f3Smrg
457ec681f3Smrg#if 0
467ec681f3Smrg#define DBG(fmt, ...)                                                          \
477ec681f3Smrg   do {                                                                        \
487ec681f3Smrg      printf(" ** %s:%d ** " fmt "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__); \
497ec681f3Smrg   } while (0)
507ec681f3Smrg#else
517ec681f3Smrg#define DBG(fmt, ...)                                                          \
527ec681f3Smrg   do {                                                                        \
537ec681f3Smrg   } while (0)
547ec681f3Smrg#endif
557ec681f3Smrg
567ec681f3Smrg/* An rnn based decoder, which can either be decoding current register
577ec681f3Smrg * values, or domain based decoding of a pm4 packet.
587ec681f3Smrg *
597ec681f3Smrg */
607ec681f3Smrgstruct rnndec {
617ec681f3Smrg   struct rnn base;
627ec681f3Smrg
637ec681f3Smrg   /* for pm4 packet decoding: */
647ec681f3Smrg   uint32_t sizedwords;
657ec681f3Smrg   uint32_t *dwords;
667ec681f3Smrg};
677ec681f3Smrg
687ec681f3Smrgstatic inline struct rnndec *
697ec681f3Smrgto_rnndec(struct rnn *rnn)
707ec681f3Smrg{
717ec681f3Smrg   return (struct rnndec *)rnn;
727ec681f3Smrg}
737ec681f3Smrg
747ec681f3Smrgstatic uint32_t
757ec681f3Smrgrnn_val(struct rnn *rnn, uint32_t regbase)
767ec681f3Smrg{
777ec681f3Smrg   struct rnndec *rnndec = to_rnndec(rnn);
787ec681f3Smrg
797ec681f3Smrg   if (!rnndec->sizedwords) {
807ec681f3Smrg      return reg_val(regbase);
817ec681f3Smrg   } else if (regbase < rnndec->sizedwords) {
827ec681f3Smrg      return rnndec->dwords[regbase];
837ec681f3Smrg   } else {
847ec681f3Smrg      // XXX throw an error
857ec681f3Smrg      return -1;
867ec681f3Smrg   }
877ec681f3Smrg}
887ec681f3Smrg
897ec681f3Smrg/* does not return */
907ec681f3Smrgstatic void
917ec681f3Smrgerror(const char *fmt)
927ec681f3Smrg{
937ec681f3Smrg   fprintf(stderr, fmt, lua_tostring(L, -1));
947ec681f3Smrg   exit(1);
957ec681f3Smrg}
967ec681f3Smrg
977ec681f3Smrg/*
987ec681f3Smrg * An enum type that can be used as string or number:
997ec681f3Smrg */
1007ec681f3Smrg
1017ec681f3Smrgstruct rnndenum {
1027ec681f3Smrg   const char *str;
1037ec681f3Smrg   int val;
1047ec681f3Smrg};
1057ec681f3Smrg
1067ec681f3Smrgstatic int
1077ec681f3Smrgl_meta_rnn_enum_tostring(lua_State *L)
1087ec681f3Smrg{
1097ec681f3Smrg   struct rnndenum *e = lua_touserdata(L, 1);
1107ec681f3Smrg   if (e->str) {
1117ec681f3Smrg      lua_pushstring(L, e->str);
1127ec681f3Smrg   } else {
1137ec681f3Smrg      char buf[32];
1147ec681f3Smrg      sprintf(buf, "%u", e->val);
1157ec681f3Smrg      lua_pushstring(L, buf);
1167ec681f3Smrg   }
1177ec681f3Smrg   return 1;
1187ec681f3Smrg}
1197ec681f3Smrg
1207ec681f3Smrg/* so, this doesn't actually seem to be implemented yet, but hopefully
1217ec681f3Smrg * some day lua comes to it's senses
1227ec681f3Smrg */
1237ec681f3Smrgstatic int
1247ec681f3Smrgl_meta_rnn_enum_tonumber(lua_State *L)
1257ec681f3Smrg{
1267ec681f3Smrg   struct rnndenum *e = lua_touserdata(L, 1);
1277ec681f3Smrg   lua_pushinteger(L, e->val);
1287ec681f3Smrg   return 1;
1297ec681f3Smrg}
1307ec681f3Smrg
1317ec681f3Smrgstatic const struct luaL_Reg l_meta_rnn_enum[] = {
1327ec681f3Smrg   {"__tostring", l_meta_rnn_enum_tostring},
1337ec681f3Smrg   {"__tonumber", l_meta_rnn_enum_tonumber},
1347ec681f3Smrg   {NULL, NULL} /* sentinel */
1357ec681f3Smrg};
1367ec681f3Smrg
1377ec681f3Smrgstatic void
1387ec681f3Smrgpushenum(struct lua_State *L, int val, struct rnnenum *info)
1397ec681f3Smrg{
1407ec681f3Smrg   struct rnndenum *e = lua_newuserdata(L, sizeof(*e));
1417ec681f3Smrg
1427ec681f3Smrg   e->val = val;
1437ec681f3Smrg   e->str = NULL;
1447ec681f3Smrg
1457ec681f3Smrg   for (int i = 0; i < info->valsnum; i++) {
1467ec681f3Smrg      if (info->vals[i]->valvalid && (info->vals[i]->value == val)) {
1477ec681f3Smrg         e->str = info->vals[i]->name;
1487ec681f3Smrg         break;
1497ec681f3Smrg      }
1507ec681f3Smrg   }
1517ec681f3Smrg
1527ec681f3Smrg   luaL_newmetatable(L, "rnnmetaenum");
1537ec681f3Smrg   luaL_setfuncs(L, l_meta_rnn_enum, 0);
1547ec681f3Smrg   lua_pop(L, 1);
1557ec681f3Smrg
1567ec681f3Smrg   luaL_setmetatable(L, "rnnmetaenum");
1577ec681f3Smrg}
1587ec681f3Smrg
1597ec681f3Smrg/* Expose rnn decode to script environment as "rnn" library:
1607ec681f3Smrg */
1617ec681f3Smrg
1627ec681f3Smrgstruct rnndoff {
1637ec681f3Smrg   struct rnn *rnn;
1647ec681f3Smrg   struct rnndelem *elem;
1657ec681f3Smrg   uint64_t offset;
1667ec681f3Smrg};
1677ec681f3Smrg
1687ec681f3Smrgstatic void
1697ec681f3Smrgpush_rnndoff(lua_State *L, struct rnn *rnn, struct rnndelem *elem,
1707ec681f3Smrg             uint64_t offset)
1717ec681f3Smrg{
1727ec681f3Smrg   struct rnndoff *rnndoff = lua_newuserdata(L, sizeof(*rnndoff));
1737ec681f3Smrg   rnndoff->rnn = rnn;
1747ec681f3Smrg   rnndoff->elem = elem;
1757ec681f3Smrg   rnndoff->offset = offset;
1767ec681f3Smrg}
1777ec681f3Smrg
1787ec681f3Smrgstatic int l_rnn_etype_array(lua_State *L, struct rnn *rnn,
1797ec681f3Smrg                             struct rnndelem *elem, uint64_t offset);
1807ec681f3Smrgstatic int l_rnn_etype_reg(lua_State *L, struct rnn *rnn, struct rnndelem *elem,
1817ec681f3Smrg                           uint64_t offset);
1827ec681f3Smrg
1837ec681f3Smrgstatic int
1847ec681f3Smrgpushdecval(struct lua_State *L, struct rnn *rnn, uint32_t regval,
1857ec681f3Smrg           struct rnntypeinfo *info)
1867ec681f3Smrg{
1877ec681f3Smrg   union rnndecval val;
1887ec681f3Smrg   switch (rnn_decodelem(rnn, info, regval, &val)) {
1897ec681f3Smrg   case RNN_TTYPE_ENUM:
1907ec681f3Smrg   case RNN_TTYPE_INLINE_ENUM:
1917ec681f3Smrg      pushenum(L, val.i, info->eenum);
1927ec681f3Smrg      return 1;
1937ec681f3Smrg   case RNN_TTYPE_INT:
1947ec681f3Smrg      lua_pushinteger(L, val.i);
1957ec681f3Smrg      return 1;
1967ec681f3Smrg   case RNN_TTYPE_UINT:
1977ec681f3Smrg   case RNN_TTYPE_HEX:
1987ec681f3Smrg      lua_pushunsigned(L, val.u);
1997ec681f3Smrg      return 1;
2007ec681f3Smrg   case RNN_TTYPE_FLOAT:
2017ec681f3Smrg      lua_pushnumber(L, val.f);
2027ec681f3Smrg      return 1;
2037ec681f3Smrg   case RNN_TTYPE_BOOLEAN:
2047ec681f3Smrg      lua_pushboolean(L, val.u);
2057ec681f3Smrg      return 1;
2067ec681f3Smrg   case RNN_TTYPE_INVALID:
2077ec681f3Smrg   default:
2087ec681f3Smrg      return 0;
2097ec681f3Smrg   }
2107ec681f3Smrg}
2117ec681f3Smrg
2127ec681f3Smrgstatic int
2137ec681f3Smrgl_rnn_etype(lua_State *L, struct rnn *rnn, struct rnndelem *elem,
2147ec681f3Smrg            uint64_t offset)
2157ec681f3Smrg{
2167ec681f3Smrg   int ret;
2177ec681f3Smrg   uint32_t regval;
2187ec681f3Smrg   DBG("elem=%p (%d), offset=%lu", elem, elem->type, offset);
2197ec681f3Smrg   switch (elem->type) {
2207ec681f3Smrg   case RNN_ETYPE_REG:
2217ec681f3Smrg      /* if a register has no bitfields, just return
2227ec681f3Smrg       * the raw value:
2237ec681f3Smrg       */
2247ec681f3Smrg      regval = rnn_val(rnn, offset);
2257ec681f3Smrg      regval <<= elem->typeinfo.shr;
2267ec681f3Smrg      ret = pushdecval(L, rnn, regval, &elem->typeinfo);
2277ec681f3Smrg      if (ret)
2287ec681f3Smrg         return ret;
2297ec681f3Smrg      return l_rnn_etype_reg(L, rnn, elem, offset);
2307ec681f3Smrg   case RNN_ETYPE_ARRAY:
2317ec681f3Smrg      return l_rnn_etype_array(L, rnn, elem, offset);
2327ec681f3Smrg   default:
2337ec681f3Smrg      /* hmm.. */
2347ec681f3Smrg      printf("unhandled type: %d\n", elem->type);
2357ec681f3Smrg      return 0;
2367ec681f3Smrg   }
2377ec681f3Smrg}
2387ec681f3Smrg
2397ec681f3Smrg/*
2407ec681f3Smrg * Struct Object:
2417ec681f3Smrg * To implement stuff like 'RB_MRT[n].CONTROL' we need a struct-object
2427ec681f3Smrg * to represent the current array index (ie. 'RB_MRT[n]')
2437ec681f3Smrg */
2447ec681f3Smrg
2457ec681f3Smrgstatic int
2467ec681f3Smrgl_rnn_struct_meta_index(lua_State *L)
2477ec681f3Smrg{
2487ec681f3Smrg   struct rnndoff *rnndoff = lua_touserdata(L, 1);
2497ec681f3Smrg   const char *name = lua_tostring(L, 2);
2507ec681f3Smrg   struct rnndelem *elem = rnndoff->elem;
2517ec681f3Smrg   int i;
2527ec681f3Smrg
2537ec681f3Smrg   for (i = 0; i < elem->subelemsnum; i++) {
2547ec681f3Smrg      struct rnndelem *subelem = elem->subelems[i];
2557ec681f3Smrg      if (!strcmp(name, subelem->name)) {
2567ec681f3Smrg         return l_rnn_etype(L, rnndoff->rnn, subelem,
2577ec681f3Smrg                            rnndoff->offset + subelem->offset);
2587ec681f3Smrg      }
2597ec681f3Smrg   }
2607ec681f3Smrg
2617ec681f3Smrg   return 0;
2627ec681f3Smrg}
2637ec681f3Smrg
2647ec681f3Smrgstatic const struct luaL_Reg l_meta_rnn_struct[] = {
2657ec681f3Smrg   {"__index", l_rnn_struct_meta_index}, {NULL, NULL} /* sentinel */
2667ec681f3Smrg};
2677ec681f3Smrg
2687ec681f3Smrgstatic int
2697ec681f3Smrgl_rnn_etype_struct(lua_State *L, struct rnn *rnn, struct rnndelem *elem,
2707ec681f3Smrg                   uint64_t offset)
2717ec681f3Smrg{
2727ec681f3Smrg   push_rnndoff(L, rnn, elem, offset);
2737ec681f3Smrg
2747ec681f3Smrg   luaL_newmetatable(L, "rnnmetastruct");
2757ec681f3Smrg   luaL_setfuncs(L, l_meta_rnn_struct, 0);
2767ec681f3Smrg   lua_pop(L, 1);
2777ec681f3Smrg
2787ec681f3Smrg   luaL_setmetatable(L, "rnnmetastruct");
2797ec681f3Smrg
2807ec681f3Smrg   return 1;
2817ec681f3Smrg}
2827ec681f3Smrg
2837ec681f3Smrg/*
2847ec681f3Smrg * Array Object:
2857ec681f3Smrg */
2867ec681f3Smrg
2877ec681f3Smrgstatic int
2887ec681f3Smrgl_rnn_array_meta_index(lua_State *L)
2897ec681f3Smrg{
2907ec681f3Smrg   struct rnndoff *rnndoff = lua_touserdata(L, 1);
2917ec681f3Smrg   int idx = lua_tointeger(L, 2);
2927ec681f3Smrg   struct rnndelem *elem = rnndoff->elem;
2937ec681f3Smrg   uint64_t offset = rnndoff->offset + (elem->stride * idx);
2947ec681f3Smrg
2957ec681f3Smrg   DBG("rnndoff=%p, idx=%d, numsubelems=%d", rnndoff, idx,
2967ec681f3Smrg       rnndoff->elem->subelemsnum);
2977ec681f3Smrg
2987ec681f3Smrg   /* if just a single sub-element, it is directly a register,
2997ec681f3Smrg    * otherwise we need to accumulate the array index while
3007ec681f3Smrg    * we wait for the register name within the array..
3017ec681f3Smrg    */
3027ec681f3Smrg   if (elem->subelemsnum == 1) {
3037ec681f3Smrg      return l_rnn_etype(L, rnndoff->rnn, elem->subelems[0], offset);
3047ec681f3Smrg   } else {
3057ec681f3Smrg      return l_rnn_etype_struct(L, rnndoff->rnn, elem, offset);
3067ec681f3Smrg   }
3077ec681f3Smrg
3087ec681f3Smrg   return 0;
3097ec681f3Smrg}
3107ec681f3Smrg
3117ec681f3Smrgstatic const struct luaL_Reg l_meta_rnn_array[] = {
3127ec681f3Smrg   {"__index", l_rnn_array_meta_index}, {NULL, NULL} /* sentinel */
3137ec681f3Smrg};
3147ec681f3Smrg
3157ec681f3Smrgstatic int
3167ec681f3Smrgl_rnn_etype_array(lua_State *L, struct rnn *rnn, struct rnndelem *elem,
3177ec681f3Smrg                  uint64_t offset)
3187ec681f3Smrg{
3197ec681f3Smrg   push_rnndoff(L, rnn, elem, offset);
3207ec681f3Smrg
3217ec681f3Smrg   luaL_newmetatable(L, "rnnmetaarray");
3227ec681f3Smrg   luaL_setfuncs(L, l_meta_rnn_array, 0);
3237ec681f3Smrg   lua_pop(L, 1);
3247ec681f3Smrg
3257ec681f3Smrg   luaL_setmetatable(L, "rnnmetaarray");
3267ec681f3Smrg
3277ec681f3Smrg   return 1;
3287ec681f3Smrg}
3297ec681f3Smrg
3307ec681f3Smrg/*
3317ec681f3Smrg * Register element:
3327ec681f3Smrg */
3337ec681f3Smrg
3347ec681f3Smrgstatic int
3357ec681f3Smrgl_rnn_reg_meta_index(lua_State *L)
3367ec681f3Smrg{
3377ec681f3Smrg   struct rnndoff *rnndoff = lua_touserdata(L, 1);
3387ec681f3Smrg   const char *name = lua_tostring(L, 2);
3397ec681f3Smrg   struct rnndelem *elem = rnndoff->elem;
3407ec681f3Smrg   struct rnntypeinfo *info = &elem->typeinfo;
3417ec681f3Smrg   struct rnnbitfield **bitfields;
3427ec681f3Smrg   int bitfieldsnum;
3437ec681f3Smrg   int i;
3447ec681f3Smrg
3457ec681f3Smrg   switch (info->type) {
3467ec681f3Smrg   case RNN_TTYPE_BITSET:
3477ec681f3Smrg      bitfields = info->ebitset->bitfields;
3487ec681f3Smrg      bitfieldsnum = info->ebitset->bitfieldsnum;
3497ec681f3Smrg      break;
3507ec681f3Smrg   case RNN_TTYPE_INLINE_BITSET:
3517ec681f3Smrg      bitfields = info->bitfields;
3527ec681f3Smrg      bitfieldsnum = info->bitfieldsnum;
3537ec681f3Smrg      break;
3547ec681f3Smrg   default:
3557ec681f3Smrg      printf("invalid register type: %d\n", info->type);
3567ec681f3Smrg      return 0;
3577ec681f3Smrg   }
3587ec681f3Smrg
3597ec681f3Smrg   for (i = 0; i < bitfieldsnum; i++) {
3607ec681f3Smrg      struct rnnbitfield *bf = bitfields[i];
3617ec681f3Smrg      if (!strcmp(name, bf->name)) {
3627ec681f3Smrg         uint32_t regval = rnn_val(rnndoff->rnn, rnndoff->offset);
3637ec681f3Smrg
3647ec681f3Smrg         regval &= typeinfo_mask(&bf->typeinfo);
3657ec681f3Smrg         regval >>= bf->typeinfo.low;
3667ec681f3Smrg         regval <<= bf->typeinfo.shr;
3677ec681f3Smrg
3687ec681f3Smrg         DBG("name=%s, info=%p, subelemsnum=%d, type=%d, regval=%x", name, info,
3697ec681f3Smrg             rnndoff->elem->subelemsnum, bf->typeinfo.type, regval);
3707ec681f3Smrg
3717ec681f3Smrg         return pushdecval(L, rnndoff->rnn, regval, &bf->typeinfo);
3727ec681f3Smrg      }
3737ec681f3Smrg   }
3747ec681f3Smrg
3757ec681f3Smrg   printf("invalid member: %s\n", name);
3767ec681f3Smrg   return 0;
3777ec681f3Smrg}
3787ec681f3Smrg
3797ec681f3Smrgstatic int
3807ec681f3Smrgl_rnn_reg_meta_tostring(lua_State *L)
3817ec681f3Smrg{
3827ec681f3Smrg   struct rnndoff *rnndoff = lua_touserdata(L, 1);
3837ec681f3Smrg   uint32_t regval = rnn_val(rnndoff->rnn, rnndoff->offset);
3847ec681f3Smrg   struct rnndecaddrinfo *info = rnn_reginfo(rnndoff->rnn, rnndoff->offset);
3857ec681f3Smrg   char *decoded;
3867ec681f3Smrg   if (info && info->typeinfo) {
3877ec681f3Smrg      decoded = rnndec_decodeval(rnndoff->rnn->vc, info->typeinfo, regval);
3887ec681f3Smrg   } else {
3897ec681f3Smrg      asprintf(&decoded, "%08x", regval);
3907ec681f3Smrg   }
3917ec681f3Smrg   lua_pushstring(L, decoded);
3927ec681f3Smrg   free(decoded);
3937ec681f3Smrg   if (info) {
3947ec681f3Smrg      free(info->name);
3957ec681f3Smrg      free(info);
3967ec681f3Smrg   }
3977ec681f3Smrg   return 1;
3987ec681f3Smrg}
3997ec681f3Smrg
4007ec681f3Smrgstatic int
4017ec681f3Smrgl_rnn_reg_meta_tonumber(lua_State *L)
4027ec681f3Smrg{
4037ec681f3Smrg   struct rnndoff *rnndoff = lua_touserdata(L, 1);
4047ec681f3Smrg   uint32_t regval = rnn_val(rnndoff->rnn, rnndoff->offset);
4057ec681f3Smrg
4067ec681f3Smrg   regval <<= rnndoff->elem->typeinfo.shr;
4077ec681f3Smrg
4087ec681f3Smrg   lua_pushnumber(L, regval);
4097ec681f3Smrg   return 1;
4107ec681f3Smrg}
4117ec681f3Smrg
4127ec681f3Smrgstatic const struct luaL_Reg l_meta_rnn_reg[] = {
4137ec681f3Smrg   {"__index", l_rnn_reg_meta_index},
4147ec681f3Smrg   {"__tostring", l_rnn_reg_meta_tostring},
4157ec681f3Smrg   {"__tonumber", l_rnn_reg_meta_tonumber},
4167ec681f3Smrg   {NULL, NULL} /* sentinel */
4177ec681f3Smrg};
4187ec681f3Smrg
4197ec681f3Smrgstatic int
4207ec681f3Smrgl_rnn_etype_reg(lua_State *L, struct rnn *rnn, struct rnndelem *elem,
4217ec681f3Smrg                uint64_t offset)
4227ec681f3Smrg{
4237ec681f3Smrg   push_rnndoff(L, rnn, elem, offset);
4247ec681f3Smrg
4257ec681f3Smrg   luaL_newmetatable(L, "rnnmetareg");
4267ec681f3Smrg   luaL_setfuncs(L, l_meta_rnn_reg, 0);
4277ec681f3Smrg   lua_pop(L, 1);
4287ec681f3Smrg
4297ec681f3Smrg   luaL_setmetatable(L, "rnnmetareg");
4307ec681f3Smrg
4317ec681f3Smrg   return 1;
4327ec681f3Smrg}
4337ec681f3Smrg
4347ec681f3Smrg/*
4357ec681f3Smrg *
4367ec681f3Smrg */
4377ec681f3Smrg
4387ec681f3Smrgstatic int
4397ec681f3Smrgl_rnn_meta_index(lua_State *L)
4407ec681f3Smrg{
4417ec681f3Smrg   struct rnn *rnn = lua_touserdata(L, 1);
4427ec681f3Smrg   const char *name = lua_tostring(L, 2);
4437ec681f3Smrg   struct rnndelem *elem;
4447ec681f3Smrg
4457ec681f3Smrg   elem = rnn_regelem(rnn, name);
4467ec681f3Smrg   if (!elem)
4477ec681f3Smrg      return 0;
4487ec681f3Smrg
4497ec681f3Smrg   return l_rnn_etype(L, rnn, elem, elem->offset);
4507ec681f3Smrg}
4517ec681f3Smrg
4527ec681f3Smrgstatic int
4537ec681f3Smrgl_rnn_meta_gc(lua_State *L)
4547ec681f3Smrg{
4557ec681f3Smrg   // TODO
4567ec681f3Smrg   // struct rnn *rnn = lua_touserdata(L, 1);
4577ec681f3Smrg   // rnn_deinit(rnn);
4587ec681f3Smrg   return 0;
4597ec681f3Smrg}
4607ec681f3Smrg
4617ec681f3Smrgstatic const struct luaL_Reg l_meta_rnn[] = {
4627ec681f3Smrg   {"__index", l_rnn_meta_index},
4637ec681f3Smrg   {"__gc", l_rnn_meta_gc},
4647ec681f3Smrg   {NULL, NULL} /* sentinel */
4657ec681f3Smrg};
4667ec681f3Smrg
4677ec681f3Smrgstatic int
4687ec681f3Smrgl_rnn_init(lua_State *L)
4697ec681f3Smrg{
4707ec681f3Smrg   const char *gpuname = lua_tostring(L, 1);
4717ec681f3Smrg   struct rnndec *rnndec = lua_newuserdata(L, sizeof(*rnndec));
4727ec681f3Smrg   _rnn_init(&rnndec->base, 0);
4737ec681f3Smrg   rnn_load(&rnndec->base, gpuname);
4747ec681f3Smrg   rnndec->sizedwords = 0;
4757ec681f3Smrg
4767ec681f3Smrg   luaL_newmetatable(L, "rnnmeta");
4777ec681f3Smrg   luaL_setfuncs(L, l_meta_rnn, 0);
4787ec681f3Smrg   lua_pop(L, 1);
4797ec681f3Smrg
4807ec681f3Smrg   luaL_setmetatable(L, "rnnmeta");
4817ec681f3Smrg
4827ec681f3Smrg   return 1;
4837ec681f3Smrg}
4847ec681f3Smrg
4857ec681f3Smrgstatic int
4867ec681f3Smrgl_rnn_enumname(lua_State *L)
4877ec681f3Smrg{
4887ec681f3Smrg   struct rnn *rnn = lua_touserdata(L, 1);
4897ec681f3Smrg   const char *name = lua_tostring(L, 2);
4907ec681f3Smrg   uint32_t val = (uint32_t)lua_tonumber(L, 3);
4917ec681f3Smrg   lua_pushstring(L, rnn_enumname(rnn, name, val));
4927ec681f3Smrg   return 1;
4937ec681f3Smrg}
4947ec681f3Smrg
4957ec681f3Smrgstatic int
4967ec681f3Smrgl_rnn_regname(lua_State *L)
4977ec681f3Smrg{
4987ec681f3Smrg   struct rnn *rnn = lua_touserdata(L, 1);
4997ec681f3Smrg   uint32_t regbase = (uint32_t)lua_tonumber(L, 2);
5007ec681f3Smrg   lua_pushstring(L, rnn_regname(rnn, regbase, 1));
5017ec681f3Smrg   return 1;
5027ec681f3Smrg}
5037ec681f3Smrg
5047ec681f3Smrgstatic int
5057ec681f3Smrgl_rnn_regval(lua_State *L)
5067ec681f3Smrg{
5077ec681f3Smrg   struct rnn *rnn = lua_touserdata(L, 1);
5087ec681f3Smrg   uint32_t regbase = (uint32_t)lua_tonumber(L, 2);
5097ec681f3Smrg   uint32_t regval = (uint32_t)lua_tonumber(L, 3);
5107ec681f3Smrg   struct rnndecaddrinfo *info = rnn_reginfo(rnn, regbase);
5117ec681f3Smrg   char *decoded;
5127ec681f3Smrg   if (info && info->typeinfo) {
5137ec681f3Smrg      decoded = rnndec_decodeval(rnn->vc, info->typeinfo, regval);
5147ec681f3Smrg   } else {
5157ec681f3Smrg      asprintf(&decoded, "%08x", regval);
5167ec681f3Smrg   }
5177ec681f3Smrg   lua_pushstring(L, decoded);
5187ec681f3Smrg   free(decoded);
5197ec681f3Smrg   if (info) {
5207ec681f3Smrg      free(info->name);
5217ec681f3Smrg      free(info);
5227ec681f3Smrg   }
5237ec681f3Smrg   return 1;
5247ec681f3Smrg}
5257ec681f3Smrg
5267ec681f3Smrgstatic const struct luaL_Reg l_rnn[] = {
5277ec681f3Smrg   {"init", l_rnn_init},
5287ec681f3Smrg   {"enumname", l_rnn_enumname},
5297ec681f3Smrg   {"regname", l_rnn_regname},
5307ec681f3Smrg   {"regval", l_rnn_regval},
5317ec681f3Smrg   {NULL, NULL} /* sentinel */
5327ec681f3Smrg};
5337ec681f3Smrg
5347ec681f3Smrg/* Expose the register state to script enviroment as a "regs" library:
5357ec681f3Smrg */
5367ec681f3Smrg
5377ec681f3Smrgstatic int
5387ec681f3Smrgl_reg_written(lua_State *L)
5397ec681f3Smrg{
5407ec681f3Smrg   uint32_t regbase = (uint32_t)lua_tonumber(L, 1);
5417ec681f3Smrg   lua_pushnumber(L, reg_written(regbase));
5427ec681f3Smrg   return 1;
5437ec681f3Smrg}
5447ec681f3Smrg
5457ec681f3Smrgstatic int
5467ec681f3Smrgl_reg_lastval(lua_State *L)
5477ec681f3Smrg{
5487ec681f3Smrg   uint32_t regbase = (uint32_t)lua_tonumber(L, 1);
5497ec681f3Smrg   lua_pushnumber(L, reg_lastval(regbase));
5507ec681f3Smrg   return 1;
5517ec681f3Smrg}
5527ec681f3Smrg
5537ec681f3Smrgstatic int
5547ec681f3Smrgl_reg_val(lua_State *L)
5557ec681f3Smrg{
5567ec681f3Smrg   uint32_t regbase = (uint32_t)lua_tonumber(L, 1);
5577ec681f3Smrg   lua_pushnumber(L, reg_val(regbase));
5587ec681f3Smrg   return 1;
5597ec681f3Smrg}
5607ec681f3Smrg
5617ec681f3Smrgstatic const struct luaL_Reg l_regs[] = {
5627ec681f3Smrg   {"written", l_reg_written},
5637ec681f3Smrg   {"lastval", l_reg_lastval},
5647ec681f3Smrg   {"val", l_reg_val},
5657ec681f3Smrg   {NULL, NULL} /* sentinel */
5667ec681f3Smrg};
5677ec681f3Smrg
5687ec681f3Smrg/* Expose API to lookup snapshot buffers:
5697ec681f3Smrg */
5707ec681f3Smrg
5717ec681f3Smrguint64_t gpubaseaddr(uint64_t gpuaddr);
5727ec681f3Smrgunsigned hostlen(uint64_t gpuaddr);
5737ec681f3Smrg
5747ec681f3Smrg/* given address, return base-address of buffer: */
5757ec681f3Smrgstatic int
5767ec681f3Smrgl_bo_base(lua_State *L)
5777ec681f3Smrg{
5787ec681f3Smrg   uint64_t addr = (uint64_t)lua_tonumber(L, 1);
5797ec681f3Smrg   lua_pushnumber(L, gpubaseaddr(addr));
5807ec681f3Smrg   return 1;
5817ec681f3Smrg}
5827ec681f3Smrg
5837ec681f3Smrg/* given address, return the remaining size of the buffer: */
5847ec681f3Smrgstatic int
5857ec681f3Smrgl_bo_size(lua_State *L)
5867ec681f3Smrg{
5877ec681f3Smrg   uint64_t addr = (uint64_t)lua_tonumber(L, 1);
5887ec681f3Smrg   lua_pushnumber(L, hostlen(addr));
5897ec681f3Smrg   return 1;
5907ec681f3Smrg}
5917ec681f3Smrg
5927ec681f3Smrgstatic const struct luaL_Reg l_bos[] = {
5937ec681f3Smrg   {"base", l_bo_base}, {"size", l_bo_size}, {NULL, NULL} /* sentinel */
5947ec681f3Smrg};
5957ec681f3Smrg
5967ec681f3Smrgstatic void
5977ec681f3Smrgopenlib(const char *lib, const luaL_Reg *reg)
5987ec681f3Smrg{
5997ec681f3Smrg   lua_newtable(L);
6007ec681f3Smrg   luaL_setfuncs(L, reg, 0);
6017ec681f3Smrg   lua_setglobal(L, lib);
6027ec681f3Smrg}
6037ec681f3Smrg
6047ec681f3Smrg/* called at start to load the script: */
6057ec681f3Smrgint
6067ec681f3Smrgscript_load(const char *file)
6077ec681f3Smrg{
6087ec681f3Smrg   int ret;
6097ec681f3Smrg
6107ec681f3Smrg   assert(!L);
6117ec681f3Smrg
6127ec681f3Smrg   L = luaL_newstate();
6137ec681f3Smrg   luaL_openlibs(L);
6147ec681f3Smrg   openlib("bos", l_bos);
6157ec681f3Smrg   openlib("regs", l_regs);
6167ec681f3Smrg   openlib("rnn", l_rnn);
6177ec681f3Smrg
6187ec681f3Smrg   ret = luaL_loadfile(L, file);
6197ec681f3Smrg   if (ret)
6207ec681f3Smrg      error("%s\n");
6217ec681f3Smrg
6227ec681f3Smrg   ret = lua_pcall(L, 0, LUA_MULTRET, 0);
6237ec681f3Smrg   if (ret)
6247ec681f3Smrg      error("%s\n");
6257ec681f3Smrg
6267ec681f3Smrg   return 0;
6277ec681f3Smrg}
6287ec681f3Smrg
6297ec681f3Smrg/* called at start of each cmdstream file: */
6307ec681f3Smrgvoid
6317ec681f3Smrgscript_start_cmdstream(const char *name)
6327ec681f3Smrg{
6337ec681f3Smrg   if (!L)
6347ec681f3Smrg      return;
6357ec681f3Smrg
6367ec681f3Smrg   lua_getglobal(L, "start_cmdstream");
6377ec681f3Smrg
6387ec681f3Smrg   /* if no handler just ignore it: */
6397ec681f3Smrg   if (!lua_isfunction(L, -1)) {
6407ec681f3Smrg      lua_pop(L, 1);
6417ec681f3Smrg      return;
6427ec681f3Smrg   }
6437ec681f3Smrg
6447ec681f3Smrg   lua_pushstring(L, name);
6457ec681f3Smrg
6467ec681f3Smrg   /* do the call (1 arguments, 0 result) */
6477ec681f3Smrg   if (lua_pcall(L, 1, 0, 0) != 0)
6487ec681f3Smrg      error("error running function `f': %s\n");
6497ec681f3Smrg}
6507ec681f3Smrg
6517ec681f3Smrg/* called at each DRAW_INDX, calls script drawidx fxn to process
6527ec681f3Smrg * the current state
6537ec681f3Smrg */
6547ec681f3Smrgvoid
6557ec681f3Smrgscript_draw(const char *primtype, uint32_t nindx)
6567ec681f3Smrg{
6577ec681f3Smrg   if (!L)
6587ec681f3Smrg      return;
6597ec681f3Smrg
6607ec681f3Smrg   lua_getglobal(L, "draw");
6617ec681f3Smrg
6627ec681f3Smrg   /* if no handler just ignore it: */
6637ec681f3Smrg   if (!lua_isfunction(L, -1)) {
6647ec681f3Smrg      lua_pop(L, 1);
6657ec681f3Smrg      return;
6667ec681f3Smrg   }
6677ec681f3Smrg
6687ec681f3Smrg   lua_pushstring(L, primtype);
6697ec681f3Smrg   lua_pushnumber(L, nindx);
6707ec681f3Smrg
6717ec681f3Smrg   /* do the call (2 arguments, 0 result) */
6727ec681f3Smrg   if (lua_pcall(L, 2, 0, 0) != 0)
6737ec681f3Smrg      error("error running function `f': %s\n");
6747ec681f3Smrg}
6757ec681f3Smrg
6767ec681f3Smrgstatic int
6777ec681f3Smrgl_rnn_meta_dom_index(lua_State *L)
6787ec681f3Smrg{
6797ec681f3Smrg   struct rnn *rnn = lua_touserdata(L, 1);
6807ec681f3Smrg   uint32_t offset = (uint32_t)lua_tonumber(L, 2);
6817ec681f3Smrg   struct rnndelem *elem;
6827ec681f3Smrg
6837ec681f3Smrg   /* TODO might be nicer if the arg isn't a number, to search the domain
6847ec681f3Smrg    * for matching bitfields.. so that the script could do something like
6857ec681f3Smrg    * 'pkt.WIDTH' insteadl of 'pkt[1].WIDTH', ie. not have to remember the
6867ec681f3Smrg    * offset of the dword containing the bitfield..
6877ec681f3Smrg    */
6887ec681f3Smrg
6897ec681f3Smrg   elem = rnn_regoff(rnn, offset);
6907ec681f3Smrg   if (!elem)
6917ec681f3Smrg      return 0;
6927ec681f3Smrg
6937ec681f3Smrg   return l_rnn_etype(L, rnn, elem, elem->offset);
6947ec681f3Smrg}
6957ec681f3Smrg
6967ec681f3Smrg/*
6977ec681f3Smrg * A wrapper object for rnndomain based decoding of an array of dwords
6987ec681f3Smrg * (ie. for pm4 packet decoding).  Mostly re-uses the register-value
6997ec681f3Smrg * decoding for the individual dwords and bitfields.
7007ec681f3Smrg */
7017ec681f3Smrg
7027ec681f3Smrgstatic int
7037ec681f3Smrgl_rnn_meta_dom_gc(lua_State *L)
7047ec681f3Smrg{
7057ec681f3Smrg   // TODO
7067ec681f3Smrg   // struct rnn *rnn = lua_touserdata(L, 1);
7077ec681f3Smrg   // rnn_deinit(rnn);
7087ec681f3Smrg   return 0;
7097ec681f3Smrg}
7107ec681f3Smrg
7117ec681f3Smrgstatic const struct luaL_Reg l_meta_rnn_dom[] = {
7127ec681f3Smrg   {"__index", l_rnn_meta_dom_index},
7137ec681f3Smrg   {"__gc", l_rnn_meta_dom_gc},
7147ec681f3Smrg   {NULL, NULL} /* sentinel */
7157ec681f3Smrg};
7167ec681f3Smrg
7177ec681f3Smrg/* called to general pm4 packet decoding, such as texture/sampler state
7187ec681f3Smrg */
7197ec681f3Smrgvoid
7207ec681f3Smrgscript_packet(uint32_t *dwords, uint32_t sizedwords, struct rnn *rnn,
7217ec681f3Smrg              struct rnndomain *dom)
7227ec681f3Smrg{
7237ec681f3Smrg   if (!L)
7247ec681f3Smrg      return;
7257ec681f3Smrg
7267ec681f3Smrg   lua_getglobal(L, dom->name);
7277ec681f3Smrg
7287ec681f3Smrg   /* if no handler for the packet, just ignore it: */
7297ec681f3Smrg   if (!lua_isfunction(L, -1)) {
7307ec681f3Smrg      lua_pop(L, 1);
7317ec681f3Smrg      return;
7327ec681f3Smrg   }
7337ec681f3Smrg
7347ec681f3Smrg   struct rnndec *rnndec = lua_newuserdata(L, sizeof(*rnndec));
7357ec681f3Smrg
7367ec681f3Smrg   rnndec->base = *rnn;
7377ec681f3Smrg   rnndec->base.dom[0] = dom;
7387ec681f3Smrg   rnndec->base.dom[1] = NULL;
7397ec681f3Smrg   rnndec->dwords = dwords;
7407ec681f3Smrg   rnndec->sizedwords = sizedwords;
7417ec681f3Smrg
7427ec681f3Smrg   luaL_newmetatable(L, "rnnmetadom");
7437ec681f3Smrg   luaL_setfuncs(L, l_meta_rnn_dom, 0);
7447ec681f3Smrg   lua_pop(L, 1);
7457ec681f3Smrg
7467ec681f3Smrg   luaL_setmetatable(L, "rnnmetadom");
7477ec681f3Smrg
7487ec681f3Smrg   lua_pushnumber(L, sizedwords);
7497ec681f3Smrg
7507ec681f3Smrg   if (lua_pcall(L, 2, 0, 0) != 0)
7517ec681f3Smrg      error("error running function `f': %s\n");
7527ec681f3Smrg}
7537ec681f3Smrg
7547ec681f3Smrg/* helper to call fxn that takes and returns void: */
7557ec681f3Smrgstatic void
7567ec681f3Smrgsimple_call(const char *name)
7577ec681f3Smrg{
7587ec681f3Smrg   if (!L)
7597ec681f3Smrg      return;
7607ec681f3Smrg
7617ec681f3Smrg   lua_getglobal(L, name);
7627ec681f3Smrg
7637ec681f3Smrg   /* if no handler just ignore it: */
7647ec681f3Smrg   if (!lua_isfunction(L, -1)) {
7657ec681f3Smrg      lua_pop(L, 1);
7667ec681f3Smrg      return;
7677ec681f3Smrg   }
7687ec681f3Smrg
7697ec681f3Smrg   /* do the call (0 arguments, 0 result) */
7707ec681f3Smrg   if (lua_pcall(L, 0, 0, 0) != 0)
7717ec681f3Smrg      error("error running function `f': %s\n");
7727ec681f3Smrg}
7737ec681f3Smrg
7747ec681f3Smrg/* called at end of each cmdstream file: */
7757ec681f3Smrgvoid
7767ec681f3Smrgscript_end_cmdstream(void)
7777ec681f3Smrg{
7787ec681f3Smrg   simple_call("end_cmdstream");
7797ec681f3Smrg}
7807ec681f3Smrg
7817ec681f3Smrg/* called at start of submit/issueibcmds: */
7827ec681f3Smrgvoid
7837ec681f3Smrgscript_start_submit(void)
7847ec681f3Smrg{
7857ec681f3Smrg   simple_call("start_submit");
7867ec681f3Smrg}
7877ec681f3Smrg
7887ec681f3Smrg/* called at end of submit/issueibcmds: */
7897ec681f3Smrgvoid
7907ec681f3Smrgscript_end_submit(void)
7917ec681f3Smrg{
7927ec681f3Smrg   simple_call("end_submit");
7937ec681f3Smrg}
7947ec681f3Smrg
7957ec681f3Smrg/* called after last cmdstream file: */
7967ec681f3Smrgvoid
7977ec681f3Smrgscript_finish(void)
7987ec681f3Smrg{
7997ec681f3Smrg   if (!L)
8007ec681f3Smrg      return;
8017ec681f3Smrg
8027ec681f3Smrg   simple_call("finish");
8037ec681f3Smrg
8047ec681f3Smrg   lua_close(L);
8057ec681f3Smrg   L = NULL;
8067ec681f3Smrg}
807