From c7a10193d42bdc01a9fbe771f3afb927d4f1640d Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Sat, 5 Sep 2020 12:00:21 +0200 Subject: [PATCH] panfrost: gen_pack: Add the aggregate concept Panfrost descriptors are big and are usually built from a combination of sub-descriptors. On top of that, layout of sub-descriptors might vary depending on the architecture version. Since unions are not really an option (too complex), here is a thin abstraction layer allowing us to manipulate aggregates in their packed format. Each aggregate is formed of one or more sections that are meant to be packed/unpacked/printed separately. Section overlapping is allowed to facilitate handling of descriptor variants. Signed-off-by: Boris Brezillon Reviewed-by: Alyssa Rosenzweig Part-of: --- src/panfrost/lib/gen_pack.py | 82 +++++++++++++++++++++++++++++++++++- 1 file changed, 81 insertions(+), 1 deletion(-) diff --git a/src/panfrost/lib/gen_pack.py b/src/panfrost/lib/gen_pack.py index 1877f27a633..c17b42c4779 100644 --- a/src/panfrost/lib/gen_pack.py +++ b/src/panfrost/lib/gen_pack.py @@ -145,6 +145,23 @@ __gen_unpack_padded(const uint8_t *restrict cl, uint32_t start, uint32_t end) #define pan_print(fp, T, var, indent) \\ MALI_ ## T ## _print(fp, &(var), indent) +#define pan_section_ptr(base, A, S) \\ + ((void *)((uint8_t *)(base) + MALI_ ## A ## _SECTION_ ## S ## _OFFSET)) + +#define pan_section_pack(dst, A, S, name) \\ + for (MALI_ ## A ## _SECTION_ ## S ## _TYPE name = { MALI_ ## A ## _SECTION_ ## S ## _header }, \\ + *_loop_terminate = (void *) (dst); \\ + __builtin_expect(_loop_terminate != NULL, 1); \\ + ({ MALI_ ## A ## _SECTION_ ## S ## _pack(pan_section_ptr(dst, A, S), &name); \\ + _loop_terminate = NULL; })) + +#define pan_section_unpack(src, A, S, name) \\ + MALI_ ## A ## _SECTION_ ## S ## _TYPE name; \\ + MALI_ ## A ## _SECTION_ ## S ## _unpack(pan_section_ptr(src, A, S), &name) + +#define pan_section_print(fp, A, S, var, indent) \\ + MALI_ ## A ## _SECTION_ ## S ## _print(fp, &(var), indent) + """ def to_alphanum(name): @@ -209,6 +226,43 @@ def parse_modifier(modifier): print("Invalid modifier") assert(False) +class Aggregate(object): + def __init__(self, parser, name, attrs): + self.parser = parser + self.sections = [] + self.name = name + self.explicit_size = int(attrs["size"]) if "size" in attrs else 0 + self.size = 0 + + class Section: + def __init__(self, name): + self.name = name + + def get_size(self): + if self.size > 0: + return self.size + + size = 0 + for section in self.sections: + size = max(size, section.offset + section.type.get_length()) + + if self.explicit_size > 0: + assert(self.explicit_size >= size) + self.size = self.explicit_size + else: + self.size = size + return self.size + + def add_section(self, type_name, attrs): + assert("name" in attrs) + section = self.Section(safe_name(attrs["name"]).lower()) + section.human_name = attrs["name"] + section.offset = int(attrs["offset"]) + assert(section.offset % 4 == 0) + section.type = self.parser.structs[attrs["type"]] + section.type_name = type_name + self.sections.append(section) + class Field(object): def __init__(self, parser, attrs): self.parser = parser @@ -279,7 +333,6 @@ class Field(object): def overlaps(self, field): return self != field and max(self.start, field.start) <= min(self.end, field.end) - class Group(object): def __init__(self, parser, parent, start, count): self.parser = parser @@ -537,6 +590,8 @@ class Parser(object): self.structs = {} # Set of enum names we've seen. self.enums = set() + self.aggregate = None + self.aggregates = {} def gen_prefix(self, name): return '{}_{}'.format(global_prefix.upper(), name) @@ -568,6 +623,13 @@ class Parser(object): self.prefix= None elif name == "value": self.values.append(Value(attrs)) + elif name == "aggregate": + aggregate_name = self.gen_prefix(safe_name(attrs["name"].upper())) + self.aggregate = Aggregate(self, aggregate_name, attrs) + self.aggregates[attrs['name']] = self.aggregate + elif name == "section": + type_name = self.gen_prefix(safe_name(attrs["type"].upper())) + self.aggregate.add_section(type_name, attrs) def end_element(self, name): if name == "struct": @@ -579,6 +641,9 @@ class Parser(object): elif name == "enum": self.emit_enum() self.enum = None + elif name == "aggregate": + self.emit_aggregate() + self.aggregate = None elif name == "panxml": # Include at the end so it can depend on us but not the converse print('#include "panfrost-job.h"') @@ -610,6 +675,21 @@ class Parser(object): # Just so it isn't left undefined print('#define %-40s 0' % (name + '_OPAQUE_header')) + def emit_aggregate(self): + aggregate = self.aggregate + print("struct %s_packed {" % aggregate.name.lower()) + print(" uint32_t opaque[{}];".format(aggregate.get_size() // 4)) + print("};\n") + print('#define {}_LENGTH {}'.format(aggregate.name.upper(), aggregate.size)) + for section in aggregate.sections: + print('#define {}_SECTION_{}_TYPE struct {}'.format(aggregate.name.upper(), section.name.upper(), section.type_name)) + print('#define {}_SECTION_{}_header {}_header'.format(aggregate.name.upper(), section.name.upper(), section.type_name)) + print('#define {}_SECTION_{}_pack {}_pack'.format(aggregate.name.upper(), section.name.upper(), section.type_name)) + print('#define {}_SECTION_{}_unpack {}_unpack'.format(aggregate.name.upper(), section.name.upper(), section.type_name)) + print('#define {}_SECTION_{}_print {}_print'.format(aggregate.name.upper(), section.name.upper(), section.type_name)) + print('#define {}_SECTION_{}_OFFSET {}'.format(aggregate.name.upper(), section.name.upper(), section.offset)) + print("") + def emit_pack_function(self, name, group, with_opaque): print("static inline void\n%s_pack(uint32_t * restrict cl,\n%sconst struct %s * restrict values)\n{" % (name, ' ' * (len(name) + 6), name))