总结riscv vector的一些constraint。
寄存器号相关
- 寄存器起始序号必须LMUL对齐,否则报illegal。
- 比如LMUL=2时,寄存器必须为V0/V2/V4这样2对齐的数。
寄存器号overlap规则:根据具体指令决定是否可以overlap,如果违反则报illegal。
当目的寄存器EEW == 源寄存器EEW时:
- 除非有特殊要求,该类指令是允许overlap的,也就是允许dest==src的。
- 比如
vadd.VV v6, v6, v6
是合法的。
- 比如
- 某些指令有特殊要求,不允许overlap,也就是不允许dest==src。
- 比如
vaesdf.vs v6, v6
是非法的,会报illegal。
- 比如
- 除非有特殊要求,该类指令是允许overlap的,也就是允许dest==src的。
当目的寄存器EEW < 源寄存器EEW时(也就是narrowing类指令):
overlap在源寄存器组中最低的部分,是合法的。
overalp不在源寄存器组中最低的部分,是非法的。
举例说明,假设VLEN=256,SEW=64,LMUL=1,vnsrl.wi指令,source EEW=2*SEW,dest EEW=SEW。
- vnsrl.wi v0, v0, 3 合法。srouce是v0和v1,最低是v0,所以v0是合法的。
- vnsrl.wi v1, v1, 3 非法
当目的寄存器EEW > 源寄存器EEW时(也就是widening类指令):
overlap在源寄存器组中最高的部分,是合法的。
overlap不在源寄存器组中最高的部分,是非法的。
举例说明,假设VLEN=128,SEW=64,LMUL=8,vzext.f4指令,source EEW=1/4*SEW,dest EEW=SEW。
- vzext.f4 v0.v6 合法。source是v6/v7,dest是v0~v7,v6/v7是最高,所以是合法的。
- vzext.f4 v0, v0/v2/v4 都非法。
要注意那些隐式的narrowing/widing操作,比如compare指令,dst是mask类型数据,EEW=E1
总结来看,overlap的constraint设计意图是,目的操作数不能覆盖还未使用的源操作数。
- 当指令编码中的vm为0(MASKED),那vd不能等于v0。
其他
ELEN >= 8,且必须为power of 2
SEW <= ELEN
VLEN >= ELEN,且必须为power of 2,且小于2^16=65536
EEW/EMUL == SEW/LMUL。这两者必须相等。
SEW <= MIN(vflmul, 1.0f) * ELEN
由于ELEN是固定的,这个公式也就是约束sew和lmul的关系。
这个约束的目的是:vector的特性是动态可伸缩的编程模型,与向量长度无关,为了程序的移植性,才做了这个限制。
举例说明,假设VLEN=256,lmul设置为1/2,sew为64,这看上去是个合法的组合,但是这个程序就没法移植到VLEN=64的平台了,所以这个配置是非法的。
继续总结,假设ELEN=64,也就是目前最大支持的值,sew和lmul可配置的组合为下表所示
| SEW/LMUL | 8 | 4 | 2 | 1 | 1/2 | 1/4 | 1/8 |
| ——– | —- | —- | —- | —- | —- | —- | —- |
| 8 | Y | Y | Y | Y | Y | Y | Y |
| 16 | Y | Y | Y | Y | Y | Y | N |
| 32 | Y | Y | Y | Y | Y | N | N |
| 64 | Y | Y | Y | Y | N | N | N |假设ELEN=32,sew和lmul可配置的组合为下表所示
| SEW/LMUL | 8 | 4 | 2 | 1 | 1/2 | 1/4 | 1/8 |
| ——– | —- | —- | —- | —- | —- | —- | —- |
| 8 | Y | Y | Y | Y | Y | Y | N |
| 16 | Y | Y | Y | Y | Y | N | N |
| 32 | Y | Y | Y | Y | N | N | N |
| 64 | N | N | N | N | N | N | N |
对于widing来说:
- lmul <=4
- sew*2 <= ELEN
- vd应该是2*lmul对齐