RISC-V "V"(向量)扩展规范v0.9+文档(3)
本帖最后由 sky 于 2020-9-28 15:50 编辑RISC-V "V"(向量)扩展规范v0.9+文档(1)RISC-V "V"(向量)扩展规范v0.9+文档(2)RISC-V "V"(向量)扩展规范v0.9+文档(3)RISC-V "V"(向量)扩展规范v0.9+文档(4)RISC-V "V"(向量)扩展规范v0.9+文档(5)
关于这篇文章:
本文主要翻译自 RISC-V "V"(向量)扩展的官方文档,翻译版本为目前最新版的 RISC-V "V"(向量)扩展规范文档,小部分地方有删减及排版调整。
由于译者水平有限,本文可能存在谬误或不当之处,欢迎指正。
以下为正文(连载中):
7 向量的加载和存储向量的加载和存储操作在向量寄存器和内存之间移动元素值。向量的加载和存储操作使用掩码,且不会在非活跃元素上引发异常。掩码向量的加载操作不会更新目标向量寄存器组中的非活跃元素。掩码向量的存储操作只更新内存中的活跃元素。
7.1 向量加载/存储的指令编码向量的加载和存储指令在标量浮点加载和存储主操作码(LOAD-FP / STORE-FP)中进行编码。 向量的加载和存储编码重新利用了标量浮点加载/存储12位立即数字段的一部分,以提供进一步的向量指令编码,其中位25保留了标准向量掩码位(请参见5.3.1节)。vmem-format.adoc
向量内存操作直接对指令中要静态传输的数据的 EEW 进行编码,从而减少混合宽度操作时,访问内存时 vtype 的改变次数。 索引操作在指令中使用显式 EEW 编码来设置所使用索引的大小,并且用 SEW / LMUL 的值指定数据宽度。
7.2 向量加载/存储的寻址模式
基本向量扩展支持单步幅跨步(unit-stride),跨步(strided)和索引(indexed)寻址模式。向量加载/存储的基址寄存器和步幅取自GPR x 寄存器。
所有向量访问的基本有效地址由中 rs1 中命名的 x 寄存器的内容给出。
向量的unit-stride操作从基本有效地址开始访问连续存储在内存中的元素。
向量的strided操作在基本有效地址处访问第一个内存元素,然后以 rs2 指定的 x 寄存器中包含的字节偏移量给定的地址增量访问后续元素。
向量索引操作把由 rs2 指定的向量偏移量添加到基本有效地址上,从而得到每个元素的有效地址。数据向量寄存器组中,EEW = SEW,EMUL = LMUL,而偏移向量寄存器组在指令中有 EEW 编码,EMUL =(EEW / SEW)* LMUL。
向量偏移量操作数被视为字节地址偏移量的向量。如果向量偏移量小于 XLEN,则在将它们添加到基本有效地址之前,先将它们加零扩展到XLEN。如果向量偏移量大于 XLEN,则在地址计算中使用最低有效的 XLEN 位。
向量寻址模式使用2位mop 字段进行编码。
表7. encoding for loads
表8. encoding for stores
向量的索引操作具有两种形式,有序的和无序的。无序的索引存储操作不保存元素顺序。
其他的 unit-stride 向量寻址模式在 unit-stride 加载和存储指令编码中分别使用5位lumop和sumop字段编码。
表9. lumop
表10. sumop
nf字段编码每个段(segment)中的字段数。对于常规向量的加载和存储,nf= 0,表示在每个元素位置的向量寄存器组和内存之间移动单个值。nf字段中较大的值用于访问段中的多个连续字段(关于段的描述参见7.8节)。
Note:nf字段替换了地址偏移量字段中的相同位。偏移量可以用单个标量整数计算代替,而段加载/存储添加了更强大的原语,可以将项目移入和移出内存。
nf字段还对整个向量寄存器的数量进行编码,以针对整个向量寄存器的加载/存储指令进行传输。
7.3 向量加载/存储的宽度编码
向量的加载和存储直接将 EEW 编码在指令中。EMUL 的计算公式为:EMUL =(EEW / SEW)* LMUL 。如果 EMUL 超出范围( EMUL> 8 或 EMUL <1/8 ),则会触发非法指令异常。向量寄存器组必须存在能指明所选 EMUL 是否合法的寄存器,否则会触发非法指令异常。
向量的加载和存储使用标准标量的浮点加载和存储中未声明的值进行编码。 mew位(inst)扩展了128位及超过128位的内存大小。
向量的加载和存储的实现中,EEW 最大到 EEW = ELEN。向量的加载和存储操作与不支持的 EEW 一起使用会引发非法指令异常。
注:
Mem bits(内存位)是内存中访问的每个元素的大小。
Reg bits(寄存器位)是寄存器中访问的每个元素的大小。
7.4 向量单步幅跨步(Unit-Stride)指令
# Vector unit-stride loads and stores
# vd destination, rs1 base address, vm is mask encoding (v0.t or <missing>)
vle32.vvd, (rs1), vm # 32-bit loads
# vs3 store data, rs1 base address, vm is mask encoding (v0.t or <missing>)
vse64.vvs3, (rs1), vm# 64-bit stores
7.5 向量跨步(Strided)指令
# Vector strided loads and stores
# vd destination, rs1 base address, rs2 byte stride
vlse8.vvd, (rs1), rs2, vm# Load bytes separated by stride
# vs3 store data, rs1 base address, rs2 byte stride
vsse128.v vs3, (rs1), rs2, vm# Store 128b values separated by stride.
Note: 步幅值可为负值或零。
7.6 向量索引(indexed)指令
# Vector indexed loads and stores
# vd destination, rs1 base address, vs2 indices
vlxei16.vvd, (rs1), vs2, vm# vs2 data EEW = SEW, indices EEW = 16b
# Vector ordered-indexed store instructions
# vs3 store data, rs1 base address, vs2 indices
vsxei32.v vs3, (rs1), vs2, vm # SEW data, 32b indices
# Vector unordered-indexed store instructions
vsuxei64.v vs3, (rs1), vs2, vm # SEW data, 64b indices
7.7 单步跨步仅故障优先加载(Unit-Stride Fault-Only-First Loads)
单位步幅跨步及仅故障优先加载指令(Unit-Stride Fault-Only-First Loads)用于对与数据相关的退出条件(while循环)进行向量化。这些指令除了只在元素0上执行陷入外,一般作为常规加载指令执行。如果元素 > 0引发异常,则该元素和目标向量寄存器中的所有后续元素都不会被修改,并且vl会减少为没有陷入处理的元素数。
vle8ff.vvd, (rs1), vm
Note:跨步及索引模式的(Strided and scatter/gather)仅故障优先指令,存在安全漏洞,故这里暂时不提。
即使未引发异常,操作中也可以处理少于vl个元素并相应地减少vl,但是如果vstart= 0和 vl> 0,则必须处理至少一个元素。
7.8 向量的加载/存储段指令(Vector Load/Store Segment Instructions)(Zvlsseg)
Note: 该指令集包含在基本的“ V”扩展中。
向量的加载/存储段指令将存储器中的多个连续字段移入、移出连续编号的向量寄存器。
Note: 这些操作通过将结构中的每个字段解包到单独的向量寄存器中,从而支持对“结构数组”这种数据类型的操作。
向量指令编码中的 nf 字段包含三位,是一个无符号整数,它比每个段的字段数 NFIELDS 少一个。
EMUL 的值必须满足 EMUL * NFIELDS ≤ 8,否则会引发非法指令异常。
Note: EMUL * NFIELDS 表示分段加载或存储指令会涉及的向量寄存器的数量。
每个字段保存在连续编号的向量寄存器组中。当 EMUL> 1 时,每个字段将占据一个向量寄存器组,并且每个字段的向量寄存器组必须满足通常的向量寄存器对齐约束(例如,当 EMUL = 2,NFIELDS = 4 时,每个字段的向量寄存器组必须从偶数向量寄存器开始,但不必以8的倍数个向量寄存器号开始)。
Note: 较早的版本有向量寄存器数量限制,但是当 NFIELDS 不是2的幂时,充分利用所有寄存器的能力就会降低。
如果分段加载或存储操作访问的向量寄存器数量增加到31以上,则会引发非法指令异常。
vl寄存器指定了要移动的结构数量,其值等于转移到每个向量寄存器组的元素的数量。
如果捕获了陷入指令,则vstart也在该体系单元内。
7.8.1 向量单步幅跨步的段加载与段存储(Vector Unit-Stride Segment Loads and Stores)
向量单步幅跨步段加载和段存储(Vector Unit-Stride Segment Loads and Stores)将连续段(“结构数组”)移动到多个目标向量寄存器组中。
Note: 对于具有不同大小字段的段,段加载将值放入单独的向量寄存器之后,软件可以稍后使用其他指令对字段进行解包。
汇编程序前缀vlseg/ vsseg分别用于单步幅跨步的段加载和段存储。
# Format
vlseg<nf>e<eew>.v vd, (rs1), vm # Unit-stride segment load template
vsseg<nf>e<eew>.v vs3, (rs1), vm # Unit-stride segment store template
# Examples
vlseg8e8.v vd, (rs1), vm # Load eight vector registers with eight byte fields.
vsseg3e32.v vs3, (rs1), vm# Store packed vector of 3*4-byte segments from vs3,vs3+1,vs3+2 to memory
对于加载操作,vd 寄存器保存从段加载的第一个字段。对于存储操作,读取vs3 寄存器获得要存储在每个段中的第一个字段。
# Example 1
# Memory structure holds packed RGB pixels (24-bit data structure, 8bpp)
vsetvli a1, t0, e8
vlseg3e8.v v8, (a0), vm
# v8 holds the red pixels
# v9 holds the green pixels
# v10 holds the blue pixels
# Example 2
# Memory structure holds complex values, 32b for real and 32b for imaginary
vsetvli a1, t0, e32
vlseg2e32.v v8, (a0), vm
# v8 holds real
# v9 holds imaginary
单步幅跨步指令也有仅故障优先版本。
# Template for vector fault-only-first unit-stride segment loads and stores.
vlseg<nf>e<eew>ff.v vd, (rs1),vm # Unit-stride fault-only-first segment loads
7.8.2 向量跨步的段加载与段存储(Vector Strided Segment Loads and Stores)
向量跨步段加载与段存储操作(Vector Strided Segment Loads and Stores)移动连续的段,其中每个段由rs2 GPR 参数中给出的跨字节偏移量分隔开。
Note: 步幅值可为负值或零。
# Format
vlsseg<nf>e<eew>.v vd, (rs1), rs2, vm # Strided segment loads
vssseg<nf>e<eew>.v vs3, (rs1), rs2, vm # Strided segment stores
# Examples
vsetvli a1, t0, e8
vlsseg3e8.v v4, (x5), x6 # Load bytes at addresses x5+i*x6 into v4,
#and bytes at addresses x5+i*x6+1 into v5,
#and bytes at addresses x5+i*x6+2 into v6.
# Examples
vsetvli a1, t0, e32
vssseg2e32.v v2, (x5), x6 # Store words from v2 to address x5+i*x6
# and words from v3 to address x5+i*x6+4
对于跨步的段存储,其中跨字节(byte stride)使得段可能在内存中重叠,这些段要看起来是按元素顺序写入的。
7.8.3 向量索引的段加载与段存储(Vector Indexed Segment Loads and Stores)
向量索引的段加载与段存储(Vector Indexed Segment Loads and Stores)移动连续的段,其中每个段的地址是通过将rs1字段中的标量基地址与向量寄存器 vs2 中的字节偏移量相加得出的。
向量寄存器组中,EEW = SEW,EMUL = LMUL,而索引向量寄存器组的 EEW 在指令中编码满足 EMUL =(EEW / SEW)* LMUL。
# Format
vlxseg<nf>ei<eew>.v vd, (rs1), vs2, vm # Indexed segment loads
vsxseg<nf>ei<eew>.v vs3, (rs1), vs2, vm # Indexed segment stores
# Examples
vsetvli a1, t0, e8
vlxseg3ei32.v v4, (x5), v3 # Load bytes at addresses x5+v3 into v4,
#and bytes at addresses x5+v3+1 into v5,
#and bytes at addresses x5+v3+2 into v6.
# Examples
vsetvli a1, t0, e32
vsxseg2e32.v v2, (x5), v5 # Store words from v2 to address x5+v5
# and words from v3 to address x5+v5+4
对于向量索引的段加载,目标向量寄存器组不能与源向量寄存器组(由vs2指定)重叠 ,否则会引发非法指令异常。
目前仅支持有序的索引段存储。段要看起来是按元素顺序编写的。
7.9 向量加载/存储整个寄存器指令
Note: 这些指令仍在考虑中。
这些指令加载并存储整个向量寄存器(即 VLEN 位)。指令以 EEW = 8 和有效向量长度evl= VLEN / 8 进行操作,而与当前 vtype 和 vl 的设置无关。如果vstart≥VLEN / 8,则不会传输任何元素。vstart≥vl时不写入任何元素,这样的的常规属性不适用于这些指令。
Note: 当前向量寄存器的类型和长度未知的情况下,或者修改 vtype 和 vl 的代价比较大时,这些指令可以用于保存和恢复向量寄存器。比如寄存器溢出,中断处理及操作系统上下文切换时。软件可以通过读取vlenb寄存器来确定传输的字节数 。
Format for Vector Load Whole Register Instructions under LOAD-FP major opcode
31 29 28 262524 20 19 15 14 12 11 7 6 0
nf| 000 | 1 | 01000 | rs1 |000| vd |0000111| VL<nf>R
Format for Vector Store Whole Register Instructions under STORE-FP major opcode
31 29 28 262524 20 19 15 14 12 11 7 6 0
nf| 000 | 1 | 01000 | rs1 |000| vs3 |0100111| VS<nf>R
指令的操作类似于非掩码的单步幅跨步加载和存储指令,基地址通过 rs1 指定的 x 标量寄存器中传递。
指令传输vd 为装载和vs3存储指定的单个向量寄存器。指令可以传递由 vd 指定的单个向量寄存器用于加载,由 vs3 指定向量寄存器用于存储。在 EEW = 8 和 EMUL = 1 的情况下寄存器进出内存。
Note: 向量整个寄存器的加载指令的编码类似于元素的未掩码加零扩展的单步幅跨步加载指令(unmasked zero-extended unit-stride loads),其中 nf 字段表示要加载和存储多少个向量寄存器。向量整个寄存器的存储指令的编码类似于元素的未掩码的单步幅跨步存储指令(unmasked unit-stride store)。当前的基本规范要求仅支持 nf= 0,并为其保留其他值 。
# Format
vl1r.v v3, (a0) # Load v3 with VLEN/8 bytes held at address in a0
vs1r.v v3, (a1) # Store v3 to address in a1
完
页:
[1]