src/sass/xconv_blocksparse_32x32x16_bprop.sass (737 lines of code) (raw):
# Kernel: xconv_blocksparse_32x32x16_bprop
[-
our ($type, $F16, $I16, $O16, $overlapC);
sub F16 { return $type eq 'h' || $F16; }
sub I16 { return $type eq 'h' || $I16; }
sub O16 { return $type eq 'h' || $O16; }
our $dtypeF = F16() ? 'U16' : '32';
our $dtypeI = I16() ? 'U16' : '32';
our $dtypeO = O16() ? 'U16' : '32';
our $dshiftF = F16() ? '1' : '2';
our $dshiftI = I16() ? '1' : '2';
our $dshiftO = O16() ? '1' : '2';
our $dsizeF = F16() ? '2' : '4';
our $dsizeI = I16() ? '2' : '4';
our $dsizeO = O16() ? '2' : '4';
sub dtypeF { return $dtypeF; }
sub dtypeI { return $dtypeI; }
sub dtypeO { return $dtypeO; }
sub dsizeF { return $dsizeF; }
sub dsizeI { return $dsizeI; }
sub dsizeO { return $dsizeO; }
sub dshiftF { return $dshiftF; }
sub dshiftI { return $dshiftI; }
sub dshiftO { return $dshiftO; }
sub overlapC { return $overlapC; }
-]
<CONSTANT_MAPPING>
offset_lut : (32*32*2 + 64)
szShareF : (16*32)
szShareI : (16*32)
param_Block[0] : c[0x0][0x140]
param_Block[1] : c[0x0][0x144]
param_LutDHW[0] : c[0x0][0x148]
param_LutDHW[1] : c[0x0][0x14c]
param_LutCK[0] : c[0x0][0x150]
param_LutCK[1] : c[0x0][0x154]
param_O[0] : c[0x0][0x158]
param_O[1] : c[0x0][0x15c]
param_F[0] : c[0x0][0x160]
param_F[1] : c[0x0][0x164]
param_I[0] : c[0x0][0x168]
param_I[1] : c[0x0][0x16c]
param_alpha : c[0x0][0x170]
param_TRS : c[0x0][0x174]
param_magic_TRS : c[0x0][0x178]
param_shift_TRS : c[0x0][0x17c]
param_CDHW : c[0x0][0x180]
param_KMPQ : c[0x0][0x184]
</CONSTANT_MAPPING>
<REGISTER_MAPPING>
0-3 ~ idx_Blk
0-63 : czero<00-63>
3, 2,11,10,19,18,27,26 : cx<0-7>y0
7, 6,15,14,23,22,31,30 : cx<0-7>y1
1, 0, 9, 8,17,16,25,24 : cx<0-7>y2
5, 4,13,12,21,20,29,28 : cx<0-7>y3
35,34,43,42,51,50,59,58 : cx<0-7>y4
39,38,47,46,55,54,63,62 : cx<0-7>y5
33,32,41,40,49,48,57,56 : cx<0-7>y6
37,36,45,44,53,52,61,60 : cx<0-7>y7
64-79 : j0Fy<0-7>, j0Ix<0-7>
80-95 : j1Fy<0-7>, j1Ix<0-7>
96-111 : F0<0-3>, F8<0-3>, I0<0-3>, I8<0-3>
112-127 : track0F<0-7>, track8F<0-7>
112-127 : track0I<0-7>, track8I<0-7>
128-135 : slice0I<0-3>, slice8I<0-3>
136-139 ~ trs<0|8>, k<0|8>
128 = shareDHW0
132 = shareDHW8
140 = shareK0, offset0Ik
141 = shareK8, offset8Ik
96-99 : block<0-3>
100-101 : Block<0-1>
102-141 ~ tid1, tid16, tid16_1, readIs2, block_F, partialC
64-65 : Lut<0-1>
66-91 ~ ck<0-3>, kEntry<0-3>, dhwOffset, lutStore, block_K, block_CK, idx_DHW, sizeLutDHW, offsetCK, cEntry, tidX, trs<00|04|08|12>
92-95 ~ tidY<0|8>, partialKTRS
96-111 : lutEntry00<0-3>, lutEntry04<0-3>, lutEntry08<0-3>, lutEntry12<0-3>
142-159 ~ writeS, readFs, readIs, predF, CTRS, KTRS, KTRS16, posKTRS, shareLutK, shareLutDHW, offsetIn, offsetCTRS, offsetK<0|8>
160-167 ~ tid, idx_N, idx_C, block_C, TRS, shareLutC, writeOs
0-7 : Out0_<0-1>, Out1_<0-1>, Out2_<0-1>, Out3_<0-1>
16-31 ~ s<0-3>
64-79 ~ s0_<0-3>, s1_<0-3>, s2_<0-3>, s3_<0-3>
80-83 : offsetC<0-3>
64-95 : shuffle_x<0-7>y0, shuffle_x<0-7>y1, shuffle_x<0-7>y2, shuffle_x<0-7>y3
64-95 : shuffle_x<0-7>y4, shuffle_x<0-7>y5, shuffle_x<0-7>y6, shuffle_x<0-7>y7
112-159 ~ tid31, tid32, alpha, readOs, lutDHW, offsetDHW, c<0-3>, lutC, offsetO<0-3>
</REGISTER_MAPPING>
--:-:2:-:1 S2R idx_Blk, SR_CTAID.X;
--:-:1:-:1 S2R tid, SR_TID.X;
--:-:3:-:1 S2R idx_N, SR_CTAID.Y;
02:-:-:-:6 LEA Block0.CC, idx_Blk, param_Block[0], 4;
--:-:-:-:2 LEA.HI.X Block1, idx_Blk, param_Block[1], RZ, 4;
// idx_C/idx_DHW, block_K/block_C, block_CK, block_F
// 02:-:-:-:1 SHR.U32 idx_C, block0, 16;
// 02:-:-:-:1 LOP.AND idx_DHW, block0, 0xffff;
// 02:-:-:-:1 SHR.U32 block_K, block1, 16;
// 02:-:-:-:1 LOP.AND block_C, block1, 0xffff;
// 02:-:-:-:1 MOV block_CK, block2;
// 02:-:-:-:1 MOV block_F, block3;
--:-:2:-:1 LDG.E.CI.128 block, [Block];
<SCHEDULE_BLOCK>
// P0 = tid >= 32
01:-:-:-:1 ISETP.GE.AND P6, PT, tid, 32, PT;
<ORDERED>
--:-:-:-:1 STS.128 [RZ], RZ;
[+ join '', map sprintf("--:-:-:-:1 LDS.U.128 czero%02d, [RZ];\n", $_ * 4), 0..15; +]
02:-:-:-:0 SHR.U32 idx_C, block0, 16;
--:-:-:-:0 SHR.U32 block_K, block1, 16;
--:-:-:-:0 LOP.AND block_C, block1, 0xffff;
--:-:-:-:1 MOV block_F, block3;
--:-:-:-:1 LOP.AND idx_DHW, block0, 0xffff;
--:-:-:-:1 MOV block_CK, block2;
</ORDERED>
// tidX = (tid & 7) << 2
// tidY = tid >> 3
--:-:-:-:1 LOP.AND tidX, tid, 7;
--:-:-:-:1 SHL tidX, tidX, 2;
--:-:-:-:1 SHR.U32 tidY0, tid, 3;
--:-:-:-:1 IADD tidY8, tidY0, 8;
// The extra tidFY0*2 here is to avoid bank conflicts on write
// writeS = (tidY0*32 + tidX) * 4
--:-:-:-:1 ISCADD writeS, tidY0, tidX, 5;
--:-:-:-:1 SHL writeS, writeS, 2;
// readFs = ((tid & 8) >> 2) | (tid & 1)
--:-:-:-:1 LOP.AND tid1, tid, 1;
--:-:-:-:1 LOP.AND readFs, tid, 8;
--:-:-:-:1 SHR.U32 readFs, readFs, 2;
--:-:-:-:1 LOP.OR readFs, readFs, tid1;
// readIs = (tid >> 1) & 3
--:-:-:-:1 BFE.U32 readIs, tid, 0x201; // 2 bits at position 1
// tid16 = tid & -16
--:-:-:-:1 LOP.AND tid16, tid, -16;
// Arrange 8 tiles horizontally in the I direction
// Add some spacing (readFs << 2) to avoid write bank conflicts
// readIs2 = readIs + (tid16 >> 1) + (readFs << 2)
--:-:-:-:1 SHR.U32 tid16_1, tid16, 1;
--:-:-:-:1 IADD readIs2, tid16_1, readIs;
--:-:-:-:1 ISCADD readIs2, readFs, readIs2, 2;
// readFs <<= 4
// readIs <<= 4
// readIs2 <<= 4
--:-:-:-:1 SHL readFs, readFs, 4;
--:-:-:-:1 SHL readIs, readIs, 4;
--:-:-:-:1 SHL readIs2, readIs2, 4;
// writeOs = readFs*32*4 + readIs2
--:-:-:-:1 ISCADD writeOs, readFs, readIs2, 7;
// Each block of 16 threads works on 4 lines
// readFs += tid16 / 4 * 32 * 4
// readIs += tid16 / 4 * 32 * 4
--:-:-:-:1 ISCADD readFs, tid16, readFs, 5;
--:-:-:-:1 ISCADD readIs, tid16, readIs, 5;
// Offset readIs by size of ShareF
--:-:-:-:1 IADD readIs, readIs, 4x<szShareF>;
// sizeLutDHW = TRS * 32 + 32
// shareLutK = sizeLutDHW * 4 + 4x<offset_lut>
// shareLutC = block_K * 4 + shareLutK
// shareLutDHW = tidX * 4 + 4x<offset_lut>
--:-:-:-:1 MOV TRS, param_TRS;
--:-:-:-:1 ISCADD sizeLutDHW, TRS, 32, 5;
--:-:-:-:1 ISCADD shareLutK, sizeLutDHW, 4x<offset_lut>, 2;
--:-:-:-:1 ISCADD shareLutC, block_K, shareLutK, 2;
--:-:-:-:1 ISCADD shareLutDHW, tidX, 4x<offset_lut>, 2;
// Align this for LDS.U.128 in STORE_O
--:-:-:-:1 LOP.AND.NZ P5, partialC, shareLutC, 15;
--:-:-:-:1 @P5 IADD3 shareLutC, shareLutC, 16, -partialC;
// CTRS = C * TRS
// KTRS = K * TRS
--:-:-:-:1 XMAD CTRS, block_C, param_TRS, RZ;
--:-:-:-:1 XMAD KTRS, block_K, param_TRS, RZ;
--:-:-:-:1 IADD KTRS16, KTRS, 16;
// KCTRS
// c = block_C * 32 + tidX
// offsetCTRS = c * TRS + block_F
--:-:-:-:1 ISCADD ck0, idx_C, tidX, 5;
--:-:-:-:1 IADD ck1, ck0, 1;
--:-:-:-:1 IADD ck2, ck0, 2;
--:-:-:-:1 IADD ck3, ck0, 3;
--:-:-:-:1 XMAD offsetCTRS, ck0, param_TRS, block_F;
// k < block_K
--:-:-:-:1 ISETP.LT.AND P0, PT, ck0, block_C, PT;
--:-:-:-:1 ISETP.LT.AND P1, PT, ck1, block_C, PT;
--:-:-:-:1 ISETP.LT.AND P2, PT, ck2, block_C, PT;
--:-:-:-:1 ISETP.LT.AND P3, PT, ck3, block_C, PT;
--:-:-:-:1 P2R predF, PR, RZ, 0x0f;
// If this value is not a multiple of 16 we want to grab the partial amount on the first fetch.
// If it is a multiple of 16 then make a full 16 line fetch.
--:-:-:-:1 LOP.AND.Z P4, partialKTRS, KTRS, 15;
--:-:-:-:1 @P4 MOV partialKTRS, 16;
// offsetIn = idx_N * KMPQ
04:-:-:-:0 XMAD.LO2C offsetIn, idx_N, param_KMPQ, RZ;
</SCHEDULE_BLOCK>
--:-:-:-:5 @P6 BRA.U CHANNEL_LUT;
// lutStore = (tidY0*32 + tidX) * 4 + 4x<offset_lut> - 16*32*4
// dhwOffset = sizeLutDHW * idx_DHW + tidY0*32 + tidX
<SCHEDULE_BLOCK>
--:-:-:-:1 IADD trs00, tidY0, 0;
--:-:-:-:1 IADD trs04, tidY0, 4;
--:-:-:-:1 IADD trs08, tidY0, 8;
--:-:-:-:1 IADD trs12, tidY0, 12;
--:-:-:-:1 ISCADD lutStore, tidY0, tidX, 5;
--:-:-:-:1 ISETP.LE.AND P0, PT, tidY0, param_TRS, PT; // LE to get single output map row as well
--:-:-:-:1 XMAD dhwOffset, sizeLutDHW, idx_DHW, lutStore;
--:-:-:-:5 ISCADD lutStore, lutStore, 4x<offset_lut - 16*32>, 2;
</SCHEDULE_BLOCK>
DHW_LOOP:
<SCHEDULE_BLOCK>
--:-:-:-:1 ISETP.LE.AND P1, PT, trs04, param_TRS, PT;
--:-:-:-:1 ISETP.LE.AND P2, PT, trs08, param_TRS, PT;
--:-:-:-:1 ISETP.LE.AND P3, PT, trs12, param_TRS, PT;
--:-:-:-:1 LEA Lut0.CC, dhwOffset, param_LutDHW[0], 2;
--:-:-:-:1 LEA.HI.X Lut1, dhwOffset, param_LutDHW[1], RZ, 2;
<ORDERED>
01:-:1:-:1 @P0 LDG.E.CI.128 lutEntry00, [Lut + 4x< 0*32>];
02:-:2:-:1 @P1 LDG.E.CI.128 lutEntry04, [Lut + 4x< 4*32>];
04:-:3:-:1 @P2 LDG.E.CI.128 lutEntry08, [Lut + 4x< 8*32>];
08:-:4:-:1 @P3 LDG.E.CI.128 lutEntry12, [Lut + 4x<12*32>];
--:-:-:-:1 IADD lutStore, lutStore, 4x<16*32>;
</ORDERED>
--:-:-:-:1 IADD trs00, trs00, 16;
--:-:-:-:1 IADD trs04, trs04, 16;
--:-:-:-:1 IADD trs08, trs08, 16;
--:-:-:-:1 IADD trs12, trs12, 16;
--:-:-:-:1 IADD dhwOffset, dhwOffset, 1x<16*32>;
01:1:-:-:1 @P0 STS.128 [lutStore + 4x< 0*32>], lutEntry00;
02:2:-:-:1 @P1 STS.128 [lutStore + 4x< 4*32>], lutEntry04;
04:3:-:-:1 @P2 STS.128 [lutStore + 4x< 8*32>], lutEntry08;
08:4:-:Y:b @P3 STS.128 [lutStore + 4x<12*32>], lutEntry12;
--:-:-:-:1 ISETP.LE.AND P0, PT, trs00, param_TRS, PT;
</SCHEDULE_BLOCK>
--:-:-:-:5 @P0 BRA.U DHW_LOOP;
--:-:-:-:5 BRA.U END_LUT;
CHANNEL_LUT:
<SCHEDULE_BLOCK>
// Load all K lut entries and the 32 values of C we need
// ck0 = tid & 31
// P4 = idx_C*32 + ck0 < block_C
// offsetC = block_CK + idx_C*32 + ck0
--:-:-:-:1 LOP.AND ck0, tid, 31;
--:-:-:-:1 IADD ck1, ck0, 1x<32>;
--:-:-:-:1 IADD ck2, ck0, 2x<32>;
--:-:-:-:1 IADD ck3, ck0, 3x<32>;
--:-:-:-:1 ISETP.LT.AND P0, PT, ck0, block_K, PT;
--:-:-:-:1 ISCADD offsetCK, idx_C, ck0, 5;
--:-:-:-:1 ISETP.LT.AND P4, PT, offsetCK, block_C, PT;
--:-:-:-:1 IADD offsetCK, block_CK, offsetCK;
--:-:-:-:1 LEA Lut0.CC, offsetCK, param_LutCK[0], 2;
--:-:-:-:1 LEA.HI.X Lut1, offsetCK, param_LutCK[1], RZ, 2;
--:5:-:-:1 @P4 LDG.E.CI.32 cEntry, [Lut];
// offsetK = block_CK + block_C + ck0
--:-:-:-:1 IADD3 offsetCK, block_CK, block_C, ck0;
</SCHEDULE_BLOCK>
CHANNEL_LOOP:
--:-:-:-:2 ISETP.LT.AND P1, PT, ck1, block_K, PT;
--:-:-:-:2 ISETP.LT.AND P2, PT, ck2, block_K, PT;
--:-:-:-:2 ISETP.LT.AND P3, PT, ck3, block_K, PT;
10:-:-:-:6 LEA Lut0.CC, offsetCK, param_LutCK[0], 2;
--:-:-:-:2 LEA.HI.X Lut1, offsetCK, param_LutCK[1], RZ, 2;
01:-:-:-:0 ISCADD lutStore, ck0, shareLutK, 2;
--:-:1:-:1 @P0 LDG.E.CI.32 kEntry0, [Lut + 4x<0*32>];
--:-:-:-:0 IADD ck0, ck0, 4x<32>;
--:-:2:-:1 @P1 LDG.E.CI.32 kEntry1, [Lut + 4x<1*32>];
--:-:-:-:0 IADD ck1, ck1, 4x<32>;
--:-:3:-:1 @P2 LDG.E.CI.32 kEntry2, [Lut + 4x<2*32>];
--:-:-:-:0 IADD ck2, ck2, 4x<32>;
--:-:4:-:1 @P3 LDG.E.CI.32 kEntry3, [Lut + 4x<3*32>];
--:-:-:-:0 IADD ck3, ck3, 4x<32>;
01:-:-:-:3 @P0 STS [lutStore + 4x<0*32>], kEntry0;
--:-:-:-:0 ISETP.LT.AND P0, PT, ck0, block_K, PT;
02:-:-:-:1 @P1 STS [lutStore + 4x<1*32>], kEntry1;
--:-:-:-:0 IADD offsetCK, offsetCK, 4x<32>;
04:-:-:-:1 @P2 STS [lutStore + 4x<2*32>], kEntry2;
08:1:-:Y:b @P3 STS [lutStore + 4x<3*32>], kEntry3;
--:-:-:-:5 @P0 BRA.U CHANNEL_LOOP;
--:-:-:-:6 @P4 LOP.AND ck0, tid, 31;
01:-:-:-:4 @P4 ISCADD lutStore, ck0, shareLutC, 2;
--:1:-:-:2 @P4 STS [lutStore], cEntry;
END_LUT:
0f:-:-:-:5 BAR.SYNC 0;
// posKTRS = tidY
--:-:-:-:0 MOV posKTRS, tidY0;
--:-:-:-:6 CAL DO_LOADS;
--:-:-:-:0 ISETP.LT.AND P5, PT, posKTRS, KTRS, PT;
[+
return F16() ? q{
04:-:-:-:1 F2F.F32.F16 F00, F00;
--:-:-:-:1 F2F.F32.F16 F01, F01;
--:-:-:-:1 F2F.F32.F16 F02, F02;
--:-:3:-:1 F2F.F32.F16 F03, F03;
08:-:-:-:1 F2F.F32.F16 F80, F80;
--:-:-:-:1 F2F.F32.F16 F81, F81;
--:-:-:-:1 F2F.F32.F16 F82, F82;
--:-:4:-:1 F2F.F32.F16 F83, F83;
} : '';
+]
[+
return I16() ? q{
10:-:-:-:1 F2F.F32.F16 I00, I00;
--:-:-:-:1 F2F.F32.F16 I01, I01;
--:-:-:-:1 F2F.F32.F16 I02, I02;
--:-:5:-:1 F2F.F32.F16 I03, I03;
20:-:-:-:1 F2F.F32.F16 I80, I80;
--:-:-:-:1 F2F.F32.F16 I81, I81;
--:-:-:-:1 F2F.F32.F16 I82, I82;
--:-:6:-:1 F2F.F32.F16 I83, I83;
} : '';
+]
04:-:-:-:1 STS.128 [writeS + 4x<0*32>], F0;
08:-:-:-:1 STS.128 [writeS + 4x<8*32>], F8;
10:-:-:-:1 STS.128 [writeS + 4x<0*32 + szShareF>], I0;
20:-:-:-:1 STS.128 [writeS + 4x<8*32 + szShareF>], I8;
--:-:-:-:5 BAR.SYNC 0;
--:-:-:-:0 LOP.XOR writeS, writeS, 4x<szShareF + szShareI>;
--:-:-:-:1 LDS.U.128 j0Fy0, [readFs + 4x<0*32 + 00>];
--:-:-:-:1 LDS.U.128 j0Ix0, [readIs + 4x<0*32 + 00>];
--:-:-:-:1 LDS.U.128 j0Fy4, [readFs + 4x<0*32 + 16>];
--:-:1:-:1 LDS.U.128 j0Ix4, [readIs + 4x<0*32 + 16>];
--:-:-:-:0 SEL partialKTRS, RZ, 16, !P5;
--:-:-:-:6 CAL DO_LOADS;
--:-:-:-:5 BRA.U LOOP;
DO_LOADS:
<SCHEDULE_BLOCK>
--:-:-:-:1 ISETP.LT.AND P5, PT, tidY0, partialKTRS, PT;
--:-:-:-:1 ISETP.LT.AND P6, PT, tidY8, partialKTRS, PT;
--:-:-:-:1 XMAD k0, posKTRS, param_magic_TRS, RZ;
--:-:-:-:1 SHR.U32 k0, k0, param_shift_TRS;
--:-:-:-:1 VMAD.U16.U16 trs0, -k0, TRS, posKTRS;
--:-:-:-:1 ISCADD shareK0, k0, shareLutK, 2;
--:-:-:-:1 ISCADD shareDHW0, trs0, shareLutDHW, 7;
--:-:-:-:1 IADD posKTRS, posKTRS, 8;
--:-:-:-:1 XMAD k8, posKTRS, param_magic_TRS, RZ;
--:-:-:-:1 SHR.U32 k8, k8, param_shift_TRS;
--:-:-:-:1 VMAD.U16.U16 trs8, -k8, TRS, posKTRS;
--:-:-:-:1 ISCADD shareK8, k8, shareLutK, 2;
--:-:-:-:1 ISCADD shareDHW8, trs8, shareLutDHW, 7;
--:-:-:-:1 IADD3 posKTRS, posKTRS, -8, partialKTRS;
<ORDERED>
--:-:-:-:1 @P5 LDS.U.32 offset0Ik, [shareK0];
--:-:5:-:1 @P5 LDS.U.128 slice0I, [shareDHW0];
--:-:-:-:1 @P6 LDS.U.32 offset8Ik, [shareK8];
--:-:6:-:1 @P6 LDS.U.128 slice8I, [shareDHW8];
</ORDERED>
--:-:-:-:1 XMAD offsetK0, k0, CTRS, trs0;
--:-:-:-:1 IADD offsetK0, offsetCTRS, offsetK0;
--:-:-:-:1 XMAD offsetK8, k8, CTRS, trs8;
--:-:-:-:1 IADD offsetK8, offsetCTRS, offsetK8;
--:-:-:-:1 @P5 R2P PR, predF, 0x0f;
--:-:-:-:1 @!P5 R2P PR, RZ, 0x0f;
--:-:-:-:1 LEA track0F0.CC, offsetK0, param_F[0], [+ dshiftF() +];
--:-:-:-:1 IADD.X track0F1, RZ, param_F[1];
--:-:-:-:1 LEA track0F2.CC, TRS, track0F0, [+ dshiftF() +];
--:-:-:-:1 IADD.X track0F3, track0F1, RZ;
--:-:-:-:1 LEA track0F4.CC, TRS, track0F2, [+ dshiftF() +];
--:-:-:-:1 IADD.X track0F5, track0F3, RZ;
--:-:-:-:1 LEA track0F6.CC, TRS, track0F4, [+ dshiftF() +];
--:-:-:-:1 IADD.X track0F7, track0F5, RZ;
--:-:-:-:1 @!P0 MOV F00, RZ;
--:-:-:-:1 @!P1 MOV F01, RZ;
--:-:-:-:1 @!P2 MOV F02, RZ;
--:-:-:-:1 @!P3 MOV F03, RZ;
<ORDERED>
--:-:-:-:1 @P0 LDG.E.CI.[+ dtypeF() +] F00, [track0F0];
--:-:-:-:1 @P1 LDG.E.CI.[+ dtypeF() +] F01, [track0F2];
--:-:-:-:1 @P2 LDG.E.CI.[+ dtypeF() +] F02, [track0F4];
--:-:3:-:1 @P3 LDG.E.CI.[+ dtypeF() +] F03, [track0F6];
</ORDERED>
--:-:-:-:1 @P6 R2P PR, predF, 0x0f;
--:-:-:-:1 @!P6 R2P PR, RZ, 0x0f;
--:-:-:-:1 LEA track8F0.CC, offsetK8, param_F[0], [+ dshiftF() +];
--:-:-:-:1 IADD.X track8F1, RZ, param_F[1];
--:-:-:-:1 LEA track8F2.CC, TRS, track8F0, [+ dshiftF() +];
--:-:-:-:1 IADD.X track8F3, track8F1, RZ;
--:-:-:-:1 LEA track8F4.CC, TRS, track8F2, [+ dshiftF() +];
--:-:-:-:1 IADD.X track8F5, track8F3, RZ;
--:-:-:-:1 LEA track8F6.CC, TRS, track8F4, [+ dshiftF() +];
--:-:-:-:1 IADD.X track8F7, track8F5, RZ;
--:-:-:-:1 @!P0 MOV F80, RZ;
--:-:-:-:1 @!P1 MOV F81, RZ;
--:-:-:-:1 @!P2 MOV F82, RZ;
--:-:-:-:1 @!P3 MOV F83, RZ;
<ORDERED>
--:-:-:-:1 @P0 LDG.E.CI.[+ dtypeF() +] F80, [track8F0];
--:-:-:-:1 @P1 LDG.E.CI.[+ dtypeF() +] F81, [track8F2];
--:-:-:-:1 @P2 LDG.E.CI.[+ dtypeF() +] F82, [track8F4];
--:2:4:-:1 @P3 LDG.E.CI.[+ dtypeF() +] F83, [track8F6];
</ORDERED>
</SCHEDULE_BLOCK>
<SCHEDULE_BLOCK>
10:-:-:-:1 ISETP.GE.AND P0, PT, slice0I0, RZ, P5;
--:-:-:-:1 ISETP.GE.AND P1, PT, slice0I1, RZ, P5;
--:-:-:-:1 ISETP.GE.AND P2, PT, slice0I2, RZ, P5;
--:-:-:-:1 ISETP.GE.AND P3, PT, slice0I3, RZ, P5;
--:-:-:-:1 IADD3 slice0I0, slice0I0, offset0Ik, offsetIn;
--:-:-:-:1 IADD3 slice0I1, slice0I1, offset0Ik, offsetIn;
--:-:-:-:1 IADD3 slice0I2, slice0I2, offset0Ik, offsetIn;
--:-:-:-:1 IADD3 slice0I3, slice0I3, offset0Ik, offsetIn;
02:-:-:-:1 LEA track0I0.CC, slice0I0, param_I[0], [+ dshiftI() +];
--:-:-:-:1 LEA.HI.X track0I1, slice0I0, param_I[1], RZ, [+ dshiftI() +];
--:-:-:-:1 LEA track0I2.CC, slice0I1, param_I[0], [+ dshiftI() +];
--:-:-:-:1 LEA.HI.X track0I3, slice0I1, param_I[1], RZ, [+ dshiftI() +];
--:-:-:-:1 LEA track0I4.CC, slice0I2, param_I[0], [+ dshiftI() +];
--:-:-:-:1 LEA.HI.X track0I5, slice0I2, param_I[1], RZ, [+ dshiftI() +];
--:-:-:-:1 LEA track0I6.CC, slice0I3, param_I[0], [+ dshiftI() +];
--:-:-:-:1 LEA.HI.X track0I7, slice0I3, param_I[1], RZ, [+ dshiftI() +];
--:-:-:-:1 @!P0 MOV I00, RZ;
--:-:-:-:1 @!P1 MOV I01, RZ;
--:-:-:-:1 @!P2 MOV I02, RZ;
--:-:-:-:1 @!P3 MOV I03, RZ;
<ORDERED>
--:-:-:-:1 @P0 LDG.E.CI.[+ dtypeI() +] I00, [track0I0];
--:-:-:-:1 @P1 LDG.E.CI.[+ dtypeI() +] I01, [track0I2];
--:-:-:-:1 @P2 LDG.E.CI.[+ dtypeI() +] I02, [track0I4];
--:-:5:-:1 @P3 LDG.E.CI.[+ dtypeI() +] I03, [track0I6];
</ORDERED>
20:-:-:-:1 ISETP.GE.AND P0, PT, slice8I0, RZ, P6;
--:-:-:-:1 ISETP.GE.AND P1, PT, slice8I1, RZ, P6;
--:-:-:-:1 ISETP.GE.AND P2, PT, slice8I2, RZ, P6;
--:-:-:-:1 ISETP.GE.AND P3, PT, slice8I3, RZ, P6;
--:-:-:-:1 IADD3 slice8I0, slice8I0, offset8Ik, offsetIn;
--:-:-:-:1 IADD3 slice8I1, slice8I1, offset8Ik, offsetIn;
--:-:-:-:1 IADD3 slice8I2, slice8I2, offset8Ik, offsetIn;
--:-:-:-:1 IADD3 slice8I3, slice8I3, offset8Ik, offsetIn;
--:-:-:-:1 LEA track8I0.CC, slice8I0, param_I[0], [+ dshiftI() +];
--:-:-:-:1 LEA.HI.X track8I1, slice8I0, param_I[1], RZ, [+ dshiftI() +];
--:-:-:-:1 LEA track8I2.CC, slice8I1, param_I[0], [+ dshiftI() +];
--:-:-:-:1 LEA.HI.X track8I3, slice8I1, param_I[1], RZ, [+ dshiftI() +];
--:-:-:-:1 LEA track8I4.CC, slice8I2, param_I[0], [+ dshiftI() +];
--:-:-:-:1 LEA.HI.X track8I5, slice8I2, param_I[1], RZ, [+ dshiftI() +];
--:-:-:-:1 LEA track8I6.CC, slice8I3, param_I[0], [+ dshiftI() +];
--:-:-:-:1 LEA.HI.X track8I7, slice8I3, param_I[1], RZ, [+ dshiftI() +];
--:-:-:-:1 @!P0 MOV I80, RZ;
--:-:-:-:1 @!P1 MOV I81, RZ;
--:-:-:-:1 @!P2 MOV I82, RZ;
--:-:-:-:1 @!P3 MOV I83, RZ;
<ORDERED>
--:-:-:-:1 @P0 LDG.E.CI.[+ dtypeI() +] I80, [track8I0];
--:-:-:-:1 @P1 LDG.E.CI.[+ dtypeI() +] I81, [track8I2];
--:-:-:-:1 @P2 LDG.E.CI.[+ dtypeI() +] I82, [track8I4];
--:2:6:-:1 @P3 LDG.E.CI.[+ dtypeI() +] I83, [track8I6];
</ORDERED>
</SCHEDULE_BLOCK>
--:-:-:-:5 RET;
LOOP:
--:-:-:-:1 ISETP.LT.AND P5, PT, posKTRS, KTRS, PT;
--:-:-:-:1 XMAD k0, posKTRS, param_magic_TRS, RZ;
--:-:-:-:1 ISETP.LT.AND P6, PT, posKTRS, KTRS16, PT;
[+
our ($dtypeF, $dshiftF, $dsizeF, $dtypeI, $dshiftI, $dsizeI);
my %insert = (
j0c3 => "--:-:-:-:1 SHR.U32 k0, k0, param_shift_TRS;\n",
j0c8 => "--:-:-:-:1 \@P5 VMAD.U16.U16 trs0, -k0, TRS, posKTRS;\n" .
"--:-:-:-:1 \@P5 ISCADD shareK0, k0, shareLutK, 2;\n" .
"--:-:-:-:1 IADD posKTRS, posKTRS, 8;\n",
j0c11 => "--:-:-:-:1 \@P5 ISCADD shareDHW0, trs0, shareLutDHW, 7;\n" .
"--:-:-:-:1 \@P5 XMAD offsetK0, k0, CTRS, trs0;\n",
F16() ? (
j0c9 => "04:-:-:-:1 \@P6 F2F.F32.F16 F00, F00;\n",
j0c10 => "--:-:-:-:1 \@P6 F2F.F32.F16 F01, F01;\n",
j0c13 => "--:-:-:-:1 \@P6 F2F.F32.F16 F02, F02;\n",
j0c15 => "--:-:3:-:1 \@P6 F2F.F32.F16 F03, F03;\n",
) : (),
j0c12 => "--:-:-:-:1 \@P5 XMAD k8, posKTRS, param_magic_TRS, RZ;\n",
j0c17 => "--:-:-:-:1 \@P5 SHR.U32 k8, k8, param_shift_TRS;\n" .
"--:-:-:-:1 \@P5 IADD offsetK0, offsetCTRS, offsetK0;\n",
j0c22 => "--:-:-:-:1 \@P5 VMAD.U16.U16 trs8, -k8, TRS, posKTRS;\n" .
"--:-:-:-:1 \@P5 ISCADD shareK8, k8, shareLutK, 2;\n" .
"--:-:-:-:1 IADD posKTRS, posKTRS, 8;\n",
j0c25 => "--:-:-:-:1 \@P5 ISCADD shareDHW8, trs8, shareLutDHW, 7;\n" .
"--:-:-:-:1 \@P5 XMAD offsetK8, k8, CTRS, trs8;\n",
j0c27 => "--:-:-:-:1 \@P5 R2P PR, predF, 0x0f;\n",
j0c28 => "--:-:-:-:1 \@!P5 R2P PR, RZ, 0x0f;\n",
j0c23 => "06:3:-:-:1 \@P6 STS.128 [writeS + 4x<0*32>], F0;\n" .
"--:-:-:-:1 \@P5 LEA track0F0.CC, offsetK0, param_F[0], $dshiftF;\n",
j0c26 => "--:-:-:-:1 \@P5 IADD.X track0F1, RZ, param_F[1];\n" .
"--:-:-:-:1 \@P5 LEA track0F2.CC, TRS, track0F0, $dshiftF;\n",
j0c29 => "--:-:-:-:1 \@P5 IADD.X track0F3, track0F1, RZ;\n" .
"--:-:-:-:1 \@P5 LEA track0F4.CC, TRS, track0F2, $dshiftF;\n",
j0c34 => "--:-:-:-:1 \@P5 IADD.X track0F5, track0F3, RZ;\n" .
"--:-:-:-:1 \@P5 LEA track0F6.CC, TRS, track0F4, $dshiftF;\n",
j0c38 => "--:-:-:-:1 \@P5 IADD.X track0F7, track0F5, RZ;\n",
j0c36 => "--:-:-:-:1 \@P5 IADD offsetK8, offsetCTRS, offsetK8;\n",
j0c31 => "--:-:-:-:1 \@P5 LDS.U.32 offset0Ik, [shareK0];\n",
j0c33 => "--:-:-:-:1 \@P5 LDS.U.128 slice0I, [shareDHW0];\n",
j0c40 => "04:-:-:-:1 \@P0 LDG.E.CI.$dtypeF F00, [track0F0];\n",
j0c42 => "--:-:-:-:1 \@P1 LDG.E.CI.$dtypeF F01, [track0F2];\n",
j0c44 => "--:-:-:-:1 \@P2 LDG.E.CI.$dtypeF F02, [track0F4];\n",
j0c46 => "--:-:3:-:1 \@P3 LDG.E.CI.$dtypeF F03, [track0F6];\n",
F16() ? (
j0c48 => "08:-:-:-:1 \@P6 F2F.F32.F16 F80, F80;\n",
j0c50 => "--:-:-:-:1 \@P6 F2F.F32.F16 F81, F81;\n",
j0c52 => "--:-:-:-:1 \@P6 F2F.F32.F16 F82, F82;\n",
j0c54 => "--:-:4:-:1 \@P6 F2F.F32.F16 F83, F83;\n",
) : (),
j1c8 => "08:4:-:-:1 \@P6 STS.128 [writeS + 4x<8*32>], F8;\n" .
"--:-:-:-:1 \@P5 LEA track8F0.CC, offsetK8, param_F[0], $dshiftF;\n",
j1c13 => "--:-:-:-:1 \@P5 IADD.X track8F1, RZ, param_F[1];\n" .
"--:-:-:-:1 \@P5 LEA track8F2.CC, TRS, track8F0, $dshiftF;\n",
j1c18 => "--:-:-:-:1 \@P5 IADD.X track8F3, track8F1, RZ;\n" .
"--:-:-:-:1 \@P5 LEA track8F4.CC, TRS, track8F2, $dshiftF;\n",
j1c23 => "--:-:-:-:1 \@P5 IADD.X track8F5, track8F3, RZ;\n" .
"--:-:-:-:1 \@P5 LEA track8F6.CC, TRS, track8F4, $dshiftF;\n",
j1c28 => "--:-:-:-:1 \@P5 IADD.X track8F7, track8F5, RZ;\n",
j1c15 => "--:-:-:-:1 \@P5 LDS.U.32 offset8Ik, [shareK8];\n",
j1c20 => "--:-:6:-:1 \@P5 LDS.U.128 slice8I, [shareDHW8];\n",
j1c31 => "08:-:-:-:1 \@P0 LDG.E.CI.$dtypeF F80, [track8F0];\n",
j1c33 => "--:-:-:-:1 \@P1 LDG.E.CI.$dtypeF F81, [track8F2];\n",
j1c35 => "--:-:-:-:1 \@P2 LDG.E.CI.$dtypeF F82, [track8F4];\n",
j1c37 => "--:2:4:-:1 \@P3 LDG.E.CI.$dtypeF F83, [track8F6];\n",
I16() ? (
j1c40 => "10:-:-:-:1 \@P6 F2F.F32.F16 I00, I00;\n",
j1c42 => "--:-:-:-:1 \@P6 F2F.F32.F16 I01, I01;\n",
j1c44 => "--:-:-:-:1 \@P6 F2F.F32.F16 I02, I02;\n",
j1c46 => "--:-:5:-:1 \@P6 F2F.F32.F16 I03, I03;\n",
) : (),
j1c62 => "10:5:-:-:1 \@P6 STS.128 [writeS + 4x<0*32 + szShareF>], I0;\n",
j2c5 => "--:-:-:-:1 ISETP.GE.AND P0, PT, slice0I0, RZ, P5;\n" .
"--:-:-:-:1 \@P5 IADD3 slice0I0, slice0I0, offset0Ik, offsetIn;\n" .
"--:-:-:-:1 ISETP.GE.AND P1, PT, slice0I1, RZ, P5;\n" .
"--:-:-:-:1 \@P5 IADD3 slice0I1, slice0I1, offset0Ik, offsetIn;\n" .
"--:-:-:-:1 ISETP.GE.AND P2, PT, slice0I2, RZ, P5;\n" .
"--:-:-:-:1 \@P5 IADD3 slice0I2, slice0I2, offset0Ik, offsetIn;\n" .
"--:-:-:-:1 ISETP.GE.AND P3, PT, slice0I3, RZ, P5;\n" .
"--:-:-:-:1 \@P5 IADD3 slice0I3, slice0I3, offset0Ik, offsetIn;\n" .
"02:-:-:-:1 \@P5 LEA track0I0.CC, slice0I0, param_I[0], $dshiftI;\n",
j2c10 => "--:-:-:-:1 \@P5 LEA.HI.X track0I1, slice0I0, param_I[1], RZ, $dshiftI;\n",
j2c11 => "--:-:-:-:1 \@P5 LEA track0I2.CC, slice0I1, param_I[0], $dshiftI;\n",
j2c16 => "--:-:-:-:1 \@P5 LEA.HI.X track0I3, slice0I1, param_I[1], RZ, $dshiftI;\n",
j2c17 => "--:-:-:-:1 \@P5 LEA track0I4.CC, slice0I2, param_I[0], $dshiftI;\n",
j2c22 => "--:-:-:-:1 \@P5 LEA.HI.X track0I5, slice0I2, param_I[1], RZ, $dshiftI;\n",
j2c23 => "--:-:-:-:1 \@P5 LEA track0I6.CC, slice0I3, param_I[0], $dshiftI;\n",
j2c28 => "--:-:-:-:1 \@P5 LEA.HI.X track0I7, slice0I3, param_I[1], RZ, $dshiftI;\n",
j2c25 => "10:-:-:-:1 \@P0 LDG.E.CI.$dtypeI I00, [track0I0];\n",
j2c27 => "--:-:-:-:1 \@P1 LDG.E.CI.$dtypeI I01, [track0I2];\n",
j2c29 => "--:-:-:-:1 \@P2 LDG.E.CI.$dtypeI I02, [track0I4];\n",
j2c31 => "--:-:5:-:1 \@P3 LDG.E.CI.$dtypeI I03, [track0I6];\n",
I16() ? (
j2c33 => "20:-:-:-:1 \@P6 F2F.F32.F16 I80, I80;\n",
j2c35 => "--:-:-:-:1 \@P6 F2F.F32.F16 I81, I81;\n",
j2c37 => "--:-:-:-:1 \@P6 F2F.F32.F16 I82, I82;\n",
j2c39 => "--:-:6:-:1 \@P6 F2F.F32.F16 I83, I83;\n",
) : (),
j2c41 => "--:-:-:-:1 \@!P0 I2I.U32.U32 I00, RZ;\n",
j2c43 => "--:-:-:-:1 \@!P1 I2I.U32.U32 I01, RZ;\n",
j2c45 => "--:-:-:-:1 \@!P2 I2I.U32.U32 I02, RZ;\n",
j2c47 => "--:-:-:-:1 \@!P3 I2I.U32.U32 I03, RZ;\n",
j2c51 => "20:6:-:-:1 \@P6 STS.128 [writeS + 4x<8*32 + szShareF>], I8;\n",
j2c52 => "--:-:-:-:1 ISETP.GE.AND P0, PT, slice8I0, RZ, P5;\n" .
"--:-:-:-:1 \@P5 IADD3 slice8I0, slice8I0, offset8Ik, offsetIn;\n" .
"--:-:-:-:1 ISETP.GE.AND P1, PT, slice8I1, RZ, P5;\n" .
"--:-:-:-:1 \@P5 IADD3 slice8I1, slice8I1, offset8Ik, offsetIn;\n" .
"--:-:-:-:1 ISETP.GE.AND P2, PT, slice8I2, RZ, P5;\n" .
"--:-:-:-:1 \@P5 IADD3 slice8I2, slice8I2, offset8Ik, offsetIn;\n" .
"--:-:-:-:1 ISETP.GE.AND P3, PT, slice8I3, RZ, P5;\n" .
"--:-:-:-:1 \@P5 IADD3 slice8I3, slice8I3, offset8Ik, offsetIn;\n" .
"--:-:-:-:1 \@P5 LEA track8I0.CC, slice8I0, param_I[0], $dshiftI;\n",
j2c57 => "--:-:-:-:1 \@P5 LEA.HI.X track8I1, slice8I0, param_I[1], RZ, $dshiftI;\n",
j2c58 => "--:-:-:-:1 \@P5 LEA track8I2.CC, slice8I1, param_I[0], $dshiftI;\n",
j2c63 => "--:-:-:-:1 \@P5 LEA.HI.X track8I3, slice8I1, param_I[1], RZ, $dshiftI;\n",
j3c0 => "--:-:-:-:1 \@P5 LEA track8I4.CC, slice8I2, param_I[0], $dshiftI;\n",
j3c5 => "--:-:-:-:1 \@P5 LEA.HI.X track8I5, slice8I2, param_I[1], RZ, $dshiftI;\n",
j3c6 => "--:-:-:-:1 \@P5 LEA track8I6.CC, slice8I3, param_I[0], $dshiftI;\n",
j3c11 => "--:-:-:-:1 \@P5 LEA.HI.X track8I7, slice8I3, param_I[1], RZ, $dshiftI;\n",
j3c8 => "20:-:-:-:1 \@P0 LDG.E.CI.$dtypeI I80, [track8I0];\n",
j3c10 => "--:-:-:-:1 \@P1 LDG.E.CI.$dtypeI I81, [track8I2];\n",
j3c12 => "--:-:-:-:1 \@P2 LDG.E.CI.$dtypeI I82, [track8I4];\n",
j3c14 => "--:2:6:-:1 \@P3 LDG.E.CI.$dtypeI I83, [track8I6];\n",
j3c25 => "--:-:-:-:1 \@!P0 I2I.U32.U32 I80, RZ;\n",
j3c27 => "--:-:-:-:1 \@!P1 I2I.U32.U32 I81, RZ;\n",
j3c29 => "--:-:-:-:1 \@!P2 I2I.U32.U32 I82, RZ;\n",
j3c31 => "--:-:-:-:1 \@!P3 I2I.U32.U32 I83, RZ;\n",
j3c15 => "--:-:-:-:5 BAR.SYNC 0;\n" .
"--:-:-:-:1 \@P6 LOP.XOR readFs, readFs, 4x<szShareF + szShareI>;\n" .
"--:-:-:-:1 \@P6 LOP.XOR readIs, readIs, 4x<szShareF + szShareI>;\n" .
"--:-:-:-:1 \@P6 LOP.XOR writeS, writeS, 4x<szShareF + szShareI>;\n",
j3c63 => "--:-:-:Y:5 \@P6 BRA.U LOOP;\n",
);
my @cOrder;
my @swirl = ([0,2],[1,2],[1,0],[0,0]);
my @y = (0,1,4,5);
foreach my $x (0,2,4,6)
{
foreach my $y (@y)
{
push @cOrder, [$x + $_->[0], $y + $_->[1]] foreach @swirl;
}
@y = reverse @y;
}
my $out;
foreach my $j (0 .. 3)
{
my $odd = $j & 1;
my $nOdd = !$odd + 0;
my $rsOffset = ($j + 1) % 4;
my $rsPred = $j == 3 ? '@P6' : ' ';
my ($c0, $c2, $c4, $c6) = $j == 3 ? (17,19,21,23) : (0,2,4,6);
$insert{"j${j}c$c0"} = sprintf "--:-:-:-:1 %s LDS.U.128 j%dFy0, [readFs + 4x<%d*32 + 00>];\n", $rsPred, $nOdd, $rsOffset;
$insert{"j${j}c$c2"} = sprintf "--:-:-:-:1 %s LDS.U.128 j%dIx0, [readIs + 4x<%d*32 + 00>];\n", $rsPred, $nOdd, $rsOffset;
$insert{"j${j}c$c4"} = sprintf "--:-:-:-:1 %s LDS.U.128 j%dFy4, [readFs + 4x<%d*32 + 16>];\n", $rsPred, $nOdd, $rsOffset;
$insert{"j${j}c$c6"} = sprintf "--:-:1:-:1 %s LDS.U.128 j%dIx4, [readIs + 4x<%d*32 + 16>];\n", $rsPred, $nOdd, $rsOffset;
foreach my $c (0 .. 63)
{
my ($x,$y) = @{$cOrder[$c]};
my $ins = $insert{"j${j}c$c"} || '';
my $stall = $ins =~ /LDS|I2I|I2F|F2I|F2F|LDG|STS|BAR|BRA/ ? 0 : 1;
my $yield = $c == 32 && $stall ? 'Y' : '-';
my $wait = $c == 0 ? '01' : '--';
my $ctrl = "$wait:-:-:$yield:$stall";
$out .= sprintf "%s FFMA cx%dy%d, j%dIx%d, j%dFy%d, cx%dy%d;\n%s", $ctrl, $x,$y, $odd,$x, $odd,$y, $x,$y, $ins;
}
}
return $out;
+]
<SCHEDULE_BLOCK>
--:-:-:-:1 LOP.AND tid31, tid, 31;
--:-:-:-:1 SHR.U32 tid32, tid, 5;
// lutDHW = (TRS*32 + tid31)*4 + 4x<offset_lut>
--:-:-:-:1 ISCADD lutDHW, TRS, tid31, 5;
--:-:-:-:1 ISCADD lutDHW, lutDHW, 4x<offset_lut>, 2;
--:-:1:-:1 LDS.U.32 offsetDHW, [lutDHW];
// readOs = (tid_32*32*4*4 + tid_31 + tid_32*16) * 4
--:-:-:-:1 ISCADD readOs, tid32, tid31, 9;
--:-:-:-:1 ISCADD readOs, tid32, readOs, 4;
--:-:-:-:1 SHL readOs, readOs, 2;
// c = idx_C*32 + tid_32*4
--:-:-:-:1 SHL tid32, tid32, 2;
--:-:-:-:1 ISCADD c0, idx_C, tid32, 5;
--:-:-:-:1 IADD c1, c0, 1;
--:-:-:-:1 IADD c2, c0, 2;
--:-:-:-:1 IADD c3, c0, 3;
// lutC = tid32*4*4 + shareLutC + 4x<0|1|2|3>
--:-:-:-:1 ISCADD lutC, tid32, shareLutC, 2;
--:-:-:-:1 MOV alpha, param_alpha;
--:-:-:-:1 FMUL shuffle_x0y0, cx0y0, alpha;
--:-:-:-:1 FMUL shuffle_x1y0, cx1y0, alpha;
--:-:-:-:1 FMUL shuffle_x2y0, cx2y0, alpha;
--:-:-:-:1 FMUL shuffle_x3y0, cx3y0, alpha;
--:-:-:-:1 FMUL shuffle_x4y0, cx4y0, alpha;
--:-:-:-:1 FMUL shuffle_x5y0, cx5y0, alpha;
--:-:-:-:1 FMUL shuffle_x6y0, cx6y0, alpha;
--:-:-:-:1 FMUL shuffle_x7y0, cx7y0, alpha;
--:-:-:-:1 FMUL shuffle_x0y1, cx0y1, alpha;
--:-:-:-:1 FMUL shuffle_x1y1, cx1y1, alpha;
--:-:-:-:1 FMUL shuffle_x2y1, cx2y1, alpha;
--:-:-:-:1 FMUL shuffle_x3y1, cx3y1, alpha;
--:-:-:-:1 FMUL shuffle_x4y1, cx4y1, alpha;
--:-:-:-:1 FMUL shuffle_x5y1, cx5y1, alpha;
--:-:-:-:1 FMUL shuffle_x6y1, cx6y1, alpha;
--:-:-:-:1 FMUL shuffle_x7y1, cx7y1, alpha;
--:-:-:-:1 FMUL shuffle_x0y2, cx0y2, alpha;
--:-:-:-:1 FMUL shuffle_x1y2, cx1y2, alpha;
--:-:-:-:1 FMUL shuffle_x2y2, cx2y2, alpha;
--:-:-:-:1 FMUL shuffle_x3y2, cx3y2, alpha;
--:-:-:-:1 FMUL shuffle_x4y2, cx4y2, alpha;
--:-:-:-:1 FMUL shuffle_x5y2, cx5y2, alpha;
--:-:-:-:1 FMUL shuffle_x6y2, cx6y2, alpha;
--:-:-:-:1 FMUL shuffle_x7y2, cx7y2, alpha;
--:-:-:-:1 FMUL shuffle_x0y3, cx0y3, alpha;
--:-:-:-:1 FMUL shuffle_x1y3, cx1y3, alpha;
--:-:-:-:1 FMUL shuffle_x2y3, cx2y3, alpha;
--:-:-:-:1 FMUL shuffle_x3y3, cx3y3, alpha;
--:-:-:-:1 FMUL shuffle_x4y3, cx4y3, alpha;
--:-:-:-:1 FMUL shuffle_x5y3, cx5y3, alpha;
--:-:-:-:1 FMUL shuffle_x6y3, cx6y3, alpha;
--:-:-:-:1 FMUL shuffle_x7y3, cx7y3, alpha;
<ORDERED>
--:-:-:-:1 STS.128 [writeOs+4x<0*128 + 00>], shuffle_x0y0;
--:-:-:-:1 STS.128 [writeOs+4x<0*128 + 16>], shuffle_x4y0;
--:-:-:-:1 STS.128 [writeOs+4x<1*128 + 00>], shuffle_x0y1;
--:-:-:-:1 STS.128 [writeOs+4x<1*128 + 16>], shuffle_x4y1;
--:-:-:-:1 STS.128 [writeOs+4x<2*128 + 00>], shuffle_x0y2;
--:-:-:-:1 STS.128 [writeOs+4x<2*128 + 16>], shuffle_x4y2;
// m < M && p < P && q < Q
01:-:-:-:1 ISETP.GE.AND P4, PT, offsetDHW, RZ, PT;
--:-:-:-:1 STS.128 [writeOs+4x<3*128 + 00>], shuffle_x0y3;
--:-:-:-:1 STS.128 [writeOs+4x<3*128 + 16>], shuffle_x4y3;
</ORDERED>
// O = n*CDHW + c*DHW + d*HW + h*W + w
// O = n*CDHW + offsetC + offsetDHW
--:-:-:-:0 XMAD.LO2C offsetDHW, idx_N, param_CDHW, offsetDHW;
</SCHEDULE_BLOCK>
--:-:-:-:5 BAR.SYNC 0;
--:-:-:-:5 CAL STORE_O;
--:-:-:-:0 IADD readOs, readOs, 4x<8*128 + 2*16>;
--:-:-:-:5 CAL STORE_O;
--:-:-:-:5 BAR.SYNC 0;
<SCHEDULE_BLOCK>
--:-:-:-:1 FMUL shuffle_x0y4, cx0y4, alpha;
--:-:-:-:1 FMUL shuffle_x1y4, cx1y4, alpha;
--:-:-:-:1 FMUL shuffle_x2y4, cx2y4, alpha;
--:-:-:-:1 FMUL shuffle_x3y4, cx3y4, alpha;
--:-:-:-:1 FMUL shuffle_x4y4, cx4y4, alpha;
--:-:-:-:1 FMUL shuffle_x5y4, cx5y4, alpha;
--:-:-:-:1 FMUL shuffle_x6y4, cx6y4, alpha;
--:-:-:-:1 FMUL shuffle_x7y4, cx7y4, alpha;
--:-:-:-:1 FMUL shuffle_x0y5, cx0y5, alpha;
--:-:-:-:1 FMUL shuffle_x1y5, cx1y5, alpha;
--:-:-:-:1 FMUL shuffle_x2y5, cx2y5, alpha;
--:-:-:-:1 FMUL shuffle_x3y5, cx3y5, alpha;
--:-:-:-:1 FMUL shuffle_x4y5, cx4y5, alpha;
--:-:-:-:1 FMUL shuffle_x5y5, cx5y5, alpha;
--:-:-:-:1 FMUL shuffle_x6y5, cx6y5, alpha;
--:-:-:-:1 FMUL shuffle_x7y5, cx7y5, alpha;
--:-:-:-:1 FMUL shuffle_x0y6, cx0y6, alpha;
--:-:-:-:1 FMUL shuffle_x1y6, cx1y6, alpha;
--:-:-:-:1 FMUL shuffle_x2y6, cx2y6, alpha;
--:-:-:-:1 FMUL shuffle_x3y6, cx3y6, alpha;
--:-:-:-:1 FMUL shuffle_x4y6, cx4y6, alpha;
--:-:-:-:1 FMUL shuffle_x5y6, cx5y6, alpha;
--:-:-:-:1 FMUL shuffle_x6y6, cx6y6, alpha;
--:-:-:-:1 FMUL shuffle_x7y6, cx7y6, alpha;
--:-:-:-:1 FMUL shuffle_x0y7, cx0y7, alpha;
--:-:-:-:1 FMUL shuffle_x1y7, cx1y7, alpha;
--:-:-:-:1 FMUL shuffle_x2y7, cx2y7, alpha;
--:-:-:-:1 FMUL shuffle_x3y7, cx3y7, alpha;
--:-:-:-:1 FMUL shuffle_x4y7, cx4y7, alpha;
--:-:-:-:1 FMUL shuffle_x5y7, cx5y7, alpha;
--:-:-:-:1 FMUL shuffle_x6y7, cx6y7, alpha;
--:-:-:-:1 FMUL shuffle_x7y7, cx7y7, alpha;
--:-:-:-:1 STS.128 [writeOs+4x<0*128 + 00>], shuffle_x0y4;
--:-:-:-:1 STS.128 [writeOs+4x<0*128 + 16>], shuffle_x4y4;
--:-:-:-:1 STS.128 [writeOs+4x<1*128 + 00>], shuffle_x0y5;
--:-:-:-:1 STS.128 [writeOs+4x<1*128 + 16>], shuffle_x4y5;
--:-:-:-:1 STS.128 [writeOs+4x<2*128 + 00>], shuffle_x0y6;
--:-:-:-:1 STS.128 [writeOs+4x<2*128 + 16>], shuffle_x4y6;
--:-:-:-:1 STS.128 [writeOs+4x<3*128 + 00>], shuffle_x0y7;
--:-:-:-:1 STS.128 [writeOs+4x<3*128 + 16>], shuffle_x4y7;
</SCHEDULE_BLOCK>
--:-:-:-:5 BAR.SYNC 0;
--:-:-:-:0 IADD readOs, readOs, -4x<8*128 + 2*16>;
--:-:-:-:5 CAL STORE_O;
--:-:-:-:0 IADD readOs, readOs, 4x<8*128 + 2*16>;
--:-:-:-:5 CAL STORE_O;
0f:-:-:-:5 EXIT;
STORE_O:
<SCHEDULE_BLOCK>
--:-:-:-:1 ISETP.LT.AND P0, PT, c0, block_C, P4;
--:-:-:-:1 ISETP.LT.AND P1, PT, c1, block_C, P4;
--:-:-:-:1 ISETP.LT.AND P2, PT, c2, block_C, P4;
--:-:-:-:1 ISETP.LT.AND P3, PT, c3, block_C, P4;
--:-:-:-:1 IADD c0, c0, 8;
--:-:-:-:1 IADD c1, c1, 8;
--:-:-:-:1 IADD c2, c2, 8;
--:-:-:-:1 IADD c3, c3, 8;
--:-:6:-:1 @P0 LDS.U.128 offsetC, [lutC];
</SCHEDULE_BLOCK>
--:-:-:-:1 @P0 LDS s0_0, [readOs + 4x<0*128 + 0*32>];
--:-:-:-:1 @P0 LDS s0_1, [readOs + 4x<0*128 + 1*32>];
--:-:-:-:1 @P0 LDS s0_2, [readOs + 4x<0*128 + 2*32>];
--:-:1:-:1 @P0 LDS s0_3, [readOs + 4x<0*128 + 3*32>];
--:-:-:-:1 @P1 LDS s1_0, [readOs + 4x<1*128 + 0*32>];
--:-:-:-:1 @P1 LDS s1_1, [readOs + 4x<1*128 + 1*32>];
--:-:-:-:1 @P1 LDS s1_2, [readOs + 4x<1*128 + 2*32>];
--:-:2:-:1 @P1 LDS s1_3, [readOs + 4x<1*128 + 3*32>];
--:-:-:-:1 @P2 LDS s2_0, [readOs + 4x<2*128 + 0*32>];
--:-:-:-:1 @P2 LDS s2_1, [readOs + 4x<2*128 + 1*32>];
--:-:-:-:1 @P2 LDS s2_2, [readOs + 4x<2*128 + 2*32>];
--:-:3:-:1 @P2 LDS s2_3, [readOs + 4x<2*128 + 3*32>];
--:-:-:-:1 @P3 LDS s3_0, [readOs + 4x<3*128 + 0*32>];
--:-:-:-:1 @P3 LDS s3_1, [readOs + 4x<3*128 + 1*32>];
--:-:-:-:1 @P3 LDS s3_2, [readOs + 4x<3*128 + 2*32>];
--:-:4:-:1 @P3 LDS s3_3, [readOs + 4x<3*128 + 3*32>];
<SCHEDULE_BLOCK>
20:-:-:-:1 @P0 IADD offsetO0, offsetC0, offsetDHW;
--:-:-:-:1 @P1 IADD offsetO1, offsetC1, offsetDHW;
--:-:-:-:1 @P2 IADD offsetO2, offsetC2, offsetDHW;
--:-:-:-:1 @P3 IADD offsetO3, offsetC3, offsetDHW;
--:-:-:-:1 @P0 LEA Out0_0.CC, offsetO0, param_O[0], [+ dshiftO() +];
--:-:-:-:1 @P0 LEA.HI.X Out0_1, offsetO0, param_O[1], RZ, [+ dshiftO() +];
--:-:-:-:1 @P1 LEA Out1_0.CC, offsetO1, param_O[0], [+ dshiftO() +];
--:-:-:-:1 @P1 LEA.HI.X Out1_1, offsetO1, param_O[1], RZ, [+ dshiftO() +];
--:-:-:-:1 @P2 LEA Out2_0.CC, offsetO2, param_O[0], [+ dshiftO() +];
--:-:-:-:1 @P2 LEA.HI.X Out2_1, offsetO2, param_O[1], RZ, [+ dshiftO() +];
--:-:-:-:1 @P3 LEA Out3_0.CC, offsetO3, param_O[0], [+ dshiftO() +];
--:-:-:-:1 @P3 LEA.HI.X Out3_1, offsetO3, param_O[1], RZ, [+ dshiftO() +];
01:-:-:-:1 @P0 FADD s0_0, s0_0, s0_1;
--:-:-:-:1 @P0 FADD s0_2, s0_2, s0_3;
02:-:-:-:1 @P1 FADD s1_0, s1_0, s1_1;
--:-:-:-:1 @P1 FADD s1_2, s1_2, s1_3;
04:-:-:-:1 @P2 FADD s2_0, s2_0, s2_1;
--:-:-:-:1 @P2 FADD s2_2, s2_2, s2_3;
08:-:-:-:1 @P3 FADD s3_0, s3_0, s3_1;
--:-:-:-:1 @P3 FADD s3_2, s3_2, s3_3;
--:-:-:-:1 @P0 FADD s0, s0_0, s0_2;
--:-:-:-:1 @P1 FADD s1, s1_0, s1_2;
--:-:-:-:1 @P2 FADD s2, s2_0, s2_2;
--:-:-:-:1 @P3 FADD s3, s3_0, s3_2;
[+
if (overlapC())
{
# If the output channels overlap across blocks we need to atomic add the results.
# In the case of fp16 use the top or bottom half of the F16x2 instruction.
# This wastes some throughput to L2 but this isn't the bottleneck.
return O16() ? q{
--:-:1:-:1 @P0 F2F.F16.F32 s0, s0;
--:-:2:-:1 @P1 F2F.F16.F32 s1, s1;
--:-:3:-:1 @P2 F2F.F16.F32 s2, s2;
--:-:4:-:1 @P3 F2F.F16.F32 s3, s3;
--:-:-:-:1 LOP.AND.NZ P5, RZ, Out0_0, 2;
--:-:-:-:1 LOP.AND.NZ P6, RZ, Out1_0, 2;
01:-:-:-:1 @P5 XMAD.PSL.CLO s0, s0, 1, RZ; // same as left shift 16
02:-:-:-:1 @P6 XMAD.PSL.CLO s1, s1, 1, RZ;
--:-:-:-:2 @P5 LOP32I.AND Out0_0, Out0_0, 0xfffffffc;
--:-:-:-:2 @P6 LOP32I.AND Out1_0, Out1_0, 0xfffffffc;
--:-:-:-:1 LOP.AND.NZ P5, RZ, Out2_0, 2;
--:-:-:-:1 LOP.AND.NZ P6, RZ, Out3_0, 2;
04:-:-:-:1 @P5 XMAD.PSL.CLO s2, s2, 1, RZ;
08:-:-:-:1 @P6 XMAD.PSL.CLO s3, s3, 1, RZ;
--:-:-:-:2 @P5 LOP32I.AND Out2_0, Out2_0, 0xfffffffc;
--:-:-:-:2 @P6 LOP32I.AND Out3_0, Out3_0, 0xfffffffc;
<ORDERED>
--:-:-:-:1 @P0 RED.E.ADD.F16x2.FTZ.RN [Out0_0], s0;
--:-:-:-:1 @P1 RED.E.ADD.F16x2.FTZ.RN [Out1_0], s1;
--:-:-:-:1 @P2 RED.E.ADD.F16x2.FTZ.RN [Out2_0], s2;
--:6:-:-:1 @P3 RED.E.ADD.F16x2.FTZ.RN [Out3_0], s3;
</ORDERED>
} : q{
<ORDERED>
--:-:-:-:1 @P0 RED.E.ADD.F32.FTZ.RN [Out0_0], s0;
--:-:-:-:1 @P1 RED.E.ADD.F32.FTZ.RN [Out1_0], s1;
--:-:-:-:1 @P2 RED.E.ADD.F32.FTZ.RN [Out2_0], s2;
--:6:-:-:1 @P3 RED.E.ADD.F32.FTZ.RN [Out3_0], s3;
</ORDERED>
};
}
else
{
return O16() ? q{
<ORDERED>
--:-:1:-:1 @P0 F2F.F16.F32 s0, s0;
--:-:2:-:1 @P1 F2F.F16.F32 s1, s1;
--:-:3:-:1 @P2 F2F.F16.F32 s2, s2;
--:-:4:-:1 @P3 F2F.F16.F32 s3, s3;
01:-:-:-:1 @P0 STG.E.CG.U16 [Out0_0], s0;
02:-:-:-:1 @P1 STG.E.CG.U16 [Out1_0], s1;
04:-:-:-:1 @P2 STG.E.CG.U16 [Out2_0], s2;
08:6:-:-:1 @P3 STG.E.CG.U16 [Out3_0], s3;
</ORDERED>
} : q{
<ORDERED>
--:-:-:-:1 @P0 STG.E.CG.32 [Out0_0], s0;
--:-:-:-:1 @P1 STG.E.CG.32 [Out1_0], s1;
--:-:-:-:1 @P2 STG.E.CG.32 [Out2_0], s2;
--:6:-:-:1 @P3 STG.E.CG.32 [Out3_0], s3;
</ORDERED>
};
}
+]
--:-:-:-:1 @P0 IADD lutC, lutC, 4x<8>;
</SCHEDULE_BLOCK>
--:-:-:-:5 RET;