pco, pygen: generate op and mod info

Signed-off-by: Simon Perretta <simon.perretta@imgtec.com>
Acked-by: Frank Binns <frank.binns@imgtec.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32258>
This commit is contained in:
Simon Perretta
2024-05-12 00:16:45 +01:00
committed by Marge Bot
parent 8887bc0d47
commit d47ac545d5
7 changed files with 288 additions and 61 deletions

View File

@@ -23,6 +23,15 @@ pco_common_h = custom_target(
depend_files : pco_pygen_dep_files,
)
pco_info_c = custom_target(
'pco_info.c',
input : ['pco_info.c.py'],
output : 'pco_info.c',
command : [prog_python, '@INPUT@'],
capture : true,
depend_files : pco_pygen_dep_files,
)
pco_isa_h = custom_target(
'pco_isa.h',
input : ['pco_isa.h.py'],
@@ -44,13 +53,14 @@ pco_ops_h = custom_target(
idep_pco_pygen = declare_dependency(
sources : [
pco_common_h,
pco_info_c,
pco_isa_h,
pco_ops_h,
],
include_directories : inc_powervr_compiler,
)
pco_pygen_c_files = []
pco_pygen_c_files = [pco_info_c]
libpowervr_compiler = static_library(
'powervr_compiler',

View File

@@ -49,6 +49,7 @@ static bool ${enum.name}_valid(uint64_t val)
% endfor
/** Bit set variants. */
% for bit_set in bit_sets.values():
#define _${bit_set.name.upper()}_VARIANT_COUNT ${len(bit_set.variants) + 1}U
enum ${bit_set.name}_variant {
${bit_set.name.upper()}_NONE,
% for variant, *_ in bit_set.variants:

View File

@@ -0,0 +1,95 @@
# Copyright © 2024 Imagination Technologies Ltd.
# SPDX-License-Identifier: MIT
from mako.template import Template
from pco_ops import *
template = """/*
* Copyright © 2024 Imagination Technologies Ltd.
*
* SPDX-License-Identifier: MIT
*/
/**
* \\file pco_info.c
*
* \\brief PCO info structures.
*/
#include "pco_common.h"
#include "pco_internal.h"
#include "pco_isa.h"
#include "pco_ops.h"
const struct pco_op_info pco_op_info[_PCO_OP_COUNT] = {
% for op in ops.values():
[${op.cname.upper()}] = {
.str = "${op.name}",
.num_dests = ${op.num_dests},
.num_srcs = ${op.num_srcs},
.mods = ${op.cop_mods},
.mod_map = {
% for mod, index in op.op_mod_map.items():
[${mod}] = ${index},
% endfor
},
.dest_mods = {
% for index, cdest_mods in op.cdest_mods.items():
[${index}] = ${cdest_mods},
% endfor
},
.src_mods = {
% for index, csrc_mods in op.csrc_mods.items():
[${index}] = ${csrc_mods},
% endfor
},
.is_pseudo = ${str(op.is_pseudo).lower()},
.has_target_cf_node = ${str(op.has_target_cf_node).lower()},
},
% endfor
};
const struct pco_op_mod_info pco_op_mod_info[_PCO_OP_MOD_COUNT] = {
% for name, (mod, cname, ctype) in op_mods.items():
[${cname}] = {
.print_early = ${str(mod.print_early).lower()},
.type = ${ctype},
% if mod.base_type == BaseType.enum:
.strs = (const char * []){
% for enum_cname, value, string in mod.enum.elems.values():
[${enum_cname}] = "${string}",
% endfor
},
% else:
.str = "${name}",
% endif
% if mod.nzdefault is not None:
.nzdefault = ${mod.nzdefault},
% endif
},
% endfor
};
const struct pco_ref_mod_info pco_ref_mod_info[_PCO_REF_MOD_COUNT] = {
% for name, (mod, cname, ctype) in ref_mods.items():
[${cname}] = {
.type = ${ctype},
% if mod.base_type == BaseType.enum:
.is_bitset = ${str(mod.enum.is_bitset).lower()},
.strs = (const char * []){
% for enum_cname, value, string in mod.enum.elems.values():
[${enum_cname}] = "${string}",
% endfor
},
% else:
.str = "${name}",
% endif
},
% endfor
};"""
def main():
print(Template(template).render(BaseType=BaseType, ops=ops, op_mods=op_mods, ref_mods=ref_mods))
if __name__ == '__main__':
main()

View File

@@ -16,6 +16,7 @@
#include "compiler/spirv/nir_spirv.h"
#include "pco.h"
#include "pco_common.h"
#include "pco_ops.h"
#include "spirv/nir_spirv.h"
#include "util/macros.h"
@@ -70,4 +71,41 @@ extern const char *pco_skip_passes;
extern bool pco_color;
void pco_debug_init(void);
/** Op info. */
struct pco_op_info {
const char *str; /** Op name string. */
unsigned num_dests; /** Number of dests. */
unsigned num_srcs; /** Number of sources. */
uint64_t mods; /** Supported mods. */
uint8_t mod_map[_PCO_OP_MOD_COUNT]; /** Index into pco_instr::mod. */
uint64_t dest_mods[_PCO_OP_MAX_DESTS]; /** Supported dest mods. */
uint64_t src_mods[_PCO_OP_MAX_SRCS]; /** Supported source mods. */
bool is_pseudo; /** Set if op is a pseudo-instruction. */
bool has_target_cf_node; /** Set if op has a cf-node as a target. */
};
extern const struct pco_op_info pco_op_info[_PCO_OP_COUNT];
/** Op mod info. */
struct pco_op_mod_info {
bool print_early : 1; /** Set if printed before the op. */
enum pco_mod_type type; /** Datatype. */
union {
const char *str; /** Mod name. */
const char **strs; /** Mod names (enums). */
};
uint32_t nzdefault; /** Default value if non-zero. */
};
extern const struct pco_op_mod_info pco_op_mod_info[_PCO_OP_MOD_COUNT];
/** Reference mod info. */
struct pco_ref_mod_info {
bool is_bitset : 1; /** Set if type is an enum bitset. */
enum pco_mod_type type; /** Datatype. */
union {
const char *str; /** Mod name. */
const char **strs; /** Mod names (enums). */
};
};
extern const struct pco_ref_mod_info pco_ref_mod_info[_PCO_REF_MOD_COUNT];
#endif /* PCO_INTERNAL_H */

View File

@@ -25,10 +25,41 @@ template = """/*
#include <stdbool.h>
#include <stdint.h>
#define _PCO_OP_MAX_DESTS ${max([op.num_dests for op in ops.values()])}U
#define _PCO_OP_MAX_SRCS ${max([op.num_srcs for op in ops.values()])}U
#define _PCO_OP_MAX_MODS ${max([len(op.op_mods) for op in ops.values()])}U
/** Ops. */
#define _PCO_OP_COUNT ${len(ops) + 1}U
enum pco_op {
PCO_OP_NONE,
% for op in ops.values():
${op.cname.upper()},
% endfor
};
/** Op mods. */
#define _PCO_OP_MOD_COUNT ${len(op_mods) + 1}U
enum pco_op_mod {
PCO_OP_MOD_NONE,
% for op_mod, cname, *_ in op_mods.values():
${cname},
% endfor
};
/** Ref mods. */
#define _PCO_REF_MOD_COUNT ${len(ref_mods) + 1}U
enum pco_ref_mod {
PCO_REF_MOD_NONE,
% for ref_mod, cname, *_ in ref_mods.values():
${cname},
% endfor
};
#endif /* PCO_OPS_H */"""
def main():
print(Template(template).render())
print(Template(template).render(ops=ops, op_mods=op_mods, ref_mods=ref_mods))
if __name__ == '__main__':
main()

View File

@@ -21,27 +21,27 @@ REF_TYPE = enum_type('ref_type', [
])
# Ref mods.
R_ONEMINUS = ref_mod('oneminus', BaseType.bool)
R_CLAMP = ref_mod('clamp', BaseType.bool)
R_ABS = ref_mod('abs', BaseType.bool)
R_NEG = ref_mod('neg', BaseType.bool)
R_FLR = ref_mod('flr', BaseType.bool)
RM_ONEMINUS = ref_mod('oneminus', BaseType.bool)
RM_CLAMP = ref_mod('clamp', BaseType.bool)
RM_ABS = ref_mod('abs', BaseType.bool)
RM_NEG = ref_mod('neg', BaseType.bool)
RM_FLR = ref_mod('flr', BaseType.bool)
R_ELEM = ref_mod_enum('elem', [
RM_ELEM = ref_mod_enum('elem', [
'e0',
'e1',
'e2',
'e3',
], is_bitset=True)
R_DTYPE = ref_mod_enum('dtype', [
RM_DTYPE = ref_mod_enum('dtype', [
('any', ''),
('unsigned', 'u'),
('signed', 'i'),
('float', 'f'),
])
R_BITS = ref_mod_enum('bits', [
RM_BITS = ref_mod_enum('bits', [
('any', ''),
('1', '1'),
('8', '8'),
@@ -50,7 +50,7 @@ R_BITS = ref_mod_enum('bits', [
('64', '64'),
])
R_REG_CLASS = ref_mod_enum('reg_class', [
RM_REG_CLASS = ref_mod_enum('reg_class', [
('virt', '$'),
('temp', 'r'),
('vtxin', 'vi'),
@@ -65,7 +65,7 @@ R_REG_CLASS = ref_mod_enum('reg_class', [
('slot', 'sl'),
])
R_IO = ref_mod_enum('io', [
RM_IO = ref_mod_enum('io', [
('s0', 's0'),
('s1', 's1'),
('s2', 's2'),
@@ -100,7 +100,7 @@ R_IO = ref_mod_enum('io', [
('cout', 'cout'),
])
R_PRED = ref_mod_enum('pred', [
RM_PRED = ref_mod_enum('pred', [
('pe', 'pe'),
('p0', 'p0'),
@@ -110,29 +110,29 @@ R_PRED = ref_mod_enum('pred', [
('p0_false', 'if(!p0)'),
])
R_DRC = ref_mod_enum('drc', [
RM_DRC = ref_mod_enum('drc', [
('pending', '?'),
('0', '0'),
('1', '1'),
])
# Op mods.
O_EXEC_CND = op_mod_enum('exec_cnd', [
OM_EXEC_CND = op_mod_enum('exec_cnd', [
('e1_zx', ''),
('e1_z1', 'if(p0)'),
('ex_zx', '(ignorepe)'),
('e1_z0', 'if(!p0)'),
], print_early=True)
O_RPT = op_mod('rpt', BaseType.uint, print_early=True, nzdefault=1)
O_ATOM = op_mod('atom', BaseType.bool)
O_END = op_mod('end', BaseType.bool)
O_OLCHK = op_mod('olchk', BaseType.bool)
O_SAT = op_mod('sat', BaseType.bool)
O_LP = op_mod('lp', BaseType.bool)
O_SCALE = op_mod('scale', BaseType.bool)
O_ROUNDZERO = op_mod('roundzero', BaseType.bool)
O_S = op_mod('s', BaseType.bool)
O_TST_OP_MAIN = op_mod_enum('tst_op_main', [
OM_RPT = op_mod('rpt', BaseType.uint, print_early=True, nzdefault=1)
OM_ATOM = op_mod('atom', BaseType.bool)
OM_END = op_mod('end', BaseType.bool)
OM_OLCHK = op_mod('olchk', BaseType.bool)
OM_SAT = op_mod('sat', BaseType.bool)
OM_LP = op_mod('lp', BaseType.bool)
OM_SCALE = op_mod('scale', BaseType.bool)
OM_ROUNDZERO = op_mod('roundzero', BaseType.bool)
OM_S = op_mod('s', BaseType.bool)
OM_TST_OP_MAIN = op_mod_enum('tst_op_main', [
('zero', 'z'),
('gzero', 'gz'),
('gezero', 'gez'),
@@ -144,52 +144,52 @@ O_TST_OP_MAIN = op_mod_enum('tst_op_main', [
('less', 'l'),
('lequal', 'le'),
])
O_TST_OP_BITWISE = op_mod_enum('tst_op_bitwise', [
OM_TST_OP_BITWISE = op_mod_enum('tst_op_bitwise', [
('zero', 'z'),
('nonzero', 'nz'),
])
O_SIGNPOS = op_mod_enum('signpos', [
OM_SIGNPOS = op_mod_enum('signpos', [
'twb',
'pwb',
'mtb',
'ftb',
])
O_DIM = op_mod('dim', BaseType.uint)
O_PROJ = op_mod('proj', BaseType.bool)
O_FCNORM = op_mod('fcnorm', BaseType.bool)
O_NNCOORDS = op_mod('nncoords', BaseType.bool)
O_LOD_MODE = op_mod_enum('lod_mode', [
OM_DIM = op_mod('dim', BaseType.uint)
OM_PROJ = op_mod('proj', BaseType.bool)
OM_FCNORM = op_mod('fcnorm', BaseType.bool)
OM_NNCOORDS = op_mod('nncoords', BaseType.bool)
OM_LOD_MODE = op_mod_enum('lod_mode', [
('normal', ''),
('bias', '.bias'),
('replace', '.replace'),
('gradient', '.gradient'),
])
O_PPLOD = op_mod('pplod', BaseType.bool)
O_TAO = op_mod('tao', BaseType.bool)
O_SOO = op_mod('soo', BaseType.bool)
O_SNO = op_mod('sno', BaseType.bool)
O_WRT = op_mod('wrt', BaseType.bool)
O_SB_MODE = op_mod_enum('sb_mode', [
OM_PPLOD = op_mod('pplod', BaseType.bool)
OM_TAO = op_mod('tao', BaseType.bool)
OM_SOO = op_mod('soo', BaseType.bool)
OM_SNO = op_mod('sno', BaseType.bool)
OM_WRT = op_mod('wrt', BaseType.bool)
OM_SB_MODE = op_mod_enum('sb_mode', [
('none', ''),
('data', '.data'),
('info', '.info'),
('both', '.both'),
])
O_ARRAY = op_mod('array', BaseType.bool)
O_INTEGER = op_mod('integer', BaseType.bool)
O_SCHEDSWAP = op_mod('schedswap', BaseType.bool)
O_F16 = op_mod('f16', BaseType.bool)
O_TILED = op_mod('tiled', BaseType.bool)
O_FREEP = op_mod('freep', BaseType.bool)
O_SM = op_mod('sm', BaseType.bool)
O_SAVMSK_MODE = op_mod_enum('savmsk_mode', [
OM_ARRAY = op_mod('array', BaseType.bool)
OM_INTEGER = op_mod('integer', BaseType.bool)
OM_SCHEDSWAP = op_mod('schedswap', BaseType.bool)
OM_F16 = op_mod('f16', BaseType.bool)
OM_TILED = op_mod('tiled', BaseType.bool)
OM_FREEP = op_mod('freep', BaseType.bool)
OM_SM = op_mod('sm', BaseType.bool)
OM_SAVMSK_MODE = op_mod_enum('savmsk_mode', [
'vm',
'icm',
'icmoc',
'icmi',
'caxy',
])
O_ATOM_OP = op_mod_enum('atom_op', [
OM_ATOM_OP = op_mod_enum('atom_op', [
'add',
'sub',
'xchg',
@@ -201,23 +201,23 @@ O_ATOM_OP = op_mod_enum('atom_op', [
'or',
'xor',
])
O_MCU_CACHE_MODE_LD = op_mod_enum('mcu_cache_mode_ld', [
OM_MCU_CACHE_MODE_LD = op_mod_enum('mcu_cache_mode_ld', [
('normal', ''),
('bypass', '.bypass'),
('force_line_fill', '.forcelinefill'),
])
O_MCU_CACHE_MODE_ST = op_mod_enum('mcu_cache_mode_st', [
OM_MCU_CACHE_MODE_ST = op_mod_enum('mcu_cache_mode_st', [
('write_through', '.writethrough'),
('write_back', '.writeback'),
('lazy_write_back', '.lazywriteback'),
])
O_BRANCH_CND = op_mod_enum('branch_cnd', [
OM_BRANCH_CND = op_mod_enum('branch_cnd', [
('exec_cond', ''),
('allinst', '.allinst'),
('anyinst', '.anyinst'),
])
O_LINK = op_mod('link', BaseType.bool)
O_PCK_FMT = op_mod_enum('pck_fmt', [
OM_LINK = op_mod('link', BaseType.bool)
OM_PCK_FMT = op_mod_enum('pck_fmt', [
'u8888',
's8888',
'o8888',
@@ -244,4 +244,9 @@ O_PCK_FMT = op_mod_enum('pck_fmt', [
'zero',
'one',
])
O_PHASE2END = op_mod('phase2end', BaseType.bool)
OM_PHASE2END = op_mod('phase2end', BaseType.bool)
# HW ops
O_NOP = hw_op('nop', [OM_EXEC_CND, OM_END])
O_FADD = hw_op('fadd', [OM_LP, OM_SAT], 1, 2, [], [[RM_ABS, RM_NEG, RM_FLR], [RM_ABS]])

View File

@@ -146,34 +146,42 @@ op_mod_enums = {}
def op_mod(name, *args, **kwargs):
assert name not in op_mods.keys(), f'Duplicate op mod "{name}".'
t = type(name, *args, **kwargs)
op_mods[name] = t
cname = f'{prefix}_op_mod_{name}'.upper()
ctype = f'{prefix}_mod_type_{t.base_type.name.upper()}'.upper()
om = op_mods[name] = (t, cname, ctype)
assert len(op_mods) <= 64, f'Too many op mods ({len(op_mods)})!'
return t
return om
def op_mod_enum(name, *args, **kwargs):
assert name not in op_mods.keys() and name not in op_mod_enums.keys(), f'Duplicate op mod enum "{name}".'
t = enum_type(name, *args, **kwargs)
op_mods[name] = t
cname = f'{prefix}_op_mod_{name}'.upper()
ctype = f'{prefix}_mod_type_{t.base_type.name.upper()}'.upper()
om = op_mods[name] = (t, cname, ctype)
op_mod_enums[name] = enums[name]
assert len(op_mods) <= 64, f'Too many op mods ({len(op_mods)})!'
return t
return om
ref_mods = {}
ref_mod_enums = {}
def ref_mod(name, *args, **kwargs):
assert name not in ref_mods.keys(), f'Duplicate ref mod "{name}".'
t = type(name, *args, **kwargs)
ref_mods[name] = t
cname = f'{prefix}_ref_mod_{name}'.upper()
ctype = f'{prefix}_mod_type_{t.base_type.name.upper()}'.upper()
rm = ref_mods[name] = (t, cname, ctype)
assert len(ref_mods) <= 64, f'Too many ref mods ({len(ref_mods)})!'
return t
return rm
def ref_mod_enum(name, *args, **kwargs):
assert name not in ref_mods.keys() and name not in ref_mod_enums.keys(), f'Duplicate ref mod enum "{name}".'
t = enum_type(name, *args, **kwargs)
ref_mods[name] = t
cname = f'{prefix}_ref_mod_{name}'.upper()
ctype = f'{prefix}_mod_type_{t.base_type.name.upper()}'.upper()
rm = ref_mods[name] = (t, cname, ctype)
ref_mod_enums[name] = enums[name]
assert len(ref_mods) <= 64, f'Too many ref mods ({len(ref_mods)})!'
return t
return rm
# Bit encoding definition helpers.
@@ -350,3 +358,42 @@ def bit_struct(name, bit_set, field_mappings, data=None):
bit_set.variants.append((f'{bit_set.name}_{name}'.upper(), total_bytes))
return bs
# Op definitions.
VARIABLE = ~0
class Op(object):
def __init__(self, name, cname, is_pseudo, op_mods, cop_mods, op_mod_map, num_dests, num_srcs, dest_mods, cdest_mods, src_mods, csrc_mods, has_target_cf_node):
self.name = name
self.cname = cname
self.is_pseudo = is_pseudo
self.op_mods = op_mods
self.cop_mods = cop_mods
self.op_mod_map = op_mod_map
self.num_dests = num_dests
self.num_srcs = num_srcs
self.dest_mods = dest_mods
self.cdest_mods = cdest_mods
self.src_mods = src_mods
self.csrc_mods = csrc_mods
self.has_target_cf_node = has_target_cf_node
ops = {}
def op(name, is_pseudo, op_mods, num_dests, num_srcs, dest_mods, src_mods, has_target_cf_node):
assert name not in ops.keys(), f'Duplicate op "{name}".'
cname = f'{prefix}_op_{name}'.replace('.', '_')
cop_mods = 0 if not op_mods else ' | '.join([f'(1 << {mod[1]})' for mod in op_mods])
op_mod_map = {mod[1]: index + 1 for index, mod in enumerate(op_mods)}
cdest_mods = {i: 0 if not dest_mods else ' | '.join([f'(1 << {mod[1]})' for mod in destn_mods]) for i, destn_mods in enumerate(dest_mods)}
csrc_mods = {i: 0 if not src_mods else ' | '.join([f'(1 << {mod[1]})' for mod in srcn_mods]) for i, srcn_mods in enumerate(src_mods)}
op = Op(name, cname, is_pseudo, op_mods, cop_mods, op_mod_map, num_dests, num_srcs, dest_mods, cdest_mods, src_mods, csrc_mods, has_target_cf_node)
ops[name] = op
return op
def pseudo_op(name, op_mods=[], num_dests=0, num_srcs=0, dest_mods=[], src_mods=[], has_target_cf_node=False):
return op(name, True, op_mods, num_dests, num_srcs, dest_mods, src_mods, has_target_cf_node)
def hw_op(name, op_mods=[], num_dests=0, num_srcs=0, dest_mods=[], src_mods=[], has_target_cf_node=False):
return op(name, False, op_mods, num_dests, num_srcs, dest_mods, src_mods, has_target_cf_node)