本文档链接 https://blog.csdn.net/weixin_42487906/article/details/115437890

RISCV向量指令集学习

参考链接

https://github.com/riscv/riscv-v-spec
RSIC-V——指令集spec阅读笔记——向量扩展0.9
RISC-V Vector Extension学习笔记

向量指令集用例

可以对照下面的说明来看这个例子

.text.balign 4.global vvaddint32# vector-vector add routine of 32-bit integers# void vvaddint32(size_t n, const int*x, const int*y, int*z)# { for (size_t i=0; i<n; i++) { z[i]=x[i]+y[i]; } }## a0 = n, a1 = x, a2 = y, a3 = z# Non-vector instructions are indented
vvaddint32:vsetvli t0, a0, e32, ta,ma  # Set vector length based on 32-bit vectorsvle32.v v0, (a1)         # Get first vectorsub a0, a0, t0         # Decrement number doneslli t0, t0, 2         # Multiply number done by 4 bytesadd a1, a1, t0         # Bump pointervle32.v v1, (a2)         # Get second vectoradd a2, a2, t0         # Bump pointervadd.vv v2, v0, v1       # Sum vectorsvse32.v v2, (a3)         # Store resultadd a3, a3, t0         # Bump pointerbnez a0, vvaddint32    # Loop backret                    # Finished

名词解释

ELEN 向量中单个元素的最大长度,bit为单位,要求ELEN>=8,且为2的幂
VLEN 向量寄存器的位数,bit为单位,要求VLEN ≥ ELEN,并且必须是2的幂
SLEN 分段距离(The striping distance in bits),要求必须为VLEN ≥ SLEN ≥ 32,并且必须为2的幂,这个暂时没懂
SEW 标准元素宽度,以bit为单位,指向量中一个元素占向量寄存器中的位数
LMUL 向量寄存器分组数
寄存器定义
v0-v31 向量数据寄存器,共32个,固定位宽为VLEN位
vtype 向量数据类型寄存器,并且只能通过vsetvl{i}指令进行更新,向量类型还决定了每个向量寄存器中元素的排布,以及如何对多个向量寄存器进行分组。
vsew[2:0] 变化的标准元素宽度(SEW, standard element width)值通过vsew中的值设置。默认情况下,向量寄存器被视为分成 VLEN / SEW 个标准宽度元素。
vlmul[2:0 ] 向量寄存器分组,分成一组的多个向量寄存器可以当作一个操作数来用,用来存放一个向量,该值也可以是小数,用来等效增加向量数据寄存器的数量
VLMAX VLMAX = LMUL * VLEN / SEW,
vta和vma 这两位元素值在执行向量指令期间分别修改了目标尾部元素(Tail Elements)和非活跃的掩码元素(Inactive masked-off Elements)的行为。
vill vill位用于编码先前的vsetvl{i} 指令试图向vtype写入不支持的值
vl 向量长度寄存器,以存放向量总共有多少个元素,只能通过vsetvli和vsetvl指令进行更新。
vlen 向量寄存器长度寄存器,是一个常数,保存值 VLEN / 8,即向量寄存器长度(以字节为单位)。
vstart vstart是一个可读可写的CSR寄存器,指定向量指令要执行的第一个元素的索引。每个向量指令执行完后,该寄存器清零。
vcsr 向量控制和状态寄存器vcsr,保存定点舍入的方式和饱和状态


向量元素到向量寄存器的映射

根据当前的 SEW 和 LMUL 设置以及 ELEN,VLEN 和 SLEN 的值,怎么将不同宽度的元素存放到矢量寄存器的字节中。并且使用最少位数的最低有效字节将元素放到每个向量寄存器中。
当 VLEN=SLEN , LMUL=1 时,从向量寄存器的最低有效位到最高有效位依次对元素进行简单排布。当 LMUL <1 时,仅使用向量寄存器中的第一个 LMUL * VLEN / SEW 元素。 向量寄存器中的剩余空间被视为尾部的一部分。



VLEN = SLEN 且 LMUL > 1时, 将向量寄存器分组后,根据向量寄存器组中的向量寄存器来划分组中的元素。当 SLEN = VLEN 时,按元素顺序将其放在组中的每个向量寄存器中,填满一个向量寄存器后,便移至组中下一个编号最高的向量寄存器。



向量 ISA 的设计目的是支持混合宽度操作,并且不需要大量显式的额外的重排指令,也不需要大量额外的数据路径(datapath)布线。在对不同精度值的向量进行操作时,推荐的做法是动态修改 vtype 值,从而使得 SEW/LMUL 为常量(因此 VLMAX 常量)。向量寄存器分组因子(LMUL)按相关元素大小增加,这样每个向量寄存器组可以保存相同数量的向量元素(本例中 VLMAX=16 ),从而简化 stripmining 代码。下表列出了执行混合宽度操作的循环的每个可能的 SEW / LMUL 操作点。 每列代表一个恒定的 SEW / LMUL 操作点。 表中列出的内容是 LMUL 值,该值生成该列的 SEW / LMUL 值。 在同一列中, LMUL 的值不同,但 VLMAX 值相同。(可以保证每个向量寄存器组中的向量元素数量相同)

配置寄存器操作指令

vsetvli/vsetvl

用例

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 和 vl CSRs,并将 vl 的新值写入 rd。
两个指令的区别:vtypei是个立即数,rs2是个寄存器
AVL=应用程序向量长度

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 值

向量操作指令中的掩码

掩码vm
在指令中占一位,使用v0寄存器存放掩码值,vm为1时不启动掩码,vm为0时,当v0的相应位为1,目标向量寄存器写入相应的值

掩码向量的加载操作不会更新目标向量寄存器组中的非活跃元素。掩码向量的存储操作只更新内存中的活跃元素。

向量加载和存储指令(访存)

mop 访存时选择访存模式


支持连续访存,跨步访存和按索引访存

lumop/sumop

还没搞懂是做什么用的 fault only first似乎可以简化循环操作

向量加载/存储的宽度编码

  • Mem bits(内存位)是内存中访问的每个元素的大小。
  • Reg bits(寄存器位)是寄存器中访问的每个元素的大小。

向量单步幅跨步(Unit-Stride)指令

#vd destination, rs1 base address, vm is mask encoding (v0.t or <missing>)vle32.v  vd, (rs1), vm # 32-bit loads

l代表load,e32代表向量元素长32

#vs3 store data, rs1 base address, vm is mask encoding (v0.t or <missing>)vse64.v  vs3, (rs1), vm  # 64-bit stores

s代表save

向量跨步(Strided)指令

# vd destination, rs1 base address, rs2 byte stridevlse8.v  vd, (rs1), rs2, vm  # Load bytes separated by stride

vls中l代表load,s代表stride,rs2存放跨步值

# vs3 store data, rs1 base address, rs2 byte stridevsse128.v vs3, (rs1), rs2, vm  # Store 128b values separated by stride.

vsse128中,第一个s是save,第二个是stride

向量索引(indexed)指令

# vd destination, rs1 base address, vs2 indicesvlxei16.v  vd, (rs1), vs2, vm  # vs2 data EEW = SEW, indices EEW = 16b

有序加载,vs2存放索引,vs2中元素大小为16bit

# Vector unordered-indexed store instructionsvsuxei64.v vs3, (rs1), vs2, vm # SEW data, 64b indices

无序存储,vs2中元素大小为64bit

向量原子操作

原子操作指令 暂时用不到

向量计算指令

向量的算术指令使用与 OP-FP 相邻的新的主要操作码1010111。 funct3 字段的三位用于定义向量指令的子类。

向量与标量之间的运算可以采取三种可能的形式,但无论采取哪种形式,都要从 vs2 指定的向量寄存器组中获取一个操作数向量,并从三个替代源之一获取第二个标量源操作数。

  • 对于整数运算,标量可以是编码在 rs1 字段中5位立即数。该值通过符号扩展或加零扩展到SEW 位。
  • 对于整数运算,可以从rs1 指定的标量寄存器x中提取标量。如果 XLEN > SEW,则使用x的最低有效SEW位。如果 XLEN < SEW,则x 寄存器的值通过符号扩展到 SEW 位。
  • 对于浮点运算,可以从标量寄存器f中获取标量。如果 FLEN> SEW,则检查f寄存器中的值是否为有效的 NaN-boxed 值,如果是,则使用f寄存器的最低有效SEW位,否则将使用规范的 NaN 值。如果执行向量指令时,任何浮点向量操作数的 EEW 都不是支持的浮点类型宽度(包括 FLEN <SEW 时),则会引发非法指令异常。

向量算术指令在vm 字段下被掩码。

# Operations returning vector results, masked by vm (v0.t, <nothing>)
vop.vv  vd, vs2, vs1, vm  # integer vector-vector      vd[i] = vs2[i] op vs1[i]
vop.vx  vd, vs2, rs1, vm  # integer vector-scalar      vd[i] = vs2[i] op x[rs1]
vop.vi  vd, vs2, imm, vm  # integer vector-immediate   vd[i] = vs2[i] op imm

浮点指令

vfop.vv  vd, vs2, vs1, vm # FP vector-vector operation vd[i] = vs2[i] fop vs1[i]
vfop.vf  vd, vs2, rs1, vm # FP vector-scalar operation vd[i] = vs2[i] fop f[rs1]4

不同的指令格式

# Integer operations overwriting sum input
vop.vv vd, vs1, vs2, vm  # vd[i] = vs1[i] * vs2[i] + vd[i]
vop.vx vd, rs1, vs2, vm  # vd[i] = x[rs1] * vs2[i] + vd[i]# Integer operations overwriting product input
vop.vv vd, vs1, vs2, vm  # vd[i] = vs1[i] * vd[i] + vs2[i]
vop.vx vd, rs1, vs2, vm  # vd[i] = x[rs1] * vd[i] + vs2[i]

从指令上看没有什么区别,怎么区分二者呢
通过vop的不同来区分

Widening向量算术指令

一些矢量算术指令被定义为加宽(widening) 操作,其中 EEW = 2 * SEW ,EMUL = 2 * LMUL。
第一个操作数可以是单宽度或双宽度。这些通常在操作码上具有前缀 vw*,或对于矢量浮点运算具有前缀 vfw*。

# Double-width result, two single-width sources: 2*SEW = SEW op SEW
vwop.vv  vd, vs2, vs1, vm  # integer vector-vector      vd[i] = vs2[i] op vs1[i]
vwop.vx  vd, vs2, rs1, vm  # integer vector-scalar      vd[i] = vs2[i] op x[rs1]

结果为双宽度,两个源操作数均为单宽度

# Double-width result, first source double-width, second source single-width: 2*SEW = 2*SEW op SEW
vwop.wv  vd, vs2, vs1, vm  # integer vector-vector      vd[i] = vs2[i] op vs1[i]
vwop.wx  vd, vs2, rs1, vm  # integer vector-scalar      vd[i] = vs2[i] op x[rs1]

结果为双宽度,源操作数1为双宽度,源操作数2为单宽度

Narrowing向量算术指令

和加宽指令类似
这些指令将 EEW/EMUL = 2 * SEW / 2 * LMUL 的向量寄存器组转换为具有当前 LMUL/SEW 向量/元素的向量寄存器组。
如果 EEW> ELEN 或 EMUL> 8,则会引发非法指令异常。

向量单宽度加减

# Integer adds.
vadd.vv vd, vs2, vs1, vm   # Vector-vector
vadd.vx vd, vs2, rs1, vm   # vector-scalar
vadd.vi vd, vs2, imm, vm   # vector-immediate# Integer subtract
vsub.vv vd, vs2, vs1, vm   # Vector-vector
vsub.vx vd, vs2, rs1, vm   # vector-scalar# Integer reverse subtract
vrsub.vx vd, vs2, rs1, vm   # vd[i] = rs1 - vs2[i]
vrsub.vi vd, vs2, imm, vm   # vd[i] = imm - vs2[i]

向量结果加宽加减,包括有符号数和无符号数

# Widening unsigned integer add/subtract, 2*SEW = SEW +/- SEW
vwaddu.vv  vd, vs2, vs1, vm  # vector-vector
vwaddu.vx  vd, vs2, rs1, vm  # vector-scalar
vwsubu.vv  vd, vs2, vs1, vm  # vector-vector
vwsubu.vx  vd, vs2, rs1, vm  # vector-scalar# Widening signed integer add/subtract, 2*SEW = SEW +/- SEW
vwadd.vv  vd, vs2, vs1, vm  # vector-vector
vwadd.vx  vd, vs2, rs1, vm  # vector-scalar
vwsub.vv  vd, vs2, vs1, vm  # vector-vector
vwsub.vx  vd, vs2, rs1, vm  # vector-scalar# Widening unsigned integer add/subtract, 2*SEW = 2*SEW +/- SEW
vwaddu.wv  vd, vs2, vs1, vm  # vector-vector
vwaddu.wx  vd, vs2, rs1, vm  # vector-scalar
vwsubu.wv  vd, vs2, vs1, vm  # vector-vector
vwsubu.wx  vd, vs2, rs1, vm  # vector-scalar# Widening signed integer add/subtract, 2*SEW = 2*SEW +/- SEW
vwadd.wv  vd, vs2, vs1, vm  # vector-vector
vwadd.wx  vd, vs2, rs1, vm  # vector-scalar
vwsub.wv  vd, vs2, vs1, vm  # vector-vector
vwsub.wx  vd, vs2, rs1, vm  # vector-scalar

向量有,无符号数元素位数扩展

vzext.vf2 vd, vs2, vm  # Zero-extend SEW/2 source to SEW destination
vsext.vf2 vd, vs2, vm  # Sign-extend SEW/2 source to SEW destination
vzext.vf4 vd, vs2, vm  # Zero-extend SEW/4 source to SEW destination
vsext.vf4 vd, vs2, vm  # Sign-extend SEW/4 source to SEW destination
vzext.vf8 vd, vs2, vm  # Zero-extend SEW/8 source to SEW destination
vsext.vf8 vd, vs2, vm  # Sign-extend SEW/8 source to SEW destination

带进位借位加减法

# Produce sum with carry.# vd[i] = vs2[i] + vs1[i] + v0.mask[i]vadc.vvm   vd, vs2, vs1, v0  # Vector-vector# vd[i] = vs2[i] + x[rs1] + v0.mask[i]vadc.vxm   vd, vs2, rs1, v0  # Vector-scalar# vd[i] = vs2[i] + imm + v0.mask[i]vadc.vim   vd, vs2, imm, v0  # Vector-immediate# Produce difference with borrow.# vd[i] = vs2[i] - vs1[i] - v0.mask[i]vsbc.vvm   vd, vs2, vs1, v0  # Vector-vector# vd[i] = vs2[i] - x[rs1] - v0.mask[i]vsbc.vxm   vd, vs2, rs1, v0  # Vector-scalar

位逻辑指令

# Bitwise logical operations.
vand.vv vd, vs2, vs1, vm   # Vector-vector
vand.vx vd, vs2, rs1, vm   # vector-scalar
vand.vi vd, vs2, imm, vm   # vector-immediatevor.vv vd, vs2, vs1, vm    # Vector-vector
vor.vx vd, vs2, rs1, vm    # vector-scalar
vor.vi vd, vs2, imm, vm    # vector-immediatevxor.vv vd, vs2, vs1, vm    # Vector-vector
vxor.vx vd, vs2, rs1, vm    # vector-scalar
vxor.vi vd, vs2, imm, vm    # vector-immediate

单宽度位移指令,逻辑左移,逻辑和算数右移

# Bit shift operations
vsll.vv vd, vs2, vs1, vm   # Vector-vector
vsll.vx vd, vs2, rs1, vm   # vector-scalar
vsll.vi vd, vs2, uimm, vm   # vector-immediatevsrl.vv vd, vs2, vs1, vm   # Vector-vector
vsrl.vx vd, vs2, rs1, vm   # vector-scalar
vsrl.vi vd, vs2, uimm, vm   # vector-immediatevsra.vv vd, vs2, vs1, vm   # Vector-vector
vsra.vx vd, vs2, rs1, vm   # vector-scalar
vsra.vi vd, vs2, uimm, vm   # vector-immediate

向量比较指令,符号左右两边分别是vs2和vs1

# Set if equal
vmseq.vv vd, vs2, vs1, vm  # Vector-vector
vmseq.vx vd, vs2, rs1, vm  # vector-scalar
vmseq.vi vd, vs2, imm, vm  # vector-immediate# Set if not equal
vmsne.vv vd, vs2, vs1, vm  # Vector-vector
vmsne.vx vd, vs2, rs1, vm  # vector-scalar
vmsne.vi vd, vs2, imm, vm  # vector-immediate# Set if less than, unsigned
vmsltu.vv vd, vs2, vs1, vm  # Vector-vector
vmsltu.vx vd, vs2, rs1, vm  # Vector-scalar# Set if less than, signed
vmslt.vv vd, vs2, vs1, vm  # Vector-vector
vmslt.vx vd, vs2, rs1, vm  # vector-scalar# Set if less than or equal, unsigned
vmsleu.vv vd, vs2, vs1, vm   # Vector-vector
vmsleu.vx vd, vs2, rs1, vm   # vector-scalar
vmsleu.vi vd, vs2, imm, vm   # Vector-immediate# Set if less than or equal, signed
vmsle.vv vd, vs2, vs1, vm  # Vector-vector
vmsle.vx vd, vs2, rs1, vm  # vector-scalar
vmsle.vi vd, vs2, imm, vm  # vector-immediate# Set if greater than, unsigned
vmsgtu.vx vd, vs2, rs1, vm   # Vector-scalar
vmsgtu.vi vd, vs2, imm, vm   # Vector-immediate# Set if greater than, signed
vmsgt.vx vd, vs2, rs1, vm    # Vector-scalar
vmsgt.vi vd, vs2, imm, vm    # Vector-immediate# Following two instructions are not provided directly
# Set if greater than or equal, unsigned
# vmsgeu.vx vd, vs2, rs1, vm    # Vector-scalar
# Set if greater than or equal, signed
# vmsge.vx vd, vs2, rs1, vm    # Vector-scalar

向量找最大最小指令,最大/小结果放入vd中

# Unsigned minimum
vminu.vv vd, vs2, vs1, vm   # Vector-vector
vminu.vx vd, vs2, rs1, vm   # vector-scalar# Signed minimum
vmin.vv vd, vs2, vs1, vm   # Vector-vector
vmin.vx vd, vs2, rs1, vm   # vector-scalar# Unsigned maximum
vmaxu.vv vd, vs2, vs1, vm   # Vector-vector
vmaxu.vx vd, vs2, rs1, vm   # vector-scalar# Signed maximum
vmax.vv vd, vs2, vs1, vm   # Vector-vector
vmax.vx vd, vs2, rs1, vm   # vector-scalar

向量单宽度整数乘法指​​令

# Signed multiply, returning low bits of product
vmul.vv vd, vs2, vs1, vm   # Vector-vector
vmul.vx vd, vs2, rs1, vm   # vector-scalar# Signed multiply, returning high bits of product
vmulh.vv vd, vs2, vs1, vm   # Vector-vector
vmulh.vx vd, vs2, rs1, vm   # vector-scalar# Unsigned multiply, returning high bits of product
vmulhu.vv vd, vs2, vs1, vm   # Vector-vector
vmulhu.vx vd, vs2, rs1, vm   # vector-scalar# Signed(vs2)-Unsigned multiply, returning high bits of product
vmulhsu.vv vd, vs2, vs1, vm   # Vector-vector
vmulhsu.vx vd, vs2, rs1, vm   # vector-scalar

向量单宽度整数除法及求余数指​​令

 # Unsigned divide.vdivu.vv vd, vs2, vs1, vm   # Vector-vectorvdivu.vx vd, vs2, rs1, vm   # vector-scalar# Signed dividevdiv.vv vd, vs2, vs1, vm   # Vector-vectorvdiv.vx vd, vs2, rs1, vm   # vector-scalar# Unsigned remaindervremu.vv vd, vs2, vs1, vm   # Vector-vectorvremu.vx vd, vs2, rs1, vm   # vector-scalar# Signed remaindervrem.vv vd, vs2, vs1, vm   # Vector-vectorvrem.vx vd, vs2, rs1, vm   # vector-scalar

向量结果双宽度整数乘法指​​令

# Widening signed-integer multiply
vwmul.vv  vd, vs2, vs1, vm # vector-vector
vwmul.vx  vd, vs2, rs1, vm # vector-scalar# Widening unsigned-integer multiply
vwmulu.vv vd, vs2, vs1, vm # vector-vector
vwmulu.vx vd, vs2, rs1, vm # vector-scalar# Widening signed-unsigned integer multiply
vwmulsu.vv vd, vs2, vs1, vm # vector-vector
vwmulsu.vx vd, vs2, rs1, vm # vector-scalar

向量单宽度整数乘加指令

# Integer multiply-add, overwrite addend
vmacc.vv vd, vs1, vs2, vm    # vd[i] = +(vs1[i] * vs2[i]) + vd[i]
vmacc.vx vd, rs1, vs2, vm    # vd[i] = +(x[rs1] * vs2[i]) + vd[i]# Integer multiply-sub, overwrite minuend
vnmsac.vv vd, vs1, vs2, vm    # vd[i] = -(vs1[i] * vs2[i]) + vd[i]
vnmsac.vx vd, rs1, vs2, vm    # vd[i] = -(x[rs1] * vs2[i]) + vd[i]# Integer multiply-add, overwrite multiplicand
vmadd.vv vd, vs1, vs2, vm    # vd[i] = (vs1[i] * vd[i]) + vs2[i]
vmadd.vx vd, rs1, vs2, vm    # vd[i] = (x[rs1] * vd[i]) + vs2[i]# Integer multiply-sub, overwrite multiplicand
vnmsub.vv vd, vs1, vs2, vm    # vd[i] = -(vs1[i] * vd[i]) + vs2[i]
vnmsub.vx vd, rs1, vs2, vm    # vd[i] = -(x[rs1] * vd[i]) + vs2[i]

向量加宽整数乘加指令

# Widening unsigned-integer multiply-add, overwrite addend
vwmaccu.vv vd, vs1, vs2, vm    # vd[i] = +(vs1[i] * vs2[i]) + vd[i]
vwmaccu.vx vd, rs1, vs2, vm    # vd[i] = +(x[rs1] * vs2[i]) + vd[i]# Widening signed-integer multiply-add, overwrite addend
vwmacc.vv vd, vs1, vs2, vm    # vd[i] = +(vs1[i] * vs2[i]) + vd[i]
vwmacc.vx vd, rs1, vs2, vm    # vd[i] = +(x[rs1] * vs2[i]) + vd[i]# Widening signed-unsigned-integer multiply-add, overwrite addend
vwmaccsu.vv vd, vs1, vs2, vm  # vd[i] = +(signed(vs1[i]) * unsigned(vs2[i])) + vd[i]
vwmaccsu.vx vd, rs1, vs2, vm  # vd[i] = +(signed(x[rs1]) * unsigned(vs2[i])) + vd[i]# Widening unsigned-signed-integer multiply-add, overwrite addend
vwmaccus.vx vd, rs1, vs2, vm  # vd[i] = +(unsigned(x[rs1]) * signed(vs2[i])) + vd[i]

向量整数合并指令

vmerge.vvm vd, vs2, vs1, v0  # vd[i] = v0.mask[i] ? vs1[i] : vs2[i]
vmerge.vxm vd, vs2, rs1, v0  # vd[i] = v0.mask[i] ? x[rs1] : vs2[i]
vmerge.vim vd, vs2, imm, v0  # vd[i] = v0.mask[i] ? imm    : vs2[i]

向量整数移动指令

vmv.v.v vd, vs1 # vd[i] = vs1[i]
vmv.v.x vd, rs1 # vd[i] = rs1
vmv.v.i vd, imm # vd[i] = imm

整数标量移动指令

整数标量读/写指令在标量x寄存器和向量寄存器的元素0之间传输单个值。指令忽略LMUL和向量寄存器组。

vmv.xs rd,vs2#x [rd] = vs2 [0](vs1 = 0)
vmv.sx vd,rs1#vd [0] = x [rs1](vs2 = 0)

需求分析

  1. 向量的加载和存储,支持跨步,按索引范存(访存操作
  2. 向量单个元素位宽可指定(8bit,32bit)/可能支持向量寄存器分组
  3. 向量之间/向量和常数的加减乘除运算
  4. 向量之间/向量和常数的比较运算
  5. 向量自身所有元素求和
  6. 向量元素的位逻辑运算
  7. 求向量中,向量元素的最大最小值

RISCV指令格式


  • 给用户自定义的指令操作码为Custom-0, Custom-1, Custom-2, Custom-3
   wire opcode_custom0 = (opcode == 7'b0001011); wire opcode_custom1 = (opcode == 7'b0101011); wire opcode_custom2 = (opcode == 7'b1011011); wire opcode_custom3 = (opcode == 7'b1111011);
  • 操作码如上,操作码定义为Custom-0, Custom-1, Custom-2, Custom-3,其余部分可仿照向量指令集,指令集主要由func3和func7区分
  • 根据NICE示例代码可知,指令格式可为任意种类指令格式,但是文档中给出,指令格式仅使用R格式指令

指令预设

访存指令

向量的加载和存储,支持跨步,按索引范存(访存操作
占用一个custom操作数,custom1

  1. 5bit保存要加载/存储的内存地址的寄存器编号
  2. 5bit保存若跨步访存的步长所在的寄存器编号/或按索引访存所存放索引的向量寄存器地址
  3. 5bit保存要存或取数据的向量寄存器的编号
  4. 2bit编码向量元素宽度
  5. 2bit编码采用连续访存还是跨步访存还是索引范存
  6. 1bit编码读操作还是写操作
    按上述要求,采用R指令,1.2.3分给rs1,rs2,rs3,456分给func7
3.4.5.6.

也可采用R型指令,可分给custom2.3.4,具体指令类型由fun7指定(待定

NICE接口学习

NICE接口官方给出了较详细的文档说明
芯来官方资料汇总 https://www.rvmcu.com/community-topic-id-340.html
官方文档说明 https://doc.nucleisys.com/hbirdv2/core/core.html#nice
nice协处理器实现示例 https://github.com/riscv-mcu/e203_hbirdv2/tree/master/rtl/e203/subsys
协处理器使用示例 https://github.com/Nuclei-Software/nuclei-board-labs/tree/master/e203_hbirdv2/common

RISCV 向量指令集和NICE接口学习笔记相关推荐

  1. Java自学.接口学习笔记!

    接口学习笔记 文章目录 接口学习笔记 1.接口的概述与生活中的举例 2.接口定义的基本格式 3.接口的抽象方法 3.1接口抽象方法的定义 3.2接口的抽象方法使用 4.接口的默认方式 4.1接口的默认 ...

  2. 阿里云Apsara Clouder专项技能认证-实现调用API接口-学习笔记

    Apsara Clouder专项技能认证-实现调用API接口-学习笔记 阿里云的一个小认证,闲来无事,考一下 一.API简介 API的概念 API(Application Programming In ...

  3. 【vn.py学习笔记(二)】vn.py底层接口 学习笔记

    [vn.py学习笔记(二)]vn.py底层接口 学习笔记 1 CTP API的工作原理 1.1 CTP介绍 1.2 API功能介绍 1.3 CTP API文件 1.4 API 通用规则 2 CTP A ...

  4. VGA 接口 学习笔记

    VGA定义 VGA的全称是Video Graphics Array,即视频图形阵列,是一个使用模拟信号进行视频传输的标准.是 IBM 于1987年提出的一个使用类比讯号的电脑显示标准.这个标准已对于现 ...

  5. 接口学习笔记(2009.11.24)

    了解接口,主要是为了一道经典面试题:接口与抽象类的区别,对接口的理解却很少,现在学习一下. 接口只包含方法.属性.事件或索引器的签名.成员的实现是在实现接口的类或结构中完成的. Interface n ...

  6. Java并发39:Executor系列--ScheduleExecutorService接口学习笔记

    [超级链接:Java并发学习系列-绪论] 本章主要学习ScheduleExecutorService接口. 1.ScheduleExecutorService接口概述 @since 1.5 Sched ...

  7. HttpSessionActivationListener接口 学习笔记

    实现了HttpSessionActivationListener接口的 JavaBean 对象可以感知自己被活化和钝化的事件 当绑定到 HttpSession 对象中的对象将要随 HttpSessio ...

  8. AJPFX关于Set接口学习笔记及总结

    Set接口中的方法和Collection中方法一致的.Set接口取出方式只有一种,迭代器. |--HashSet:底层数据结构是哈希表,线程是不同步的.无序,高效: HashSet集合保证元素唯一性: ...

  9. webservice接口与HTTP接口学习笔记

    一.webservice 的概念 Web 是使应用程序可以与平台和编程语言无关的方式进行相互通信的一项技术.Web 服务是一个软件接口,它描述了一组可以在网络上通过标准化的 XML 消息传递访问的操作 ...

最新文章

  1. 不到 100 行 Python 代码教你做出精美炫酷的可视化大屏
  2. 从DataSet导出Txt
  3. Redis添加密码认证Cacti监控读取Redis状态值为 -1 的最快速解决方案
  4. leetcode 1328. Break a Palindrome | 1328. 破坏回文串(贪心)
  5. java for循环 等待_java – 主题:忙等待 – 空循环
  6. mongodb更新操作符$inc,$mul
  7. 基于python和opencv的人脸识别
  8. java easing_p5.js入门教程之平滑过渡(Easing)
  9. java访问权限的控制
  10. ERP知识普及连载(21)
  11. easyswoole验证码的使用
  12. 【C语言开源库】C语言开源库zlog的使用
  13. 淘宝褚霸谈做技术的心态
  14. 编码器脉冲计数器/2路DI高速计数器Modbus RTU模块
  15. (智能间距换行均满足)Excel中单元格批量调整行间距,行高自动适应内容,且自动换行
  16. Docker安装java环境并部署jar包运行
  17. 当代人工智能复习2022
  18. XFS 存储核心技术详解
  19. 微信小程序—千变万化的图片处理(canvas那些滤镜效果)
  20. L2-001. 紧急救援 (dijkstra算法)

热门文章

  1. 计算机硬件有哪些升级空间等级查询,你的电脑要不要升级内存?怎么升级?答案都在这里~...
  2. TPshop项目-功能测试(1)
  3. python,ffprobe获取视频信息
  4. 利用ps导出svg(主要用于上传自定义图标到iconfont)
  5. 批量下载sra文件linux,Linux下从NCBI批量下载SRA数据的sra和aspera方法
  6. 阿里巴巴、Amazon、Windows、Android、Google、Internet、iPhone、汽车底盘、以及信用卡都属于平台经济--产品平台---供应链平台---产业平台--双边市场平台
  7. STM32 - ADC采集电压 中断处理
  8. 基于C++的社交应用的数据存储与实现
  9. 数据库系统概论练习3
  10. 地方政府留言板文本数据