1 /* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
4 * Copyright (C) 2014 Rob Clark <robclark@freedesktop.org>
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 * Rob Clark <robclark@freedesktop.org>
30 #define LUA_COMPAT_APIINTCASTS
47 #define DBG(fmt, ...) \
48 do { printf(" ** %s:%d ** "fmt "\n", \
49 __FUNCTION__, __LINE__, ##__VA_ARGS__); } while (0)
51 #define DBG(fmt, ...) do {} while (0)
54 /* An rnn based decoder, which can either be decoding current register
55 * values, or domain based decoding of a pm4 packet.
61 /* for pm4 packet decoding: */
66 static inline struct rnndec
*to_rnndec(struct rnn
*rnn
)
68 return (struct rnndec
*)rnn
;
71 static uint32_t rnn_val(struct rnn
*rnn
, uint32_t regbase
)
73 struct rnndec
*rnndec
= to_rnndec(rnn
);
75 if (!rnndec
->sizedwords
) {
76 return reg_val(regbase
);
77 } else if (regbase
< rnndec
->sizedwords
) {
78 return rnndec
->dwords
[regbase
];
86 static void error(const char *fmt
)
88 fprintf(stderr
, fmt
, lua_tostring(L
, -1));
93 * An enum type that can be used as string or number:
101 static int l_meta_rnn_enum_tostring(lua_State
*L
)
103 struct rnndenum
*e
= lua_touserdata(L
, 1);
105 lua_pushstring(L
, e
->str
);
108 sprintf(buf
, "%u", e
->val
);
109 lua_pushstring(L
, buf
);
114 /* so, this doesn't actually seem to be implemented yet, but hopefully
115 * some day lua comes to it's senses
117 static int l_meta_rnn_enum_tonumber(lua_State
*L
)
119 struct rnndenum
*e
= lua_touserdata(L
, 1);
120 lua_pushinteger(L
, e
->val
);
124 static const struct luaL_Reg l_meta_rnn_enum
[] = {
125 {"__tostring", l_meta_rnn_enum_tostring
},
126 {"__tonumber", l_meta_rnn_enum_tonumber
},
127 {NULL
, NULL
} /* sentinel */
130 static void pushenum(struct lua_State
*L
, int val
, struct rnnenum
*info
)
132 struct rnndenum
*e
= lua_newuserdata(L
, sizeof(*e
));
137 for (int i
= 0; i
< info
->valsnum
; i
++) {
138 if (info
->vals
[i
]->valvalid
&& (info
->vals
[i
]->value
== val
)) {
139 e
->str
= info
->vals
[i
]->name
;
144 luaL_newmetatable(L
, "rnnmetaenum");
145 luaL_setfuncs(L
, l_meta_rnn_enum
, 0);
148 luaL_setmetatable(L
, "rnnmetaenum");
151 /* Expose rnn decode to script environment as "rnn" library:
156 struct rnndelem
*elem
;
160 static void push_rnndoff(lua_State
*L
, struct rnn
*rnn
,
161 struct rnndelem
*elem
, uint64_t offset
)
163 struct rnndoff
*rnndoff
= lua_newuserdata(L
, sizeof(*rnndoff
));
165 rnndoff
->elem
= elem
;
166 rnndoff
->offset
= offset
;
169 static int l_rnn_etype_array(lua_State
*L
, struct rnn
*rnn
,
170 struct rnndelem
*elem
, uint64_t offset
);
171 static int l_rnn_etype_reg(lua_State
*L
, struct rnn
*rnn
,
172 struct rnndelem
*elem
, uint64_t offset
);
174 static int pushdecval(struct lua_State
*L
, struct rnn
*rnn
,
175 uint32_t regval
, struct rnntypeinfo
*info
)
178 switch (rnn_decodelem(rnn
, info
, regval
, &val
)) {
180 case RNN_TTYPE_INLINE_ENUM
:
181 pushenum(L
, val
.i
, info
->eenum
);
184 lua_pushinteger(L
, val
.i
);
188 lua_pushunsigned(L
, val
.u
);
190 case RNN_TTYPE_FLOAT
:
191 lua_pushnumber(L
, val
.f
);
193 case RNN_TTYPE_BOOLEAN
:
194 lua_pushboolean(L
, val
.u
);
196 case RNN_TTYPE_INVALID
:
203 static int l_rnn_etype(lua_State
*L
, struct rnn
*rnn
,
204 struct rnndelem
*elem
, uint64_t offset
)
208 DBG("elem=%p (%d), offset=%lu", elem
, elem
->type
, offset
);
209 switch (elem
->type
) {
211 /* if a register has no bitfields, just return
214 regval
= rnn_val(rnn
, offset
);
215 regval
<<= elem
->typeinfo
.shr
;
216 ret
= pushdecval(L
, rnn
, regval
, &elem
->typeinfo
);
219 return l_rnn_etype_reg(L
, rnn
, elem
, offset
);
220 case RNN_ETYPE_ARRAY
:
221 return l_rnn_etype_array(L
, rnn
, elem
, offset
);
224 printf("unhandled type: %d\n", elem
->type
);
231 * To implement stuff like 'RB_MRT[n].CONTROL' we need a struct-object
232 * to represent the current array index (ie. 'RB_MRT[n]')
235 static int l_rnn_struct_meta_index(lua_State
*L
)
237 struct rnndoff
*rnndoff
= lua_touserdata(L
, 1);
238 const char *name
= lua_tostring(L
, 2);
239 struct rnndelem
*elem
= rnndoff
->elem
;
242 for (i
= 0; i
< elem
->subelemsnum
; i
++) {
243 struct rnndelem
*subelem
= elem
->subelems
[i
];
244 if (!strcmp(name
, subelem
->name
)) {
245 return l_rnn_etype(L
, rnndoff
->rnn
, subelem
,
246 rnndoff
->offset
+ subelem
->offset
);
253 static const struct luaL_Reg l_meta_rnn_struct
[] = {
254 {"__index", l_rnn_struct_meta_index
},
255 {NULL
, NULL
} /* sentinel */
258 static int l_rnn_etype_struct(lua_State
*L
, struct rnn
*rnn
,
259 struct rnndelem
*elem
, uint64_t offset
)
261 push_rnndoff(L
, rnn
, elem
, offset
);
263 luaL_newmetatable(L
, "rnnmetastruct");
264 luaL_setfuncs(L
, l_meta_rnn_struct
, 0);
267 luaL_setmetatable(L
, "rnnmetastruct");
276 static int l_rnn_array_meta_index(lua_State
*L
)
278 struct rnndoff
*rnndoff
= lua_touserdata(L
, 1);
279 int idx
= lua_tointeger(L
, 2);
280 struct rnndelem
*elem
= rnndoff
->elem
;
281 uint64_t offset
= rnndoff
->offset
+ (elem
->stride
* idx
);
283 DBG("rnndoff=%p, idx=%d, numsubelems=%d",
284 rnndoff
, idx
, rnndoff
->elem
->subelemsnum
);
286 /* if just a single sub-element, it is directly a register,
287 * otherwise we need to accumulate the array index while
288 * we wait for the register name within the array..
290 if (elem
->subelemsnum
== 1) {
291 return l_rnn_etype(L
, rnndoff
->rnn
, elem
->subelems
[0], offset
);
293 return l_rnn_etype_struct(L
, rnndoff
->rnn
, elem
, offset
);
299 static const struct luaL_Reg l_meta_rnn_array
[] = {
300 {"__index", l_rnn_array_meta_index
},
301 {NULL
, NULL
} /* sentinel */
304 static int l_rnn_etype_array(lua_State
*L
, struct rnn
*rnn
,
305 struct rnndelem
*elem
, uint64_t offset
)
307 push_rnndoff(L
, rnn
, elem
, offset
);
309 luaL_newmetatable(L
, "rnnmetaarray");
310 luaL_setfuncs(L
, l_meta_rnn_array
, 0);
313 luaL_setmetatable(L
, "rnnmetaarray");
322 static int l_rnn_reg_meta_index(lua_State
*L
)
324 struct rnndoff
*rnndoff
= lua_touserdata(L
, 1);
325 const char *name
= lua_tostring(L
, 2);
326 struct rnndelem
*elem
= rnndoff
->elem
;
327 struct rnntypeinfo
*info
= &elem
->typeinfo
;
328 struct rnnbitfield
**bitfields
;
332 switch (info
->type
) {
333 case RNN_TTYPE_BITSET
:
334 bitfields
= info
->ebitset
->bitfields
;
335 bitfieldsnum
= info
->ebitset
->bitfieldsnum
;
337 case RNN_TTYPE_INLINE_BITSET
:
338 bitfields
= info
->bitfields
;
339 bitfieldsnum
= info
->bitfieldsnum
;
342 printf("invalid register type: %d\n", info
->type
);
346 for (i
= 0; i
< bitfieldsnum
; i
++) {
347 struct rnnbitfield
*bf
= bitfields
[i
];
348 if (!strcmp(name
, bf
->name
)) {
349 uint32_t regval
= rnn_val(rnndoff
->rnn
, rnndoff
->offset
);
351 regval
&= typeinfo_mask(&bf
->typeinfo
);
352 regval
>>= bf
->typeinfo
.low
;
353 regval
<<= bf
->typeinfo
.shr
;
355 DBG("name=%s, info=%p, subelemsnum=%d, type=%d, regval=%x",
356 name
, info
, rnndoff
->elem
->subelemsnum
,
357 bf
->typeinfo
.type
, regval
);
359 return pushdecval(L
, rnndoff
->rnn
, regval
, &bf
->typeinfo
);
363 printf("invalid member: %s\n", name
);
367 static int l_rnn_reg_meta_tostring(lua_State
*L
)
369 struct rnndoff
*rnndoff
= lua_touserdata(L
, 1);
370 uint32_t regval
= rnn_val(rnndoff
->rnn
, rnndoff
->offset
);
371 struct rnndecaddrinfo
*info
= rnn_reginfo(rnndoff
->rnn
, rnndoff
->offset
);
373 if (info
&& info
->typeinfo
) {
374 decoded
= rnndec_decodeval(rnndoff
->rnn
->vc
,
375 info
->typeinfo
, regval
);
377 asprintf(&decoded
, "%08x", regval
);
379 lua_pushstring(L
, decoded
);
388 static int l_rnn_reg_meta_tonumber(lua_State
*L
)
390 struct rnndoff
*rnndoff
= lua_touserdata(L
, 1);
391 uint32_t regval
= rnn_val(rnndoff
->rnn
, rnndoff
->offset
);
393 regval
<<= rnndoff
->elem
->typeinfo
.shr
;
395 lua_pushnumber(L
, regval
);
399 static const struct luaL_Reg l_meta_rnn_reg
[] = {
400 {"__index", l_rnn_reg_meta_index
},
401 {"__tostring", l_rnn_reg_meta_tostring
},
402 {"__tonumber", l_rnn_reg_meta_tonumber
},
403 {NULL
, NULL
} /* sentinel */
406 static int l_rnn_etype_reg(lua_State
*L
, struct rnn
*rnn
,
407 struct rnndelem
*elem
, uint64_t offset
)
409 push_rnndoff(L
, rnn
, elem
, offset
);
411 luaL_newmetatable(L
, "rnnmetareg");
412 luaL_setfuncs(L
, l_meta_rnn_reg
, 0);
415 luaL_setmetatable(L
, "rnnmetareg");
424 static int l_rnn_meta_index(lua_State
*L
)
426 struct rnn
*rnn
= lua_touserdata(L
, 1);
427 const char *name
= lua_tostring(L
, 2);
428 struct rnndelem
*elem
;
430 elem
= rnn_regelem(rnn
, name
);
434 return l_rnn_etype(L
, rnn
, elem
, elem
->offset
);
437 static int l_rnn_meta_gc(lua_State
*L
)
440 //struct rnn *rnn = lua_touserdata(L, 1);
445 static const struct luaL_Reg l_meta_rnn
[] = {
446 {"__index", l_rnn_meta_index
},
447 {"__gc", l_rnn_meta_gc
},
448 {NULL
, NULL
} /* sentinel */
451 static int l_rnn_init(lua_State
*L
)
453 const char *gpuname
= lua_tostring(L
, 1);
454 struct rnndec
*rnndec
= lua_newuserdata(L
, sizeof(*rnndec
));
455 _rnn_init(&rnndec
->base
, 0);
456 rnn_load(&rnndec
->base
, gpuname
);
457 rnndec
->sizedwords
= 0;
459 luaL_newmetatable(L
, "rnnmeta");
460 luaL_setfuncs(L
, l_meta_rnn
, 0);
463 luaL_setmetatable(L
, "rnnmeta");
468 static int l_rnn_enumname(lua_State
*L
)
470 struct rnn
*rnn
= lua_touserdata(L
, 1);
471 const char *name
= lua_tostring(L
, 2);
472 uint32_t val
= (uint32_t)lua_tonumber(L
, 3);
473 lua_pushstring(L
, rnn_enumname(rnn
, name
, val
));
477 static int l_rnn_regname(lua_State
*L
)
479 struct rnn
*rnn
= lua_touserdata(L
, 1);
480 uint32_t regbase
= (uint32_t)lua_tonumber(L
, 2);
481 lua_pushstring(L
, rnn_regname(rnn
, regbase
, 1));
485 static int l_rnn_regval(lua_State
*L
)
487 struct rnn
*rnn
= lua_touserdata(L
, 1);
488 uint32_t regbase
= (uint32_t)lua_tonumber(L
, 2);
489 uint32_t regval
= (uint32_t)lua_tonumber(L
, 3);
490 struct rnndecaddrinfo
*info
= rnn_reginfo(rnn
, regbase
);
492 if (info
&& info
->typeinfo
) {
493 decoded
= rnndec_decodeval(rnn
->vc
, info
->typeinfo
, regval
);
495 asprintf(&decoded
, "%08x", regval
);
497 lua_pushstring(L
, decoded
);
506 static const struct luaL_Reg l_rnn
[] = {
507 {"init", l_rnn_init
},
508 {"enumname", l_rnn_enumname
},
509 {"regname", l_rnn_regname
},
510 {"regval", l_rnn_regval
},
511 {NULL
, NULL
} /* sentinel */
516 /* Expose the register state to script enviroment as a "regs" library:
519 static int l_reg_written(lua_State
*L
)
521 uint32_t regbase
= (uint32_t)lua_tonumber(L
, 1);
522 lua_pushnumber(L
, reg_written(regbase
));
526 static int l_reg_lastval(lua_State
*L
)
528 uint32_t regbase
= (uint32_t)lua_tonumber(L
, 1);
529 lua_pushnumber(L
, reg_lastval(regbase
));
533 static int l_reg_val(lua_State
*L
)
535 uint32_t regbase
= (uint32_t)lua_tonumber(L
, 1);
536 lua_pushnumber(L
, reg_val(regbase
));
540 static const struct luaL_Reg l_regs
[] = {
541 {"written", l_reg_written
},
542 {"lastval", l_reg_lastval
},
544 {NULL
, NULL
} /* sentinel */
547 /* Expose API to lookup snapshot buffers:
550 uint64_t gpubaseaddr(uint64_t gpuaddr
);
551 unsigned hostlen(uint64_t gpuaddr
);
553 /* given address, return base-address of buffer: */
554 static int l_bo_base(lua_State
*L
)
556 uint64_t addr
= (uint64_t)lua_tonumber(L
, 1);
557 lua_pushnumber(L
, gpubaseaddr(addr
));
561 /* given address, return the remaining size of the buffer: */
562 static int l_bo_size(lua_State
*L
)
564 uint64_t addr
= (uint64_t)lua_tonumber(L
, 1);
565 lua_pushnumber(L
, hostlen(addr
));
569 static const struct luaL_Reg l_bos
[] = {
572 {NULL
, NULL
} /* sentinel */
575 static void openlib(const char *lib
, const luaL_Reg
*reg
)
578 luaL_setfuncs(L
, reg
, 0);
579 lua_setglobal(L
, lib
);
582 /* called at start to load the script: */
583 int script_load(const char *file
)
591 openlib("bos", l_bos
);
592 openlib("regs", l_regs
);
593 openlib("rnn", l_rnn
);
595 ret
= luaL_loadfile(L
, file
);
599 ret
= lua_pcall(L
, 0, LUA_MULTRET
, 0);
607 /* called at start of each cmdstream file: */
608 void script_start_cmdstream(const char *name
)
613 lua_getglobal(L
, "start_cmdstream");
615 /* if no handler just ignore it: */
616 if (!lua_isfunction(L
, -1)) {
621 lua_pushstring(L
, name
);
623 /* do the call (1 arguments, 0 result) */
624 if (lua_pcall(L
, 1, 0, 0) != 0)
625 error("error running function `f': %s\n");
628 /* called at each DRAW_INDX, calls script drawidx fxn to process
631 void script_draw(const char *primtype
, uint32_t nindx
)
636 lua_getglobal(L
, "draw");
638 /* if no handler just ignore it: */
639 if (!lua_isfunction(L
, -1)) {
644 lua_pushstring(L
, primtype
);
645 lua_pushnumber(L
, nindx
);
647 /* do the call (2 arguments, 0 result) */
648 if (lua_pcall(L
, 2, 0, 0) != 0)
649 error("error running function `f': %s\n");
653 static int l_rnn_meta_dom_index(lua_State
*L
)
655 struct rnn
*rnn
= lua_touserdata(L
, 1);
656 uint32_t offset
= (uint32_t)lua_tonumber(L
, 2);
657 struct rnndelem
*elem
;
659 /* TODO might be nicer if the arg isn't a number, to search the domain
660 * for matching bitfields.. so that the script could do something like
661 * 'pkt.WIDTH' insteadl of 'pkt[1].WIDTH', ie. not have to remember the
662 * offset of the dword containing the bitfield..
665 elem
= rnn_regoff(rnn
, offset
);
669 return l_rnn_etype(L
, rnn
, elem
, elem
->offset
);
673 * A wrapper object for rnndomain based decoding of an array of dwords
674 * (ie. for pm4 packet decoding). Mostly re-uses the register-value
675 * decoding for the individual dwords and bitfields.
678 static int l_rnn_meta_dom_gc(lua_State
*L
)
681 //struct rnn *rnn = lua_touserdata(L, 1);
686 static const struct luaL_Reg l_meta_rnn_dom
[] = {
687 {"__index", l_rnn_meta_dom_index
},
688 {"__gc", l_rnn_meta_dom_gc
},
689 {NULL
, NULL
} /* sentinel */
692 /* called to general pm4 packet decoding, such as texture/sampler state
694 void script_packet(uint32_t *dwords
, uint32_t sizedwords
,
695 struct rnn
*rnn
, struct rnndomain
*dom
)
700 lua_getglobal(L
, dom
->name
);
702 /* if no handler for the packet, just ignore it: */
703 if (!lua_isfunction(L
, -1)) {
708 struct rnndec
*rnndec
= lua_newuserdata(L
, sizeof(*rnndec
));
711 rnndec
->base
.dom
[0] = dom
;
712 rnndec
->base
.dom
[1] = NULL
;
713 rnndec
->dwords
= dwords
;
714 rnndec
->sizedwords
= sizedwords
;
716 luaL_newmetatable(L
, "rnnmetadom");
717 luaL_setfuncs(L
, l_meta_rnn_dom
, 0);
720 luaL_setmetatable(L
, "rnnmetadom");
722 lua_pushnumber(L
, sizedwords
);
724 if (lua_pcall(L
, 2, 0, 0) != 0)
725 error("error running function `f': %s\n");
728 /* helper to call fxn that takes and returns void: */
729 static void simple_call(const char *name
)
734 lua_getglobal(L
, name
);
736 /* if no handler just ignore it: */
737 if (!lua_isfunction(L
, -1)) {
742 /* do the call (0 arguments, 0 result) */
743 if (lua_pcall(L
, 0, 0, 0) != 0)
744 error("error running function `f': %s\n");
747 /* called at end of each cmdstream file: */
748 void script_end_cmdstream(void)
750 simple_call("end_cmdstream");
753 /* called at start of submit/issueibcmds: */
754 void script_start_submit(void)
756 simple_call("start_submit");
759 /* called at end of submit/issueibcmds: */
760 void script_end_submit(void)
762 simple_call("end_submit");
765 /* called after last cmdstream file: */
766 void script_finish(void)
771 simple_call("finish");