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>
29 #define LUA_COMPAT_APIINTCASTS
46 #define DBG(fmt, ...) \
47 do { printf(" ** %s:%d ** "fmt "\n", \
48 __FUNCTION__, __LINE__, ##__VA_ARGS__); } while (0)
50 #define DBG(fmt, ...) do {} while (0)
53 /* An rnn based decoder, which can either be decoding current register
54 * values, or domain based decoding of a pm4 packet.
60 /* for pm4 packet decoding: */
65 static inline struct rnndec
*to_rnndec(struct rnn
*rnn
)
67 return (struct rnndec
*)rnn
;
70 static uint32_t rnn_val(struct rnn
*rnn
, uint32_t regbase
)
72 struct rnndec
*rnndec
= to_rnndec(rnn
);
74 if (!rnndec
->sizedwords
) {
75 return reg_val(regbase
);
76 } else if (regbase
< rnndec
->sizedwords
) {
77 return rnndec
->dwords
[regbase
];
85 static void error(const char *fmt
)
87 fprintf(stderr
, fmt
, lua_tostring(L
, -1));
92 * An enum type that can be used as string or number:
100 static int l_meta_rnn_enum_tostring(lua_State
*L
)
102 struct rnndenum
*e
= lua_touserdata(L
, 1);
104 lua_pushstring(L
, e
->str
);
107 sprintf(buf
, "%u", e
->val
);
108 lua_pushstring(L
, buf
);
113 /* so, this doesn't actually seem to be implemented yet, but hopefully
114 * some day lua comes to it's senses
116 static int l_meta_rnn_enum_tonumber(lua_State
*L
)
118 struct rnndenum
*e
= lua_touserdata(L
, 1);
119 lua_pushinteger(L
, e
->val
);
123 static const struct luaL_Reg l_meta_rnn_enum
[] = {
124 {"__tostring", l_meta_rnn_enum_tostring
},
125 {"__tonumber", l_meta_rnn_enum_tonumber
},
126 {NULL
, NULL
} /* sentinel */
129 static void pushenum(struct lua_State
*L
, int val
, struct rnnenum
*info
)
131 struct rnndenum
*e
= lua_newuserdata(L
, sizeof(*e
));
136 for (int i
= 0; i
< info
->valsnum
; i
++) {
137 if (info
->vals
[i
]->valvalid
&& (info
->vals
[i
]->value
== val
)) {
138 e
->str
= info
->vals
[i
]->name
;
143 luaL_newmetatable(L
, "rnnmetaenum");
144 luaL_setfuncs(L
, l_meta_rnn_enum
, 0);
147 luaL_setmetatable(L
, "rnnmetaenum");
150 /* Expose rnn decode to script environment as "rnn" library:
155 struct rnndelem
*elem
;
159 static void push_rnndoff(lua_State
*L
, struct rnn
*rnn
,
160 struct rnndelem
*elem
, uint64_t offset
)
162 struct rnndoff
*rnndoff
= lua_newuserdata(L
, sizeof(*rnndoff
));
164 rnndoff
->elem
= elem
;
165 rnndoff
->offset
= offset
;
168 static int l_rnn_etype_array(lua_State
*L
, struct rnn
*rnn
,
169 struct rnndelem
*elem
, uint64_t offset
);
170 static int l_rnn_etype_reg(lua_State
*L
, struct rnn
*rnn
,
171 struct rnndelem
*elem
, uint64_t offset
);
173 static int pushdecval(struct lua_State
*L
, struct rnn
*rnn
,
174 uint32_t regval
, struct rnntypeinfo
*info
)
177 switch (rnn_decodelem(rnn
, info
, regval
, &val
)) {
179 case RNN_TTYPE_INLINE_ENUM
:
180 pushenum(L
, val
.i
, info
->eenum
);
183 lua_pushinteger(L
, val
.i
);
187 lua_pushunsigned(L
, val
.u
);
189 case RNN_TTYPE_FLOAT
:
190 lua_pushnumber(L
, val
.f
);
192 case RNN_TTYPE_BOOLEAN
:
193 lua_pushboolean(L
, val
.u
);
195 case RNN_TTYPE_INVALID
:
202 static int l_rnn_etype(lua_State
*L
, struct rnn
*rnn
,
203 struct rnndelem
*elem
, uint64_t offset
)
207 DBG("elem=%p (%d), offset=%lu", elem
, elem
->type
, offset
);
208 switch (elem
->type
) {
210 /* if a register has no bitfields, just return
213 regval
= rnn_val(rnn
, offset
);
214 regval
<<= elem
->typeinfo
.shr
;
215 ret
= pushdecval(L
, rnn
, regval
, &elem
->typeinfo
);
218 return l_rnn_etype_reg(L
, rnn
, elem
, offset
);
219 case RNN_ETYPE_ARRAY
:
220 return l_rnn_etype_array(L
, rnn
, elem
, offset
);
223 printf("unhandled type: %d\n", elem
->type
);
230 * To implement stuff like 'RB_MRT[n].CONTROL' we need a struct-object
231 * to represent the current array index (ie. 'RB_MRT[n]')
234 static int l_rnn_struct_meta_index(lua_State
*L
)
236 struct rnndoff
*rnndoff
= lua_touserdata(L
, 1);
237 const char *name
= lua_tostring(L
, 2);
238 struct rnndelem
*elem
= rnndoff
->elem
;
241 for (i
= 0; i
< elem
->subelemsnum
; i
++) {
242 struct rnndelem
*subelem
= elem
->subelems
[i
];
243 if (!strcmp(name
, subelem
->name
)) {
244 return l_rnn_etype(L
, rnndoff
->rnn
, subelem
,
245 rnndoff
->offset
+ subelem
->offset
);
252 static const struct luaL_Reg l_meta_rnn_struct
[] = {
253 {"__index", l_rnn_struct_meta_index
},
254 {NULL
, NULL
} /* sentinel */
257 static int l_rnn_etype_struct(lua_State
*L
, struct rnn
*rnn
,
258 struct rnndelem
*elem
, uint64_t offset
)
260 push_rnndoff(L
, rnn
, elem
, offset
);
262 luaL_newmetatable(L
, "rnnmetastruct");
263 luaL_setfuncs(L
, l_meta_rnn_struct
, 0);
266 luaL_setmetatable(L
, "rnnmetastruct");
275 static int l_rnn_array_meta_index(lua_State
*L
)
277 struct rnndoff
*rnndoff
= lua_touserdata(L
, 1);
278 int idx
= lua_tointeger(L
, 2);
279 struct rnndelem
*elem
= rnndoff
->elem
;
280 uint64_t offset
= rnndoff
->offset
+ (elem
->stride
* idx
);
282 DBG("rnndoff=%p, idx=%d, numsubelems=%d",
283 rnndoff
, idx
, rnndoff
->elem
->subelemsnum
);
285 /* if just a single sub-element, it is directly a register,
286 * otherwise we need to accumulate the array index while
287 * we wait for the register name within the array..
289 if (elem
->subelemsnum
== 1) {
290 return l_rnn_etype(L
, rnndoff
->rnn
, elem
->subelems
[0], offset
);
292 return l_rnn_etype_struct(L
, rnndoff
->rnn
, elem
, offset
);
298 static const struct luaL_Reg l_meta_rnn_array
[] = {
299 {"__index", l_rnn_array_meta_index
},
300 {NULL
, NULL
} /* sentinel */
303 static int l_rnn_etype_array(lua_State
*L
, struct rnn
*rnn
,
304 struct rnndelem
*elem
, uint64_t offset
)
306 push_rnndoff(L
, rnn
, elem
, offset
);
308 luaL_newmetatable(L
, "rnnmetaarray");
309 luaL_setfuncs(L
, l_meta_rnn_array
, 0);
312 luaL_setmetatable(L
, "rnnmetaarray");
321 static int l_rnn_reg_meta_index(lua_State
*L
)
323 struct rnndoff
*rnndoff
= lua_touserdata(L
, 1);
324 const char *name
= lua_tostring(L
, 2);
325 struct rnndelem
*elem
= rnndoff
->elem
;
326 struct rnntypeinfo
*info
= &elem
->typeinfo
;
327 struct rnnbitfield
**bitfields
;
331 switch (info
->type
) {
332 case RNN_TTYPE_BITSET
:
333 bitfields
= info
->ebitset
->bitfields
;
334 bitfieldsnum
= info
->ebitset
->bitfieldsnum
;
336 case RNN_TTYPE_INLINE_BITSET
:
337 bitfields
= info
->bitfields
;
338 bitfieldsnum
= info
->bitfieldsnum
;
341 printf("invalid register type: %d\n", info
->type
);
345 for (i
= 0; i
< bitfieldsnum
; i
++) {
346 struct rnnbitfield
*bf
= bitfields
[i
];
347 if (!strcmp(name
, bf
->name
)) {
348 uint32_t regval
= rnn_val(rnndoff
->rnn
, rnndoff
->offset
);
350 regval
&= typeinfo_mask(&bf
->typeinfo
);
351 regval
>>= bf
->typeinfo
.low
;
352 regval
<<= bf
->typeinfo
.shr
;
354 DBG("name=%s, info=%p, subelemsnum=%d, type=%d, regval=%x",
355 name
, info
, rnndoff
->elem
->subelemsnum
,
356 bf
->typeinfo
.type
, regval
);
358 return pushdecval(L
, rnndoff
->rnn
, regval
, &bf
->typeinfo
);
362 printf("invalid member: %s\n", name
);
366 static int l_rnn_reg_meta_tostring(lua_State
*L
)
368 struct rnndoff
*rnndoff
= lua_touserdata(L
, 1);
369 uint32_t regval
= rnn_val(rnndoff
->rnn
, rnndoff
->offset
);
370 struct rnndecaddrinfo
*info
= rnn_reginfo(rnndoff
->rnn
, rnndoff
->offset
);
372 if (info
&& info
->typeinfo
) {
373 decoded
= rnndec_decodeval(rnndoff
->rnn
->vc
,
374 info
->typeinfo
, regval
);
376 asprintf(&decoded
, "%08x", regval
);
378 lua_pushstring(L
, decoded
);
387 static int l_rnn_reg_meta_tonumber(lua_State
*L
)
389 struct rnndoff
*rnndoff
= lua_touserdata(L
, 1);
390 uint32_t regval
= rnn_val(rnndoff
->rnn
, rnndoff
->offset
);
392 regval
<<= rnndoff
->elem
->typeinfo
.shr
;
394 lua_pushnumber(L
, regval
);
398 static const struct luaL_Reg l_meta_rnn_reg
[] = {
399 {"__index", l_rnn_reg_meta_index
},
400 {"__tostring", l_rnn_reg_meta_tostring
},
401 {"__tonumber", l_rnn_reg_meta_tonumber
},
402 {NULL
, NULL
} /* sentinel */
405 static int l_rnn_etype_reg(lua_State
*L
, struct rnn
*rnn
,
406 struct rnndelem
*elem
, uint64_t offset
)
408 push_rnndoff(L
, rnn
, elem
, offset
);
410 luaL_newmetatable(L
, "rnnmetareg");
411 luaL_setfuncs(L
, l_meta_rnn_reg
, 0);
414 luaL_setmetatable(L
, "rnnmetareg");
423 static int l_rnn_meta_index(lua_State
*L
)
425 struct rnn
*rnn
= lua_touserdata(L
, 1);
426 const char *name
= lua_tostring(L
, 2);
427 struct rnndelem
*elem
;
429 elem
= rnn_regelem(rnn
, name
);
433 return l_rnn_etype(L
, rnn
, elem
, elem
->offset
);
436 static int l_rnn_meta_gc(lua_State
*L
)
439 //struct rnn *rnn = lua_touserdata(L, 1);
444 static const struct luaL_Reg l_meta_rnn
[] = {
445 {"__index", l_rnn_meta_index
},
446 {"__gc", l_rnn_meta_gc
},
447 {NULL
, NULL
} /* sentinel */
450 static int l_rnn_init(lua_State
*L
)
452 const char *gpuname
= lua_tostring(L
, 1);
453 struct rnndec
*rnndec
= lua_newuserdata(L
, sizeof(*rnndec
));
454 _rnn_init(&rnndec
->base
, 0);
455 rnn_load(&rnndec
->base
, gpuname
);
456 rnndec
->sizedwords
= 0;
458 luaL_newmetatable(L
, "rnnmeta");
459 luaL_setfuncs(L
, l_meta_rnn
, 0);
462 luaL_setmetatable(L
, "rnnmeta");
467 static int l_rnn_enumname(lua_State
*L
)
469 struct rnn
*rnn
= lua_touserdata(L
, 1);
470 const char *name
= lua_tostring(L
, 2);
471 uint32_t val
= (uint32_t)lua_tonumber(L
, 3);
472 lua_pushstring(L
, rnn_enumname(rnn
, name
, val
));
476 static int l_rnn_regname(lua_State
*L
)
478 struct rnn
*rnn
= lua_touserdata(L
, 1);
479 uint32_t regbase
= (uint32_t)lua_tonumber(L
, 2);
480 lua_pushstring(L
, rnn_regname(rnn
, regbase
, 1));
484 static int l_rnn_regval(lua_State
*L
)
486 struct rnn
*rnn
= lua_touserdata(L
, 1);
487 uint32_t regbase
= (uint32_t)lua_tonumber(L
, 2);
488 uint32_t regval
= (uint32_t)lua_tonumber(L
, 3);
489 struct rnndecaddrinfo
*info
= rnn_reginfo(rnn
, regbase
);
491 if (info
&& info
->typeinfo
) {
492 decoded
= rnndec_decodeval(rnn
->vc
, info
->typeinfo
, regval
);
494 asprintf(&decoded
, "%08x", regval
);
496 lua_pushstring(L
, decoded
);
505 static const struct luaL_Reg l_rnn
[] = {
506 {"init", l_rnn_init
},
507 {"enumname", l_rnn_enumname
},
508 {"regname", l_rnn_regname
},
509 {"regval", l_rnn_regval
},
510 {NULL
, NULL
} /* sentinel */
515 /* Expose the register state to script enviroment as a "regs" library:
518 static int l_reg_written(lua_State
*L
)
520 uint32_t regbase
= (uint32_t)lua_tonumber(L
, 1);
521 lua_pushnumber(L
, reg_written(regbase
));
525 static int l_reg_lastval(lua_State
*L
)
527 uint32_t regbase
= (uint32_t)lua_tonumber(L
, 1);
528 lua_pushnumber(L
, reg_lastval(regbase
));
532 static int l_reg_val(lua_State
*L
)
534 uint32_t regbase
= (uint32_t)lua_tonumber(L
, 1);
535 lua_pushnumber(L
, reg_val(regbase
));
539 static const struct luaL_Reg l_regs
[] = {
540 {"written", l_reg_written
},
541 {"lastval", l_reg_lastval
},
543 {NULL
, NULL
} /* sentinel */
546 /* Expose API to lookup snapshot buffers:
549 uint64_t gpubaseaddr(uint64_t gpuaddr
);
550 unsigned hostlen(uint64_t gpuaddr
);
552 /* given address, return base-address of buffer: */
553 static int l_bo_base(lua_State
*L
)
555 uint64_t addr
= (uint64_t)lua_tonumber(L
, 1);
556 lua_pushnumber(L
, gpubaseaddr(addr
));
560 /* given address, return the remaining size of the buffer: */
561 static int l_bo_size(lua_State
*L
)
563 uint64_t addr
= (uint64_t)lua_tonumber(L
, 1);
564 lua_pushnumber(L
, hostlen(addr
));
568 static const struct luaL_Reg l_bos
[] = {
571 {NULL
, NULL
} /* sentinel */
574 static void openlib(const char *lib
, const luaL_Reg
*reg
)
577 luaL_setfuncs(L
, reg
, 0);
578 lua_setglobal(L
, lib
);
581 /* called at start to load the script: */
582 int script_load(const char *file
)
590 openlib("bos", l_bos
);
591 openlib("regs", l_regs
);
592 openlib("rnn", l_rnn
);
594 ret
= luaL_loadfile(L
, file
);
598 ret
= lua_pcall(L
, 0, LUA_MULTRET
, 0);
606 /* called at start of each cmdstream file: */
607 void script_start_cmdstream(const char *name
)
612 lua_getglobal(L
, "start_cmdstream");
614 /* if no handler just ignore it: */
615 if (!lua_isfunction(L
, -1)) {
620 lua_pushstring(L
, name
);
622 /* do the call (1 arguments, 0 result) */
623 if (lua_pcall(L
, 1, 0, 0) != 0)
624 error("error running function `f': %s\n");
627 /* called at each DRAW_INDX, calls script drawidx fxn to process
630 void script_draw(const char *primtype
, uint32_t nindx
)
635 lua_getglobal(L
, "draw");
637 /* if no handler just ignore it: */
638 if (!lua_isfunction(L
, -1)) {
643 lua_pushstring(L
, primtype
);
644 lua_pushnumber(L
, nindx
);
646 /* do the call (2 arguments, 0 result) */
647 if (lua_pcall(L
, 2, 0, 0) != 0)
648 error("error running function `f': %s\n");
652 static int l_rnn_meta_dom_index(lua_State
*L
)
654 struct rnn
*rnn
= lua_touserdata(L
, 1);
655 uint32_t offset
= (uint32_t)lua_tonumber(L
, 2);
656 struct rnndelem
*elem
;
658 /* TODO might be nicer if the arg isn't a number, to search the domain
659 * for matching bitfields.. so that the script could do something like
660 * 'pkt.WIDTH' insteadl of 'pkt[1].WIDTH', ie. not have to remember the
661 * offset of the dword containing the bitfield..
664 elem
= rnn_regoff(rnn
, offset
);
668 return l_rnn_etype(L
, rnn
, elem
, elem
->offset
);
672 * A wrapper object for rnndomain based decoding of an array of dwords
673 * (ie. for pm4 packet decoding). Mostly re-uses the register-value
674 * decoding for the individual dwords and bitfields.
677 static int l_rnn_meta_dom_gc(lua_State
*L
)
680 //struct rnn *rnn = lua_touserdata(L, 1);
685 static const struct luaL_Reg l_meta_rnn_dom
[] = {
686 {"__index", l_rnn_meta_dom_index
},
687 {"__gc", l_rnn_meta_dom_gc
},
688 {NULL
, NULL
} /* sentinel */
691 /* called to general pm4 packet decoding, such as texture/sampler state
693 void script_packet(uint32_t *dwords
, uint32_t sizedwords
,
694 struct rnn
*rnn
, struct rnndomain
*dom
)
699 lua_getglobal(L
, dom
->name
);
701 /* if no handler for the packet, just ignore it: */
702 if (!lua_isfunction(L
, -1)) {
707 struct rnndec
*rnndec
= lua_newuserdata(L
, sizeof(*rnndec
));
710 rnndec
->base
.dom
[0] = dom
;
711 rnndec
->base
.dom
[1] = NULL
;
712 rnndec
->dwords
= dwords
;
713 rnndec
->sizedwords
= sizedwords
;
715 luaL_newmetatable(L
, "rnnmetadom");
716 luaL_setfuncs(L
, l_meta_rnn_dom
, 0);
719 luaL_setmetatable(L
, "rnnmetadom");
721 lua_pushnumber(L
, sizedwords
);
723 if (lua_pcall(L
, 2, 0, 0) != 0)
724 error("error running function `f': %s\n");
727 /* helper to call fxn that takes and returns void: */
728 static void simple_call(const char *name
)
733 lua_getglobal(L
, name
);
735 /* if no handler just ignore it: */
736 if (!lua_isfunction(L
, -1)) {
741 /* do the call (0 arguments, 0 result) */
742 if (lua_pcall(L
, 0, 0, 0) != 0)
743 error("error running function `f': %s\n");
746 /* called at end of each cmdstream file: */
747 void script_end_cmdstream(void)
749 simple_call("end_cmdstream");
752 /* called at start of submit/issueibcmds: */
753 void script_start_submit(void)
755 simple_call("start_submit");
758 /* called at end of submit/issueibcmds: */
759 void script_end_submit(void)
761 simple_call("end_submit");
764 /* called after last cmdstream file: */
765 void script_finish(void)
770 simple_call("finish");