有人预言,RISC-V或将是继Intel和Arm之后的第三大主流处理器体系。欢迎访问全球首家只专注于RISC-V单片机行业应用的中文网站
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
本帖最后由 sky 于 2020-9-28 15:50 编辑
关于这篇文章:
由于译者水平有限,本文可能存在谬误或不当之处,欢迎指正。
以下为正文(连载中):
4 向量元素到向量寄存器的映射
本节会说明:根据当前的 SEW 和 LMUL 设置以及 ELEN,VLEN 和 SLEN 的值,怎么将不同宽度的元素存放到矢量寄存器的字节中。并且使用最少位数的最低有效字节将元素放到每个向量寄存器中。
4.1 VLEN = SLEN 且 LMUL ≤ 1时
当 VLEN=SLEN , LMUL=1 时,从向量寄存器的最低有效位到最高有效位依次对元素进行简单排布。
Note: 为了提高可读性,向量寄存器采用字节为单位按从右到左的顺序排布元素,字节地址从高到低。元素内的位按低位优先(little-endian)格式进行编号,位索引从右至左递增。
- LMUL=1 examples.
-
- The element index is given in hexadecimal and is shown placed at the
- least-significant byte of the stored element.
-
-
- VLEN=SLEN=32b
-
- Byte 3 2 1 0
-
- SEW=8b 3 2 1 0
- SEW=16b 1 0
- SEW=32b 0
-
- VLEN=SLEN=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=SLEN=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
- SEW=128b 0
-
- VLEN=SLEN=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
- SEW=128b 1 0
复制代码
当 LMUL <1 时,仅使用向量寄存器中的第一个 LMUL * VLEN / SEW 元素。 向量寄存器中的剩余空间被视为尾部的一部分。
- Example, VLEN=SLEN=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.2 VLEN = SLEN 且 LMUL > 1时 将向量寄存器分组后,根据向量寄存器组中的向量寄存器来划分组中的元素。当 SLEN = VLEN 时,按元素顺序将其放在组中的每个向量寄存器中,填满一个向量寄存器后,便移至组中下一个编号最高的向量寄存器。
- LMUL examples for SLEN=VLEN
-
- VLEN=SLEN=32b, SEW=8b, LMUL=2
-
- Byte 3 2 1 0
- v2*n 3 2 1 0
- v2*n+1 7 6 5 4
-
- VLEN=SLEN=32b, SEW=16b, LMUL=2
-
- Byte 3 2 1 0
- v2*n 1 0
- v2*n+1 3 2
-
- VLEN=SLEN=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=SLEN=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=SLEN=64b, SEW=32b, LMUL=2
-
- Byte 7 6 5 4 3 2 1 0
- v2*n 1 0
- v2*n+1 3 2
-
- VLEN=SLEN=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=SLEN=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=SLEN=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.3 VLEN < SLEN 且 LMUL ≤ 1时
分段距离(The striping distance in bits)SLEN 表示的是在相同的元素级混合宽度算术运算操作中的向量寄存器bit位之间的最大位移。
Note: 分段距离 SLEN 可以设计为小于 VLEN ,以减少在混合宽度操作中的跨数据路径(cross-datapath)布线。上述这种情况,SLEN 通常至少为128位。 对于跨数据路径布线不受限制的情况下,通常会将 SLEN 设置为 VLEN 。
Note: 与 v0.8 相比,SLEN <VLEN 的映射模式已改为以直接方式支持分数LMUL,可以提供更大的吞吐量。 主要的复杂之处在于,即使数量不多,内存连接也会更加复杂。
当 SLEN <VLEN 时,每个向量寄存器分为 VLEN / SLEN 个区段,每个区段均包含 SLEN 位。
当 LMUL = 1 时,连续的向量元素映射到连续的区段,successive vector elements are mapped into successive sections, wrapping back around to the first section until the vector register is full.
- LMUL=1 examples for SLEN < VLEN
-
- VLEN=256b, SLEN=128b, SEW=8b, LMUL=1
-
- Section 1 | 0
- Byte 1F1E1D1C1B1A19181716151413121110| F E D C B A 9 8 7 6 5 4 3 2 1 0
- 1F1D1B1917151311 F D B 9 7 5 3 1|1E1C1A1816141210 E C A 8 6 4 2 0
-
- VLEN=256b, SLEN=128b, SEW=16b, LMUL=1
-
- Byte 1F1E1D1C1B1A19181716151413121110| F E D C B A 9 8 7 6 5 4 3 2 1 0
- F D B 9 7 5 3 1| E C A 8 6 4 2 0
-
- VLEN=256b, SLEN=128b, SEW=32b, LMUL=1
-
- Byte 1F1E1D1C1B1A19181716151413121110| F E D C B A 9 8 7 6 5 4 3 2 1 0
- 7 5 3 1| 6 4 2 0
-
- VLEN=256b, SLEN=128b, SEW=64b, LMUL=1
-
- Byte 1F1E1D1C1B1A19181716151413121110| F E D C B A 9 8 7 6 5 4 3 2 1 0
- 3 1| 2 0
-
- VLEN=256b, SLEN=64b, SEW=16b, LMUL=1
-
- Section 3 | 2 | 1 | 0
- Byte 1F1E1D1C1B1A1918|1716151413121110| F E D C B A 9 8| 7 6 5 4 3 2 1 0
- F B 7 3| E A 6 2| D 9 5 1| C 8 4 0
-
- VLEN=256b, SLEN=64b, SEW=32b, LMUL=1
-
- Byte 1F1E1D1C1B1A1918|1716151413121110| F E D C B A 9 8| 7 6 5 4 3 2 1 0
- 7 3| 6 2| 5 1| 4 0
-
- VLEN=256b, SLEN=64b, SEW=64b, LMUL=1
-
- Byte 1F1E1D1C1B1A1918|1716151413121110| F E D C B A 9 8| 7 6 5 4 3 2 1 0
- 3| 2| 1| 0
复制代码
当 LMUL <1 时,只使用向量寄存器中的第一个 LMUL * VLEN / SEW 元素,这些元素以与 LMUL = 1 时相同的方式映射到区段。向量寄存器中的剩余空间被视为尾部的一部分。
Note: 与 SLEN = VLEN 的设计一样,SLEN <VLEN 的实现可以简单地处理分数形式的 LMUL ,就像向量长度随着 LMUL = 1 减小了一样。
- Example, VLEN=256b, SLEN=128b
-
- SEW=8b, LMUL=1/4
-
- Section 1 0
- Byte 1F1E1D1C1B1A19181716151413121110| F E D C B A 9 8 7 6 5 4 3 2 1 0
- - - - - - - - - - - - - 7 5 3 1| - - - - - - - - - - - - 6 4 2 0
-
- SEW=16b, LMUL=1/4
-
- Byte 1F1E1D1C1B1A19181716151413121110| F E D C B A 9 8 7 6 5 4 3 2 1 0
- - - - - - - 3 1| - - - - - - 2 0
-
- SEW=32b, LMUL=1/4
-
- Byte 1F1E1D1C1B1A19181716151413121110| F E D C B A 9 8 7 6 5 4 3 2 1 0
- - - - 1| - - - 0
复制代码
Note: SLEN <VLEN 的映射模式的确需要在向量存储系统中的内存字节和向量寄存器字节之间建立全宽度(full-width)跨数据路径(cross-datapath)连接,这通常是不可避免的。
4.4 VLEN < SLEN 且 LMUL > 1时
当 SLEN <VLEN , LMUL> 1 时,第一个向量寄存器与初始的 VLEN / SEW 个元素放在一起,方式与 LMUL = 1 时相同。 该组中的第二个向量寄存器与相同模式的下一组 VLEN / SEW 个元素打包在一起。
- LMUL examples for SLEN < VLEN
-
- VLEN=256b, SLEN=128b, SEW=32b, LMUL=2
-
- Section 1 | 0
- Byte 1F1E1D1C1B1A19181716151413121110| F E D C B A 9 8 7 6 5 4 3 2 1 0
- v2*n 7 5 3 1| 6 4 2 0
- v2*n+1 F D B 9| E C A 8
-
- VLEN=256b, SLEN=128b, SEW=64b, LMUL=2
-
- Byte 1F1E1D1C1B1A19181716151413121110|F E D C B A 9 8 7 6 5 4 3 2 1 0
- v2*n 3 1| 2 0
- v2*n+1 7 5| 6 4
-
- VLEN=256b, SLEN=128b, SEW=64b, LMUL=4
-
- Byte 1F1E1D1C1B1A19181716151413121110|F E D C B A 9 8 7 6 5 4 3 2 1 0
- v4*n 3 1| 2 0
- v4*n+1 7 5| 6 4
- v4*n+2 B 9| A 8
- v4*n+3 F D| E C
复制代码
Note: 大多数情况下,SLEN ≥ ELEN。
一个主要约束是不更改 SEW 的值(用于访问向量寄存器组中保存的值)。
4.5 跨混合宽度操作的映射
向量 ISA 的设计目的是支持混合宽度操作,并且不需要大量显式的额外的重排指令,也不需要大量额外的数据路径(datapath)布线。在对不同精度值的向量进行操作时,推荐的做法是动态修改 vtype 值,从而使得 SEW/LMUL 为常量(因此 VLMAX 常量)。
下面的示例列举了 VLEN=256b/SLEN=128b 时,4种不同的压缩元素宽度(8b、16b、32b、64b)的实现。向量寄存器分组因子(LMUL)按相关元素大小增加,这样每个向量寄存器组可以保存相同数量的向量元素(本例中 VLMAX=16 ),从而简化 stripmining 代码。
- Examples VLEN=256b, SLEN=128b, with SEW/LMUL=16
-
- Section 1 | 0
- Byte 1F1E1D1C1B1A19181716151413121110| F E D C B A 9 8 7 6 5 4 3 2 1 0
- vn - - - - - - - - F D B 9 7 5 3 1| - - - - - - - - E C A 8 6 4 2 0 SEW=8b, LMUL=1/2
-
- Byte 1F1E1D1C1B1A19181716151413121110| F E D C B A 9 8 7 6 5 4 3 2 1 0
- vn F D B 9 7 5 3 1| E C A 8 6 4 2 0 SEW=16b, LMUL=1
-
- Byte 1F1E1D1C1B1A19181716151413121110| F E D C B A 9 8 7 6 5 4 3 2 1 0
- v2*n 7 5 3 1| 6 4 2 0 SEW=32b, LMUL=2
- v2*n+1 F D B 9| E C A 8
-
- Byte 1F1E1D1C1B1A19181716151413121110| F E D C B A 9 8 7 6 5 4 3 2 1 0 SEW=64b, LMUL=4
- v4*n 3 1| 2 0
- v4*n+1 7 5| 6 4
- v4*n+2 B 9| A 8
- v4*n+3 F D| E C
复制代码
下表列出了执行混合宽度操作的循环的每个可能的 SEW / LMUL 操作点。 每列代表一个恒定的 SEW / LMUL 操作点。 表中列出的内容是 LMUL 值,该值生成该列的 SEW / LMUL 值。 在同一列中, LMUL 的值不同,但 VLMAX 值相同。
当需要较少的向量寄存器组时,设置较大的 LMUL 可以用于简单地增加向量长度,从而减少指令的获取和调度开销。
Note: 表格为了完整起见,列出了 SEW / LMUL 值大于等于2048的情况。
4.6 掩码寄存器布局
无论 SEW 和 LMUL 值是多少,向量掩码仅占用一个向量寄存器。 在掩码向量寄存器中为每个元素分配了单个掩码位。
Note:较早的设计( v0.9 之前的版本)每个掩码值的位数(MLEN)不同。 在 v0.9 中,MLEN = 1。
4.6.1 SLEN = VLEN 时掩码元素位置
元素 i 的掩码位位于掩码寄存器的位 i 中,与 SEW 或 LMUL 无关。
- SLEN=VLEN=32b
-
- Byte 3 2 1 0
- LMUL=1,SEW=8b
- 3 2 1 0 Element
- [03][02][01][00] Mask bit position in decimal
-
- LMUL=2,SEW=16b
- 1 0
- [01] [00]
- 3 2
- [03] [02]
-
- LMUL=4,SEW=32b 0
- [00]
- 1
- [01]
- 2
- [02]
- 3
- [03]
- LMUL=2,SEW=8b
- 3 2 1 0
- [03][02][01][00]
- 7 6 5 4
- [07][06][05][04]
- LMUL=8,SEW=32b
- 0
- [00]
- 1
- [01]
- 2
- [02]
- 3
- [03]
- 4
- [04]
- 5
- [05]
- 6
- [06]
- 7
- [07]
- LMUL=8,SEW=8b
- 3 2 1 0
- [03][02][01][00]
- 7 6 5 4
- [07][06][05][04]
- B A 9 8
- [11][10][09][08]
- F E D C
- [15][14][13][12]
- 13 12 11 10
- [19][18][17][16]
- 17 16 15 14
- [23][22][21][20]
- 1B 1A 19 18
- [27][26][25][24]
- 1F 1E 1D 1C
- [31][30][29][28]
复制代码
4.6.2 SLEN < VLEN 时掩码元素位置
当 SLEN <VLEN 时,掩码元素被划分在向量掩码寄存器的 VLEN / SLEN 区段中。掩码元素0在区段0的最低有效位中,掩码元素1在区段1的最低有效位中,依此类推。通常,元素 i 的掩码位位于:
- Mask register element location examples for SLEN < VLEN
- The bit position of the LSB of each mask element is in decimal inside [] braces.
- VLEN=256b, SLEN=128b, SEW=32b, LMUL=2, MLEN=16b
- Section 1 | 0
- Byte 1F1E1D1C1B1A19181716151413121110| F E D C B A 9 8 7 6 5 4 3 2 1 0
- v2*n 7 5 3 1| 6 4 2 0
- [131] [130] [129] [128] [3] [2] [1] [0]
- v2*n+1 F D B 9| E C A 8
- [135] [134] [133] [132] [7] [6] [5] [4]
- VLEN=256b, SLEN=128b, SEW=32b, LMUL=1/2, MLEN=64b
- Section 1 | 0
- Byte 1F1E1D1C1B1A19181716151413121110| F E D C B A 9 8 7 6 5 4 3 2 1 0
- vn - - 3 1| - - 2 0
- [129] [128] [1] [0]
- VLEN=256b, SLEN=128b, SEW=64b, LMUL=1, MLEN=64b
- Section 1 | 0
- Byte 1F1E1D1C1B1A19181716151413121110| F E D C B A 9 8 7 6 5 4 3 2 1 0
- vn 3 1| 2 0
- [129] [128] [1] [0]
复制代码
5 向量指令格式
向量扩展中的指令有三个主要操作码( LOAD-FP,STORE-FP,AMO )和一个新的操作码(OP-V)。
向量的加载和存储是在标量浮点加载和存储的主要操作码(LOAD-FP / STORE-FP)中进行编码。向量的加载和存储编码重新利用了标准标量浮点加载/存储12位立即数字段的一部分,以供进一步的向量指令编码,其中位25保留了标准向量掩码位(详细参见“5.3.1 节Mask Encoding”)
向量指令可以具有标量或向量操作数,产生标量或向量结果,大多数向量指令可以在掩码下无条件或有条件地执行。
向量的加载和存储操作在向量寄存器元素和内存之间移动位模式(bit patterns)。向量算术指令对向量寄存器元素中保存的值进行操作。
5.1 标量操作数
标量操作数可以是立即数,也可以取自 x 寄存器,f 寄存器或向量寄存器的元素0。 标量结果被写入 x 或 f 寄存器或向量寄存器的元素0。无论当前的 LMUL 设置值多少,任何向量寄存器都可用于保存标量。
5.2 向量操作数
每个向量操作数都有一个有效元素宽度( effective element width,EEW)和一个有效LMUL(EMUL),用于确定向量寄存器组中所有元素的大小和位置。 默认情况下,对于大多数指令的大多数操作数,EEW = SEW ,EMUL = LMUL。
一些向量指令的源向量操作数和目标向量操作数具有相同数量的元素,但宽度不同,因此 EEW 和 EMUL 可以分别不同于 SEW 和 LMUL ,但 EEW / EMUL = SEW / LMUL 。 例如,大多数加宽的算术指令的源组: EEW = SEW , EMUL = LMUL ,目标组: EEW = 2 * SEW 和 EMUL = 2 * LMUL 。缩窄的指令的源组: EEW = 2 * SEW 和 EMUL = 2 * LMUL,目标组: EEW = SEW 和 EMUL = LMUL。
向量操作数或结果可能会占用一个或多个向量寄存器,这由 EMUL 决定 ,并由组中编号最小的向量寄存器来指定。 若使用其他寄存器来指定向量寄存器组将导致非法指令异常。
指令使用的最大向量寄存器组不能超过8个向量寄存器(即 EMUL≤ 8 ),如果向量指令在一组中需要大于8个向量寄存器,则会引发非法指令异常。 例如,当 LMUL = 8 时,尝试进行加宽操作产生加宽的向量寄存器组将引发非法指令异常,因为这意味着 EMUL = 16。
加宽后的标量值(比如加宽操作中的结果)将保存在向量寄存器的第一个元素中,且 EMUL = 1。
5.3 向量掩码
许多向量指令都支持掩码。 被掩码(非活跃)的元素操作不产生异常。 根据 vtype 中的 vma 位(3.3.3节)的设置,用掩码不受干扰或掩码不可知(mask-undisturbed or mask-agnostic)这两种策略来处理与掩码元素相对应的目标向量寄存器元素。
在基本向量扩展中,由向量寄存器 v0 保存用于控制掩码向量指令执行的掩码值。
Note: 以后的向量扩展可能会提供更长的指令编码,并为完整的掩码寄存器说明符提供空间。
只有当目标向量寄存器写入掩码值(如,comparisons)或归约的标量结果时,用于掩码向量指令的目标向量寄存器组才可以与源掩码寄存器( v0 )重叠。 否则,将引发非法指令异常。
其他向量寄存器可用于保存有效的掩码值,并且提供掩码向量逻辑运算以执行谓词计算。
当使用比较结果写入掩码时,当前向量长度结束后的目标掩码位将根据 vtype中的 vta 位设置的尾部策略( undisturbed or agnostic )(3.3.3节)处理。
5.3.1 掩码编码
掩码编码在指令( inst[25] )中的 vm 字段中,占一位。
Note:在较早版本中,vm 字段占2位,即vm [1:0],使用 v0 寄存器并编码标量运算,表示真值和掩码值。
向量掩码在汇编代码中表示为另一个向量操作数,用 .t 表示当 v0.mask 为 1 时是否发生操作。如果未指定掩码操作数,则假定为未掩码的向量执行( vm = 1 )。 - vop.v* v1, v2, v3, v0.t # enabled where v0.mask[i]=1, m=0
- vop.v* v1, v2, v3 # unmasked vector operation, m=1
复制代码
Note: 即使基本向量扩展中,仅支持一个向量掩码寄存器 v0 ,并且仅支持真实的谓词形式,汇编语法仍将其完全写出,以便与以后的扩展兼容,以后的扩展可能会添加掩码寄存器说明符并支持真值和掩码值。 掩码操作数上的 .t 后缀还有助于掩码编码的可视化。
5.4 一些定义
向量指令执行期间操作的元素索引可以分为四个不相交的子集。
- 预启动元素(The prestart elements)是指索引小于vstart寄存器初始值的元素。预启动元素不会引发异常,也不会更新目标向量寄存器。
- 活跃元素(The active elements) 指的是向量指令执行期间,在当前向量长度范围内的元素,并且在该元素位置启用了当前掩码。活动元素可以引发异常并更新目标向量寄存器组。
- 非活跃元素(The inactive elements)指的是向量指令执行期间,在当前向量长度范围内的元素,但是在该元素位置禁用了当前掩码。 除非指定了masked agnostic( vtype.vma = 1 ),否则非活跃元素不会引发异常,也不会更新任何目标向量寄存器组,在 vtype.vma = 1 这种情况下,非活跃元素可能会被1覆盖。
- 尾部元素(The tail elements) 是超出当前向量长度设置的元素。 尾部元素不会引发异常,并且只在指定了tail agnostic尾部不可知性(vtype.vta = 1)的情况下,才会更新目标向量寄存器组,在这种情况下,尾部元素可能会被1覆盖。 当LMUL <1时,尾部包含VLMAX之后的元素,这些元素保存在同一向量寄存器中。
- 另外,主体部分(body),用于表示活跃元素或非活跃元素的集合,即在预启动元素之后但在尾部元素之前。
- for element index x
- prestart = (0 <= x < vstart)
- mask(x) = unmasked || v0[x].LSB == 1
- active(x) = (vstart <= x < vl) && mask(x)
- inactive(x) = (vstart <= x < vl) && !mask(x)
- body(x) = active(x) || inactive(x)
- tail(x) = (vl <= x < max(VLMAX,VLEN/SEW))
复制代码
6 配置参数设置(Configuration-Setting)
本节介绍一组可以快速设置vl 和 vtype 值的指令。
6.1 vsetvli/vsetvl 指令
vsetvli 指令根据其参数设置 vtype 和 vl CSRs,并将 vl 的新值写入 rd。
- vsetvli rd, rs1, vtypei # rd = new vl, rs1 = AVL, vtypei = new vtype setting
- vsetvl rd, rs1, rs2 # rd = new vl, rs1 = AVL, rs2 = new vtype value
复制代码
新的 vtype 编码于在 vsetvli 的立即数字段和 vsetvl 的 rs2寄存器中。 新的 向量长度基于请求的应用程序向量长度(AVL)设置,该长度在 rs1 和 rd 字段中编码如下:
表6. 用于vsetvli/vsetvl 指令的AVL
当 rs1 不是 x0 时,AVL 是 rs1 指定的 x 寄存器中保存的无符号整数,并且新的 vl 值也将写入 rd 指定的 x 寄存器中。
当 rs1 = x0 但 rd!= x0 时,最大无符号整数值(〜0)用作 AVL ,并将所得的VLMAX 写入 vl 以及 rd 指定的 x 寄存器。
当 rs1 = x0 且 rd = x0 时,vl 中的当前向量长度用作 AVL ,并且结果值仅写入 vl 。
Note:如果不减小 VLMAX ,则这种形式的指令允许在保持当前 vl 的同时更改 vtype 寄存器 。如果 SEW / LMUL 比率更改导致 VLMAX 缩小,则可以通过此指令减小 vl 值。选择该设计是为了确保vl始终是当前vtype 设置的合法值。当前的vl 值可以从vlCSR 读取。
- Suggested assembler names used for vsetvli immediate
- e8 # SEW=8b
- e16 # SEW=16b
- e32 # SEW=32b
- e64 # SEW=64b
- e128 # SEW=128b
- e256 # SEW=256b
- e512 # SEW=512b
- e1024 # SEW=1024b
- mf8 # LMUL=1/8
- mf4 # LMUL=1/4
- mf2 # LMUL=1/2
- m1 # LMUL=1, assumed if m setting absent
- m2 # LMUL=2
- m4 # LMUL=4
- m8 # LMUL=8
- Examples:
- vsetvli t0, a0, e8 # SEW= 8, LMUL=1
- vsetvli t0, a0, e8,m2 # SEW= 8, LMUL=2
- vsetvli t0, a0, e32,mf2 # SEW=32, LMUL=1/2
复制代码
如果实现中不支持 vtype 的设置,则设置 vtype 中的 vill 位,将 vtype 中的其余位设置为零,并将vl寄存器也设置为零。
6.2 vl的约束
vsetvl{i}指令首先根据 vtype 参数,设定 VLMAX ,然后设置vl服从以下约束:
- 如果 AVL ≤ VLMAX ,则 vl = AVL
- 如果 AVL < (2 * VLMAX),则ceil(AVL / 2) ≤ vl ≤ VLMAX
- 如果 AVL ≥ (2 * VLMAX),则 vl = VLMAX
- 如果输入相同的 AVL 和 VLMAX 值,则任何实现中,v1 都是确定的
- 满足之前提及的规则:
- 如果 AVL = 0,则 vl = 0
- 如果 AVL > 0,vl > 0
- vl ≤ VLMAX
- vl ≤ AVL
- 从 vl 中读取的值(用作 vsetvl{i} 的 AVL 参数时)会在 vl 中产生相同的值,前提是所得的 VLMAX 等于读取vl时的 VLMAX 值。
Note:vl的设置规则足够严格,可以在寄存器溢出和 AVL ≤ VLMAX时上下文交换的情况下保护 vl 的行为,但又足够灵活,确保能够提高 AVL> VLMAX 时的向量通道利用率。
6.3 vsetvl指令vsetvl的操作方式与 vsetvli 类似,不同之处在于:vsetvl 从 rs2 中获取一个vtype值并可以用于上下文还原,并且此时,vtypei字段太小而无法保存所需的设置。
Note: 可以将几种常用的复杂类型保存在不同的 x 寄存器中,并根据需要使用 vsetvl 进行交换。
6.4 例子
为了在混合宽度操作上提供高吞吐量,可以动态更改 SEW 和 LMUL 的设置。
- # Example: Load 16-bit values, widen multiply to 32b, shift 32b result
- # right by 3, store 32b values.
- loop:
- vsetvli a3, a0, e16,m4 # vtype = 16-bit integer vectors
- vle16.v v4, (a1) # Get 16b vector
- slli t1, a3, 1 # Multiply length by two bytes/element
- add a1, a1, t1 # Bump pointer
- vwmul.vx v8, v4, x10 # 32b in <v8--v15>
- vsetvli x0, a0, e32,m8 # Operate on 32b values
- vsrl.vi v8, v8, 3
- vse32.v v8, (a2) # Store vector of 32b elements
- slli t1, a3, 2 # Multiply length by four bytes/element
- add a2, a2, t1 # Bump pointer
- sub a0, a0, a3 # Decrement count
- bnez a0, loop # Any more?
复制代码完 |