RISC-V \\V\\ Vector Extension 1.0 翻译进行中
本文翻译自官方文档:riscv-v-spec-1.0.pdf (opens new window) ,只翻译了部分内容,能力有限,如有错误还请指正。
# 1. 介绍
本文档是RISC-V矢量扩展的1.0版本,供公众审阅。
作为RISC-V国际批准程序的一部分,1.0版本被视为冻结供公众审议。1.0版本被认为是足够稳定的,可以开始开发工具链、功能模拟器和实现,包括在上游软件项目中,除非在批准过程中发现严重问题,否则预计不会有不兼容的更改。一旦批准,该规范将发布2.0版本。
本规范包含了当前冻结的矢量指令的完整集合。在开发过程中考虑过但未在本文件中出现的其他指示不包括在审查和批准过程中,并可能完全修订或放弃。[标准向量扩展](#18. Standard Vector Extensions)部分列出了标准向量扩展,以及每个扩展支持哪些指令和元素宽度。
# 2. 编译器的参数
每个支持矢量扩展的部分都定义了两个参数:
- ELEN:element-length,内部能够处理的一个向量元素的最大 bit 数目,要求大于 8 且是 2 的整数次幂。
- VLEN:vector-length,一个向量寄存器的总 bit 数(宽度),显然 VLEN 应该大于等于 ELEN,也是 2 的整数次幂。risc-v sprc 要求 VLEN 小于 2^16
# 3. 向量拓展的编程模型
向量拓展在标量RISC-V ISA的基础上增加 了32 个向量寄存器,同时增加了 7 个非特权 CSRs (vstart, vxsat, vxrm, vcsr, vtype, vl,vlenb)。
Address | Privilege | Name | Description |
---|---|---|---|
0x008 | URW | vstart | 一条向量指令索要执行的第一个元素的索引 |
0x009 | URW | vxsat | 定点饱和(saturate)标志 |
0x00A | URW | vxrm | 定点数四舍五入模式 |
0x00F | URW | vcsr | 向量控制和状态寄存器 |
0xC20 | URO | vl | 向量长度 |
0xC21 | URO | vtype | 向量数据类型 |
0xC22 | URO | vlenb | VLEN/8 (向量寄存器的字节长度) |
# 3.1 向量寄存器
向量拓展向标量RISC-V ISA添加了32个体系结构向量寄存器v0-v31。每个矢量寄存器都有一个固定的VLEN位。
# 3.2 Vector Context Status in mstatus
# 3.3. Vector Context Status in vsstatus
# 3.4. 向量类型寄存器, vtype
# 3.4.1. 向量宽度 vsew[2:0]
vsew中的值设置动态选择的元素宽度(SEW)。默认情况下,向量寄存器被视为被划分为VLEN/SEW元素。
# 3.4.2. 组合向量寄存器 vlmul[2:0]
多个向量寄存器可以组合在一起,这样一个向量指令就可以在多个向量寄存器上操作。这里使用术语向量寄存器组来指用作向量指令的单个操作数的一个或多个向量寄存器。向量寄存器组可用于为较长的应用程序向量提供更高的执行效率,但包含它们的主要原因是允许使用与单宽度元素相同的向量长度操作双宽度或更大的元素。当向量长度乘法器LMUL大于1时,表示组合成向量寄存器组的向量寄存器的默认数量。实现必须支持LMUL整数1、2、4和8。
LMUL 也可以是一个小于 1 的分数,这种情况下将会缩减一个向量寄存器内的元素个数,只用其低位的部分LMUL 同时引入了一个新的参数:VLMAX= LMUL * VLEN / SEW,即融合后的可执行的最长向量长度,这是一条向量指令应当能执行到的元素数量。
LMUL的设置有两个目的:
- 为更长的应用向量处理器提供潜在的提高执行效率的可能性
- 在不改变向量长度的情况下,利用更多的向量寄存器,支持处理更宽的元素
# 3.4.3. Vector Tail Agnostic and Vector Mask Agnostic vta and vma
vta 用于指示 “tail elements” 的填充方法,vma 用于指示被 mask 元素的填充方法。分别用于在向量指令执行期间决定尾部元素和目标非活跃元素的行为。这两个参数在可以配置 vtype 的汇编指令 vset{i}vl{i} 中以特定符号标识。
- undisturbed:量寄存器组的相应目标元素将保留原值不变。
- agnostic:目标操作数元素既可以保留原值也可以全部置1。
在有些处理器中,会采用寄存器重命名的技术,比如超标量流水线处理器,在undisturbed策略下,必须从旧的物理目标向量寄存器中读取元素值,才能复制到新的物理目标寄存器中;也可以说,在新的物理寄存器进行重命名时,需要根据重命名映射表,查到原有的映射关系,然后把其中的元素值读出来,写到重命名后的对应元素。这对于不需要这些非活跃元素和尾部元素值的之后的运算既降低了性能也增加了功耗。因此undisturbed策略就显得很不可观,此时按照agnostic策略进行运算比较好。
在v0.9之前,当这些标志没有在vsetvli上指定时,它们默认为掩码不受干扰/尾不受干扰。但是,不建议使用不带这些标志的vsetvli,现在必须指定标志设置。默认情况下可能应该是尾部不可知论/掩码不可知论,因此软件必须指定何时关心非参与元素,但考虑到引入这些标志之前指令的历史意义,决定在未来的汇编代码中总是需要它们。
# 3.4.4. Vector Type Illegal vill
vill 位反映上一条的 vset{i}vl{i} 指令是不是合法的如果 vill 被置位了,后面再执行向量指令就会引起异常。
# 3.5. 向量长度寄存器 vl
XLEN位宽的vl寄存器只能被一个带有返回值的vset{i}vl{i} 指令和仅故障优先索引负载指令更新。
vl寄存器保存着一个无符号整数,用于指定要用vector指令的结果更新的元素的数量,详见预启动、活动、非活动、主体和尾元素定义小节。
# 3.6. 向量字节长度 vlenb
VLEN/8,用于计算向量的字节长度。
如果没有这个CSR,需要几个指令来以字节计算VLEN,并且代码必须干扰当前的vl和vtype设置,这需要它们被保存和恢复。
# 3.7. 向量起始地址寄存器 vstart
一条向量指令索要执行的第一个元素的索引,通常被用来记录发生trap时恢复的位置,其他用途见下文。任意一条向量指令执行时,vstart之前的向量将被忽略,该条向量执行结束后vstart被置0,所有向量指令包括vset{i}vl{i}执行结束后都会把该寄存器置零
所有向量指令,包括vset{i}vl{i},都会将vstart CSR重置为零。
# 3.8. Vector Fixed-Point Rounding Mode Register vxrm
向量定点舍入模式寄存器的一些规则
# 3.9. Vector Fixed-Point Saturation Flag vxsat
# 3.10. Vector Control and Status Register vcsr
# 3.11. State of Vector Extension at Reset
# 6. 配置指令(vsetvli/vsetivli/vsetvl)
处理大量元素的常见方法之一是“剥离挖掘”,其中循环的每次迭代都处理一定数量的元素,迭代一直持续到处理完所有元素。RISC-V矢量规范为这种方法提供了直接的、可移植的支持。应用程序指定要处理的元素总数(应用程序向量长度或AVL)作为vl的候选值,硬件根据微架构实现和vtype设置,通过通用寄存器响应每次迭代(存储在vl中)将处理的元素数量(通常更少)。在示例剥离和对SEW的更改中显示了一个简单的循环结构,描述了代码跟踪剩余元素数量和硬件每次迭代处理的数量的容易程度。
提供了一组指令,允许快速配置vl和vtype中的值,以匹配应用程序的需要。vset (i)vl(i)指令根据参数设置vtype和vl,并将vl的新值写入rd。
# 6.1. vtype encoding
新的vtype设置编码在vsetvli和vsetivli的直接字段中,以及vsetvl的rs2寄存器中。
在vset指令中,vtype被完整载入,。在汇编中使用一些固定的字符表示特定的配置。
# 6.2. AVL encoding
新的向量长度设置基于AVL, vsetvli和vsetvl的AVL编码在rs1和rd字段中,如下所示:
# 6.3. 设置 vl 的规则
vset{i}vl{i}指令首先根据vtype参数设置VLMAX,然后按照以下约束设置vl:
- vl = AVL 如果AVL ≤ VLMAX
- ceil(AVL / 2) ≤ vl ≤ VLMAX 如果 AVL < (2 * VLMAX)
- vl = VLMAX if AVL ≥ (2 * VLMAX)
- 确定任何给定的实现相同的输入AVL和VLMAX值
- 这些特定的属性遵循之前的规则:
- vl = 0 if AVL = 0
- vl > 0 if AVL > 0
- vl ≤ VLMAX
- vl ≤ AVL
- 从vl读取的值,当用作vset{i}vl{i}的AVL参数时,vl的结果是相同的值,只要结果VLMAX等于读取vl时VLMAX的值
ceil(x):返回大于或等于 x 的最小的整数值。
vl设置规则设计得足够严格,以保护AVL VLMAX跨寄存器溢出和上下文交换的vl行为,但又足够灵活,使实现能够提高AVL > VLMAX的矢量通道利用率。
例如,这允许在VLMAX < AVL < 2VLMAX时设置vl = ceil(AVL / 2),以便在一个露天矿循环的最后两个迭代中均匀分配工作。要求2确保缩减循环的第一次剥矿迭代使用所有迭代中最大的向量长度,即使在AVL < 2VLMAX的情况下。这允许软件避免需要显式地计算在条带化循环期间观察到的最大向量长度。需求2还允许实现在VLMAX < AVL < 2*VLMAX时将vl设置为VLMAX
# 6.4. 例子:stripmining 和 改变SEW
SEW和LMUL设置可以动态更改,以在单个循环中提供混合宽度操作的高吞吐量。