pvr: csbgen: Add *_unpack() functions for all generated struct types
Signed-off-by: Matt Coster <matt.coster@imgtec.com> Reviewed-by: Frank Binns <frank.binns@imgtec.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/16884>
This commit is contained in:
parent
4c0941f0d4
commit
7c615b4103
|
@ -200,6 +200,9 @@ class Csbgen(Node):
|
|||
def get_enum(self, enum_name: str) -> Enum:
|
||||
return self._enums[enum_name]
|
||||
|
||||
def get_struct(self, struct_name: str) -> Struct:
|
||||
return self._structs[struct_name]
|
||||
|
||||
|
||||
class Enum(Node):
|
||||
__slots__ = ["_values"]
|
||||
|
@ -369,6 +372,23 @@ class Struct(Node):
|
|||
|
||||
print("}\n")
|
||||
|
||||
def _emit_unpack_function(self, root: Csbgen) -> None:
|
||||
print(textwrap.dedent("""\
|
||||
static inline __attribute__((always_inline)) void
|
||||
%s_unpack(__attribute__((unused)) const void * restrict src,
|
||||
%s__attribute__((unused)) struct %s * restrict values)
|
||||
{""") % (self.full_name, ' ' * len(self.full_name), self.full_name))
|
||||
|
||||
group = Group(0, 1, self.size, self.fields)
|
||||
dwords, length = group.collect_dwords_and_length()
|
||||
if length:
|
||||
# Cast src to make header C++ friendly
|
||||
print(" const uint32_t * restrict dw = (const uint32_t * restrict) src;")
|
||||
|
||||
group.emit_unpack_function(root, dwords, length)
|
||||
|
||||
print("}\n")
|
||||
|
||||
def emit(self, root: Csbgen) -> None:
|
||||
print("#define %-33s %6d" % (self.full_name + "_length", self.length))
|
||||
|
||||
|
@ -382,6 +402,7 @@ class Struct(Node):
|
|||
print("};\n")
|
||||
|
||||
self._emit_pack_function(root)
|
||||
self._emit_unpack_function(root)
|
||||
|
||||
|
||||
class Field(Node):
|
||||
|
@ -839,6 +860,73 @@ class Group:
|
|||
print(" dw[%d] = %s;" % (index, v))
|
||||
print(" dw[%d] = %s >> 32;" % (index + 1, v))
|
||||
|
||||
def emit_unpack_function(self, root: Csbgen, dwords: t.Dict[int, Group.DWord], length: int) -> None:
|
||||
for index in range(length):
|
||||
# Ignore MBZ dwords
|
||||
if index not in dwords:
|
||||
continue
|
||||
|
||||
# For 64 bit dwords, we aliased the two dword entries in the dword
|
||||
# dict it occupies. Now that we're emitting the unpack function,
|
||||
# skip the duplicate entries.
|
||||
dw = dwords[index]
|
||||
if index > 0 and index - 1 in dwords and dw == dwords[index - 1]:
|
||||
continue
|
||||
|
||||
# Special case: only one field and it's a struct at the beginning
|
||||
# of the dword. In this case we unpack directly from the
|
||||
# source. This is the only way we handle embedded structs
|
||||
# larger than 32 bits.
|
||||
if len(dw.fields) == 1:
|
||||
field = dw.fields[0]
|
||||
if root.is_known_struct(field.type) and field.start % 32 == 0:
|
||||
prefix = root.get_struct(field.type)
|
||||
print("")
|
||||
print(" %s_unpack(data, &dw[%d], &values->%s);" % (prefix, index, field.name))
|
||||
continue
|
||||
|
||||
dword_start = index * 32
|
||||
|
||||
if dw.size == 32:
|
||||
v = "dw[%d]" % index
|
||||
elif dw.size == 64:
|
||||
v = "v%d" % index
|
||||
print(" const uint%d_t %s = dw[%d] | ((uint64_t)dw[%d] << 32);" % (dw.size, v, index, index + 1))
|
||||
else:
|
||||
raise RuntimeError("Unsupported dword size %d" % dw.size)
|
||||
|
||||
# Unpack any fields of struct type first.
|
||||
for field_index, field in enumerate(f for f in dw.fields if root.is_known_struct(f.type)):
|
||||
prefix = root.get_struct(field.type).prefix
|
||||
vname = "v%d_%d" % (index, field_index)
|
||||
print("")
|
||||
print(" uint32_t %s = __pvr_uint_unpack(%s, %d, %d);"
|
||||
% (vname, v, field.start - dword_start, field.end - dword_start))
|
||||
print(" %s_unpack(data, &%s, &values->%s);" % (prefix, vname, field.name))
|
||||
|
||||
for field in dw.fields:
|
||||
dword_field_start = field.start - dword_start
|
||||
dword_field_end = field.end - dword_start
|
||||
|
||||
if field.type == "mbo" or root.is_known_struct(field.type):
|
||||
continue
|
||||
elif field.type == "uint" or root.is_known_enum(field.type) or field.type == "bool":
|
||||
print(" values->%s = __pvr_uint_unpack(%s, %d, %d);"
|
||||
% (field.name, v, dword_field_start, dword_field_end))
|
||||
elif field.type == "int":
|
||||
print(" values->%s = __pvr_sint_unpack(%s, %d, %d);"
|
||||
% (field.name, v, dword_field_start, dword_field_end))
|
||||
elif field.type == "float":
|
||||
print(" values->%s = __pvr_float_unpack(%s);" % (field.name, v))
|
||||
elif field.type == "offset":
|
||||
print(" values->%s = __pvr_offset_unpack(%s, %d, %d);"
|
||||
% (field.name, v, dword_field_start, dword_field_end))
|
||||
elif field.type == "address":
|
||||
print(" values->%s = __pvr_address_unpack(%s, %d, %d, %d);"
|
||||
% (field.name, v, field.shift, dword_field_start, dword_field_end))
|
||||
else:
|
||||
print("/* unhandled field %s, type %s */" % (field.name, field.type))
|
||||
|
||||
|
||||
class Parser:
|
||||
__slots__ = ["parser", "context", "filename"]
|
||||
|
|
|
@ -51,6 +51,10 @@
|
|||
# error #define __pvr_get_address before including this file
|
||||
#endif
|
||||
|
||||
#ifndef __pvr_make_address
|
||||
# error #define __pvr_make_address before including this file
|
||||
#endif
|
||||
|
||||
union __pvr_value {
|
||||
float f;
|
||||
uint32_t dw;
|
||||
|
@ -78,6 +82,15 @@ __pvr_uint(uint64_t v, uint32_t start, NDEBUG_UNUSED uint32_t end)
|
|||
return v << start;
|
||||
}
|
||||
|
||||
static inline __attribute__((always_inline)) uint64_t
|
||||
__pvr_uint_unpack(uint64_t packed, uint32_t start, uint32_t end)
|
||||
{
|
||||
const int width = end - start + 1;
|
||||
const uint64_t mask = ~0ull >> (64 - width);
|
||||
|
||||
return (packed >> start) & mask;
|
||||
}
|
||||
|
||||
static inline __attribute__((always_inline)) uint64_t
|
||||
__pvr_sint(int64_t v, uint32_t start, uint32_t end)
|
||||
{
|
||||
|
@ -98,6 +111,15 @@ __pvr_sint(int64_t v, uint32_t start, uint32_t end)
|
|||
return (v & mask) << start;
|
||||
}
|
||||
|
||||
static inline __attribute__((always_inline)) int64_t
|
||||
__pvr_sint_unpack(uint64_t packed, uint32_t start, uint32_t end)
|
||||
{
|
||||
const int width = end - start + 1;
|
||||
const uint64_t mask = ~0ull >> (64 - width);
|
||||
|
||||
return (int64_t)((packed >> start) & mask);
|
||||
}
|
||||
|
||||
static inline __attribute__((always_inline)) uint64_t
|
||||
__pvr_offset(uint64_t v,
|
||||
NDEBUG_UNUSED uint32_t start,
|
||||
|
@ -113,6 +135,20 @@ __pvr_offset(uint64_t v,
|
|||
return v;
|
||||
}
|
||||
|
||||
static inline __attribute__((always_inline)) uint64_t
|
||||
__pvr_offset_unpack(uint64_t packed,
|
||||
NDEBUG_UNUSED uint32_t start,
|
||||
NDEBUG_UNUSED uint32_t end)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
uint64_t mask = (~0ull >> (64 - (end - start + 1))) << start;
|
||||
|
||||
assert((packed & ~mask) == 0);
|
||||
#endif
|
||||
|
||||
return packed;
|
||||
}
|
||||
|
||||
static inline __attribute__((always_inline)) uint64_t
|
||||
__pvr_address(__pvr_address_type address,
|
||||
uint32_t shift,
|
||||
|
@ -125,12 +161,30 @@ __pvr_address(__pvr_address_type address,
|
|||
return ((addr_u64 >> shift) << start) & mask;
|
||||
}
|
||||
|
||||
static inline __attribute__((always_inline)) __pvr_address_type
|
||||
__pvr_address_unpack(uint64_t packed,
|
||||
uint32_t shift,
|
||||
uint32_t start,
|
||||
uint32_t end)
|
||||
{
|
||||
uint64_t mask = (~0ull >> (64 - (end - start + 1))) << start;
|
||||
uint64_t addr_u64 = ((packed & mask) >> start) << shift;
|
||||
|
||||
return __pvr_make_address(addr_u64);
|
||||
}
|
||||
|
||||
static inline __attribute__((always_inline)) uint32_t __pvr_float(float v)
|
||||
{
|
||||
__pvr_validate_value(v);
|
||||
return ((union __pvr_value){ .f = (v) }).dw;
|
||||
}
|
||||
|
||||
static inline __attribute__((always_inline)) float
|
||||
__pvr_float_unpack(uint32_t packed)
|
||||
{
|
||||
return ((union __pvr_value){ .dw = (packed) }).f;
|
||||
}
|
||||
|
||||
static inline __attribute__((always_inline)) uint64_t
|
||||
__pvr_sfixed(float v, uint32_t start, uint32_t end, uint32_t fract_bits)
|
||||
{
|
||||
|
|
|
@ -35,10 +35,14 @@
|
|||
|
||||
#define __pvr_address_type pvr_dev_addr_t
|
||||
#define __pvr_get_address(pvr_dev_addr) (pvr_dev_addr).addr
|
||||
/* clang-format off */
|
||||
#define __pvr_make_address(addr_u64) (pvr_dev_addr_t){ .addr = addr_u64 }
|
||||
/* clang-format on */
|
||||
|
||||
#include "csbgen/rogue_cdm.h"
|
||||
#include "csbgen/rogue_lls.h"
|
||||
|
||||
#undef __pvr_make_address
|
||||
#undef __pvr_get_address
|
||||
#undef __pvr_address_type
|
||||
|
||||
|
|
|
@ -36,9 +36,11 @@
|
|||
|
||||
#define __pvr_address_type uint64_t
|
||||
#define __pvr_get_address(pvr_dev_addr) (pvr_dev_addr)
|
||||
#define __pvr_make_address(addr_u64) (addr_u64)
|
||||
|
||||
#include "csbgen/rogue_pds.h"
|
||||
|
||||
#undef __pvr_make_address
|
||||
#undef __pvr_get_address
|
||||
#undef __pvr_address_type
|
||||
|
||||
|
|
|
@ -42,6 +42,9 @@
|
|||
|
||||
#define __pvr_address_type pvr_dev_addr_t
|
||||
#define __pvr_get_address(pvr_dev_addr) (pvr_dev_addr).addr
|
||||
/* clang-format off */
|
||||
#define __pvr_make_address(addr_u64) (pvr_dev_addr_t){ .addr = addr_u64 }
|
||||
/* clang-format on */
|
||||
|
||||
#include "csbgen/rogue_hwdefs.h"
|
||||
|
||||
|
|
Loading…
Reference in New Issue