diff --git a/src/compiler/isaspec/decode.py b/src/compiler/isaspec/decode.py index 9acbd17ab18..9f50dc94a11 100755 --- a/src/compiler/isaspec/decode.py +++ b/src/compiler/isaspec/decode.py @@ -88,8 +88,8 @@ ${expr.get_c_name()}(struct decode_scope *scope) * emit various tables when they have pointers to each other) */ -%for name, bitset in isa.bitsets.items(): -static const struct isa_bitset bitset_${bitset.get_c_name()}; +%for name, bitset in isa.all_bitsets(): +static const struct isa_bitset bitset_${bitset.get_c_name()}_gen_${bitset.gen_min}; %endfor %for root_name, root in isa.roots.items(): @@ -100,12 +100,12 @@ const struct isa_bitset *${root.get_c_name()}[]; * bitset tables: */ -%for name, bitset in isa.bitsets.items(): +%for name, bitset in isa.all_bitsets(): % for case in bitset.cases: % for field_name, field in case.fields.items(): % if field.get_c_typename() == 'TYPE_BITSET': % if len(field.params) > 0: -static const struct isa_field_params ${case.get_c_name()}_${field.get_c_name()} = { +static const struct isa_field_params ${case.get_c_name()}_gen_${bitset.gen_min}_${field.get_c_name()} = { .num_params = ${len(field.params)}, .params = { % for param in field.params: @@ -117,7 +117,7 @@ static const struct isa_field_params ${case.get_c_name()}_${field.get_c_name()} % endif % endif % endfor -static const struct isa_case ${case.get_c_name()} = { +static const struct isa_case ${case.get_c_name()}_gen_${bitset.gen_min} = { % if case.expr is not None: .expr = &${isa.expressions[case.expr].get_c_name()}, % endif @@ -138,7 +138,7 @@ static const struct isa_case ${case.get_c_name()} = { % if field.get_c_typename() == 'TYPE_BITSET': .bitsets = ${isa.roots[field.type].get_c_name()}, % if len(field.params) > 0: - .params = &${case.get_c_name()}_${field.get_c_name()}, + .params = &${case.get_c_name()}_gen_${bitset.gen_min}_${field.get_c_name()}, % endif % endif % if field.get_c_typename() == 'TYPE_ENUM': @@ -152,10 +152,10 @@ static const struct isa_case ${case.get_c_name()} = { }, }; % endfor -static const struct isa_bitset bitset_${bitset.get_c_name()} = { +static const struct isa_bitset bitset_${bitset.get_c_name()}_gen_${bitset.gen_min} = { <% pattern = bitset.get_pattern() %> % if bitset.extends is not None: - .parent = &bitset_${isa.bitsets[bitset.extends].get_c_name()}, + .parent = &bitset_${isa.bitsets[bitset.extends].get_c_name()}_gen_${isa.bitsets[bitset.extends].gen_min}, % endif .name = "${name}", .gen = { @@ -168,7 +168,7 @@ static const struct isa_bitset bitset_${bitset.get_c_name()} = { .num_cases = ${len(bitset.cases)}, .cases = { % for case in bitset.cases: - &${case.get_c_name()}, + &${case.get_c_name()}_gen_${bitset.gen_min}, % endfor }, }; @@ -180,10 +180,12 @@ static const struct isa_bitset bitset_${bitset.get_c_name()} = { %for root_name, root in isa.roots.items(): const struct isa_bitset *${root.get_c_name()}[] = { -% for leaf_name, leaf in isa.leafs.items(): -% if leaf.get_root() == root: - &bitset_${leaf.get_c_name()}, -% endif +% for leaf_name, leafs in isa.leafs.items(): +% for leaf in leafs: +% if leaf.get_root() == root: + &bitset_${leaf.get_c_name()}_gen_${leaf.gen_min}, +% endif +% endfor % endfor (void *)0 }; diff --git a/src/compiler/isaspec/encode.py b/src/compiler/isaspec/encode.py index a0bfbf55b73..f24cfba5deb 100755 --- a/src/compiler/isaspec/encode.py +++ b/src/compiler/isaspec/encode.py @@ -219,10 +219,17 @@ class State(object): yield root def encode_leafs(self, root): - for name, leaf in self.isa.leafs.items(): - if leaf.get_root() != root: - continue - yield leaf + for name, leafs in self.isa.leafs.items(): + for leaf in leafs: + if leaf.get_root() != root: + continue + yield leaf + + def encode_leaf_groups(self, root): + for name, leafs in self.isa.leafs.items(): + if leafs[0].get_root() != root: + continue + yield leafs # expressions used in a bitset (case or field or recursively parent bitsets) def bitset_used_exprs(self, bitset): @@ -514,12 +521,23 @@ encode${root.get_c_name()}(struct encode_state *s, struct bitset_params *p, ${ro { % if root.encode.case_prefix is not None: switch (${root.get_c_name()}_case(s, src)) { -% for leaf in s.encode_leafs(root): - case ${s.case_name(root, leaf.name)}: { +% for leafs in s.encode_leaf_groups(root): + case ${s.case_name(root, leafs[0].name)}: { +% for leaf in leafs: +% if leaf.has_gen_restriction(): + if (s->gen >= ${leaf.gen_min} && s->gen <= ${leaf.gen_max}) { +% endif <% snippet = encode_bitset.render(s=s, root=root, leaf=leaf) %> bitmask_t val = uint64_t_to_bitmask(${hex(leaf.get_pattern().match)}); BITSET_OR(val.bitset, val.bitset, ${root.snippets[snippet]}(s, p, src).bitset); return val; +% if leaf.has_gen_restriction(): + } +% endif +% endfor +% if leaf.has_gen_restriction(): + break; +% endif } % endfor default: diff --git a/src/compiler/isaspec/isa.py b/src/compiler/isaspec/isa.py index 22976caa492..6575f0b2e9b 100644 --- a/src/compiler/isaspec/isa.py +++ b/src/compiler/isaspec/isa.py @@ -356,6 +356,9 @@ class BitSet(object): return min(self.gen_max, parent.get_gen_max()) return self.gen_max + def has_gen_restriction(self): + return self.gen_min != 0 or self.gen_max != (1 << 32) - 1 + def get_c_name(self): return get_c_name(self.name) @@ -417,9 +420,11 @@ class ISA(object): self.roots = {} # Table of leaf nodes of bitset hierarchies: + # Note that there may be multiple leaves for a particular name + # (distinguished by gen), so the values here are lists. self.leafs = {} - # Table of all bitsets: + # Table of all non-ambiguous bitsets (i.e. no per-gen ambiguity): self.bitsets = {} # Max needed bitsize for one instruction @@ -464,15 +469,23 @@ class ISA(object): else: dbg("derived: " + b.name) self.bitsets[b.name] = b - self.leafs[b.name] = b + self.leafs.setdefault(b.name, []).append(b) + def validate_isa(self): + # Do one-time fixups # Remove non-leaf nodes from the leafs table: - for name, bitset in self.bitsets.items(): - if bitset.extends is not None: + for name, bitsets in list(self.leafs.items()): + for bitset in bitsets: if bitset.extends in self.leafs: del self.leafs[bitset.extends] - def validate_isa(self): + # Fix multi-gen leaves in bitsets + for name, bitsets in self.leafs.items(): + if len(bitsets) == 1: + continue + + del self.bitsets[name] + # Validate that all bitset fields have valid types, and in # the case of bitset type, the sizes match: builtin_types = ['branch', 'int', 'uint', 'hex', 'offset', 'uoffset', 'float', 'bool', 'enum'] @@ -502,11 +515,12 @@ class ISA(object): # Validate that all the leaf node bitsets have no remaining # undefined bits - for name, bitset in self.leafs.items(): - pat = bitset.get_pattern() - sz = bitset.get_size() - assert ((pat.mask | pat.field_mask) == (1 << sz) - 1), "leaf bitset {} has undefined bits: {:x}".format( - bitset.name, ~(pat.mask | pat.field_mask) & ((1 << sz) - 1)) + for name, bitsets in self.leafs.items(): + for bitset in bitsets: + pat = bitset.get_pattern() + sz = bitset.get_size() + assert ((pat.mask | pat.field_mask) == (1 << sz) - 1), "leaf bitset {} has undefined bits: {:x}".format( + bitset.name, ~(pat.mask | pat.field_mask) & ((1 << sz) - 1)) # TODO somehow validating that only one bitset in a hierarchy # matches any given bit pattern would be useful. @@ -551,3 +565,14 @@ class ISA(object): parts.append('0x0') return parts + + # Returns all bitsets in the ISA, including all per-gen variants, in + # (name, bitset) pairs. + def all_bitsets(self): + for name, bitset in self.bitsets.items(): + yield name, bitset + for name, bitsets in self.leafs.items(): + if len(bitsets) == 1: + continue + for bitset in bitsets: + yield name, bitset diff --git a/src/freedreno/isa/encode.c b/src/freedreno/isa/encode.c index 4e61d685583..6f6fdce2d1d 100644 --- a/src/freedreno/isa/encode.c +++ b/src/freedreno/isa/encode.c @@ -33,6 +33,8 @@ struct bitset_params; struct encode_state { + unsigned gen; + struct ir3_compiler *compiler; /** @@ -321,6 +323,7 @@ isa_assemble(struct ir3_shader_variant *v) foreach_block (block, &shader->block_list) { foreach_instr (instr, &block->instr_list) { struct encode_state s = { + .gen = shader->compiler->gen * 100, .compiler = shader->compiler, .instr = instr, };