pco, pygen: validate phases and io allocations for ops

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/33998>
This commit is contained in:
Simon Perretta
2024-12-01 21:09:53 +00:00
committed by Marge Bot
parent c201332fff
commit 765e9d837d
6 changed files with 262 additions and 18 deletions
+23 -1
View File
@@ -58,6 +58,28 @@ const struct pco_op_info pco_op_info[_PCO_OP_COUNT] = {
% endfor
},
% endif
#ifndef NDEBUG
% if op.bname in encode_maps:
.grp_dest_maps = {
% for phase, dests, _ in encode_maps[op.bname].op_ref_maps:
[${phase}] = {
% for dest in dests:
[${loop.index}] = ${dest},
% endfor
},
% endfor
},
.grp_src_maps = {
% for phase, _, srcs in encode_maps[op.bname].op_ref_maps:
[${phase}] = {
% for src in srcs:
[${loop.index}] = ${src},
% endfor
},
% endfor
},
% endif
#endif /* NDEBUG */
},
% endfor
};
@@ -104,7 +126,7 @@ const struct pco_ref_mod_info pco_ref_mod_info[_PCO_REF_MOD_COUNT] = {
def main():
try:
print(Template(template).render(BaseType=BaseType, ops=ops, op_mods=op_mods, ref_mods=ref_mods, group_maps=group_maps))
print(Template(template).render(BaseType=BaseType, ops=ops, op_mods=op_mods, ref_mods=ref_mods, group_maps=group_maps, encode_maps=encode_maps))
except:
raise Exception(exceptions.text_error_template().render())
+9
View File
@@ -362,8 +362,14 @@ struct pco_op_info {
bool has_target_cf_node; /** Set if op has a cf-node as a target. */
uint8_t dest_intrn_map[_PCO_OP_MAX_DESTS];
uint8_t src_intrn_map[_PCO_OP_MAX_SRCS];
#ifndef NDEBUG
uint32_t grp_dest_maps[_PCO_OP_PHASE_COUNT][_PCO_OP_MAX_DESTS];
uint32_t grp_src_maps[_PCO_OP_PHASE_COUNT][_PCO_OP_MAX_SRCS];
#endif /* NDEBUG */
};
extern const struct pco_op_info pco_op_info[_PCO_OP_COUNT];
static_assert(_PCO_REF_MAP_COUNT <= 32,
"enum pco_ref_map must fit into an uint32_t");
/** Op mod info. */
struct pco_op_mod_info {
@@ -2164,5 +2170,8 @@ void pco_print_instr(pco_shader *shader, pco_instr *instr);
void pco_print_igrp(pco_shader *shader, pco_igrp *igrp);
void pco_print_cf_node_name(pco_shader *shader, pco_cf_node *cf_node);
void pco_print_shader_info(pco_shader *shader);
void pco_print_phase(pco_shader *shader,
enum pco_alutype alutype,
enum pco_op_phase phase);
#endif /* PCO_INTERNAL_H */
+1
View File
@@ -37,6 +37,7 @@ REF_MAP = enum_type('ref_map', [
('ftt', 'ftt'),
('p0', 'p0'),
('pe', 'pe'),
('imm', 'imm'),
('drc', 'drc'),
-2
View File
@@ -95,8 +95,6 @@ IO = enum_type('io', [
('ftt', 'ftt'),
('cout', 'cout'),
('p0', 'p0'),
])
PRED = enum_type('pred', [
+28 -6
View File
@@ -528,9 +528,9 @@ static void _pco_print_instr(pco_print_state *state, pco_instr *instr)
* \param[in] alutype ALU type.
* \param[in] phase Phase.
*/
static void pco_print_phase(pco_print_state *state,
enum pco_alutype alutype,
enum pco_op_phase phase)
static void _pco_print_phase(pco_print_state *state,
enum pco_alutype alutype,
enum pco_op_phase phase)
{
switch (alutype) {
case PCO_ALUTYPE_MAIN:
@@ -567,7 +567,7 @@ static void pco_print_igrp_phases(pco_print_state *state, pco_igrp *igrp)
if (printed)
pco_printf(state, ",");
pco_print_phase(state, igrp->hdr.alutype, phase);
_pco_print_phase(state, igrp->hdr.alutype, phase);
printed = true;
}
@@ -772,13 +772,13 @@ static void _pco_print_igrp(pco_print_state *state, pco_igrp *igrp)
else if (printed)
pco_printf(state, " ");
pco_print_phase(state, igrp->hdr.alutype, phase);
_pco_print_phase(state, igrp->hdr.alutype, phase);
pco_printf(state, ": ");
_pco_print_instr(state, igrp->instrs[phase]);
if (state->verbose) {
pco_printf(state, " /* ");
pco_print_phase(state, igrp->hdr.alutype, phase);
_pco_print_phase(state, igrp->hdr.alutype, phase);
pco_printf(state, " bytes: %u */\n", igrp->enc.len.instrs[phase]);
}
@@ -1233,3 +1233,25 @@ void pco_print_shader_info(pco_shader *shader)
};
return _pco_print_shader_info(&state, shader);
}
/**
* \brief Print the name of a phase(wrapper).
*
* \param[in] shader PCO shader.
* \param[in] alutype ALU type.
* \param[in] phase Phase.
*/
void pco_print_phase(pco_shader *shader,
enum pco_alutype alutype,
enum pco_op_phase phase)
{
pco_print_state state = {
.fp = stdout,
.shader = shader,
.indent = 0,
.is_grouped = shader->is_grouped,
.verbose = false,
};
return _pco_print_phase(&state, alutype, phase);
}
+201 -9
View File
@@ -19,6 +19,8 @@
#include <inttypes.h>
#include <stdio.h>
#ifndef NDEBUG
enum ref_cursor {
REF_CURSOR_NONE,
REF_CURSOR_INSTR_DEST,
@@ -58,7 +60,12 @@ static void pco_assert(struct val_state *state,
if (cond)
return;
printf("PCO validation failed with assertion \"%s\" - ", cond_str);
printf("PCO validation failed ");
if (state->when)
printf("%s ", state->when);
printf("with assertion \"%s\" - ", cond_str);
va_list args;
va_start(args, fmt);
@@ -77,6 +84,18 @@ static void pco_assert(struct val_state *state,
printf(" instr src #%" PRIuPTR, state->ref - state->instr->src);
break;
case REF_CURSOR_IGRP_DEST:
printf(" igrp dest #%" PRIuPTR, state->ref - state->igrp->srcs.s);
break;
case REF_CURSOR_IGRP_ISS:
printf(" igrp iss #%" PRIuPTR, state->ref - state->igrp->iss.is);
break;
case REF_CURSOR_IGRP_SRC:
printf(" igrp src #%" PRIuPTR, state->ref - state->igrp->srcs.s);
break;
default:
unreachable();
}
@@ -98,6 +117,14 @@ static void pco_assert(struct val_state *state,
if (state->instr) {
printf(" instr ");
if (state->shader->is_grouped) {
printf("(phase ");
pco_print_phase(state->shader,
state->instr->parent_igrp->hdr.alutype,
state->instr->phase);
printf(") ");
}
pco_print_instr(state->shader, state->instr);
}
@@ -108,13 +135,13 @@ static void pco_assert(struct val_state *state,
printf(".\n");
pco_print_shader_info(state->shader);
pco_print_shader(state->shader, stdout, state->when);
abort();
}
#define PCO_ASSERT(state, cond, fmt, ...) \
pco_assert(state, cond, #cond, fmt, ##__VA_ARGS__)
# define PCO_ASSERT(state, cond, fmt, ...) \
pco_assert(state, cond, #cond, fmt, ##__VA_ARGS__)
/**
* \brief Validates SSA assignments and uses.
@@ -234,15 +261,175 @@ static void pco_validate_src_maps(struct val_state *state)
}
}
# define CHECK_IO(io, ref) \
case PCO_REF_MAP_##io: \
if (pco_ref_is_io(ref) && pco_ref_get_io(ref) == PCO_IO_##io) \
return true; \
break;
/**
* \brief Checks whether a ref type corresponds to a supported mapping.
*
* \param[in] ref Src/dest reference.
* \param[in] ref_maps Supported mappings.
* \return True if the ref type corresponds to a supported mapping.
*/
static inline bool ref_is_in_map(pco_ref ref, enum pco_ref_map ref_maps)
{
u_foreach_bit (_ref_map, ref_maps) {
enum pco_ref_map ref_map = _ref_map;
switch (ref_map) {
case PCO_REF_MAP__:
if (pco_ref_is_null(ref))
return true;
break;
CHECK_IO(S0, ref)
CHECK_IO(S1, ref)
CHECK_IO(S2, ref)
CHECK_IO(S3, ref)
CHECK_IO(S4, ref)
CHECK_IO(S5, ref)
CHECK_IO(W0, ref)
CHECK_IO(W1, ref)
CHECK_IO(IS0, ref)
CHECK_IO(IS1, ref)
CHECK_IO(IS2, ref)
CHECK_IO(IS3, ref)
CHECK_IO(IS4, ref)
CHECK_IO(IS5, ref)
CHECK_IO(FT0, ref)
CHECK_IO(FT1, ref)
CHECK_IO(FT2, ref)
CHECK_IO(FTE, ref)
CHECK_IO(FT3, ref)
CHECK_IO(FT4, ref)
CHECK_IO(FT5, ref)
CHECK_IO(FTT, ref)
case PCO_REF_MAP_P0:
if (pco_ref_is_pred(ref) && ref.val == PCO_PRED_P0)
return true;
break;
case PCO_REF_MAP_PE:
if (pco_ref_is_pred(ref) && ref.val == PCO_PRED_PE)
return true;
break;
case PCO_REF_MAP_IMM:
if (pco_ref_is_imm(ref))
return true;
break;
case PCO_REF_MAP_DRC:
if (pco_ref_is_drc(ref))
return true;
break;
case PCO_REF_MAP_TEMP:
if ((pco_ref_is_reg(ref) || pco_ref_is_idx_reg(ref)) &&
pco_ref_get_reg_class(ref) == PCO_REG_CLASS_TEMP)
return true;
break;
case PCO_REF_MAP_COEFF:
if ((pco_ref_is_reg(ref) || pco_ref_is_idx_reg(ref)) &&
pco_ref_get_reg_class(ref) == PCO_REG_CLASS_COEFF)
return true;
break;
default:
unreachable();
}
}
return false;
}
# undef CHECK_IO
/**
* \brief Validates I/O references for igrps.
*
* \param[in,out] state Validation state.
*/
static void pco_validate_ref_maps(struct val_state *state)
{
bool needs_s124;
pco_foreach_func_in_shader (func, state->shader) {
state->func = func;
pco_foreach_igrp_in_func (igrp, func) {
state->cf_node = &igrp->parent_block->cf_node;
state->igrp = igrp;
/* Igrp source mappings. */
state->ref_cursor = REF_CURSOR_IGRP_SRC;
for (unsigned s = 0; s < ARRAY_SIZE(igrp->srcs.s); ++s) {
state->ref = &igrp->srcs.s[s];
pco_ref src = igrp->srcs.s[s];
if (pco_ref_is_null(src))
continue;
bool valid = ref_src_map_valid(src, PCO_IO_S0 + s, &needs_s124);
PCO_ASSERT(state,
valid,
"HW register reference should be mapped to %s",
needs_s124 ? "S1/S2/S4" : "S0/S2/S3");
}
pco_foreach_instr_in_igrp (instr, igrp) {
const struct pco_op_info *info = &pco_op_info[instr->op];
enum pco_op_phase phase = instr->phase;
state->instr = instr;
/* Instruction dests. */
state->ref_cursor = REF_CURSOR_INSTR_DEST;
for (unsigned d = 0; d < instr->num_dests; ++d) {
state->ref = &instr->dest[d];
PCO_ASSERT(state,
ref_is_in_map(instr->dest[d],
info->grp_dest_maps[phase][d]),
"Invalid dest assignment.");
}
/* Instruction sources. */
state->ref_cursor = REF_CURSOR_INSTR_SRC;
for (unsigned s = 0; s < instr->num_srcs; ++s) {
state->ref = &instr->src[s];
PCO_ASSERT(state,
ref_is_in_map(instr->src[s],
info->grp_src_maps[phase][s]),
"Invalid src assignment.");
}
state->instr = NULL;
}
state->igrp = NULL;
state->cf_node = NULL;
}
state->func = NULL;
state->ref = NULL;
state->ref_cursor = REF_CURSOR_NONE;
}
}
/**
* \brief Validates a PCO shader.
*
* \param[in] shader PCO shader.
* \param[in] when When the validation check is being run.
*/
void pco_validate_shader(UNUSED pco_shader *shader, UNUSED const char *when)
void pco_validate_shader(pco_shader *shader, const char *when)
{
#ifndef NDEBUG
if (PCO_DEBUG(VAL_SKIP))
return;
@@ -255,8 +442,13 @@ void pco_validate_shader(UNUSED pco_shader *shader, UNUSED const char *when)
if (!shader->is_grouped) {
pco_validate_ssa(&state);
pco_validate_src_maps(&state);
} else {
PCO_ASSERT(&state,
shader->is_legalized,
"Legalize pass should have been run before grouping");
pco_validate_ref_maps(&state);
}
puts("finishme: pco_validate_shader");
#endif /* NDEBUG */
}
#else /* NDEBUG */
void pco_validate_shader(UNUSED pco_shader *shader, UNUSED const char *when) {}
#endif /* NDEBUG */