0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

RISCV该如何开启和使用V扩展指令?

嵌入式IoT 来源:嵌入式IoT 作者:bigmagic 2021-06-18 16:28 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

用哪吒D1开发板体验riscv向量底层编程

1.前言

2.机器模式处理器状态寄存器(MSTATUS)

3.编译选项支持V扩展

4.RISCV向量计算的原理

5.通过实例分析RISCV V扩展的运作机制

6.RVV使用体验

1.前言

RISCV V扩展即向量指令扩展(RVV),这部分作为研究AI加速计算领域有着非常关键的作用。既然的D1支持了rvv扩展(0.7.1,最新的版本已经0.10版本),那么就实际的从底层原理角度分析一下使用的流程。利用了多媒体加速指令集,可以让计算变得更加的高效,同时并行计算的特性使得同时多次计算一组数字成为可能,类似于arm的NEON等等,那么RISCV又该如何去开启和使用V扩展指令,让计算变得更加高效呢?

下面会通过一个裸机代码入手,结合实战去展示riscv rvv的使用。

https://github.com/bigmagic123/d1-nezha-baremeta/tree/main/src/2.vector_example

2.机器模式处理器状态寄存器(MSTATUS)

机器模式状态处理寄存器可以查看玄铁C910的用户手册,开启的V扩展的位是[23:24]位,如果不设置这两位,那么使用V扩展指令的时候,会出现指令未定义的异常。

这里需要注意的是,RISCV的各家的VS标志并不是一定是这两位,比如sifive会定义在

但是无论怎么说,都需要设置机器状态控制器去开启v扩展指令的支持。

/* Enable FPU and accelerator if present */

li t0, MSTATUS_FS | MSTATUS_XS | (0x01800000)

csrs mstatus, t0

在启动代码中,通过0x01800000设置mstatus开启V扩展支持。

3.编译选项支持V扩展

默认情况下,平头哥提供的交叉编译工具链已支持了V扩展的编译。只需要在编译选项中开启即可。

从传递给riscv 的gcc的选项来看,带有v扩展即可。

-march是指定了riscv的模块化的指令集选项,可以通过选项指定目标RISC-V支持的模块化的指令集的组合。比如下面几种组合。

rv32i[m][a][f[d]][c]

rv32g[c]

rv64i[m][a][f[d]][c]

rv64g[c]

往往也会结合-mabi进行使用。-mabi决定了RISCV目标支持的ABI函数调用的规程。

4.RISCV向量计算的原理

在riscv的V扩展中,一共定义了32个寄存器,v0~v31,这32个寄存器,每个长度都是VLEN长度。在玄铁C906定义长度为128位。

而在V扩展的操作中,需要扩展下面的寄存器组。

下面来具体分析一些每个寄存器的作用。

vstart

矢量起始位置寄存器指定了执行矢量指令时起始元素位置,每条矢量指令执行后 VSTART 会被清零。

该寄存器只有在处理器进入陷阱或者中断状态时,才会被硬件写入。

所以的向量指令都会从vstart中给定的元素编号开始执行,支持完成后,自动变为0。

为什么会有这个寄存器,原因是在V扩展指令中,每个寄存器是可以分割与合并的,并不是单独操作。

vxsat

这个是向量定点的饱和标志位,该位指示定点指令是否必须使输出值饱和,以此适应目标格式。

vxrm

向量定点舍入模式寄存器,指定了定点指令采用的舍入模式。

vl

矢量长度寄存器指定了矢量指令更新目的寄存器的范围,矢量指令更新目的寄存器中元素序号小于 VL 的元素,清零目的寄存器中元素序号大于等于 VL 的元素。特别的,当 VSTART》=VL 或 VL 为 0 时,目的寄存器的所有元素不 被更新。该寄存器是任意模式下的只读寄存器,但是 vsetvli、vsetvl 以及 fault-only-first 指令能够更新该寄存器的值。

该寄存器的值是通过vsetvli/vsetvl指令自动设置的。

vtype

VTYPE 寄存器指定了矢量寄存器组的数据类型以及矢量寄存器的元素组成。

通过C910的数据手册,可看出

向量长度寄存器VLENB

该寄存器用于表示矢量寄存器的数据位宽,以实际位宽除以 8 得到的字节数体现。C906 矢量寄存器为 128 位,因此 VLENB 值固定为 16。该寄存器位长是 64 位,用户模式只读。

5.通过实例分析RISCV V扩展的运作机制

下面一个rvv实际的函数

void test_v(void)

{

float a[]={1.0,2.0,3.0,4.0};

float b[]={1.0,2.0,3.0,4.0};

float c[]={0.0,0.0,0.0,0.0};

int len=4;

int i=0;

//inline assembly for RVV 0.7.1

//for(i=0; i《len; i++){c[i]=a[i]+b[i];}

asm volatile(

“mv t4, %[LEN]

“mv t1, %[PA]

“mv t2, %[PB]

“mv t3, %[PC]

“LOOP1:

“vsetvli t0, t4, e32,m1

sub t4, t4, t0

“slli t0, t0, 2

” //Multiply number done by 4 bytes

“vle.v v0, (t1)

add t1, t1, t0

“vle.v v1, (t2)

“add t2, t2, t0

“vfadd.vv v2, v0, v1

“vse.v v2, (t3)

“add t3, t3, t0

“bnez t4, LOOP1

:[LEN]“r”(len), [PA]“r”(a),[PB]“r”(b),[PC]“r”(c)

:“cc”,“memory”, “t0”, “t1”, “t2”, “t3”, “t4”,

“v0”, “v1”, “v2”

);

for(i=0; i《len; i++){

printf(“

”);

printf(“%f

”,c[i]);

printf(“

”);

}

}

这里采用的是内联汇编,可以更加深入的分析RVV的运作机制和底层原理。

在riscv中,内联汇编的写法

asm volatile(“nop”);

这样编译器在编译后会生成可以执行的汇编代码。

该函数的功能

for(i=0; i《len; i++){c[i]=a[i]+b[i];}

通过上述分析,通过向量计算,可以一次性计算出上面四次循环加法。

vsetvli t0, t4, e32,m1

vsetvli表示设置每个向量的长度,t4的值表示的是len,也就是4。

e32表示每个元素为32位,m1表示使用1倍数量的向量寄存器。

该条指令相当于把一个向量寄存器(128位)分成四等分,这是一条设置指令,设置vl寄存器。返回值为t0,这里由于是刚好装下4条32位的数字,所以返回值为4。

sub t4, t4, t0

通过查看数组是否计算完成,来进行循环计算,这里t4为0了。

slli t0, t0, 2

往左移动两位,也就是将t0乘以4。这里计算的目的是如果存在很长的数组,可以偏移t0个字节从而指向数组的下个地址。

vle.v v0, (t1)

填充向量寄存器(t1)为a数组,一条指令将数据放到向量寄存器v0中。

add t1, t1, t0

将a数组的起始元素加上16字节(4个元素)的偏移。

vle.v v1, (t2)

填充b数组的数组到向量寄存器v1中。

add t2, t2, t0

将数组b的元素的起始地址偏移16字节,也就是4个元素。

vfadd.vv v2, v0, v1

执行向量加法,将向量的结果保存到向量寄存器v2中。

vse.v v2, (t3)

将向量寄存器中值写回到c数组中。

add t3, t3, t0

将数组c的元素指针偏移4个元素。

bnez t4, LOOP1

直到计算的len长度为0,此时跳出循环计算。

由于此时计算只有4字节,所以一次循环就计算完成了,不用多次计算。

采用向量寄存器的计算,可以把四次循环计算用一次计算就完成。当然这种如果大量计算时,才能体现出更大的优势。

最后的结果如下:

通过对数组的计算

float a[]={1.0,2.0,3.0,4.0};

float b[]={1.0,2.0,3.0,4.0};

float c[]={0.0,0.0,0.0,0.0};

最后c数组的结果

float c[]={2.0,4.0,6.0,8.0};

其理论数据和实际数据一样。

6.RVV使用体验

刚接触到riscv 的 V扩展编程时,很多概念都理解的很模糊,感觉十分的困难,通过一段时间梳理之后,发现和以前mips上接触的mxu或者arm的neno使用上大多数是一样的,就需要去设置使用寄存器的长度,当然这些底层函数如果进行一层封装后,再给用户使用,那才是比较方便的,但是本文只是介绍底层实现的原理,并不多介绍使用的细节。

RVV还有一个特性就是寄存器的扩充,比如D1采用的玄铁C906的核,支持的是32个128位的向量寄存器,也可以将两个或多个向量寄存器拼成一个来使用。这样寄存器的长度更加长,能够同时做到并行计算也就更多。这取决于如何做向量的优化设计。

原文标题:用哪吒D1开发板体验riscv向量底层编程

文章出处:【微信公众号:嵌入式IoT】欢迎添加关注!文章转载请注明出处。

责任编辑:haq

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 寄存器
    +关注

    关注

    31

    文章

    5590

    浏览量

    129077
  • 开发板
    +关注

    关注

    25

    文章

    6126

    浏览量

    113425

原文标题:用哪吒D1开发板体验riscv向量底层编程

文章出处:【微信号:Embeded_IoT,微信公众号:嵌入式IoT】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    易灵思FPGA RISC-V自定义指令的使用方法

    RISC-V(Reduced Instruction Set Computing-V)是一个开源指令集架构(ISA),它的设计目标是提供一个简洁、可扩展且高效的
    的头像 发表于 11-24 11:36 3725次阅读
    易灵思FPGA RISC-<b class='flag-5'>V</b>自定义<b class='flag-5'>指令</b>的使用方法

    【CIE全国RISC-V创新应用大赛】+MUSE Pi Pro RiscV UEFI固件开发

    启动的支持。 RiscV是一种开源的指令集架构(ISA),与UEFI的结合为新兴硬件平台提供了高效的系统启动和管理方案。 1. 环境设置说明 在构建RiscV固件之前,首先需要配置开发环境。以下是设置
    发表于 11-13 00:20

    riscv底层原理分析gd32vf103的中断行为

    的处理,通过csrrw ra, CSR_JALMNXTI, ra指令进行分析。 不难发现,这个是个芯来自定义扩展指令,CSR_JALMNXTI寄存器通过gdb解析可以看到如下的数据
    发表于 10-31 08:04

    全志D1开发板(哪吒 RISCV64)开箱评测

    。 2.支持RVV 这个也较为关键,在RISCV中对于多媒体加速指令上,采用的是V扩展,也就是RISCV
    发表于 10-31 07:50

    riscv实现自定义指令并用qemu运行

    1.说明 riscv支持指令集自定义扩展,这大大增加了riscv的可玩性,同时对于一些实际应用中,自己通过一条指令来实现特定的功能,效率非
    发表于 10-31 07:37

    用哪吒D1开发板体验riscv向量底层编程

    使用的流程。利用了多媒体加速指令集,可以让计算变得更加的高效,同时并行计算的特性使得同时多次计算一组数字成为可能,类似于arm的NEON等等,那么RISCV又该如何去开启和使用V
    发表于 10-29 06:21

    在Linux环境中使用riscv-torture的方法

    步骤: 1、安装riscv-gnu-toolchain 要使用riscv-torture,您需要先安装riscv-gnu-toolchain,工具链提供了RISC-
    发表于 10-24 06:32

    risc-v P扩展(一) P指令集简介

    解码、医学成像、计算机视觉、嵌入式控制、机器人技术、人机界面等。 P指令扩展提高了RISC-V CPU IP产品的DSP算法处理能力。随着RISC-V P
    发表于 10-23 07:40

    RISCV-K指令扩展分享

    RISC-V K扩展指的是RISC-V用于提升密码学算法的速度、减小应用程序大小的一个扩展指令集。主要包含了:AES加密算法的加速
    发表于 10-23 06:12

    RVB 位操作指令扩展(一)

    中进行应用,B扩展分为了几个更细小的子集,zba、zbb、zbc、zbs。 目前,B扩展标准已冻结,可参考官方文档riscv-bitmanip 二、B扩展中包含的
    发表于 10-22 08:11

    基于E203 NICE协处理器扩展指令

    扩展到某些特定领域可以非常明显地提高能效比。NICE协处理器(Nuclei Instruction Co-unitExtension,蜂鸟内核指令协处理器扩展机制)是一个独立于蜂鸟E203内核的一块运算
    发表于 10-21 14:35

    RISC-V V扩展指令代码

    1.指令V扩展的主要内容: 矢量指令:针对数据并行性,增加了一系列新的矢量指令,可以同时对多个数据进行操作,提高了计算效率。浮点
    发表于 10-21 13:11

    RISC-V B扩展介绍及实现

    B扩展简介 RISCV B扩展指的是RISCV用于位运算加速的一个扩展指令集,目的是使用一条
    发表于 10-21 13:01

    e203进行F指令扩展的具体实现

    的简单译码单元来进行(minidec)。 译码单元 译码阶段的主要工作是对所有指令的信息进行译码,将其译成对应的指令操作传给派遣单元,针对F指令扩展对应的
    发表于 10-21 11:51

    浮点指令扩展中16位指令的处理

    指令取代对应的宽指令由它们决定。 为了能在一系列的程序上得到良好的代码压缩效果, RISC-V 架构师精心挑选了 RVC扩展中的指令。同时,
    发表于 10-20 11:02