1. 引言
以下是《riscv-v-spec-1.0.pdf》文档的关键内容:
这是一份关于向量扩展的详细技术文档,内容覆盖了向量指令集的多个关键方面,如向量寄存器状态映射、向量指令格式、向量加载和存储操作、向量内存对齐约束、向量内存一致性模型、向量算术指令格式、向量整数和浮点算术指令、向量归约操作、向量掩码指令、向量置换指令、异常处理以及标准向量扩展等。
首先,文档定义了向量元素和向量寄存器状态之间的映射关系,并阐述了向量指令的格式。在此基础上,提出了配置设置指令,如vsetvl、ivsetiv和vlsetvl,用于设定向量长度(VL)和向量对齐长度(AVL)。
接着,文档详细说明了向量加载和存储操作,以及向量内存对齐和一致性模型。这些模型确保了向量操作的高效性和准确性。
然后,文档介绍了向量算术指令格式,包括向量整数、固定点和浮点算术指令。这些指令支持广泛的数学运算,为高性能计算提供了强大的支持。
此外,文档还涉及向量归约操作、掩码指令和置换指令,这些指令增强了向量操作的灵活性和功能性。
最后,文档讨论了异常处理机制,并列举了标准向量扩展指令列表。这些扩展指令为向量处理器提供了丰富的功能集,使其能够适应不同的应用场景和性能需求。
综上所述,这份文档为向量指令集的设计和实现提供了全面的指导和参考,有助于开发者更好地理解和利用向量处理器的能力。
【RISC-V 指令集】RISC-V 向量V扩展指令集介绍(一)-向量扩展编程模型-CSDN博客
【RISC-V 指令集】RISC-V 向量V扩展指令集介绍(二)-向量元素到向量寄存器状态的映射-CSDN博客
4 向量元素到向量寄存器状态的映射
以下图表说明了根据当前的SEW和LMUL设置以及实现的VLEN,如何将不同宽度的元素打包到向量寄存器的字节中。元素被打包到每个向量寄存器中,其中最低有效字节位于最低编号的位中。选择这种映射是为了为软件提供最简单和最可移植的模型,但在某些操作上,对于更宽的向量数据路径,可能会产生较大的布线成本。向量指令集是专门设计的,以支持内部重新排列不同SEW的向量数据以减少数据路径布线成本的实现,同时在外部保留简单的软件模型。例如,微架构可以跟踪写入向量寄存器的EEW,然后如果以不同的EEW访问寄存器,则插入额外的加扰操作以重新排列数据。
4.1. LMUL = 1时的映射
当LMUL=1时,元素简单地按照从向量寄存器的最低有效位到最高有效位的顺序进行打包。为了提高可读性,向量寄存器布局从右到左绘制,字节地址递增。元素内的位以小端格式编号,位索引从右到左递增,对应于幅度的增加。
LMUL=1 的示例。
元素索引以十六进制给出,并显示在存储元素的最低有效字节处。
cpp
VLEN=32b
Byte 3 2 1 0
SEW=8b 3 2 1 0
SEW=16b 1 0
SEW=32b 0
VLEN=64b
Byte 7 6 5 4 3 2 1 0
SEW=8b 7 6 5 4 3 2 1 0
SEW=16b 3 2 1 0
SEW=32b 1 0
SEW=64b 0
VLEN=128b
Byte F E D C B A 9 8 7 6 5 4 3 2 1 0
SEW=8b F E D C B A 9 8 7 6 5 4 3 2 1 0
SEW=16b 7 6 5 4 3 2 1 0
SEW=32b 3 2 1 0
SEW=64b 1 0
VLEN=256b
Byte 1F1E1D1C1B1A19181716151413121110 F E D C B A 9 8 7 6 5 4 3 2 1 0
SEW=8b 1F1E1D1C1B1A19181716151413121110 F E D C B A 9 8 7 6 5 4 3 2 1 0
SEW=16b F E D C B A 9 8 7 6 5 4 3 2 1 0
SEW=32b 7 6 5 4 3 2 1 0
SEW=64b 3 2 1 0
4.2. LMUL < 1时的映射
当LMUL < 1时,仅使用向量寄存器中的前LMUL*VLEN/SEW个元素。向量寄存器中的剩余空间被视为尾部的一部分,因此必须遵守vta设置。
cpp
Example, VLEN=128b, LMUL=1/4
Byte F E D C B A 9 8 7 6 5 4 3 2 1 0
SEW=8b - - - - - - - - - - - - 3 2 1 0
SEW=16b - - - - - - 1 0
SEW=32b - - - 0
4.3. LMUL > 1时的映射
当向量寄存器分组时,向量寄存器组的元素将按照元素顺序连续打包,从编号最低的向量寄存器开始,并在每个向量寄存器填满后移动到组中编号次高的向量寄存器。
cpp
LMUL > 1 examples
VLEN=32b, SEW=8b, LMUL=2
Byte 3 2 1 0
v2*n 3 2 1 0
v2*n+1 7 6 5 4
VLEN=32b, SEW=16b, LMUL=2
Byte 3 2 1 0
v2*n 1 0
v2*n+1 3 2
VLEN=32b, SEW=16b, LMUL=4
Byte 3 2 1 0
v4*n 1 0
v4*n+1 3 2
v4*n+2 5 4
v4*n+3 7 6
VLEN=32b, SEW=32b, LMUL=4
Byte 3 2 1 0
v4*n 0
v4*n+1 1
v4*n+2 2
v4*n+3 3
VLEN=64b, SEW=32b, LMUL=2
Byte 7 6 5 4 3 2 1 0
v2*n 1 0
v2*n+1 3 2
VLEN=64b, SEW=32b, LMUL=4
Byte 7 6 5 4 3 2 1 0
v4*n 1 0
v4*n+1 3 2
v4*n+2 5 4
v4*n+3 7 6
VLEN=128b, SEW=32b, LMUL=2
Byte F E D C B A 9 8 7 6 5 4 3 2 1 0
v2*n 3 2 1 0
v2*n+1 7 6 5 4
VLEN=128b, SEW=32b, LMUL=4
Byte F E D C B A 9 8 7 6 5 4 3 2 1 0
v4*n 3 2 1 0
v4*n+1 7 6 5 4
v4*n+2 B A 9 8
v4*n+3 F E D C
4.4. 混合宽度操作中的映射
向量ISA被设计为支持混合宽度操作,而无需额外的显式重排指令。当对不同精度值的多个向量进行操作时,推荐的软件策略是动态修改vtype以保持SEW/LMUL恒定(因此VLMAX也恒定)。以下示例显示了在VLEN=128b实现中的四种不同的打包元素宽度(8b、16b、32b、64b)。向量寄存器分组因子(LMUL)根据相对元素大小而增加,以便每个组可以容纳相同数量的向量元素(在此示例中VLMAX=8),从而简化stripmining代码。
cpp
Example VLEN=128b, with SEW/LMUL=16
Byte F E D C B A 9 8 7 6 5 4 3 2 1 0
vn - - - - - - - - 7 6 5 4 3 2 1 0 SEW=8b, LMUL=1/2
vn 7 6 5 4 3 2 1 0 SEW=16b, LMUL=1
v2*n 3 2 1 0 SEW=32b, LMUL=2
v2*n+1 7 6 5 4
v4*n 1 0 SEW=64b, LMUL=4
v4*n+1 3 2
v4*n+2 5 4
v4*n+3 7 6
下表显示了具有混合宽度操作的循环中每个可能的恒定SEW/LMUL操作点。每列代表一个恒定的SEW/LMUL操作点。表中的条目是产生该列SEW/LMUL值的LMUL值,对应于该行的数据宽度。在每列中,一个数据宽度的LMUL设置表示它可以与同一列中也具有LMUL设置的其他数据宽度对齐,以便它们都具有相同的VLMAX。
更大的LMUL设置也可以用来简单地增加向量长度,以减少在需要较少向量寄存器组的情况下的指令获取和分发开销。
4.5. 掩码寄存器布局
无论SEW和LMUL如何,向量掩码仅占用一个向量寄存器。在掩码向量寄存器中,每个元素都分配有一个掩码位。元素i的掩码位位于掩码寄存器的第i位,与SEW或LMUL无关。