From 8cfe660326a2fb455bed0499c80f38f6f17f8f0e Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Mon, 13 Apr 2020 15:56:06 -0400 Subject: [PATCH] pan/bi: Rewrite conversion packing To support roundmodes and other goodies. Signed-off-by: Alyssa Rosenzweig Part-of: --- src/panfrost/bifrost/bi_pack.c | 91 +++++++++++++++++++++++----------- src/panfrost/bifrost/bifrost.h | 51 +++++++++---------- 2 files changed, 84 insertions(+), 58 deletions(-) diff --git a/src/panfrost/bifrost/bi_pack.c b/src/panfrost/bifrost/bi_pack.c index 7c2f11ab821..dc304f3d7d9 100644 --- a/src/panfrost/bifrost/bi_pack.c +++ b/src/panfrost/bifrost/bi_pack.c @@ -749,49 +749,80 @@ bi_pack_fma_convert(bi_instruction *ins, struct bi_registers *regs) nir_alu_type to_base = nir_alu_type_get_base_type(ins->dest_type); unsigned to_size = nir_alu_type_get_type_size(ins->dest_type); bool to_unsigned = to_base == nir_type_uint; + bool to_float = to_base == nir_type_float; /* Sanity check */ assert((from_base != to_base) || (from_size != to_size)); assert((MAX2(from_size, to_size) / MIN2(from_size, to_size)) <= 2); - if (from_size == 16 && to_size == 16) { - /* f2i_i2f16 */ - unreachable("i16 not yet implemented"); - } else if (from_size == 32 && to_size == 32) { - unsigned op = 0; + /* f32 to f16 is special */ + if (from_size == 32 && to_size == 16 && from_base == nir_type_float && to_base == from_base) { + /* TODO: second vectorized source? */ + struct bifrost_fma_2src pack = { + .src0 = bi_get_src(ins, regs, 0, true), + .src1 = BIFROST_SRC_STAGE, /* 0 */ + .op = BIFROST_FMA_FLOAT32_TO_16 + }; - if (from_base == nir_type_float) { - op = BIFROST_FMA_FLOAT32_TO_INT(to_unsigned); - } else { - op = BIFROST_FMA_INT_TO_FLOAT32(from_unsigned); - } + RETURN_PACKED(pack); + } - return bi_pack_fma_1src(ins, regs, op); - } else if (from_size == 16 && to_size == 32) { - bool from_y = ins->swizzle[0][0]; + /* Otherwise, figure out the mode */ + unsigned op = 0; + + if (from_size == 16 && to_size == 32) { + unsigned component = ins->swizzle[0][0]; + assert(component <= 1); + + if (from_base == nir_type_float) + op = BIFROST_CONVERT_5(component); + else + op = BIFROST_CONVERT_4(from_unsigned, component, to_float); + } else { + unsigned mode = 0; + unsigned swizzle = (from_size == 16) ? bi_swiz16(ins, 0) : 0; + bool is_unsigned = from_unsigned; if (from_base == nir_type_float) { - return bi_pack_fma_1src(ins, regs, - BIFROST_FMA_FLOAT16_TO_32(from_y)); - } else { - unreachable("i16 not yet implemented"); - } - } else if (from_size == 32 && to_size == 16) { - if (from_base == nir_type_float) { - /* TODO: second vectorized source? */ - struct bifrost_fma_2src pack = { - .src0 = bi_get_src(ins, regs, 0, true), - .src1 = BIFROST_SRC_STAGE, /* 0 */ - .op = BIFROST_FMA_FLOAT32_TO_16 - }; - - RETURN_PACKED(pack); + assert(to_base != nir_type_float); + is_unsigned = to_unsigned; + + if (from_size == 32 && to_size == 32) + mode = BIFROST_CONV_F32_TO_I32; + else if (from_size == 16 && to_size == 16) + mode = BIFROST_CONV_F16_TO_I16; + else + unreachable("Invalid float conversion"); } else { - unreachable("i16 not yet implemented"); + assert(to_base == nir_type_float); + assert(from_size == to_size); + + if (to_size == 32) + mode = BIFROST_CONV_I32_TO_F32; + else if (to_size == 16) + mode = BIFROST_CONV_I16_TO_F16; + else + unreachable("Invalid int conversion"); } + + /* Fixup swizzle for 32-bit only modes */ + + if (mode == BIFROST_CONV_I32_TO_F32) + swizzle = 0b11; + else if (mode == BIFROST_CONV_F32_TO_I32) + swizzle = 0b10; + + op = BIFROST_CONVERT(is_unsigned, ins->roundmode, swizzle, mode); + + /* Unclear what the top bit is for... maybe 16-bit related */ + bool mode2 = mode == BIFROST_CONV_F16_TO_I16; + bool mode6 = mode == BIFROST_CONV_I16_TO_F16; + + if (!(mode2 || mode6)) + op |= 0x100; } - unreachable("Unknown convert"); + return bi_pack_fma_1src(ins, regs, BIFROST_FMA_CONVERT | op); } static unsigned diff --git a/src/panfrost/bifrost/bifrost.h b/src/panfrost/bifrost/bifrost.h index 88ed61601b2..8700b18d436 100644 --- a/src/panfrost/bifrost/bifrost.h +++ b/src/panfrost/bifrost/bifrost.h @@ -333,39 +333,34 @@ struct bifrost_shift_add { unsigned op : 7; } __attribute__((packed)); -#define BIFROST_FMA_INT16_TO_32 (0xe0198 >> 3) - -struct bifrost_fma_int16_to_32 { - unsigned src0 : 3; - unsigned is_unsigned : 1; - unsigned swizzle : 1; - unsigned to_float : 1; - unsigned op : 17; -} __attribute__((packed)); - -/* We could combine but it's easier to just use FMA_ONE_SRC */ -#define BIFROST_FMA_FLOAT16_TO_32(y) (0xe01a2 | ((y) ? 1 : 0)) - /* Two sources for vectorization */ #define BIFROST_FMA_FLOAT32_TO_16 (0xdd000 >> 3) -/* Again we could combine but easier to just ONE_SRC with an - * argumnt for unsignedness */ -#define BIFROST_FMA_FLOAT32_TO_INT(u) (0xe0136 | ((u) ? 1 : 0)) -#define BIFROST_FMA_INT_TO_FLOAT32(u) (0xe0178 | ((u) ? 1 : 0)) +enum bifrost_convert_mode { + BIFROST_CONV_UNK0 = 0, + BIFROST_CONV_F32_TO_I32 = 1, + BIFROST_CONV_F16_TO_I16 = 2, + BIFROST_CONV_I32_TO_F32 = 3, + BIFROST_CONV_I16_TO_X32 = 4, + BIFROST_CONV_F16_TO_F32 = 5, + BIFROST_CONV_I16_TO_F16 = 6, + BIFROST_CONV_UNK7 = 7 +}; -/* Used for f2i16 and i2f16 */ -#define BIFROST_FMA_F2I16 (0xe00) +/* i16 to x32 */ +#define BIFROST_CONVERT_4(is_unsigned, component, to_float) \ + ((is_unsigned & 1) | ((component & 1) << 1) | ((to_float & 1) << 2) | \ + ((0x3) << 3) | ((4) << 5) | 0x100) -struct bifrost_fma_f2i_i2f16 { - unsigned src0 : 3; - unsigned is_unsigned : 1; - unsigned direction : 2; /* 00 for i2f, 11 for f2i */ - unsigned swizzle : 2; - unsigned unk : 2; /* always 10 */ - unsigned direction_2 : 1; /* 0 for f2i, 1 for i2f */ - unsigned op : 12; -} __attribute__((packed)); +/* f16 to f32 */ +#define BIFROST_CONVERT_5(component) \ + ((component & 1) | ((1) << 1) | ((5) << 5) | 0x100) + +/* Other conversions */ +#define BIFROST_CONVERT(is_unsigned, roundmode, swizzle, mode) \ + ((is_unsigned & 1) | ((roundmode & 3) << 1) | ((swizzle & 3) << 3) | ((mode & 7) << 5)) + +#define BIFROST_FMA_CONVERT (0xe0000) enum bifrost_ldst_type { BIFROST_LDST_F16 = 0, -- 2.30.2