《RISC-V "V" Vector Extension Version 1.0》阅读笔记

  • RISC-V "V" Vector Extension Version 1.0
    • 1、Introduction
    • 2、Implementation-defined Constant Parameters
    • 3、Vector Extension Programmer’s Model
      • 3.1、向量寄存器( Vector Registers)
      • 3.2.、Vector Context Status in mstatus(mstatus 中的向量上下文状态)
      • 3.3、Vector Context Status in vsstatus(3.3. vsstatus 中的向量上下文状态)
      • 3.4.向量类型寄存器,vtype
        • 3.4.1. Vector selected element width vsew[2:0]
        • 3.4.2. Vector Register Grouping (vlmul[2:0])
        • 3.4.3. Vector Tail Agnostic and Vector Mask Agnostic vta and vma(向量尾不可知和向量掩码不可知 vta 和 vma)
        • 3.4.4. Vector Type Illegal vill(矢量类型非法vill)
      • 3.5. Vector Length Register vl
      • 3.6. Vector Byte Length vlenb
      • 3.7. Vector Start Index CSR vstart
      • 3.8.矢量定点舍入模式寄存器 vxrm( Vector Fixed-Point Rounding Mode Register vxrm)
      • 3.9. (矢量定点饱和标志 vxsat)Vector Fixed-Point Saturation Flag vxsat
      • 3.10、矢量控制和状态寄存器 vcsr(Vector Control and Status Register vcsr)
      • 3.11. (复位时向量扩展的状态)State of Vector Extension at Reset
    • 4、(向量元素到向量寄存器状态的映射)Mapping of Vector Elements to Vector Register State
      • 4.1. Mapping for LMUL = 1
      • 4.2. Mapping for LMUL < 1
      • 4.3. Mapping for LMUL > 1
      • 4.4.跨混合宽度操作的映射( Mapping across Mixed-Width Operations)
      • 4.5. (掩码寄存器布局)Mask Register Layout
    • 5、(矢量指令格式)Vector Instruction Formats
      • 5.1、标量操作数(Scalar Operands)
      • 5.2.向量操作数(Vector Operands)
      • 5.3. Vector Masking(矢量掩蔽)
    • 6、配置-设置说明 (vsetvli/vsetivli/vsetvl)
      • 6.1、vtype 编码
      • 6.2. AVL encoding
      • 6.3.设置 vl 的约束
      • 6.4. Example of stripmining and changes to SEW
    • 7、Vector Loads and Stores
      • 7.1. Vector Load/Store Instruction Encoding
      • 7.2.向量加载/存储寻址模式(Vector Load/Store Addressing Modes)
      • 7.3. Vector Load/Store Width Encoding
      • 7.4.向量单位步长指令(Vector Unit-Stride Instructions)
      • 7.5。矢量跨步指令(Vector Strided Instructions)
      • 7.6.向量索引指令(Vector Indexed Instructions)
      • 7.7.单位步幅仅故障首次加载( Unit-stride Fault-Only-First Loads)
      • 7.8.向量加载/存储段指令(Vector Load/Store Segment Instructions)
        • 7.8.1.向量单位步长段加载和存储( Vector Unit-Stride Segment Loads and Stores)
        • 7.8.2.向量跨步段加载和存储(Vector Strided Segment Loads and Stores)
        • 7.8.3.向量索引段加载和存储(Vector Indexed Segment Loads and Stores)
      • 7.9、向量加载/存储整个寄存器指令(Vector Load/Store Whole Register Instructions)
    • 8、向量内存对齐约束(Vector Memory Alignment Constraints)
    • 9、向量内存一致性模型(Vector Memory Consistency Model)
    • 10、向量算术指令格式(Vector Arithmetic Instruction Formats)
      • 10.1。矢量算术指令编码(Vector Arithmetic Instruction encoding)
      • 10.2.加宽向量算术指令(Widening Vector Arithmetic Instructions)
      • 10.3.窄化向量算术指令(Narrowing Vector Arithmetic Instructions)
    • 11、向量整数运算指令(Vector Integer Arithmetic Instructions)
      • 11.1。向量单宽度整数加减法(Vector Single-Width Integer Add and Subtract)
      • 11.2.向量加宽整数加/减(Vector Widening Integer Add/Subtract)
      • 11.3.向量整数扩展(Vector Integer Extension)
  • 未完待续。。。。。
  • 参考:

RISC-V “V” Vector Extension Version 1.0

本文是自己学习做的笔记,供大家学习使用。RVV-spec源码和pdf下载地址如下:
https://github.com/riscv/riscv-v-spec/releases

1、Introduction

本文档是 RISC-V 矢量扩展的 1.0 版,供公众审查。

作为 RISC-V 国际批准过程的一部分,此版本 1.0 被视为已冻结以供公众审查。 1.0 版被认为足够稳定,可以开始开发工具链、功能模拟器和实现,包括在上游软件项目中,并且预计不会有不兼容的更改,除非在批准期间发现严重问题。一旦获得批准,该规范将获得 2.0 版。

该规范包括完整的当前冻结向量指令集。其他在开发过程中考虑过但未出现在本文档中的说明不包括在审查和批准过程中,可能会被完全修改或放弃。标准向量扩展部分列出了标准向量扩展以及每个扩展支持哪些指令和元素宽度。

2、Implementation-defined Constant Parameters

每个支持向量扩展的 hart 定义了两个参数:

1、任何操作可以产生或消耗的向量元素的最大比特大小,ELEN ≥ 8,必须是 2 的幂。

2、单个向量寄存器的位数,VLEN≥ELEN,必须是2的幂,不能大于2^16。

标准向量扩展(Section Standard Vector Extensions)和架构配置文件可能会对 ELEN 和 VLEN 设置进一步的限制:

1、未来的扩展可能允许 ELEN > VLEN 通过使用来自多个向量寄存器的位来保存一个元素,但当前的提议不包括此选项。

2、VLEN 的上限允许软件知道索引将变为 16 位(65,536 的最大 VLMAX 出现在 LMUL=8 和 SEW=8 且 VLEN=65,536 时)。每个向量寄存器超过 64Kib 的任何未来扩展都将需要新的配置指令,这样使用旧配置指令的软件就不会看到更大的向量长度。

向量扩展支持编写二进制代码,该代码在某些约束下将在具有不同 VLEN 参数值的 harts 上可移植地执行,前提是 harts 支持所需的元素类型和指令。

注意 可以编写代码来暴露实现参数的差异。

注意 通常,在 VLEN 或 ELEN 参数有任何差异的 hart 之间执行期间,无法迁移具有活动向量状态的线程上下文。

3、Vector Extension Programmer’s Model

向量扩展将 32 个向量寄存器和 7 个非特权 CSR(vstart、vxsat、vxrm、vcsr、vtype、vl、vlenb)添加到基本标量 RISC-V ISA。

注意 4 个 CSR 编号 0x00B-0x00E 暂时保留给未来的向量 CSR,其中一些可能会镜像到 vcsr。

3.1、向量寄存器( Vector Registers)

向量扩展将 32 个架构向量寄存器 v0-v31 添加到基本标量 RISC-V ISA。

每个向量寄存器都有一个固定的 VLEN 位状态。

3.2.、Vector Context Status in mstatus(mstatus 中的向量上下文状态)

向量上下文状态字段 VS 被添加到 mstatus[10:9] 并在 sstatus[10:9] 中隐藏。它的定义类似于浮点上下文状态字段 FS。

当 mstatus.VS 设置为 Off 时,尝试执行任何向量指令或访问向量 CSR,会引发非法指令异常。

当 mstatus.VS 设置为 Initial 或 Clean 时,执行任何更改向量状态的指令,包括向量 CSR,都会将 mstatus.VS 更改为 Dirty。实现也可以随时将 mstatus.VS 从 Initial 或 Clean 更改为 Dirty,即使向量状态没有变化。

注意 mstatus.VS 的精确设置是一种优化。软件通常会使用 VS 来减少上下文交换开销。

如果 mstatus.VS 为 Dirty,则 mstatus.SD 为 1;否则,根据现有规范设置 mstatus.SD。

实现可能有一个可写的 misa.V 字段。类似于处理浮点单元的方式,即使 misa.V 是明确的,mstatus.VS 字段也可能存在。

注意 当 misa.V 被清除时允许 mstatus.VS 存在,启用矢量仿真并简化在具有可写 misa.V 的系统中对 mstatus.VS 的处理。

3.3、Vector Context Status in vsstatus(3.3. vsstatus 中的向量上下文状态)

当存在管理程序扩展时,向量上下文状态字段 VS 被添加到 vsstatus[10:9]。它的定义类似于浮点上下文状态字段 FS。

当 V=1 时,vsstatus.VS 和 mstatus.VS 都有效:尝试执行任何向量指令,或访问向量 CSR,当任一字段设置为 Off 时引发非法指令异常。

当 V=1 且 vsstatus.VS 和 mstatus.VS 均未设置为 Off 时,执行任何更改向量状态的指令,包括向量 CSR,都会将 mstatus.VS 和 vsstatus.VS 更改为 Dirty。实现也可以随时将 mstatus.VS 或 vsstatus.VS 从 Initial 或 Clean 更改为 Dirty,即使向量状态没有变化。

如果 vsstatus.VS 为 Dirty,则 vsstatus.SD 为 1;否则,根据现有规范设置 vsstatus.SD。

如果 mstatus.VS 为 Dirty,则 mstatus.SD 为 1;否则,根据现有规范设置 mstatus.SD。

对于具有可写 misa.V 字段的实现,即使 misa.V 被清除,vsstatus.VS 字段也可能存在。

3.4.向量类型寄存器,vtype

只读 XLEN-wide 向量类型 CSR,vtype 提供了用于解释向量寄存器文件内容的默认类型,并且只能通过 vset{i}vl{i} 指令进行更新。向量类型决定了每个向量寄存器中元素的组织方式,以及多个向量寄存器的分组方式。 vtype 寄存器还指示如何处理向量结果中被屏蔽的元素和超过当前向量长度的元素。

注意 仅通过 vset{i}vl{i} 指令允许更新简化了 vtype 寄存器状态的维护。

vtype 寄存器有五个字段,vill、vma、vta、vsew[2:0] 和 vlmul[2:0]。vtype[XLEN-2:8] 应写入零,并保留该字段中的非零值。

注意 此图显示了 RV32 系统的布局,而通常 vill 应位于 XLEN-1 位。

注意 支持 ELEN=32 的小型实现只需要 vtype 中的七位状态:两位用于 ma 和 ta,两位用于 vsew[1:0],三位用于 vlmul[2:0]。 vill 表示的非法值可以使用 vsew[1:0] 中的非法 64 位组合进行内部编码,而不需要额外的存储位来保存 vill。

注意 进一步的标准和自定义向量扩展可以扩展这些字段以支持更多种类的数据类型。

注意 vtype CSR 的主要动机是允许向量指令集适合 32 位指令编码空间。在执行向量指令之前,可以使用单独的 vset{i}vl{i} 指令来设置 vl 和/或 vtype 字段,并且实现可以选择将这两个指令融合到单个内部向量微操作中。在许多情况下,vl 和 vtype 值可以在多个指令中重复使用,从而减少 vset{i}vl{i} 指令的静态和动态指令开销。预计未来扩展的 64 位指令编码将允许在指令编码中静态指定这些字段。

3.4.1. Vector selected element width vsew[2:0]

vsew 中的值设置 SEW。默认情况下,向量寄存器被视为分为 VLEN/SEW个 元素

注意 虽然预计较大的 vsew[2:0] 编码 (100-111) 将用于编码较大的 SEW,但此时编码已正式保留。

支持的元素宽度可能随 LMUL 变化。

注意 当前的标准向量扩展集不会随 LMUL 改变支持的元素宽度。仅当使用 LMUL 组合来自多个向量寄存器的位时,某些未来的扩展才可能支持更大的 SEW。在这种情况下,依赖于大型 SEW 的软件应尝试使用最大的 LMUL,从而使用最少的向量寄存器组,以增加代码将在其上运行的实现数量。设置 vtype 后要检查 vtype 中的 vill 位,看是否支持配置,如果不支持则提供备用代码路径。或者,配置文件可以要求每个 LMUL 设置的最小 SEW。

3.4.2. Vector Register Grouping (vlmul[2:0])

多个向量寄存器可以组合在一起,这样一条向量指令就可以对多个向量寄存器进行操作。

术语 vector register group在本文中用于指代用作向量指令的单个操作数的一个或多个向量寄存器。向量寄存器组可用于为更长的应用程序向量提供更高的执行效率,但包含它们的主要原因是允许以与单宽度元素相同的向量长度对双宽度或更大的元素进行操作。向量长度乘数 LMUL 大于 1 时,表示组合成向量寄存器组的向量寄存器的默认数量。实现必须支持 1、2、4 和 8 的 LMUL 整数值。

注意 向量体系结构包括采用具有不同元素宽度但元素数量相同的多个源和目标向量操作数的指令。每个向量操作数的有效 LMUL (EMUL) 取决于保存元素所需的寄存器数量。例如,对于扩展加法运算,例如将 32 位值相加以产生 64 位结果,双宽度结果需要两倍于单宽度输入的 LMUL。

LMUL 也可以是小数值,减少单个向量寄存器中使用的位数。小数 LMUL 用于在对混合宽度值进行操作时增加有效可用向量寄存器组的数量。

注意 只有整数 LMUL 值,在一系列大小上运行的循环必须为最窄的数据类型分配至少一个完整的向量寄存器 (LMUL=1),然后会消耗多个向量寄存器 (LMUL>1) 以形成一个每个更宽的向量操作数的向量寄存器组。这会限制可用向量寄存器组的数量。使用小数 LMUL,最宽的值只需要占用一个向量寄存器,而更窄的值可以占用一个向量寄存器的一小部分,即使在处理混合宽度时,也允许将所有 32 个架构向量寄存器名称用于向量循环中的不同值价值观。小数 LMUL 意味着部分向量寄存器未使用,但在某些情况下,相对于较少的较长寄存器驻留向量,具有更多较短的驻留寄存器向量可以提高效率。

实现必须提供分数 LMUL 设置,以允许支持的最窄类型占据向量寄存器的一部分,对应于支持的最窄类型的宽度与支持的最大类型宽度的比率。一般来说,要求是支持 LMUL ≥ SEWMIN/ELEN,其中 SEWMIN 是支持的最窄 SEW 值,ELEN 是支持的最宽 SEW 值。在标准扩展中,SEWMIN=8。对于 ELEN=32 的标准向量扩展,必须支持 1/2 和 1/4 的小数 LMUL。对于 ELEN=64 的标准向量扩展,必须支持 1/2、1/4 和 1/8 的小数 LMUL。

注意当 LMUL < SEWMIN/ELEN 时,不能保证实现在小数向量寄存器中有足够的位来存储至少一个元素,因为 VLEN=ELEN 是一个有效的实现选择。例如,在 VLEN=ELEN=32 和 SEWMIN=8 的情况下,1/8 的 LMUL 将仅在向量寄存器中提供四位存储。

对于给定的支持小数 LMUL 设置,实现必须支持 SEWMIN 和 LMUL * ELEN 之间的 SEW 设置,包括端点。

尝试设置不受支持的 SEW 和 LMUL 配置会在 vtype 中设置 vill 位。

使用 LMUL < SEWMIN/ELEN 的 vtype 编码是保留的,但如果实现不支持这些配置,则可以设置 vill。

注意 在这种情况下要求所有实现设置 vill 将禁止将来在扩展中使用这种情况,因此允许将来定义 LMUL

注意 如果 vsetvli 指令尝试写入 LMUL < SEWMIN/ELEN,建议汇编器提供警告(而不是错误)。

LMUL 由 vtype 中带符号的 vlmul 字段设置(即 LMUL = 2^vlmul[2:0])。

推导出的值 VLMAX = LMUL*VLEN/SEW 表示在给定当前 SEW 和 LMUL 设置的情况下,可以使用单个向量指令操作的最大元素数,如下表所示。

当 LMUL=2 时,向量寄存器组包含向量寄存器 v n 和向量寄存器 v n+1,提供两倍的向量长度(以位为单位)。指定带有奇数向量寄存器的 LMUL=2 向量寄存器组的指令被保留。

当LMUL=4时,向量寄存器组包含四个向量寄存器,并且使用不是4的倍数的向量寄存器号指定LMUL=4向量寄存器组的指令被保留。

当LMUL=8时,向量寄存器组包含8个向量寄存器,并且使用不是8的倍数的寄存器号指定LMUL=8向量寄存器组的指令被保留。

屏蔽寄存器始终包含在单个向量寄存器中,与 LMUL 无关。

3.4.3. Vector Tail Agnostic and Vector Mask Agnostic vta and vma(向量尾不可知和向量掩码不可知 vta 和 vma)

这两个位分别在向量指令执行期间修改目标尾部元素和目标非活动屏蔽元素的行为。尾集和非活动集包含在矢量操作期间未接收新结果的元素位置,如部分 Prestart、Active、Inactive、Body 和 Tail Element Definitions 中所定义。

所有系统都必须支持所有四个选项:

无论 vta 的设置如何,掩码目标尾部元素始终被视为与尾部不可知(Tail Agnostic)。

当一个集合被标记为未受干扰时,向量寄存器组中相应的目标元素集合将保留它们先前保存的值。

当一个集合被标记为不可知时,任何向量目标操作数中的相应目标元素集合可以保留它们之前持有的值,或者被 1 覆盖。在单个向量指令中,每个目标元素可以不受干扰或被 1 覆盖,以任何组合,并且当使用相同的输入执行指令时,不受干扰或被 1 覆盖的模式不需要是确定性的。

注意 添加了不可知策略以适应具有向量寄存器重命名的机器。使用不受干扰的策略,必须从旧的物理目标向量寄存器中读取所有元素,然后将其复制到新的物理目标向量寄存器中。当后续计算不需要这些非活动值或尾值时,这会导致效率低下。

注意 选择全 1 而不是全 0 的值作为覆盖值,以阻止软件开发人员依赖写入的值。

注意 一个简单的按顺序实现可以忽略这些设置并使用不受干扰的策略简单地执行所有向量指令。仍然必须在 vtype 中提供 vta 和 vma 状态位以实现兼容性并支持线程迁移。

注意 乱序实现可以选择使用 tail-agnostic + mask-undisturded 来实现 tail-agnostic + mask-agnostic 以降低实现复杂性。

注意 不可知结果策略的定义是宽松的,以适应在小型有序核心(可能使不可知区域不受干扰)上的 harts 和具有寄存器重命名的较大无序核心(可能覆盖不可知元素与 1)。由于可能需要在中间重新启动,我们允许在单个向量指令中任意混合不可知策略。这允许混合策略也允许实现可能改变向量寄存器的不同颗粒的策略,例如,在一个主动操作的颗粒中使用不受干扰,但对于尾部的颗粒重命名为全 1。

此外,除了掩码加载指令外,掩码结果尾部的任何元素也可以写入掩码生成操作使用 vl=VLMAX 计算的值。此外,对于掩码逻辑指令和 vmsbf.m、vmsif.m、vmsof.m 掩码操作指令,结果尾部的任何元素都可以写入掩码生成操作使用 vl=VLEN 计算的值、SEW=8 和 LMUL=8(即,可以覆盖屏蔽寄存器的所有位)。

**注意 **掩码尾部总是被视为不可知的,以降低管理掩码数据的复杂性,可以按位粒度写入。似乎很少有软件需要支持屏蔽寄存器值的尾部不受干扰。允许掩码生成指令写回指令的结果避免了逻辑屏蔽尾部的需要,除非掩码加载不能将内存值写入目标掩码尾部,因为这意味着访问内存超出了软件意图。

汇编语法向 vsetvli 指令添加了两个强制标志:

注意 在 v0.9 之前,当未在 vsetvli 上指定这些标志时,它们默认为掩码未受干扰/尾部未受干扰。但是,不推荐使用不带这些标志的 vsetvli,并且现在必须指定标志设置。默认值可能应该是 tail-agnostic/mask-agnostic,所以软件必须指定它何时关心非参与元素,但考虑到在引入这些标志之前指令的历史意义,决定总是需要它们在未来的汇编代码中。

3.4.4. Vector Type Illegal vill(矢量类型非法vill)

vill 位用于对先前的 vset{i}vl{i} 指令尝试将不受支持的值写入 vtype 进行编码。

注意 vill 位保存在 CSR 的 XLEN-1 位中,以支持通过符号位上的分支检查非法值。

在确定实现是否支持该值时,必须考虑 vtype 参数的所有位。

注意必须检查所有位以确保新代码在 vtype 陷阱中假设不受支持的矢量特征,而不是在旧实现上错误地执行。

设置了 vill 位的 vtype 值是不受支持的值。

如果设置了 vill 位,则任何执行依赖于 vtype 的向量指令的尝试都将引发非法指令异常。

注意 vset{i}vl{i} 和整体寄存器加载、存储和移动不依赖于 vtype。

当 vill 位设置时,vtype 中的其他 XLEN-1 位应为零。

3.5. Vector Length Register vl

XLEN 位范围的只读 vl CSR 只能由 vset{i}vl{i} 指令和 fault-only-first 向量加载指令变体更新。

vl 寄存器保存一个无符号整数,指定要使用向量指令的结果更新的元素的数量,如在预启动、活动、非活动、主体和尾部元素定义部分中进一步详述。

注意 vl 中实现的位数取决于实现的最小支持类型的最大向量长度。 VLEN=32 并支持 SEW=8 的最小向量实现将需要 v1 中的至少六个位来保存值 0-32(VLEN=32,LMUL=8 和 SEW=8,产生 VLMAX=32)。

3.6. Vector Byte Length vlenb

XLEN 位宽只读 CSR vlenb 保存值 VLEN/8,即向量寄存器长度(以字节为单位)。

注意 vlenb 中的值是任何实现中的设计时间常数

注意 如果没有此 CSR,则需要几条指令来计算 VLEN(以字节为单位),并且代码必须扰乱当前的 vl 和 vtype 设置,这需要保存和恢复它们。

3.7. Vector Start Index CSR vstart

vstart 读写 CSR 指定要由向量指令执行的第一个元素的索引,如 Prestart、Active、Inactive、Body 和 Tail Element Definitions 部分所述。

通常,vstart 仅由硬件在向量指令的陷阱上写入,vstart 值表示发生陷阱的元素(同步异常或异步中断),并且在可恢复陷阱后应恢复执行被处理。

所有向量指令都定义为以 vstart CSR 中给定的元素编号开始执行,使目标向量中的早期元素不受干扰,并在执行结束时将 vstart CSR 重置为零。

注意 所有向量指令,包括 vset{i}vl{i},将 vstart CSR 重置为零。

vstart 不会被引发非法指令异常的向量指令修改。

vstart CSR 被定义为只有足够的可写位来保存最大元素索引(比最大 VLMAX 小一)。

注意 最大向量长度是通过最大的 LMUL 设置 (8) 和最小的 SEW 设置 (8) 获得的,因此 VLMAX_max = 8*VLEN/8 = VLEN。例如,对于 VLEN=256,vstart 将有 8 位来表示从 0 到 255 的索引。

保留使用大于当前 SEW 设置的最大元素索引的 vstart 值。

注意 如果 vstart 超出范围,建议执行陷阱。不需要陷阱,因为将来可能使用高 vstart 位来存储不精确的陷阱信息。

vstart CSR 可由非特权代码写入,但非零 vstart 值可能会导致向量指令在某些实现上运行得非常慢,因此应用程序程序员不应使用 vstart。一些向量指令不能使用非零 vstart 值执行,并且会引发如下定义的非法指令异常。

注意 使非特权代码可见 vstart 支持用户级线程库。

当尝试执行具有 vstart 值的向量指令时,允许实现引发非法指令异常,而在执行具有相同 vtype 设置的相同指令时,实现永远不会产生这种异常。

注意 例如,某些实现在执行向量算术指令期间绝不会产生中断,而是等到指令完成后才产生中断。当 vstart 非零时尝试执行向量算术指令时,允许此类实现引发非法指令异常。

注意 在具有不同微架构的两个 hart 之间迁移软件线程时,新的 hart 微架构可能不支持 vstart 值。然后,接收 hart 上的运行时可能必须模拟指令执行到下一个支持的 vstart 元素位置。或者,可以将迁移事件限制为仅在相互支持的 vstart 位置发生。

3.8.矢量定点舍入模式寄存器 vxrm( Vector Fixed-Point Rounding Mode Register vxrm)

向量定点舍入模式寄存器在最低有效位 (vxrm[1:0]) 中保存一个两位读写舍入模式字段。高位 vxrm[XLEN-1:2] 应写为零。

矢量定点舍入模式被赋予一个单独的 CSR 地址以允许独立访问,但也反映为 vcsr 中的一个字段。

注意 可以在使用单个 csrwi 指令保存原始舍入模式的同时设置新的舍入模式。

定点舍入算法指定如下。假设预舍入结果是 v,并且要舍入该结果的 d 位。然后舍入结果为 (v >> d) + r,其中 r 取决于下表中指定的舍入模式。

舍入函数:
roundoff_unsigned(v, d) = (unsigned(v) >> d) + r
roundoff_signed(v, d) = (signed(v) >> d) + r 用于在下面的指令描述中表示此操作。

3.9. (矢量定点饱和标志 vxsat)Vector Fixed-Point Saturation Flag vxsat

vxsat CSR 有一个读写最低有效位 (vxsat[0]),它指示定点指令是否必须使输出值饱和以适应目标格式。位 vxsat[XLEN-1:1] 应写为零。

vxsat 是位在 vcsr 中镜像。

3.10、矢量控制和状态寄存器 vcsr(Vector Control and Status Register vcsr)

vxrm 和 vxsat 单独的 CSR 也可以通过矢量控制和状态 CSR 中的字段 vcsr 访问。

3.11. (复位时向量扩展的状态)State of Vector Extension at Reset

向量扩展在复位时必须具有一致的状态。特别是,vtype 和 vl 必须具有可以通过单个 vsetvl 指令读取然后恢复的值。

注意 建议在复位时设置 vtype.vill,vtype 中的剩余位为零,vl 设置为零。

vstart、vxrm、vxsat CSR 在复位时可以具有任意值。

注意 向量单元的大多数使用都需要一个初始的 vset{i}vl{i},它将重置 vstart。 vxrm 和 vxsat 字段应在使用前在软件中显式重置。

向量寄存器在复位时可以具有任意值。

4、(向量元素到向量寄存器状态的映射)Mapping of Vector Elements to Vector Register State

下图说明了如何根据当前 SEW 和 LMUL 设置以及实现 VLEN 将不同宽度元素打包到向量寄存器的字节中。元素被打包到每个向量寄存器中,最低有效字节位于最低编号位中。

选择该映射是为了为软件提供最简单和最便携的模型,但在某些操作上可能会为更宽的矢量数据路径产生大量布线成本。矢量指令集专门设计用于支持在内部为不同 SEW 重新排列矢量数据以降低数据路径布线成本,同时在外部保留简单软件模型的实现。

注意 例如,微体系结构可以跟踪写入向量寄存器的 EEW,然后如果使用不同的 EEW 访问寄存器,则插入额外的加扰操作以重新排列数据。

4.1. Mapping for LMUL = 1

当 LMUL=1 时,元素按从向量寄存器的最低有效位到最高有效位的顺序简单地打包。

注意 为了提高可读性,向量寄存器布局是按照字节地址从右到左的顺序绘制的。元素中的位以小端格式编号,从右到左增加位索引对应于增加的幅度。

4.2. Mapping for LMUL < 1

当 LMUL < 1 时,仅使用向量寄存器中的第一个 LMUL*VLEN/SEW 元素。向量寄存器中的剩余空间被视为尾部的一部分,因此必须遵守 vta 设置。

4.3. Mapping for LMUL > 1

当向量寄存器被分组时,向量寄存器组的元素按元素顺序连续打包,从编号最小的向量寄存器开始,一旦每个向量寄存器被填充,就移动到组中编号第二高的向量寄存器。

4.4.跨混合宽度操作的映射( Mapping across Mixed-Width Operations)

矢量 ISA 旨在支持混合宽度操作,而无需额外的显式重排指令。对具有不同精度值的多个向量进行操作时,推荐的软件策略是动态修改 vtype 以保持 SEW/LMUL 不变(因此 VLMAX 不变)。

以下示例显示了 VLEN=128b 实现中的四种不同的打包元素宽度(8b、16b、32b、64b)。向量寄存器分组因子 (LMUL) 增加了相对元素大小,以便每个组可以容纳相同数量的向量元素(在本例中为 VLMAX=8)以简化剥离代码。

下表显示了具有混合宽度操作的循环的每个可能的恒定 SEW/LMUL 操作点。每列代表一个恒定的 SEW/LMUL 工作点。表中的条目是 LMUL 值,它们为该行的数据宽度产生该列的 SEW/LMUL 值。在每一列中,一个数据宽度的 LMUL 设置表明它可以与同一列中也具有 LMUL 设置的其他数据宽度对齐,这样所有数据宽度都具有相同的 VLMAX。

在需要较少向量寄存器组的情况下,更大的 LMUL 设置也可用于简单地增加向量长度以减少指令获取和调度开销。

4.5. (掩码寄存器布局)Mask Register Layout

一个向量掩码只占用一个向量寄存器,与 SEW 和 LMUL 无关。

在掩码向量寄存器中为每个元素分配一个掩码位。元素 i 的屏蔽位位于屏蔽寄存器的位 i 中,与 SEW 或 LMUL 无关。

5、(矢量指令格式)Vector Instruction Formats

矢量扩展中的指令适用于两个现有的主要操作码(LOAD-FP 和 STORE-FP)和一个新的主要操作码(OP-V)。

矢量加载和存储在标量浮点加载和存储主要操作码 (LOAD-FP/STORE-FP) 中进行编码。

向量加载和存储编码将标准标量浮点加载/存储 12 位立即数字段的一部分重新用于提供进一步的向量指令编码,位 25 保存标准向量掩码位(请参阅掩码编码)。

LOAD-FP 主操作码下向量加载指令的格式

STORE-FP主要操作码下向量存储指令的格式

OP-V 主要操作码下向量算术指令的格式

OP-V主要操作码下的向量配置指令格式

向量指令可以具有标量或向量源操作数并产生标量或向量结果,并且大多数向量指令可以在掩码下无条件或有条件地执行。

向量在向量寄存器元素和内存之间加载和存储移动位模式。矢量算术指令对保存在矢量寄存器元素中的值进行操作。

5.1、标量操作数(Scalar Operands)

标量操作数可以是立即数,也可以取自 x 寄存器、f 寄存器或向量寄存器 0。标量结果写入 x 或 f 寄存器或向量寄存器 0。无论当前的 LMUL 设置如何,任何向量寄存器都可用于保存标量。

注意 Zfinx(“F in X”)是一个提议的新 ISA 扩展,其中浮点指令从整数寄存器文件中获取参数。向量扩展也与 Zfinx 兼容,其中 Zfinx 向量扩展具有向量标量浮点指令,它们从 x 寄存器获取标量参数。

注意 我们考虑过但没有追求将 f 寄存器覆盖在 v 寄存器上。采用的方法降低了向量寄存器压力,避免了与标准调用约定的交互,简化了高性能标量浮点设计,并提供了与 Zfinx ISA 选项的兼容性。在某些实现中,用 v 覆盖 f 将提供降低状态位数量的优势,但会使高性能设计复杂化,并且会妨碍与建议的 Zfinx ISA 选项的兼容性。

5.2.向量操作数(Vector Operands)

每个向量操作数都有一个有效元素宽度 (effective element width:EEW) 和一个有效 LMUL (EMUL),用于确定向量寄存器组中所有元素的大小和位置。默认情况下,对于大多数指令的大多数操作数,EEW=SEW 和 EMUL=LMUL。

一些向量指令的源向量操作数和目标向量操作数具有相同的元素数量但宽度不同,因此 EEW 和 EMUL 分别不同于 SEW 和 LMUL,但 EEW/EMUL = SEW/LMUL。例如,大多数扩展算术指令具有 EEW=SEW 和 EMUL=LMUL 的源组,但具有 EEW=2SEW 和 EMUL=2LMUL 的目标组。窄化指令的源操作数具有 EEW=2SEW 和 EMUL=2LMUL,但目标操作数为 EEW=SEW 和 EMUL=LMUL。

向量操作数或结果可能会占用一个或多个向量寄存器,具体取决于 EMUL,但始终使用组中编号最小的向量寄存器指定。使用编号最小的向量寄存器以外的其他向量寄存器来指定向量寄存器组是一种保留编码。

仅当满足以下条件之一时,目标向量寄存器组才能与源向量寄存器组重叠:

1、目标 EEW 等于源 EEW。

2、目标 EEW 小于源 EEW,并且重叠在源寄存器组的最低编号部分(例如,当 LMUL=1 时,vnsrl.wi v0, v0, 3 是合法的,但 v1 的目标不是)。

3、目标 EEW 大于源 EEW,源 EMUL 至少为 1,并且重叠在目标寄存器组的最高编号部分(例如,当 LMUL=8 时,vzext.vf4 v0、v6 是合法的,但是v0、v2 或 v4 的来源不是)。

为了确定寄存器组重叠约束,掩码元素具有 EEW=1。

注意 重叠约束旨在支持机器中的可恢复异常,而无需重命名寄存器。

保留任何违反重叠约束的指令编码。

一条指令使用的最大向量寄存器组不能超过 8 个向量寄存器(即 EMUL≤8),如果一个向量指令在一个组中需要超过 8 个向量寄存器,则保留指令编码。例如,当 LMUL=8 时产生扩展向量寄存器组结果的扩展操作被保留,因为这意味着结果 EMUL=16。

加宽的标量值,例如加宽归约运算的输入和输出,保存在向量寄存器的第一个元素中,并且 EMUL=1。

5.3. Vector Masking(矢量掩蔽)

许多向量指令都支持屏蔽。被屏蔽(非活动)的元素操作永远不会产生异常。根据 vtype 中 vma 位的设置(Section Vector Tail Agnostic 和 Vector Mask Agnostic vta 和 vma),对应于被屏蔽元素的目标向量寄存器元素使用 maskundisturbed 或 mask-agnostic 策略进行处理。

用于控制屏蔽向量指令执行的屏蔽值始终由向量寄存器 v0 提供。

注意 未来的向量扩展可能会为完整的掩码寄存器说明符提供更长的指令编码空间。

屏蔽向量指令的目标向量寄存器组不能与源屏蔽寄存器 (v0) 重叠,除非目标向量寄存器正在写入屏蔽值(例如,比较)或归约的标量结果。这些指令编码是保留的。

注意 此约束支持使用非零 vstart 值重新启动。

其他向量寄存器可用于保存工作掩码值,并提供掩码向量逻辑运算来执行谓词计算。

正如章节 Vector Tail Agnostic 和 Vector Mask Agnostic vta 和 vma 中所指定的,无论 vta 的设置如何,掩码目标值始终被视为尾部不可知。

5.3.1. Mask Encoding(掩码编码)

在可用的情况下,掩码在指令 (inst[25]) 中的单个位 vm 字段中进行编码。

向量掩码在汇编代码中表示为另一个向量操作数,.t 表示当 v0.mask[i] 为 1 时发生操作(t 表示“真”)。如果未指定屏蔽操作数,则假定未屏蔽向量执行 (vm=1)。

注意 即使当前的向量扩展只支持一个向量掩码寄存器 v0 并且只支持真正的谓词形式,汇编语法将其完整地写出来以与可能添加掩码寄存器说明符并支持真掩码和补码掩码的未来扩展兼容价值观。掩码操作数上的 .t 后缀也有助于在视觉上对掩码的使用进行编码。

注意 .mask 后缀不是程序集语法的一部分。我们只在掩码向量下标的上下文中附加它,例如 v0.mask[i]。

5.4. Prestart、Active、Inactive、Body 和 Tail 元素定义

在向量指令执行期间操作的目标元素索引可以分为三个不相交的子集。

1、预启动元素(The prestart elements )是那些元素索引小于 vstart 寄存器中初始值的元素。预启动元素不会引发异常并且不会更新目标向量寄存器。

2、主体元素(The body elements )是那些元素索引大于或等于 vstart 寄存器中的初始值,并且小于 vl 中当前向量长度设置的元素。主体可以分为两个不相交的子集:

(1)(The active elements)向量指令执行期间的活动元素是主体内的元素,并且在该元素位置启用了当前掩码。活动元素可以引发异常并更新目标向量寄存器组。

(2)(The inactive elements )非活动元素是主体内的元素,但当前掩码在该元素位置被禁用。非活动元素不会引发异常并且不会更新任何目标向量寄存器组,除非指定了掩码不可知 (vtype.vma=1),在这种情况下,非活动元素可能会被 1 覆盖。

3、(The tail elements )向量指令执行期间的尾元素(The tail elements )是超过 vl 中指定的当前向量长度设置的元素。尾元素不会引发异常,并且不会更新任何目标向量寄存器组,除非指定了尾不可知 (vtype.vta=1),在这种情况下尾元素可能被 1 覆盖,或者被掩码生产指令的情况,但掩码负载除外。当 LMUL < 1 时,尾部包括超过 VLMAX 且保存在同一向量寄存器中的元素。

当 vstart ≥ vl 时,没有主体元素,也没有任何目标向量寄存器组中的元素被更新,包括没有尾元素被更新为不可知的值。

注意 因此,当 vl=0 时,无论 vstart 为何,都不会更新目标向量寄存器组中的任何元素,包括不可知元素。

即使 vstart ≥ vl,包括 vl=0 时,写入 x 寄存器或 f 寄存器的指令也会这样做。

注意 某些指令(例如 vslidedown 和 vrgather)可能会读取源向量寄存器组中超过 vl 甚至 VLMAX 的索引。一般策略是在源向量寄存器组中的索引大于 VLMAX 时返回值 0。

6、配置-设置说明 (vsetvli/vsetivli/vsetvl)

处理大量元素的常用方法之一是“剥离(stripmining)”,其中循环的每次迭代都处理一定数量的元素,并且迭代继续进行,直到处理完所有元素。 RISC-V 矢量规范为这种方法提供了直接、可移植的支持。应用程序将要处理的元素总数(应用程序向量长度或 AVL)指定为 vl 的候选值,并且硬件通过通用寄存器以硬件将在每次迭代中处理的(通常更小的)元素数进行响应(存储在 vl 中),基于微架构实现和 vtype 设置。一个简单的循环结构,显示在 SEW 的剥离和更改示例中,描述了代码跟踪剩余元素数量和硬件处理的每次迭代数量的容易程度。

提供了一组指令以允许快速配置 vl 和 vtype 中的值以匹配应用程序需求。 vset{i}vl{i} 指令根据参数设置 vtype 和 vl CSR,并将 vl 的新值写入 rd。

6.1、vtype 编码

注意 此图显示了 RV32 系统的布局,而通常 vill 应位于 XLEN-1 位。

新的 vtype 设置编码在 vsetvli 和 vsetivli 的立即数字段中,以及 vsetvl 的 rs2 寄存器中。

vsetvl 变体的操作与 vsetvli 类似,不同之处在于它从 rs2 获取 vtype 值并可用于上下文恢复。

如果实现不支持 vtype 设置,则在 vtype 中设置 vill 位,将 vtype 中的其余位设置为零,并且 vl 寄存器也设置为零。

注意 早期的草案在将 vtype 设置为非法值时需要一个陷阱。但是,这会在 CSR 写入 ISA 时添加第一个数据相关陷阱。当非法值写入 vtype 而不是设置 vill 时,实现可以选择捕获,以允许仿真支持新配置以实现前向兼容性。当前方案通过检查 vill 对于给定设置是否清晰,支持对支持的向量单元配置的轻量级运行时询问。

6.2. AVL encoding

新的向量长度设置基于 AVL,对于 vsetvli 和 vsetvl,它在 rs1 和 rd 字段中编码如下:

当 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,但不写入目标寄存器。这种形式只能在 VLMAX 和因此 vl 实际上没有被新的 SEW/LMUL 比率改变时使用。保留使用将导致 VLMAX 变化的新 SEW/LMUL 比率的指令。在这种情况下,实现可能会设置 vill。

注意 指令的最后一种形式允许在保持当前 vl 的同时更改 vtype 寄存器,前提是不降低 VLMAX。选择此设计是为了确保 vl 始终为当前 vtype 设置保持合法值。当前的 vl 值可以从 vl CSR 中读取。如果新的 SEW/LMUL 比率导致 VLMAX 缩小,则 vl 值可以通过该指令减小,因此这种情况已被保留,因为不清楚这是一个普遍有用的操作,否则实现可以假设 vl 没有被改变这个指令来优化他们的微架构。

对于 vsetivli 指令,AVL 被编码为 rs1 字段中的 5 位零扩展立即数 (0-31)。

注意 vsetivli 的 AVL 编码与常规 CSR 立即值相同。

注意 当向量的维度很小并且已知可以放入向量寄存器时,vsetivli 指令提供更紧凑的代码,在这种情况下没有剥离开销。

6.3.设置 vl 的约束

vset{i}vl{i} 指令首先根据它们的 vtype 参数设置 VLMAX,然后设置 vl 遵守以下约束:

  1. 如果 AVL ≤ VLMAX,则 vl = AVL

  2. ceil(AVL / 2) ≤ vl ≤ VLMAX 如果 AVL < (2 * VLMAX)

  3. 如果 AVL ≥ (2 * VLMAX),则 vl = VLMAX

  4. 对相同输入 AVL 和 VLMAX 值的任何给定实现具有确定性

  5. 这些特定属性遵循先前的规则:

​ a. 如果 AVL = 0,则 vl = 0

​ b. vl > 0 如果 AVL > 0

​ c. vl ≤ VLMAX

​ d. vl ≤ AVL

​ e. 从 vl 读取的值用作 vset{i}vl{i} 的 AVL 参数时会在 vl 中产生相同的值,前提是结果 VLMAX 等于读取 vl 时的 VLMAX 值。

注意 vl 设置规则设计得足够严格,以在 AVL ≤ VLMAX 的寄存器溢出和上下文交换中保持 vl 行为,但又足够灵活,以使实现能够提高 AVL > VLMAX 的向量通道利用率。

例如:

这允许实现为 VLMAX < AVL < 2VLMAX 设置 vl = ceil(AVL / 2),以便在 stripmine 循环的最后两次迭代中均匀分配工作。要求 2 确保归约循环的第一次 stripmine 迭代使用所有迭代中最大的向量长度,即使在 AVL < 2VLMAX 的情况下也是如此。这允许软件避免需要显式计算在剥离循环期间观察到的向量长度的运行最大值。要求 2 还允许实现将 vl 设置为 VLMAX,因为 VLMAX < AVL < 2VLMAX

6.4. Example of stripmining and changes to SEW

SEW 和 LMUL 设置可以动态更改,以在单个循环中提供混合宽度操作的高吞吐量。

7、Vector Loads and Stores

Vector 在向量寄存器和内存之间加载和存储移动值。向量加载和存储被屏蔽,并且不会在非活动元素上引发异常。**屏蔽向量加载不会更新目标向量寄存器组中的非活动元素,除非指定了屏蔽不可知 (vtype.vma=1)。**掩码向量存储仅更新活动内存元素。所有向量加载和存储都可以生成并接受非零的 vstart 值。

7.1. Vector Load/Store Instruction Encoding

Vector loads and stores 在标量浮点加载和存储主要操作码 (LOAD-FP/STORE-FP) 中进行编码。向量加载和存储编码将标准标量浮点加载/存储 12 位立即数字段的一部分重新用于提供进一步的向量指令编码,位 25 保存标准向量掩码位(请参阅掩码编码)。

LOAD-FP 主操作码下向量加载指令的格式

STORE-FP主要操作码下向量存储指令的格式

向量内存单元步长和常量步长操作直接对指令中要静态传输的数据的 EEW 进行编码,以减少在混合宽度例程中访问内存时 vtype 更改的次数。索引操作使用指令中的显式 EEW 编码来设置所用索引的大小,并使用 SEW/LMUL 来指定数据宽度。

7.2.向量加载/存储寻址模式(Vector Load/Store Addressing Modes)

矢量扩展支持单位步长、跨步和索引(分散/聚集)寻址模式(unit-stride, strided, and indexed (scatter/gather) addressing modes)。 Vector load/store基址寄存器和步幅取自 GPR x 寄存器。所有向量访问的基本有效地址(The base effective address)由 rs1 中命名的 x 寄存器的内容给出。

(unit-stride)向量单位步长操作访问从基有效地址开始连续存储在内存中的元素。

(strided)向量常量跨步操作访问位于基有效地址的第一个内存元素,然后以地址增量访问后续元素,地址增量由 rs2 指定的 x 寄存器中包含的字节偏移量给出。

(indexed)向量索引操作将vs2指定的向量偏移操作数的每个元素的内容添加到基有效地址,以给出每个元素的有效地址。数据向量寄存器组有EEW=SEW,EMUL=LMUL,而偏移向量寄存器组在指令中有EEW编码,EMUL=(EEW/SEW)*LMUL。

向量偏移操作数被视为字节地址偏移的向量。

注意索引操作也可用于访问对象向量中的字段,其中 vs2 向量保存指向对象基址的指针,标量 x 寄存器保存每个对象中成员字段的偏移量。支持这种情况是为什么没有定义索引操作以通过数据 EEW 缩放元素索引。

如果向量偏移元素比 XLEN 窄,则在添加到基本有效地址之前,它们会被零扩展到 XLEN。如果向量偏移元素比 XLEN 宽,则在地址计算中使用最低有效 XLEN 位。如果偏移元素不支持 EEW,则实现必须引发非法指令异常。

注意 配置文件可能会对小于 ELEN 的最大支持索引 EEW 设置上限(例如,仅达到 XLEN)。

矢量寻址模式使用 2 位 mop[1:0] 字段进行编码。

向量单位跨度和恒定跨度( unit-stride and constant-stride)内存访问不保证各个元素访问之间的顺序。

向量索引的加载和存储内存操作有两种形式,有序和无序。索引排序变体保留内存访问的元素排序。

对于无序指令(mop[1:0]!=11),不保证元素访问顺序。如果访问的是强排序的 IO 区域,则可以按任何顺序启动元素访问。

注意 要提供对强有序 IO 区域的有序向量访问,应使用有序索引指令。

对于具有精确向量陷阱的实现,索引无序存储的异常也必须是精确的。

额外的单位跨度向量寻址模式(Additional unit-stride vector addressing modes)分别使用单位跨度加载和存储指令编码中的 5 位 lumop 和 sumop 字段进行编码。

nf[2:0] 字段编码每个段中的字段数。对于常规向量加载和存储,nf=0,表示单个值在向量寄存器组和每个元素位置的内存之间移动。 nf 字段中的较大值用于访问段内的多个连续字段,如下文部分向量加载/存储段指令中所述。

nf[2:0] 字段还编码要为整个向量寄存器加载/存储指令传输的整个向量寄存器的数量。

7.3. Vector Load/Store Width Encoding

Vector loads and stores 在指令中直接编码了 EEW。相应的 EMUL 计算为 EMUL = (EEW/SEW)*LMUL。如果 EMUL 超出范围(EMUL>8 或 EMUL<1/8),则保留指令编码。向量寄存器组必须具有所选 EMUL 的合法寄存器说明符,否则保留指令编码。

Vector unit-stride and constant-stride 使用指令中编码的 EEW/EMUL 作为数据值,而向量索引加载和存储使用指令中编码的 EEW/EMUL 作为索引值,使用 vtype 中编码的 SEW/LMUL数据值。

矢量加载和存储使用标准标量浮点加载和存储未声明的宽度值进行编码。

实现必须提供与所有支持的 SEW 设置相对应的 EEW 向量加载和存储。不支持的 EEW 宽度的向量加载/存储编码必须引发非法指令异常。

Mem bits 是内存中访问的每个元素的大小。

数据寄存器位是寄存器中访问的每个数据元素的大小。

索引位是寄存器中访问的每个索引的大小。

设置后的 mew 位 (inst[28]) 预计将用于对 128 位及以上的扩展内存大小进行编码,但这些编码目前是保留的。

7.4.向量单位步长指令(Vector Unit-Stride Instructions)

提供了额外的单位步长掩码加载和存储指令以将掩码值传输到内存或从内存中传出。这些操作类似于未屏蔽字节加载或存储( unmasked byte loads or stores )(EEW=8),除了有效向量长度为 evl=ceil(vl/8)(即 EMUL=1),并且目标寄存器始终使用尾部不可知策略写入.

vlm.v 和 vsm.v 使用与 vle8.v 和 vse8.v 相同的 width[2:0]=0 编码进行编码,但区别在于不同的 lumop 和 sumop 编码。由于 vlm.v 和 vsm.v 作为字节加载和存储操作,因此对于这些指令,vstart 以字节为单位。

注意 以前的汇编程序助记符 vle1.v 和 vse1.v 令人困惑,因为这些指令与其他元素加载/存储指令的长度处理方式不同。为了避免软件流失,这些旧的程序集助记符被保留为别名。

注意 提供掩码加载和存储的主要动机是支持在内部重新排列数据以减少跨数据路径布线的机器。然而,这些指令还提供了一种方便的机制来使用内存中的压缩位向量作为掩码值,并且还通过减少更改 vl 的需要来降低掩码溢出/填充的成本。

7.5。矢量跨步指令(Vector Strided Instructions)

支持负步幅零步幅

跨步指令中的元素访问相对于彼此是无序的。

当 rs2=x0 时,允许但不要求实现比活动元素的数量执行更少的内存操作,并且可以在同一静态指令的不同动态执行中执行不同数量的内存操作。

注意 如果意图要求执行所有内存访问,编译器必须注意,当立即跨度为 0 时,不要对 rs2 使用 x0 形式。

当 rs2!=x0 且 x[rs2]=0 的值时,实现必须为每个活动元素执行一次内存访问(但这些访问不会被排序)。

注意 与其他体系结构要求一样,实现必须看起来执行每个内存访问。微架构可以自由优化其他代理无法观察到的访问,例如,在服从 RVWMO 的幂等内存区域中。

对于非幂等内存区域,根据定义,每个访问都可以被设备观察到,因此优化是不可能的。

注意 当需要对同一内存地址重复有序向量访问时,可以使用有序索引操作。

7.6.向量索引指令(Vector Indexed Instructions)

注意索引加载和存储的汇编语法使用 eix 而不是 ex 来指示静态编码的 EEW 是索引而不是数据。

注意索引操作助记符有一个“U”或“O”来区分无序和有序,而其他向量寻址模式没有字符。虽然这可能不太一致,但这种方法最大限度地减少了对现有软件的破坏,因为 VSXEI 以前的意思是“有序”——并且操作码可以在过渡期间作为别名保留,以帮助减少软件流失。

7.7.单位步幅仅故障首次加载( Unit-stride Fault-Only-First Loads)

unit-stride fault-only-first load 指令用于向量化具有数据相关退出条件的循环(“while”循环)。这些指令作为常规加载执行,只是它们只会采用由元素 0 上的同步异常引起的陷阱。如果元素 0 引发异常,则不修改 vl,并采用陷阱。如果元素 > 0 引发异常,则不采用相应的陷阱,并且向量长度 vl 减少到会引发异常的元素的索引。

加载指令可以覆盖超过报告陷阱的元素索引的活动目标向量寄存器组元素。类似地,fault-only-first 加载指令可以更新活动目标元素,使其超过导致修剪向量长度的元素(但不超过原始向量长度)。这些虚假更新的值不必与内存中寻址存储位置的值相对应。仅当已知由于陷阱或向量长度修整而不会重新启动相应的元素加载操作时,才能访问非幂等内存位置。

注意 首次加载故障存在安全问题,因为它们可用于探测有效的有效地址。 unit-stride 版本只允许探测与已知区域直接相邻的区域,因此在用于非特权代码时减少了安全影响。但是,在 S 模式下运行的代码可以建立任意页面转换,从而允许探测由管理程序提供的随机客户物理地址。由于缺乏编码空间,没有提供 Strided 和 scatter/gather-only-first 指令,但它们也可能代表更大的安全漏洞,即使是非特权软件也可以轻松检查多个随机页面的可访问性,而不会遇到陷阱。本标准未解决仅故障优先指令可能的安全缓解措施。

即使没有引发异常,也允许实现处理少于 vl 的元素并相应地减少 vl,但如果 vstart=0 且 vl>0,则必须处理至少一个元素。

当仅故障优先指令由于中断而发生陷阱时,实现不应减少 vl 而应设置 vstart 值。

注意当仅故障第一指令将在第一个之后触发元素上的调试数据观察点陷阱时,实现不应减少 vl 而是应触发调试陷阱,否则事件可能会丢失。

7.8.向量加载/存储段指令(Vector Load/Store Segment Instructions)

向量加载/存储段指令将内存中的多个连续字段移入和移出连续编号的向量寄存器。

**注意 **名称“段”反映了移动的项目是具有同质元素的子数组。这些操作可用于在内存和寄存器之间转置数组,并且可以通过将结构中的每个字段解包到单独的向量寄存器中来支持对“结构数组”数据类型的操作。

向量指令编码中的三位 nf 字段是一个无符号整数,它包含比每个段的字段数 NFIELDS 少一。

EMUL 设置必须使 EMUL * NFIELDS ≤ 8,否则保留指令编码。

注意乘积 EMUL * NFIELDS 表示将被分段加载或存储指令触及的底层向量寄存器的数量。这个约束使得这个总数不大于架构寄存器文件的 1/4,并且与 EMUL=8 的常规操作相同。

每个字段将保存在连续编号的向量寄存器组中。当 EMUL>1 时,每个字段将占用多个连续编号的向量寄存器中保存的向量寄存器组,并且每个字段的向量寄存器组必须遵循通常的向量寄存器对齐约束(例如,当 EMUL=2 和 NFIELDS=4 时,每个域的向量寄存器组必须从偶数向量寄存器开始,但不必从 8 个向量寄存器号的倍数开始)。

如果段加载或存储访问的向量寄存器编号将增加超过 31,则保留指令编码。

注意此约束是为了帮助实现与未来可能更长的指令编码的前向兼容性,该指令编码具有更多可寻址向量寄存器。

vl 寄存器给出要移动的段数,它等于传送到每个向量寄存器组的元素数。掩蔽也应用于整个段的级别。

对于段加载和存储,用于访问每个段内的字段的各个内存访问相对于彼此是无序的,即使对于有序索引段加载和存储也是如此。

vstart 值以整个段为单位。如果在访问段期间发生陷阱,则在采取陷阱之前是否执行故障段的访问子集是由实现定义的。

7.8.1.向量单位步长段加载和存储( Vector Unit-Stride Segment Loads and Stores)

向量单位跨度加载和存储段指令将打包的连续段移动到多个目标向量寄存器组中。

注意在段包含具有不同大小字段的结构的情况下,软件稍后可以在段加载将数据带入向量寄存器后使用附加指令解压缩单个结构字段。

汇编器前缀 vlseg/vsseg 分别用于单位跨度段的加载和存储。

对于加载( loads),vd 寄存器将保存从段加载的第一个字段。对于存储,读取 vs3 寄存器以提供要存储到每个段的第一个字段。

也有单元步长指令的仅故障优先版本。(There are also fault-only-first versions of the unit-stride instructions.)

对于仅故障的第一个段加载,如果在访问段的过程中检测到异常,则无论元素索引是否为零,是否加载段的子集都是实现定义的。

这些指令可能会在报告陷阱的点或修剪向量长度的点之后覆盖目标向量寄存器组元素。

7.8.2.向量跨步段加载和存储(Vector Strided Segment Loads and Stores)

向量跨步段加载和存储移动连续段,其中每个段由 rs2 GPR 参数中给出的字节跨度偏移量分隔。

注意 支持负步幅和零步幅。

可以以任何顺序访问每个段中的字段,包括字节跨度使得段在内存中重叠的情况。

7.8.3.向量索引段加载和存储(Vector Indexed Segment Loads and Stores)

向量索引段加载和存储移动连续段,其中每个段位于通过将 rs1 字段中的标量基地址添加到向量寄存器 vs2 中的字节偏移量来给出的地址。提供了有序和无序形式,其中有序形式按元素顺序访问段。然而,即使对于有序的形式,对单个段内的字段的访问也不是相对于彼此进行排序的。

数据向量寄存器组的EEW=SEW,EMUL=LMUL,而索引向量寄存器组的EEW在指令中编码为EMUL=(EEW/SEW)*LMUL。

对于向量索引段加载,目标向量寄存器组不能与源向量寄存器组(由 vs2 指定)重叠,否则会保留指令编码。

注意 此约束支持重新启动索引段加载,这些加载在加载结构的过程中会引发异常。

7.9、向量加载/存储整个寄存器指令(Vector Load/Store Whole Register Instructions)

这些指令加载和存储整个向量寄存器组。

注意 当向量寄存器的当前内容的类型或长度未知时,或者修改 vl 和 vtype 的成本很高时,这些指令旨在用于保存和恢复向量寄存器。示例包括编译器寄存器溢出、在向量寄存器中传递值的向量函数调用、中断处理程序和操作系统上下文切换。软件可以通过读取 vlenb 寄存器来确定传输的字节数。

加载指令在 mew 和 width 字段中按照常规单位步长加载的模式编码了一个 EEW。

注意 因为寄存器中字节布局与内存中字节布局相同,所以无论EEW如何,相同的数据都会写入目标寄存器组。因此,仅提供 EEW=8 变体就足够了。提供了完整的 EEW 变体集,以便编码的 EEW 可用作指示目标寄存器组接下来将使用此 EEW 访问的提示,这有助于在内部重新排列数据的实现。

向量整个寄存器存储指令的编码类似于 EEW=8 的元素的未屏蔽单元步长存储。

nf 字段使用 NFIELDS 编码对要加载和存储的向量寄存器数量进行编码(图 NFIELDS 编码)。

寄存器的编码数量必须是 2 的幂,并且向量寄存器数量必须与向量寄存器组对齐,否则保留指令编码。 NFIELDS 表示要传输的向量寄存器的数量,在基数之后依次编号。仅支持 NFIELDS 值 1、2、4、8,保留其他值。当传输多个寄存器时,编号最小的向量寄存器保存在编号最小的内存地址中,并且连续的向量寄存器编号连续放置在内存中。

无论 vtype 和 vl 中的当前设置如何,指令都以有效向量长度 evl=NFIELDS*VLEN/EEW 运行。如果 vstart ≥ vl 则不写入元素的通常属性不适用于这些指令。相反,如果 vstart ≥ evl 则不写入任何元素。

这些指令的操作类似于未屏蔽的单位步长加载和存储指令,基地址在由 rs1 指定的标量 x 寄存器中传递。

如果基地址未自然对齐到以字节为单位的编码 EEW 的大小 (EEW/8) 或以字节为单位的实现的最小支持 SEW 大小中的较大者,则允许实现在整个寄存器加载和存储时引发未对齐的地址异常 (SEWmin/8)。

注意 允许基于与编码的 EEW 不对齐而引发未对齐异常可简化这些指令的实现。一些子集实现可能不支持较小的 SEW 宽度,因此即使大于编码的 EEW,也允许报告支持的最小 SEW 的未对齐异常。例如,一个极端的非标准实现可能有 SEWMIN>XLEN。软件环境可以强制要求最低对齐要求来支持 ABI。

注意 对于不支持的 EEW 值,实现应该在 vlr指令上引发非法指令异常。

注意我们已经考虑添加一个完整的寄存器掩码加载指令(vl1rm.v),但决定从初始扩展中省略。主要目的是通知微架构数据将用作掩码。使用以下代码序列可以达到相同的效果,其成本最多为四条指令。其中,第一个可能会被删除,因为 vl 通常已经在一个标量寄存器中,如果后面的向量指令需要一个新的 SEW/LMUL,最后一个可能已经存在。因此,在最好的情况下,只需要两条指令(其中只有一条执行向量运算)来合成专用指令的效果:

8、向量内存对齐约束(Vector Memory Alignment Constraints)

如果向量内存指令访问的元素与元素的大小不自然对齐,则该元素被成功传输或在该元素上引发地址未对齐异常。

对未对齐的向量内存访问的支持独立于实现对未对齐的标量内存访问的支持。

注意 一个实现可能没有、一个或两个标量和向量内存访问支持硬件中的部分或全部未对齐访问。应定义一个单独的 PMA 以确定相关地址范围内是否支持向量未对齐访问。

矢量未对齐内存访问遵循与标量未对齐内存访问相同的原子性规则。

9、向量内存一致性模型(Vector Memory Consistency Model)

向量内存指令似乎在本地 hart 上按程序顺序执行。

向量存储器指令在指令级遵循 RVWMO。

除了vector indexed-ordered loads and stores,,指令中的元素操作是无序的。

Vector indexed-ordered 分别按元素顺序从/向内存加载和存储读取和写入元素。

注意 需要更正式的定义。

受向量长度寄存器 vl 影响的指令对 vl 具有控制依赖性,而不是数据依赖性。

类似地,屏蔽向量指令对源屏蔽寄存器具有控制依赖性,而不是数据依赖性。

注意 将向量长度和掩码视为控制而不是数据通常与相应标量代码的语义相匹配,其中通常会使用分支指令。将掩码视为控制允许掩码向量加载指令在知道掩码值之前访问内存,而无需错误推测恢复机制。

注意目前未定义提议的 RVTSO 内存模型(Ztso 扩展)下的向量内存指令的行为。

10、向量算术指令格式(Vector Arithmetic Instruction Formats)

矢量算术指令使用与 OP-FP 相邻的新主操作码 (OP-V = 10101112)。三位 funct3 字段用于定义向量指令的子类别。

OP-V 主要操作码下向量算术指令的格式

10.1。矢量算术指令编码(Vector Arithmetic Instruction encoding)

funct3 字段对操作数类型和源位置进行编码。

根据操作码,使用无符号或二进制补码有符号整数算术执行整数运算。

注意在本讨论中,定点运算被认为是整数运算。

所有标准向量浮点算术运算都遵循 IEEE-754/2008 标准。所有向量浮点运算都使用 frm 寄存器中的动态舍入模式。当任何向量浮点指令包含无效的舍入模式时使用 frm 字段,即使是那些不依赖于舍入模式的指令,或者当 vl=0 时,或者当 vstart ≥ vl 时,保留。

注意 所有向量浮点代码都依赖于 frm 中的有效值。当舍入模式无效时,实现可以使所有向量 FP 指令报告异常,以简化控制逻辑。

向量-向量运算从分别由 vs2 和 vs1 指定的向量寄存器组中获取两个操作数向量。

矢量标量运算可以有三种可能的形式。在所有三种形式中,向量寄存器组操作数由 vs2 指定。第二个标量源操作数来自三个备选源之一:

  1. 对于整数运算,标量可以是 5 位立即数 imm[4:0],编码在 rs1 字段中。除非另有说明,否则该值符号扩展到 SEW 位。

  2. 对于整数运算,可以从 rs1 指定的标量 x 寄存器中获取标量。如果 XLEN>SEW,除非另有说明,否则使用 x 寄存器的最低 SEW 位。如果 XLEN

  3. 对于浮点运算,可以从标量 f 寄存器中获取标量。如果 FLEN > SEW,则检查 f 寄存器中的值是否为有效的 NaN 装箱值,在这种情况下,使用 f 寄存器的最低有效 SEW 位,否则使用规范的 NaN 值。保留任何浮点向量操作数的 EEW 不是受支持的浮点类型宽度(包括 FLEN < SEW 时)的向量指令。

注意 一些指令对 5 位立即数进行零扩展,并通过在汇编语法中命名立即数 uimm 来表示这一点。

**注意 **当向建议的 Zfinx/Zdinx/Zhinx 扩展添加向量扩展时,浮点标量参数取自 x 寄存器。这些扩展不支持 NaN 装箱,因此向量浮点标量值使用与整数标量操作数相同的规则生成(即,当 XLEN > SEW 使用最低 SEW 位时,当 XLEN < SEW 使用符号扩展值)。

矢量算术指令在 vm 字段的控制下被屏蔽。

注意 在编码中,vs2 是第一个操作数,而 rs1/imm 是第二个操作数。这与标准标量排序相反。这种安排保留了现有的编码约定,即只读取一个标量寄存器的指令,从 rs1 读取它,并且 5 位立即数来自 rs1 字段。

向量三元算术指令的汇编语法模式(乘加)

注意 对于三元乘加运算,汇编语法总是将目标向量寄存器放在最前面,然后是 rs1 或 vs1,然后是 vs2。这种排序为这些三元运算提供了更自然的汇编程序读取,因为乘法操作数总是彼此相邻。

10.2.加宽向量算术指令(Widening Vector Arithmetic Instructions)

一些向量算术指令被定义为扩展操作,其中目标向量寄存器组具有 EEW=2SEW 和 EMUL=2LMUL。这些通常在操作码上被赋予 vw* 前缀,或者为向量浮点指令赋予 vfw*。

第一个向量寄存器组操作数可以是单宽或双宽。

注意 最初,w 后缀用于操作码,但这可能与使用 w 后缀表示双字整数中的字长操作混淆,因此 w 被移至前缀。

注意 浮点扩展操作已从 vwf* 更改为 vfw*,以便与将写入 fw* 的任何标量扩展浮点操作更加一致。

扩展指令编码必须遵循节向量操作数中的约束。

10.3.窄化向量算术指令(Narrowing Vector Arithmetic Instructions)

提供了一些指令来将双宽度源向量转换为单宽度目标向量。这些指令将 EEW/EMUL=2SEW/2LMUL 由 vs2 指定的向量寄存器组转换为具有当前 SEW/LMUL 设置的向量寄存器组。如果有第二个源向量寄存器组(由 vs1 指定),则它具有与结果相同(更窄)的宽度(即 EEW=SEW)。

注意 另一种设计决策是将 SEW/LMUL 视为定义源向量寄存器组的大小。这里的选择是基于这样一种信念,即所选择的方法将需要更少的 vtype 更改。

注意设置掩码寄存器的比较操作也隐含地缩小操作。

操作码上的 vn* 前缀用于区分汇编程序中的这些指令,或 vfn* 前缀用于缩小浮点操作码。双宽度源向量寄存器组由源操作数后缀中的 w 表示(例如,vnsra.wv)

窄化指令编码必须遵循Section Vector Operands 中的约束。

11、向量整数运算指令(Vector Integer Arithmetic Instructions)

提供了一组向量整数算术指令。除非另有说明,否则整数运算会在溢出时回绕( wrap around)。

11.1。向量单宽度整数加减法(Vector Single-Width Integer Add and Subtract)

提供向量整数加减法。还为向量标量形式提供了反向减法指令。

注意 可以使用带有 x0 标量操作数的反向减法指令对整数值向量求反。提供了汇编伪指令 vneg.v vd,vs = vrsub.vx vd,vs,x0。

11.2.向量加宽整数加/减(Vector Widening Integer Add/Subtract)

加宽加/减指令在有符号和无符号变体中都提供,具体取决于较窄的源操作数是在形成双宽度和之前先进行符号扩展还是零扩展。

注意 使用标量操作数为 x0 的加宽加法指令可以将整数值的宽度加倍。提供汇编伪指令 vwcvt.x.x.v vd,vs,vm = vwadd.vx vd,vs,x0,vm 和 vwcvtu.x.x.v vd,vs,vm = vwaddu.vx vd,vs,x0,vm。

11.3.向量整数扩展(Vector Integer Extension)

向量整数扩展指令零或符号扩展 EEW 小于 SEW 的源向量整数操作数,以填充目标中 SEW 大小的元素。源的 EEW 是 SEW 的 1/2、1/4 或 1/8,而源的 EMUL 是 (EEW/SEW)*LMUL。目的地的 EEW 等于 SEW,EMUL 等于 LMUL。

如果源 EEW 不是支持的宽度,或者源 EMUL 低于最小合法 LMUL,则保留指令编码。

注意 标准向量加载指令访问与目标寄存器元素大小相同的内存值。一些应用程序代码需要对更宽元素中的一系列操作数宽度进行操作,例如,从内存中加载一个字节并添加到一个八字节元素。为了避免必须提供向量加载指令的数量与数据类型(字节、字、半字以及有符号/无符号变体)的数量的叉积,我们改为添加显式扩展指令,如果合适,可以使用加宽算术指令不可用。

未完待续。。。。。

参考:

riscv中vsetvli的相关用法, AVL, VLMAX, VL的计算
risc-v vector扩展1.0版本解读(riscv-v-spec-1.0)
riscv-v-spec-1.0(矢量指令) 学习理解(1-5 & 18 segment)
RSIC-V——指令集spec阅读笔记——向量扩展0.9
RISC-V自动向量化测试报告
rvv-intrinsic-doc
RVV与NEON区别

【《RISC-V “V“ Vector Extension Version 1.0》阅读笔记】相关推荐

  1. trainer setup_Detectron2源码阅读笔记-(一)Configamp;Trainer

    一.代码结构概览 1.核心部分 configs:储存各种网络的yaml配置文件 datasets:存放数据集的地方 detectron2:运行代码的核心组件 tools:提供了运行代码的入口以及一切可 ...

  2. VoxelNet阅读笔记

    作者:Tom Hardy Date:2020-02-11 来源:VoxelNet阅读笔记

  3. Transformers包tokenizer.encode()方法源码阅读笔记

    Transformers包tokenizer.encode()方法源码阅读笔记_天才小呵呵的博客-CSDN博客_tokenizer.encode

  4. 源码阅读笔记 BiLSTM+CRF做NER任务 流程图

    源码阅读笔记 BiLSTM+CRF做NER任务(二) 源码地址:https://github.com/ZhixiuYe/NER-pytorch 本篇正式进入源码的阅读,按照流程顺序,一一解剖. 一.流 ...

  5. Mina源码阅读笔记(一)-整体解读

    2019独角兽企业重金招聘Python工程师标准>>> 今天的这一节,将从整体上对mina的源代码进行把握,网上已经有好多关于mina源码的阅读笔记,但好多都是列举了一下每个接口或者 ...

  6. “CoreCLR is now Open Source”阅读笔记

    英文原文:CoreCLR is now Open Source 阅读笔记如下: CoreCLR是.NET Core的执行引擎,功能包括GC(Garbage Collection), JIT(将CIL代 ...

  7. QCon 2015 阅读笔记 - 团队建设

    QCon 2015阅读笔记 QCon 2015 阅读笔记 - 移动开发最佳实践 QCon 2015 阅读笔记 - 团队建设 中西对话:团队管理的五项理论和实战 - 谢欣.董飞(今日头条,LinkedI ...

  8. 05《软件需求模式》阅读笔记

    剩下的两个阅读笔记写第二部分.各类需求模式,共八个领域和它的需求模式,这一次写前四个. 基础需求模式,它是所有种类的系统都可能需要的一些东西.系统间接口需求模式使用系统间接口需求模式定义被定义的系统和 ...

  9. [置顶] Linux协议栈代码阅读笔记(一)

    Linux协议栈代码阅读笔记(一) (基于linux-2.6.21.7) (一)用户态通过诸如下面的C库函数访问协议栈服务 int socket(int domain, int type, int p ...

  10. 大型网站技术架构:核心原理与案例分析阅读笔记二

    大型网站技术架构:核心原理与案例分析阅读笔记二 网站架构设计时可能会存在误区,其实不必一味追随大公司的解决方案,也不必为了技术而技术,要根据本公司的实际情况,制定适合本公司发展的网站架构设计,否则会变 ...

最新文章

  1. 首场见习挑战赛倒计时3天!20000元奖学金瓜分就等你了!
  2. 第三十四篇:在SOUI中使用异步通知
  3. 备战金九银十,阿里P8师兄指导完整攻略(附:学习资料+面试宝典+项目实战笔记)
  4. ios+openflow 问题
  5. BigData之Hive beeline:beeline的简介、使用方法之详细攻略
  6. Android 高效的`InjectView – ButterKnife`
  7. opengl加载显示3D模型nff类型文件
  8. PAT L3-015 ---- 球队“食物链”(DFS)
  9. Git笔记(22) 项目贡献要点
  10. pytorch学习笔记(二十一):Channels
  11. 你必须了解的基础的 Linux 网络命令
  12. SCCM 2012 SP1系列(一)先决条件准备-1
  13. Nginx静态文件路径配置
  14. 网站卡顿,推荐这些免费使用加速工具的网站
  15. 部分设计模式案例代码
  16. OpenCV从摄像头中检测人脸
  17. 阿里云云盾抗下全球最大DDoS攻击(5亿次请求,95万QPS HTTPS CC攻击) ,阿里百万级QPS资源调度系统,一般的服务器qps多少? QPS/TPS/并发量/系统吞吐量...
  18. 分享一个超好用的项目进度模板(包括计划进度与实际进度对比甘特图)
  19. 第二届SDN大赛--必答题2
  20. Go中append和链表的关系

热门文章

  1. Java安全-注入漏洞(SQL注入、命令注入、表达式注入、模板注入)
  2. SQL注入基础--判断闭合形式
  3. 《笨办法学python3》再笨的人都能学会python,附PDF,拿走不谢
  4. Could not resolve placeholder 占位符不能被解析
  5. LINUX嵌入式系统开发平台选择
  6. 案例分享 | 基于Linkis+DSS构建合合信息一站式数据开发平台
  7. python获取指定端口流量_python如何查看系统网络流量的信息
  8. AVFoundation开发秘籍笔记-03资源和元数据
  9. 免费svn服务器,百度云开发者教程
  10. C#使用GetPixel函数获取指定坐标点的rgb值