Mesa (main): pvr: csbgen: Add *_unpack() functions for all generated struct types
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Wed Jun 8 09:22:03 UTC 2022
Module: Mesa
Branch: main
Commit: 7c615b4103819e7c71e000b42f4821def70e780b
URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=7c615b4103819e7c71e000b42f4821def70e780b
Author: Matt Coster <matt.coster at imgtec.com>
Date: Thu May 12 12:00:44 2022 +0100
pvr: csbgen: Add *_unpack() functions for all generated struct types
Signed-off-by: Matt Coster <matt.coster at imgtec.com>
Reviewed-by: Frank Binns <frank.binns at imgtec.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/16884>
---
src/imagination/csbgen/gen_pack_header.py | 88 ++++++++++++++++++++++++++
src/imagination/csbgen/pvr_packet_helpers.h | 54 ++++++++++++++++
src/imagination/include/hwdef/rogue_hw_utils.h | 4 ++
src/imagination/rogue/rogue_build_data.c | 2 +
src/imagination/vulkan/pvr_csb.h | 3 +
5 files changed, 151 insertions(+)
diff --git a/src/imagination/csbgen/gen_pack_header.py b/src/imagination/csbgen/gen_pack_header.py
index 9a932c45244..1261837c078 100644
--- a/src/imagination/csbgen/gen_pack_header.py
+++ b/src/imagination/csbgen/gen_pack_header.py
@@ -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"]
diff --git a/src/imagination/csbgen/pvr_packet_helpers.h b/src/imagination/csbgen/pvr_packet_helpers.h
index 9cef13265a6..ae2b5fd89b0 100644
--- a/src/imagination/csbgen/pvr_packet_helpers.h
+++ b/src/imagination/csbgen/pvr_packet_helpers.h
@@ -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)
{
diff --git a/src/imagination/include/hwdef/rogue_hw_utils.h b/src/imagination/include/hwdef/rogue_hw_utils.h
index 39e3bea0b13..db95dfce0df 100644
--- a/src/imagination/include/hwdef/rogue_hw_utils.h
+++ b/src/imagination/include/hwdef/rogue_hw_utils.h
@@ -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
diff --git a/src/imagination/rogue/rogue_build_data.c b/src/imagination/rogue/rogue_build_data.c
index 010a10971dd..2eebf82f455 100644
--- a/src/imagination/rogue/rogue_build_data.c
+++ b/src/imagination/rogue/rogue_build_data.c
@@ -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
diff --git a/src/imagination/vulkan/pvr_csb.h b/src/imagination/vulkan/pvr_csb.h
index 372c41ebd1d..500b5e1296d 100644
--- a/src/imagination/vulkan/pvr_csb.h
+++ b/src/imagination/vulkan/pvr_csb.h
@@ -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"
More information about the mesa-commit
mailing list