1. 引言
以下是《riscv-v-spec-1.0.pdf》文档的关键内容:
这是一份关于向量扩展的详细技术文档,内容覆盖了向量指令集的多个关键方面,如向量寄存器状态映射、向量指令格式、向量加载和存储操作、向量内存对齐约束、向量内存一致性模型、向量算术指令格式、向量整数和浮点算术指令、向量归约操作、向量掩码指令、向量置换指令、异常处理以及标准向量扩展等。
首先,文档定义了向量元素和向量寄存器状态之间的映射关系,并阐述了向量指令的格式。在此基础上,提出了配置设置指令,如vsetvl、ivsetiv和vlsetvl,用于设定向量长度(VL)和向量对齐长度(AVL)。
接着,文档详细说明了向量加载和存储操作,以及向量内存对齐和一致性模型。这些模型确保了向量操作的高效性和准确性。
然后,文档介绍了向量算术指令格式,包括向量整数、固定点和浮点算术指令。这些指令支持广泛的数学运算,为高性能计算提供了强大的支持。
此外,文档还涉及向量归约操作、掩码指令和置换指令,这些指令增强了向量操作的灵活性和功能性。
最后,文档讨论了异常处理机制,并列举了标准向量扩展指令列表。这些扩展指令为向量处理器提供了丰富的功能集,使其能够适应不同的应用场景和性能需求。
综上所述,这份文档为向量指令集的设计和实现提供了全面的指导和参考,有助于开发者更好地理解和利用向量处理器的能力。
【RISC-V 指令集】RISC-V 向量V扩展指令集介绍(一)-向量扩展编程模型-CSDN博客
【RISC-V 指令集】RISC-V 向量V扩展指令集介绍(二)-向量元素到向量寄存器状态的映射-CSDN博客【RISC-V 指令集】RISC-V 向量V扩展指令集介绍(三)-向量指令格式-CSDN博客
【RISC-V 指令集】RISC-V 向量V扩展指令集介绍(四)- 配置和设置指令(vsetvli/vsetivli/vsetvl)-CSDN博客
【RISC-V 指令集】RISC-V 向量V扩展指令集介绍(五)- 向量加载和存储-CSDN博客
【RISC-V 指令集】RISC-V 向量V扩展指令集介绍(六)- 向量内存一致性模型-CSDN博客
10. 向量算术指令格式
向量算术指令使用了一个新的主要操作码(OP-V = 10101112),它与OP-FP相邻。三位的funct3字段用于定义向量指令的子类别。
OP-V主要操作码下的向量算术指令格式:
10.1. 向量算术指令编码
The funct3 field encodes the operand type and source locations.
Table 15. funct3
funct3[2:0] | Category | Operand | Type of Scale Operand | ||
0 | 0 | 0 | OPIVV | vector-vector | N/A |
0 | 0 | 1 | OPFVV | vector-vector | N/A |
0 | 1 | 0 | OPMVV | vector-vector | N/A |
0 | 1 | 1 | OPIVI | vector-immediate | imm[4:0] |
1 | 0 | 0 | OPIVX | vector-scalar | GPR x register rs1 |
1 | 0 | 1 | OPFVF | vector-scalar | FP f register rs1 |
1 | 1 | 0 | OPMVX | vector-scalar | GPR x register rs1 |
1 | 1 | 1 | OPCFG | scalars-imms | GPR x register rs1 & rs2/imm |
整数操作根据操作码使用无符号或二进制补码有符号整数算术执行。
注意:在此讨论中,Fixed-point(固定点)操作被视为整数操作。
所有标准的向量浮点算术操作都遵循IEEE-754/2008标准。所有向量浮点操作都使用frm寄存器中的动态舍入模式。当任何向量浮点指令(即使是不依赖于舍入模式的指令)在frm字段包含无效的舍入模式时,或者当vl=0,或者当vstart=vl时,使用frm字段是保留的。
注意:所有向量浮点代码都将依赖于frm中的有效值。当舍入模式无效时,为简化控制逻辑,实现可以使所有向量浮点指令报告异常。
向量-向量操作分别从vs2和vs1指定的向量寄存器组中获取两个操作数向量。
向量-标量操作有三种可能的形式。在这三种形式中,向量寄存器组操作数由vs2指定。第二个标量源操作数来自三个替代来源之一:
-
对于整数操作,标量可以是一个5位立即数,即imm[4:0],编码在rs1字段中。除非另有规定,否则该值将符号扩展到SEW位。
-
对于整数操作,标量可以从rs1指定的标量x寄存器中获取。如果XLEN>SEW,则使用x寄存器的最低有效SEW位,除非另有规定。如果XLEN<SEW,则从x寄存器中的值将符号扩展到SEW位。
-
对于浮点操作,标量可以从标量f寄存器中获取。如果FLEN>SEW,将检查f寄存器中的值是否为有效的NaN装箱值,在这种情况下,将使用f寄存器的最低有效SEW位,否则将使用规范的NaN值。任何浮点向量操作数的EEW不是受支持的浮点类型宽度(包括FLEN<SEW的情况)的向量指令都是保留的。
注意:
有些指令将5位立即数零扩展,并在汇编语法中通过命名立即数uimm来表示这一点。
在向拟议的Zinx/Zdinx/Zhinx扩展添加向量扩展时,浮点标量参数从x寄存器中获取。这些扩展不支持NaN装箱,因此向量浮点标量值的产生遵循与整数标量操作数相同的规则(即,当XLEN>SEW时,使用最低的SEW位;当XLEN<SEW时,使用符号扩展的值)。
向量算术指令在vm字段的控制下被屏蔽。
# Assembly syntax pattern for vector binary arithmetic instructions
# Operations returning vector results, masked by vm (v0.t, <nothing>)
vop.vv vd, vs2, vs1, vm # integer vector-vector vd[i] = vs2[i] op vs1[i]
vop.vx vd, vs2, rs1, vm # integer vector-scala r vd[i] = vs2[i] op x[rs1]
vop.vi vd, vs2, imm, vm # integer vector-immediate vd[i] = vs2[i] op imm
vfop.vv vd, vs2, vs1, vm # FP vector-vector operation vd[i] = vs2[i] fop vs1[i]
vfop.vf vd, vs2, rs1, vm # FP vector-scalar operation vd[i] = vs2[i] fop f[rs1]
在编码中,vs2 是第一个操作数,而 rs1/imm 是第二个操作数。这与标准的标量排序相反。这样的安排保留了现有的编码约定,即只读取一个标量寄存器的指令会从 rs1 读取,而 5 位立即数则来源于 rs1 字段。
# Assembly syntax pattern for vector ternary arithmetic instructions (multiply-add)
# Integer operations overwriting sum input
vop.vv vd, vs1, vs2, vm # vd[i] = vs1[i] * vs2[i] + vd[i]
vop.vx vd, rs1, vs2, vm # vd[i] = x[rs1] * vs2[i] + vd[i]
# Integer operations overwriting product input
vop.vv vd, vs1, vs2, vm # vd[i] = vs1[i] * vd[i] + vs2[i]
vop.vx vd, rs1, vs2, vm # vd[i] = x[rs1] * vd[i] + vs2[i]
# Floating-point operations overwriting sum input
vfop.vv vd, vs1, vs2, vm # vd[i] = vs1[i] * vs2[i] + vd[i]
vfop.vf vd, rs1, vs2, vm # vd[i] = f[rs1] * vs2[i] + vd[i]
# Floating-point operations overwriting product input
vfop.vv vd, vs1, vs2, vm # vd[i] = vs1[i] * vd[i] + vs2[i]
vfop.vf vd, rs1, vs2, vm # vd[i] = f[rs1] * vd[i] + vs2[i]
对于三元乘法-加法操作,汇编器语法总是首先放置目标向量寄存器,然后放置 rs1 或 vs1,接着是 vs2。这种排序为这些三元操作提供了更自然的汇编器读取方式,因为乘法操作数总是相邻的。
10.2 扩展算术指令
定义了一些向量算术指令为扩展操作,其中目标向量寄存器组的EEW=2SEW且EMUL=2LMUL。这些指令的操作码前一般会加上vw前缀,对于向量浮点指令,则加上vfw前缀。
Assembly syntax pattern for vector widening arithmetic instructions
# Double-width result, two single-width sources: 2*SEW = SEW op SEW
vwop.vv vd, vs2, vs1, vm # integer vector-vector vd[i] = vs2[i] op vs1[i]
vwop.vx vd, vs2, rs1, vm # integer vector-scala r vd[i] = vs2[i] op x[rs1]
# Double-width result, first source double-width, second source single-width: 2*SEW = 2*SEW op SEW
vwop.wv vd, vs2, vs1, vm # integer vector-vector vd[i] = vs2[i] op vs1[i]
vwop.wx vd, vs2, rs1, vm # integer vector-scala r vd[i] = vs2[i] op x[rs1]
注意:
原本,我们在操作码上使用了w后缀,但这可能与w后缀表示双字整数中的字大小操作混淆,因此将w移动到前缀位置。
为了使浮点扩展操作与任何将写为fw的标量扩展浮点操作更加一致,已将浮点扩展操作从vwf更改为vfw*。
扩展指令编码必须遵循“向量操作数”部分中的约束。
10.3 缩小指令编码
提供了一些指令,用于将双宽度的源向量转换为单宽度的目标向量。这些指令将vs2指定的向量寄存器组(其中EEW/EMUL=2SEW/2LMUL)转换为具有当前SEW/LMUL设置的向量寄存器组。如果存在第二个源向量寄存器组(由vs1指定),则其宽度与结果(即EEW=SEW)相同(更窄)。
注意:另一种设计决策是将SEW/LMUL视为定义源向量寄存器组的大小。这里的选择是基于这样一种信念,即所选的方法将需要更少的vtype更改。
设置掩码寄存器的比较操作也隐含着一个缩小操作。在汇编器中,操作码上的vn前缀用于区分这些指令,对于缩小浮点操作码,则使用vfn前缀。双宽度源向量寄存器组由源操作数后缀中的w表示(例如,vnsra .wv)。
Assembly syntax pattern for vector narrowing arithmetic instructions
# Single-width result vd, double-width source vs2, single-width source vs1/rs1
# SEW = 2*SEW op SEW
vnop.wv vd, vs2, vs1, vm # integer vector-vector vd[i] = vs2[i] op vs1[i]
vnop.wx vd, vs2, rs1, vm # integer vector-scala r vd[i] = vs2[i] op x[rs1]
缩小指令编码必须遵循“向量操作数”部分中的约束。