跳转至

SIMT指令

SIMT指令只能在SIMT块中使用,操作类型包括:覆盖了现有的标量操作、reduce操作、浮点操作、diverge处理操作。SIMT指令的寄存器操作数均需要位宽表达,汇编通用格式如下:

Opcode                                                            /*表示指令无输出*/
Opcode Operand0.<T>, ->{LL_GPR, UL_GPR}.<T>                       /*输出到块内寄存器,SIMT块中有U/T/M/N四组刻度尺寄存器*/
Opcode Operand0.<T>, Operand1.<T>                                 /*表示指令无输出*/
Opcode Operand0.<T>, Operand1.<T>, ->{LL_GPR}.<T>                 /*输出到块内寄存器,SIMT块中有U/T/M/N四组刻度尺寄存器*/
Opcode Operand0.<T>, Operand1.<T>, Operand2.<T>                   /*表示指令无输出*/
Opcode Operand0.<T>, Operand1.<T>, Operand2.<T>, ->{LL_GPR}.<T>   /*输出到块内寄存器,SIMT块中有U/T/M/N四组刻度尺寄存器*/
Opcode Operand0.<T>, Operand1.<T>, Operand2, Operand3             /*表示指令无输出*/

一般情况下,输入及输出寄存器操作数的位宽表达包括:

  • '.fd' : 输入位宽标识,表示输入为位宽64bit的双精度浮点类型。
  • '.fs' : 输入位宽标识,表示输入为位宽32bit的单精度浮点类型。
  • '.fh' : 输入位宽标识,表示输入为位宽16bit的半精度浮点类型。
  • '.fb' : 输入位宽标识,表示输入为位宽8bit的fp8浮点类型。
  • '.bf' : 输入位宽标识,表示输入为位宽16bit的bf16浮点类型。
  • '.flb' : 输入位宽标识,表示输入为位宽8bit的fp8.1浮点类型。
  • '.ud' : 输入位宽标识,表示输入为位宽64bit的无符号整型。
  • '.uw' : 输入位宽标识,表示输入为位宽32bit的无符号整型。
  • '.uh' : 输入位宽标识,表示输入为位宽16bit的无符号整型。
  • '.ub' : 输入位宽标识,表示输入为位宽8bit的无符号整型。
  • '.sd' : 输入位宽标识,表示输入为位宽64bit的有符号整型。
  • '.sw' : 输入位宽标识,表示输入为位宽32bit的有符号整型。
  • '.sh' : 输入位宽标识,表示输入为位宽16bit的有符号整型。
  • '.sb' : 输入位宽标识,表示输入为位宽8bit的有符号整型。
  • '.d' : 输出位宽标识,表示输出位宽为64bit。
  • '.w' : 输出位宽标识,表示输出位宽为32bit。
  • '.h' : 输出位宽标识,表示输出位宽为16bit。
  • '.b' : 输出位宽标识,表示输出位宽为8bit。

对于cvt类的指令,输入和输出位宽标识范围为:.fd,.fs,.fh,.fb,.bf,.flb,.ud,.uw,.uh,.ub,.sd,.sw,.sh,.sb。比如:

fcvt t#1.fs, ->t.fd                   /*浮点类型间的转换,将单精度浮点数转换成双精度浮点数*/
fcvti t#1.fh, ->t.sw                  /*浮点到整型的转换,将半精度浮点数转换成有符号字*/
icvt t#1.uh, ->t.sw                   /*整型类型间的转换,将无符号半字转换成有符号字*/
icvtf t#1.sw, ->t.fs                  /*整型到浮点的转换,将有符号半字转成成单精度浮点数*/

使用限制说明:

  • 输出到全局寄存器的指令当前仅限于归约类指令,对于这类微指令的输出位宽限制64bit。如果规约到访存到需使用对应的规约访存指令。
  • 全局寄存器表示标量值,即对于SIMT块来说是常量,而块内寄存器为向量值,即块内的值可以是变化的。
  • 浮点操作数的输入位宽标识需要使用.fd,.fs,.fh,.fb,.bf,.flb,整型操作数的输入位宽标识需要使用.ud,.uw,.uh,.ub,.sd,.sw,.sh,.sb。(1)
  • 对于非访存的整型操作微指令,寄存器操作数上均需带上位宽信息且寄存器操作数的位宽信息需要保持一致。当前汇编上要求输入位宽标识一致,位宽标识不一致的微指令运行行为不可预期,同时输入位宽标识与输出位宽标识对应。(1)
  • 对于访存操作微指令,地址计算的基址部分位宽默认64bit,地址偏移部分位宽不限制。访存读指令的输出位宽与访存指令加载的数据位宽一致,访存写指令的数据寄存器位宽与访存指令需存储的数据位宽一致。(2)
  • 当前微指令直接引用上一条微指令的结果时,需要保持位宽一致,否则执行结果不可预期。(3)
  • 但是对于符号敏感的操作,使用输入位宽标识时需要主要符号位的使用,当运算结果与输出位宽标识不一致时,输入位宽小于输出位宽时按照输入位宽标识的符号进行相应的扩展操作。(4)
  • SIMT块指令中有分支时,需要使用SIMT stack相关的微指令保障功能。(5)
  • 除了访存指令的地址计算/cvt类微指令/浮点微指令中位宽标识含有数据类型的含义,其他场景中仅用于位宽表达。
  • LC,LB系统寄存器可以直接用SIMT指令索引。

详细的微指令可以参见手册中向量指令这一章节。

基本指令示例:

(0)Reduce操作汇编示意

rdadd t#1.uh, ->x1.d                   /*寄存器reduce指令,将SIMT块中所有线程的rdadd中16位宽的t#1的值累加,最终的累加值无符号扩展到64bit,写到x1寄存器中*/
rdadd t#1.sw, ->x1.d                   /*寄存器reduce指令,将SIMT块中所有线程的rdadd中32位宽的t#1的值累加,最终的累加值有符号扩展到64bit,写到x1寄存器中*/
sw.add.rd [t#1.d], t#2.w               /*访存reduce指令,将SIMT块中所有线程的sw.add对应的t#2.w的值累加,再与访存地址t#1中的值累加,再存回地址t#1中*/

(1)算术逻辑类操作汇编示意

add t#1.sw, t#2.sw, ->t.w              /*将整型的32bit的t#1与32bit的t#2相加写到t刻度尺寄存器中,且输出位宽为32bit,汇编要求用sw表示输入位宽时,都采用sw*/
add a0.uw, t#2.uw, ->t.w               /*uw的写法与sw的写法,输入位宽表达上含义一致*/
fadd t#1.fs, t#2.fs, ->t.w             /*两个单精度浮点数相加,结果写到t刻度尺寄存器中,输出位宽为32bit,输入位宽与输出位宽对应*/

(2)访存类操作汇编示意

lb [a0.sd, t#1.sw], ->t.b              /*基址a0的位宽要求64bit,地址偏移t#1由32bit有符号扩展到64bit后与基址相加得到64bit访存地址,目的寄存器位宽与lb的加载的数据位宽一致,为8bit*/
lw [a1.sd, t#1.sb], ->t.w              /*基址a1的位宽要求64bit,地址偏移t#1由8bit有符号扩展到64bit后与基址相加得到64bit访存地址,目的寄存器位宽与lw的加载的数据位宽一致,为32bit*/
sw t#1.sw, [a2.ud, lc0.ud]             /*sw微指令的数据寄存器位宽与sw的存储数据位宽一致,均为32bit宽度*/ 
icvt t#1.sw, ->t.sd
sd t#1.sd, [a3.sd, t#2.sb]             /*sd微指令的数据寄存器位宽为64bit,因此需要先将lw的结果通过icvt转换成64bit宽度后才能使用*/
(3)指令间有依赖汇编示意

sub t#1.sw, t#2.sw, ->t.w
add a0.sw, t#1.sw, ->t.w              /*add指令使用sub的结果,保持位宽都是32bit*/
icvt t#1.sw, ->t.sd
and t#1.sd, x1.sd, ->t.d              /索引前序指令的结果时,需要位宽一致,and使用add的结果,为保持位宽一致,需要使用icvt指令进行转换,将32bit的位宽转成64bbit*/

(4)

div t#1.sw, t#2.sw, ->t.w             /*位宽为32bit的有符号除法操作*/
div t#1.uw, t#2.uw, ->t.w             /*位宽为32bit的无符号除法操作*/
mul t#1.sd, t#2.sd, ->t.d             /*位宽为64bit的有符号乘法*/
mul t#1.ud, t#2.ud, ->t.d             /*位宽为64bit的无符号乘法*/

(5)diverge指令示意:

并行块中为了处理diverge的情况,需要注意的是块内条件指令的汇聚点的label及汇聚点的pc.pop的增加。当前块内所有的条件跳转指令,包括整型比较跳转及浮点比较跳转,均是需要汇聚点的label描述。对于超出编码范围的汇聚点地址或者跳转目标地址,编译器会转成b.cond处理。

...
lw [a1.ud, lc0.ud<<2], ->t.w    
b.eq t#1.sw, t#2.sw, _block_D, _converge_E_   /*指示该分支的converge点为_converge_E_*/ 
addi zero.uw, 2, ->m.w
j _converge_E
_block_D:
addi zero.uw, 1, ->u.w
_converge_E:
pc.pop                                       /*converge点pop决定是否还有另一侧的分支待执行,还是顺序往下执行*/
...