RISC-V向量指令扩展(二)

前边我们提到RISC-V向量扩展将32个向量寄存器和7个非特权的CSRs添加到一个及标量RISC-V指令集架构中,本节讨论一下各个寄存器的功能以及各个组成字段的含义。各个寄存器的位宽为固定的VLEN。

·vstart

向量起始索引,RISC-V定义该寄存器为可读可写,规定了向量指令执行的第一个元素的索引;vstart寄存器还可以在指令执行过程中产生陷阱被写入,记录同步异常和外部异常中断时正在执行的元素索引,方便跳出陷阱后继续执行剩下的元素。所有向量指令保证目的寄存器vstart之前的元素不被更改,指令执行结束,vstart寄存器置零。
向量指令执行期间目标元素索引被划分为三个不相交的子集:预启动元素,主体元素,尾部元素。

·vxsat

向量定点饱和寄存器,可读可写,用于表示运算结果是否饱和,最低位有效vxsat[0]。
该寄存器除了有独自的地址空间外,在vcsr寄存器中也有相应的字段,像这种类型的寄存器不止一个,具体原因后续讲述。
该寄存器有效表示输出结果饱和,需要进行截位以适应目的寄存器的格式,若发生有符号向上溢出时,取正值最大值;发生有符号向下溢出,取负数最小值给到目的寄存器。

·vxrm

向量定点舍入模式,浮点舍入模式由单独的浮点舍入寄存器frm决定。低两位有效,其余位恒为0,可读可写。同样,与vxsat相同,该寄存器除了有独自的地址空间外,在vcsr寄存器中也有相应的字段。
vxrm共有四种模式:
a)round-to-nearest-up(rnu):就近舍入,当为中间值时,向上舍入(四舍五入)。
b)round-to-nearest-even(rne):就近舍入,当为中间值时,向偶数舍入。
c)round-down(rdn):向下舍入,直接取移位后的值。
d)round-to-odd(rod):向奇数舍入。
设源操作数为vs1,有d位要被截位,则舍入后的值为(vs1>>d)+r,其中r为不同舍入模式下的差值。
vxrm[1:0]不同值对应的不同模式编码如下:
RISC-V向量指令扩展(二)_第1张图片
其中,r取决的是舍入模式,vs1[d-1]为舍入字段最高位,vs1[d]为舍入后结果最高位。
①向上舍入模式中,当vs1[d-1]=0时,表示距离舍入方向更近些直接截掉舍入即可。
②就近舍入偏向偶数模式中,根据表达式vs1[d-1] & (vs1[d-2:0]≠0 | vs1[d])选择偏移量r的值,例如,当vs1[d-1]=1,vs1[d-2:0]=0,且vs1[d]为0时,表达式为0,即r=0(截断低d位后结果为偶数,所以偏移量为0)。又当vs1[d-1]=1,vs1[d-2:0]=0,且vs1[d]即舍入后最高位为1时,截断低d位后结果为奇数,所以偏移量为1,截断结果加r,向偶数舍入。另外,当vs1[d]=1,截断结果为奇数,vs1[d-1]=0,vs1[d-2:0]≠0,此时r=0,因为舍入前操作数不为中间数,就近舍入。
③向下舍入模式直接截断低d位,不额外增加偏移量。
④向奇数舍入模式中,根据表达式!vs1[d] & vs1[d-1:0]≠0选择偏移量r的值,例如,vs1[d]=0,截断结果为偶数,vs1[d-1:0]=0无需偏移,当vs1[d-1:0]≠0时,截断加1向数舍入。

·vcsr

向量控制状态寄存器,低三位有效,由vxrm[1:0]和vxsat[0]组成,具体分配为

													**vcsr[2:1]=vxrm[1:0],vcsr[0]=vxsat[0]**

那么单独的vxrm和vxsat地址和vcsr中的二者地址有什么区别呢?或者说这么设计的作用是什么?是否浪费了一定的地址空间?

前面也提到过,拥有这种设计的寄存器不止一个,riscv-v中规定fflags和frm寄存器也采用类似设计。
实际上,这种设计主要是关于读写寄存器的速度而设计的,当要读取这两种寄存器的值时,只需要读取vcsr一个寄存器就好,不需要读取两个寄存器两个地址操作了,写入是相同的道理;又当要对其中某一个寄存器进行更改时,那么就不需要对另一个进行操作了,这时就只需要对单独的寄存器地址进行操作就好了。
那么有人会有疑问,对vcsr的[2:1]或者[0]单独进行操作不就好了,当然不是,对其中一个位段操作时,要先把另一个字段读出来然后对需要更改的字段赋值时将不更改的字段赋原值,也就是说多了一个读寄存器的操作。

·vl

向量长度寄存器,只读,规定了一条向量指令需要操作的元素个数,为无符号数。该寄存器只被vsetvli、vsetvl指令和fault-only-first向量加载(load)指令变量更改。
当vl=0或者vstart≥vl时,目的寄存器的所有元素都不被更改,也可以说指令不执行。
vl的宽度由最小元素宽度(SEW)和最大向量长度决定,其中SEW规定了指令执行元素的宽度,最小为8,最大向量长度为组成的最长的向量寄存器组,由VLMUL决定,最大为8。所以最多元素个数为

													**VLMAX = VLMUL * (VLEN/SEW)**

当VLMUL和SEW取极值时,VLMAX = VLEN,也就是说vl的最大值由VLEN决定。

·vtype

向量类型寄存器,只读,只能通过vsetvl{i}指令更新以维护vtype寄存器的状态。该寄存器决定了每个向量寄存器中元素的组织形式,并决定向量寄存器的分组方式、单个向量寄存器的元素组成、指示如何处理屏蔽元素(被mask)和向量结果中超过当前向量长度的元素。
vtype寄存器分为五大域:如下表:
RISC-V向量指令扩展(二)_第2张图片

①vill

当vsetvl指令想要向vtype字段写入不支持的值时,vill字段置1。并将vtype其他字段全部清零,非法置位时,后续依赖于vtype执行的指令全部产生非法指令异常。

②vma、vta

vma(vector mask agnostic)、vta(vector tail agnostic)字段分别用于在向量指令执行期间决定尾部元素和目标非活跃元素的行为。
决定的元素行为主要分为两种:undisturbed(不受干扰)agnostic(不可预知)。具体分配如下
RISC-V向量指令扩展(二)_第3张图片

其中,当一个元素被标记为undisturbed时,向量寄存器组的相应目标元素将保留原值不变。当一个元素被标记为agnostic时,目标操作数元素既可以保留原值也可以全部置1。
那么为什么需要添加agnostic策略呢?
在有些处理器中,会采用寄存器重命名的技术,比如超标量流水线处理器,在undisturbed策略下,必须从旧的物理目标向量寄存器中读取元素值,才能复制到新的物理目标寄存器中;也可以说,在新的物理寄存器进行重命名时,需要根据重命名映射表,查到原有的映射关系,然后把其中的元素值读出来,写到重命名后的对应元素。这对于不需要这些非活跃元素和尾部元素值的之后的运算既降低了性能也增加了功耗。因此undisturbed策略就显得很不可观,此时按照agnostic策略进行运算比较好。

③VSEW

VSEW(vector selected elements width),选择元素宽度,用于动态选择元素的位宽。因此向量寄存器的元素个数就为VLEN/VSEW。
元素宽度的确定方式并不是等于VSEW的值,而是

													**SEW=(8*2VSEW)**

因此元素宽度SEW的取值范围理论上来讲为8-2048,但在RISC-V规范中,将VSEW[2]=1的所有值保留。所以

													**SEW=8、16、32、64**

例如,当SEW=8,VLEN=128时,向量寄存器共有128/8=16个元素。

④VLMUL

前边也提到过,引入向量操作的目的就是为了提高效率,该字段用于将多个向量寄存器组合在一起组成向量寄存器组。以便在单个指令可以在多个向量寄存器上操作。
与VSEW相同,向量寄存器分组数lmul的值为

														**lmul=2vlmul**

需要注意的是,vlmul是一个有符号数,也就是说,lmul的值除了可以是整数外,还可以是分数小数,减少单个向量寄存器中使用的位数。小数分组主要用于混合宽度指令操作。因此lmul的取值是1/8,1/4,1/2,1,2,4,8。
与VSEW定义结合,单个向量指令能够执行的最大元素数量为

												**VLMAX = LMUL * (VLEN/SEW)**

另外,掩码寄存器只有一个寄存器,通常为v0,所以与VLMUL设置无关。

⑤vlenb

vlenb为只读,恒为VLEN/8,表示以字节为单位的向量寄存器长度,当有些指令需要以字节为单位使用向量寄存器时,用于减少额外的计算过程。

更多内容欢迎关注我的公众号-“司晔”


RISC-V向量指令扩展(二)_第4张图片

你可能感兴趣的:(risc-v)