pvr: Add support for validating modifier combos

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/21474>
This commit is contained in:
Simon Perretta 2023-02-12 15:26:06 +00:00 committed by Marge Bot
parent 8ef839374e
commit bdbd69edb8
5 changed files with 191 additions and 42 deletions

View file

@ -251,6 +251,7 @@ ForEachMacros: [
'rogue_foreach_instr_in_shader_safe',
'rogue_foreach_instr_in_shader_rev',
'rogue_foreach_instr_in_shader_safe_rev',
'rogue_foreach_mod_in_set',
'rogue_foreach_reg',
'rogue_foreach_reg_safe',
'rogue_foreach_reg_use',

View file

@ -348,15 +348,16 @@ enum rogue_instr_phase {
ROGUE_INSTR_PHASE_INVALID = ~0,
};
#define rogue_foreach_phase_in_set(p, phases) \
for (uint64_t __phases = (phases), p; \
((p) = ffsll(__phases) - 1, __phases); \
__phases &= ~(1ull << (p)))
/* TODO: put into bitscan.h */
#define u_foreach_bit64_rev(b, dword) \
for (uint64_t __dword = (dword), b; \
((b) = util_last_bit64(__dword) - 1, __dword); \
__dword &= ~(1ull << (b)))
#define rogue_foreach_phase_in_set_rev(p, phases) \
for (uint64_t __phases = (phases), p; \
((p) = util_last_bit64(__phases) - 1, __phases); \
__phases &= ~(1ull << (p)))
#define rogue_foreach_phase_in_set(p, phases) u_foreach_bit64(p, phases)
#define rogue_foreach_phase_in_set_rev(p, phases) u_foreach_bit64_rev(p, phases)
#define rogue_foreach_mod_in_set(m, mods) u_foreach_bit64(m, mods)
/** Rogue basic block. */
typedef struct rogue_block {
@ -1046,6 +1047,8 @@ enum rogue_alu_op_mod {
typedef struct rogue_alu_op_mod_info {
const char *str;
uint64_t exclude; /* Can't use this op mod with any of these. */
uint64_t require; /* Required op mods for this to be used (OR). */
} rogue_alu_op_mod_info;
extern const rogue_alu_op_mod_info
@ -1113,6 +1116,8 @@ enum rogue_ctrl_op_mod {
typedef struct rogue_ctrl_op_mod_info {
const char *str;
uint64_t exclude; /* Can't use this op mod with any of these. */
uint64_t require; /* Required op mods for this to be used (OR). */
} rogue_ctrl_op_mod_info;
extern const rogue_ctrl_op_mod_info
@ -1383,7 +1388,6 @@ typedef struct rogue_backend_op_info {
extern const rogue_backend_op_info
rogue_backend_op_infos[ROGUE_BACKEND_OP_COUNT];
/* TODO: Some of these may not be used together; express that in op mod info. */
enum rogue_backend_op_mod {
/* In order of priority */
ROGUE_BACKEND_OP_MOD_PROJ, /* Projection (send T co-ordinate). */
@ -1440,6 +1444,8 @@ enum rogue_backend_op_mod {
typedef struct rogue_backend_op_mod_info {
const char *str;
uint64_t exclude; /* Can't use this op mod with any of these. */
uint64_t require; /* Required op mods for this to be used (OR). */
} rogue_backend_op_mod_info;
extern const rogue_backend_op_mod_info
@ -1531,6 +1537,25 @@ enum rogue_bitwise_op {
ROGUE_BITWISE_OP_COUNT,
};
enum rogue_bitwise_op_mod {
/* In order of priority */
ROGUE_BITWISE_OP_MOD_TWB, /* Top word break. */
ROGUE_BITWISE_OP_MOD_PWB, /* Partial word break. */
ROGUE_BITWISE_OP_MOD_MTB, /* Mask top break. */
ROGUE_BITWISE_OP_MOD_FTB, /* Find top break. */
ROGUE_BITWISE_OP_MOD_COUNT,
};
typedef struct rogue_bitwise_op_mod_info {
const char *str;
uint64_t exclude; /* Can't use this op mod with any of these. */
uint64_t require; /* Required op mods for this to be used (OR). */
} rogue_bitwise_op_mod_info;
extern const rogue_bitwise_op_mod_info
rogue_bitwise_op_mod_infos[ROGUE_BITWISE_OP_MOD_COUNT];
#define ROGUE_BITWISE_OP_MAX_SRCS 7
#define ROGUE_BITWISE_OP_MAX_DSTS 2
@ -1586,21 +1611,18 @@ typedef struct rogue_bitwise_instr {
rogue_src_use src_use[ROGUE_BITWISE_OP_MAX_SRCS];
} rogue_bitwise_instr;
#if 0
static inline
void
rogue_set_bitwise_op_mod(rogue_bitwise_instr *bitwise, enum rogue_bitwise_op_mod mod)
static inline void rogue_set_bitwise_op_mod(rogue_bitwise_instr *bitwise,
enum rogue_bitwise_op_mod mod)
{
bitwise->mod |= BITFIELD64_BIT(mod);
bitwise->mod |= BITFIELD64_BIT(mod);
}
static inline
bool
rogue_bitwise_op_mod_is_set(const rogue_bitwise_instr *bitwise, enum rogue_bitwise_op_mod mod)
static inline bool
rogue_bitwise_op_mod_is_set(const rogue_bitwise_instr *bitwise,
enum rogue_bitwise_op_mod mod)
{
return !!(bitwise->mod & BITFIELD64_BIT(mod));
return !!(bitwise->mod & BITFIELD64_BIT(mod));
}
#endif
/**
* \brief Allocates and initializes a new bitwise instruction.

View file

@ -289,7 +289,7 @@ static void rogue_encode_alu_instr(const rogue_alu_instr *alu,
#undef DM
#undef SM
#define OM(op_mod) BITFIELD64_BIT(ROGUE_BACKEND_OP_MOD_##op_mod)
#define OM(op_mod) ROGUE_BACKEND_OP_MOD_##op_mod
static void rogue_encode_backend_instr(const rogue_backend_instr *backend,
unsigned instr_size,
rogue_instr_encoding *instr_encoding)
@ -471,7 +471,7 @@ static void rogue_encode_backend_instr(const rogue_backend_instr *backend,
rogue_backend_op_mod_is_set(backend, OM(PPLOD));
}
if (instr_size >= 3) {
if (instr_size > 3) {
instr_encoding->backend.dma.smp.extb = 1;
instr_encoding->backend.dma.smp.w =

View file

@ -282,8 +282,11 @@ const rogue_backend_op_info rogue_backend_op_infos[ROGUE_BACKEND_OP_COUNT] = {
[1] = T(REGARRAY),
[2] = T(VAL),
},
.dst_stride = {
[0] = ~0U,
},
.src_stride = {
[1] = 3,
[1] = ~0U,
},
},
[ROGUE_BACKEND_OP_FITRP_PIXEL] = { .str = "fitrp.pixel", .num_dsts = 1, .num_srcs = 4,
@ -318,6 +321,15 @@ const rogue_backend_op_info rogue_backend_op_infos[ROGUE_BACKEND_OP_COUNT] = {
[4] = T(REG) | T(IO),
[5] = T(VAL),
},
/* TODO: This may depend on the other options set. */
.src_stride = {
[1] = 3,
[2] = ~0U,
[3] = 3,
},
.dst_stride = {
[0] = ~0U,
},
},
[ROGUE_BACKEND_OP_SMP2D] = { .str = "smp2d", .num_dsts = 1, .num_srcs = 6,
.phase_io = { .dst[0] = IO(S4), .src[1] = IO(S0), .src[2] = IO(S1), .src[3] = IO(S2), },
@ -336,6 +348,15 @@ const rogue_backend_op_info rogue_backend_op_infos[ROGUE_BACKEND_OP_COUNT] = {
[4] = T(REG) | T(IO),
[5] = T(VAL),
},
/* TODO: This may depend on the other options set. */
.src_stride = {
[1] = 3,
[2] = ~0U,
[3] = 3,
},
.dst_stride = {
[0] = ~0U,
},
},
[ROGUE_BACKEND_OP_SMP3D] = { .str = "smp3d", .num_dsts = 1, .num_srcs = 6,
.phase_io = { .dst[0] = IO(S4), .src[1] = IO(S0), .src[2] = IO(S1), .src[3] = IO(S2), },
@ -354,6 +375,15 @@ const rogue_backend_op_info rogue_backend_op_infos[ROGUE_BACKEND_OP_COUNT] = {
[4] = T(REG) | T(IO),
[5] = T(VAL),
},
/* TODO: This may depend on the other options set. */
.src_stride = {
[1] = 3,
[2] = ~0U,
[3] = 3,
},
.dst_stride = {
[0] = ~0U,
},
},
};
#undef B
@ -361,36 +391,37 @@ const rogue_backend_op_info rogue_backend_op_infos[ROGUE_BACKEND_OP_COUNT] = {
#undef OM
#undef IO
#define OM(op_mod) BITFIELD64_BIT(ROGUE_BACKEND_OP_MOD_##op_mod)
const rogue_backend_op_mod_info rogue_backend_op_mod_infos[ROGUE_BACKEND_OP_MOD_COUNT] = {
[ROGUE_BACKEND_OP_MOD_PROJ] = { .str = "proj", },
[ROGUE_BACKEND_OP_MOD_FCNORM] = { .str = "fcnorm", },
[ROGUE_BACKEND_OP_MOD_NNCOORDS] = { .str = "nncoords", },
[ROGUE_BACKEND_OP_MOD_BIAS] = { .str = "bias", },
[ROGUE_BACKEND_OP_MOD_REPLACE] = { .str = "replace", },
[ROGUE_BACKEND_OP_MOD_GRADIENT] = { .str = "gradient", },
[ROGUE_BACKEND_OP_MOD_BIAS] = { .str = "bias", .exclude = OM(REPLACE) | OM(GRADIENT) },
[ROGUE_BACKEND_OP_MOD_REPLACE] = { .str = "replace", .exclude = OM(BIAS) | OM(GRADIENT) },
[ROGUE_BACKEND_OP_MOD_GRADIENT] = { .str = "gradient", .exclude = OM(BIAS) | OM(REPLACE) },
[ROGUE_BACKEND_OP_MOD_PPLOD] = { .str = "pplod", },
[ROGUE_BACKEND_OP_MOD_PPLOD] = { .str = "pplod", .require = OM(BIAS) | OM(REPLACE) },
[ROGUE_BACKEND_OP_MOD_TAO] = { .str = "tao", },
[ROGUE_BACKEND_OP_MOD_SOO] = { .str = "soo", },
[ROGUE_BACKEND_OP_MOD_SNO] = { .str = "sno", },
[ROGUE_BACKEND_OP_MOD_WRT] = { .str = "wrt", },
[ROGUE_BACKEND_OP_MOD_DATA] = { .str = "data", },
[ROGUE_BACKEND_OP_MOD_INFO] = { .str = "info", },
[ROGUE_BACKEND_OP_MOD_BOTH] = { .str = "both", },
[ROGUE_BACKEND_OP_MOD_DATA] = { .str = "data", .exclude = OM(INFO) | OM(BOTH) },
[ROGUE_BACKEND_OP_MOD_INFO] = { .str = "info", .exclude = OM(DATA) | OM(BOTH) },
[ROGUE_BACKEND_OP_MOD_BOTH] = { .str = "both", .exclude = OM(DATA) | OM(INFO) },
[ROGUE_BACKEND_OP_MOD_BYPASS] = { .str = "bypass", },
[ROGUE_BACKEND_OP_MOD_FORCELINEFILL] = { .str = "forcelinefill", },
[ROGUE_BACKEND_OP_MOD_BYPASS] = { .str = "bypass", .exclude = OM(FORCELINEFILL) | OM(WRITETHROUGH) | OM(WRITEBACK) | OM(LAZYWRITEBACK) },
[ROGUE_BACKEND_OP_MOD_FORCELINEFILL] = { .str = "forcelinefill", .exclude = OM(BYPASS) | OM(WRITETHROUGH) | OM(WRITEBACK) | OM(LAZYWRITEBACK) },
[ROGUE_BACKEND_OP_MOD_WRITETHROUGH] = { .str = "writethrough", },
[ROGUE_BACKEND_OP_MOD_WRITEBACK] = { .str = "writeback", },
[ROGUE_BACKEND_OP_MOD_LAZYWRITEBACK] = { .str = "lazywriteback", },
[ROGUE_BACKEND_OP_MOD_WRITETHROUGH] = { .str = "writethrough", .exclude = OM(BYPASS) | OM(FORCELINEFILL) | OM(WRITEBACK) | OM(LAZYWRITEBACK) },
[ROGUE_BACKEND_OP_MOD_WRITEBACK] = { .str = "writeback", .exclude = OM(BYPASS) | OM(FORCELINEFILL) | OM(WRITETHROUGH) | OM(LAZYWRITEBACK) },
[ROGUE_BACKEND_OP_MOD_LAZYWRITEBACK] = { .str = "lazywriteback", .exclude = OM(BYPASS) | OM(FORCELINEFILL) | OM(WRITETHROUGH) | OM(WRITEBACK) },
[ROGUE_BACKEND_OP_MOD_SLCBYPASS] = { .str = "slcbypass", },
[ROGUE_BACKEND_OP_MOD_SLCWRITEBACK] = { .str = "slcwriteback", },
[ROGUE_BACKEND_OP_MOD_SLCWRITETHROUGH] = { .str = "slcwritethrough", },
[ROGUE_BACKEND_OP_MOD_SLCNOALLOC] = { .str = "slcnoalloc", },
[ROGUE_BACKEND_OP_MOD_SLCBYPASS] = { .str = "slcbypass", .exclude = OM(SLCWRITEBACK) | OM(SLCWRITETHROUGH) | OM(SLCNOALLOC) },
[ROGUE_BACKEND_OP_MOD_SLCWRITEBACK] = { .str = "slcwriteback", .exclude = OM(SLCBYPASS) | OM(SLCWRITETHROUGH) | OM(SLCNOALLOC) },
[ROGUE_BACKEND_OP_MOD_SLCWRITETHROUGH] = { .str = "slcwritethrough", .exclude = OM(SLCBYPASS) | OM(SLCWRITEBACK) | OM(SLCNOALLOC) },
[ROGUE_BACKEND_OP_MOD_SLCNOALLOC] = { .str = "slcnoalloc", .exclude = OM(SLCBYPASS) | OM(SLCWRITEBACK) | OM(SLCWRITETHROUGH) },
[ROGUE_BACKEND_OP_MOD_ARRAY] = { .str = "array", },
[ROGUE_BACKEND_OP_MOD_INTEGER] = { .str = "integer", },
@ -400,6 +431,21 @@ const rogue_backend_op_mod_info rogue_backend_op_mod_infos[ROGUE_BACKEND_OP_MOD_
[ROGUE_BACKEND_OP_MOD_SAT] = { .str = "sat", },
};
#undef OM
#define OM(op_mod) BITFIELD64_BIT(ROGUE_BITWISE_OP_MOD_##op_mod)
const rogue_bitwise_op_mod_info
rogue_bitwise_op_mod_infos[ROGUE_BITWISE_OP_MOD_COUNT] = {
[ROGUE_BITWISE_OP_MOD_TWB] = { .str = "twb",
.exclude = OM(PWB) | OM(MTB) | OM(FTB) },
[ROGUE_BITWISE_OP_MOD_PWB] = { .str = "pwb",
.exclude = OM(TWB) | OM(MTB) | OM(FTB) },
[ROGUE_BITWISE_OP_MOD_MTB] = { .str = "mtb",
.exclude = OM(TWB) | OM(PWB) | OM(FTB) },
[ROGUE_BITWISE_OP_MOD_FTB] = { .str = "ftb",
.exclude = OM(TWB) | OM(PWB) | OM(MTB) },
};
#undef OM
#define P(type) BITFIELD64_BIT(ROGUE_INSTR_PHASE_##type)
#define PH(type) ROGUE_INSTR_PHASE_##type

View file

@ -224,6 +224,23 @@ static void validate_src(rogue_validation_state *state,
state->ctx.ref = NULL;
}
static bool validate_alu_op_mod_combo(uint64_t mods)
{
rogue_foreach_mod_in_set (mod, mods) {
const rogue_alu_op_mod_info *info = &rogue_alu_op_mod_infos[mod];
/* Check if any excluded op mods have been included. */
if (info->exclude & mods)
return false;
/* Check if any required op mods have been missed. */
if (info->require && !(info->require & mods))
return false;
}
return true;
}
static void validate_alu_instr(rogue_validation_state *state,
const rogue_alu_instr *alu)
{
@ -238,10 +255,13 @@ static void validate_alu_instr(rogue_validation_state *state,
if (rogue_alu_comp_is_none(alu) && alu->op == ROGUE_ALU_OP_TST)
validate_log(state, "ALU comparison not set for test op.");
/* Initial check if instruction modifiers are valid. */
/* Check if instruction modifiers are valid. */
if (!rogue_mods_supported(alu->mod, info->supported_op_mods))
validate_log(state, "Unsupported ALU op modifiers.");
if (!validate_alu_op_mod_combo(alu->mod))
validate_log(state, "Unsupported ALU op modifier combination.");
/* Instruction repeat checks. */
if (alu->instr.repeat > 1 && !info->dst_repeat_mask &&
!info->src_repeat_mask) {
@ -270,6 +290,23 @@ static void validate_alu_instr(rogue_validation_state *state,
}
}
static bool validate_backend_op_mod_combo(uint64_t mods)
{
rogue_foreach_mod_in_set (mod, mods) {
const rogue_backend_op_mod_info *info = &rogue_backend_op_mod_infos[mod];
/* Check if any excluded op mods have been included. */
if (info->exclude & mods)
return false;
/* Check if any required op mods have been missed. */
if (info->require && !(info->require & mods))
return false;
}
return true;
}
static void validate_backend_instr(rogue_validation_state *state,
const rogue_backend_instr *backend)
{
@ -279,10 +316,13 @@ static void validate_backend_instr(rogue_validation_state *state,
const rogue_backend_op_info *info = &rogue_backend_op_infos[backend->op];
/* Initial check if instruction modifiers are valid. */
/* Check if instruction modifiers are valid. */
if (!rogue_mods_supported(backend->mod, info->supported_op_mods))
validate_log(state, "Unsupported backend op modifiers.");
if (!validate_backend_op_mod_combo(backend->mod))
validate_log(state, "Unsupported backend op modifier combination.");
/* Instruction repeat checks. */
if (backend->instr.repeat > 1 && !info->dst_repeat_mask &&
!info->src_repeat_mask) {
@ -311,6 +351,23 @@ static void validate_backend_instr(rogue_validation_state *state,
}
}
static bool validate_ctrl_op_mod_combo(uint64_t mods)
{
rogue_foreach_mod_in_set (mod, mods) {
const rogue_ctrl_op_mod_info *info = &rogue_ctrl_op_mod_infos[mod];
/* Check if any excluded op mods have been included. */
if (info->exclude & mods)
return false;
/* Check if any required op mods have been missed. */
if (info->require && !(info->require & mods))
return false;
}
return true;
}
/* Returns true if instruction can end block. */
static bool validate_ctrl_instr(rogue_validation_state *state,
const rogue_ctrl_instr *ctrl)
@ -327,10 +384,13 @@ static bool validate_ctrl_instr(rogue_validation_state *state,
validate_log(state,
"Ctrl op did not expect target block, but one provided.");
/* Initial check if instruction modifiers are valid. */
/* Check if instruction modifiers are valid. */
if (!rogue_mods_supported(ctrl->mod, info->supported_op_mods))
validate_log(state, "Unsupported CTRL op modifiers.");
if (!validate_ctrl_op_mod_combo(ctrl->mod))
validate_log(state, "Unsupported CTRL op modifier combination.");
/* Instruction repeat checks. */
if (ctrl->instr.repeat > 1 && !info->dst_repeat_mask &&
!info->src_repeat_mask) {
@ -369,6 +429,23 @@ static bool validate_ctrl_instr(rogue_validation_state *state,
return info->ends_block;
}
static bool validate_bitwise_op_mod_combo(uint64_t mods)
{
rogue_foreach_mod_in_set (mod, mods) {
const rogue_bitwise_op_mod_info *info = &rogue_bitwise_op_mod_infos[mod];
/* Check if any excluded op mods have been included. */
if (info->exclude & mods)
return false;
/* Check if any required op mods have been missed. */
if (info->require && !(info->require & mods))
return false;
}
return true;
}
static void validate_bitwise_instr(rogue_validation_state *state,
const rogue_bitwise_instr *bitwise)
{
@ -378,10 +455,13 @@ static void validate_bitwise_instr(rogue_validation_state *state,
const rogue_bitwise_op_info *info = &rogue_bitwise_op_infos[bitwise->op];
/* Initial check if instruction modifiers are valid. */
/* Check if instruction modifiers are valid. */
if (!rogue_mods_supported(bitwise->mod, info->supported_op_mods))
validate_log(state, "Unsupported bitwise op modifiers.");
if (!validate_bitwise_op_mod_combo(bitwise->mod))
validate_log(state, "Unsupported bitwise op modifier combination.");
/* Instruction repeat checks. */
if (bitwise->instr.repeat > 1 && !info->dst_repeat_mask &&
!info->src_repeat_mask) {