手把手教你蜂鸟e203协处理器的扩展
NICE协处理器
赛题要求:
对蜂鸟E203 RISC-V内核进行运算算子(譬如加解密算法、浮点运算、矢量运算等)的扩展,可通过NICE协处理器接口进行添加,也可直接实现RISC-V指令子集(譬如P扩展、F/D扩展、V扩展、B扩展、K扩展等)
对于采用NICE协处理器接口进行的扩展实现,需要在蜂鸟软件开发平台HBird SDK中进行相关软件驱动的添加
实现思路:
- 1.硬件设计,编写相应的verilog文件,需要注意的是NICE协处理器定义了一些基本的接口;
- 2.编写驱动,通过内联汇编的伪指令.insn配置相关的驱动设置;
- 3.编写用于测试的.C文件。
参考示例:
- 背景: 假设有一个3行3列的矩阵按顺序存储在存储器中,每个元素都是32位的整数,目标进行逐行和逐列的累加和,若采用C语言调用主数据通路进行实现,基本思路是循环,按行/列读取各个元素然后相加得到各行/列的累加和,将其转换为汇编语言,则需要约上百个周期才能完成全部运算。

硬件实现:(不太好写)
(e203_hbirdv2-master\e203_hbirdv2-master\rtl\e203\subsys\e203_subsys_nice_core.v)->NICE协处理器工作机理:
- 请求通道:主处理器在流水线的EXU级时,将指令的编码信息和源操作数传输到协处理器。
- 反馈通道:协处理器告诉主处理器其已完成了该指令,并将结果反馈到主处理器。
- 存储器请求通道:协处理器向主处理器发起存储器读写请求。
- 存储器反馈通道:主处理器向协处理器写回存储器读写结果。

->NICE示例协处理器的设计:
控制模块(和主处理器通过NICE协处理器的接口进行交互)+累加器(累加运算)->NICE示例协处理器的自定义指令

->verilog文件中包含内容:
自定义指令的编码+各模块功能实现(以状态机实现的转换)软件驱动:
(nuclei-board-labs-master\nuclei-board-labs-master\e203_hbirdv2\common\demo_nice\insn.h)
基本格式:
.insn r opcode, func3, func7, rd, rs1, rs2
//.insn告知编译器当前的指令是.insn形式的指令
//r用来表示指令类型为R-type
//opcode、func3、func7、rd、rs1、rs2分别代表R类型指令格式的各位域
具体实现:(累加和)
// custom lbuf
__STATIC_FORCEINLINE void custom_lbuf(int addr)
{
int zero = 0; asm volatile (
".insn r 0x7b, 2, 1, x0, %1, x0"
:"=r"(zero)
:"r"(addr)
);
} // custom sbuf
__STATIC_FORCEINLINE void custom_sbuf(int addr)
{
int zero = 0; asm volatile (
".insn r 0x7b, 2, 2, x0, %1, x0"
:"=r"(zero)
:"r"(addr)
);
} // custom rowsum
__STATIC_FORCEINLINE int custom_rowsum(int addr)
{
int rowsum; asm volatile (
".insn r 0x7b, 6, 6, %0, %1, x0"
:"=r"(rowsum)
:"r"(addr)
); return rowsum;
}
- 测试程序:(nuclei-board-labs-master\nuclei-board-labs-master\e203_hbirdv2\common\demo_nice\insn.c --> 功能实现;nuclei-board-labs-master\nuclei-board-labs-master\e203_hbirdv2\common\demo_nice\main.c --> 顶层文件,测试输出)
/***********************************insn.c*********************************/
// normal_case:通过主流水线来实现的累加操作
int normal_case(unsigned int array[ROW_LEN][COL_LEN])
{
volatile unsigned char i=0, j=0;
volatile unsigned int col_sum[COL_LEN]={0};
volatile unsigned int row_sum[ROW_LEN]={0};
volatile unsigned int tmp=0;
for (i = 0; i < ROW_LEN; i++)
{
tmp = 0;
for (j = 0; j < COL_LEN; j++)
{
col_sum[j] += array[i][j];
tmp += array[i][j];
}
row_sum[i] = tmp;
}
} // nice_case:调用NICE协处理器实现的累加操作
int nice_case(unsigned int array[ROW_LEN][COL_LEN])
{
volatile unsigned char i, j;
volatile unsigned int col_sum[COL_LEN]={0};
volatile unsigned int row_sum[ROW_LEN]={0};
volatile unsigned int init_buf[3]={0}; custom_lbuf((int)init_buf);
for (i = 0; i < ROW_LEN; i++)
{
row_sum[i] = custom_rowsum((int)array[i]);
}
custom_sbuf((int)col_sum);
} /***********************************main.c*********************************/
// 主要就是调用两个函数然后输出结果
int main(void)
{
int i=100;
int arr[4]={1,2,3,4};
unsigned int array[ROW_LEN][COL_LEN]=
{{10,20,30},
{20,30,40},
{30,40,50}
};
unsigned int begin_instret, end_instret, instret_normal, instret_nice;
unsigned int begin_cycle, end_cycle, cycle_normal, cycle_nice; printf("**********************************************\n");
printf("** begin to sum the array using ordinary add sum\n");
begin_instret = __get_rv_instret();
begin_cycle = __get_rv_cycle(); normal_case(array); end_instret = __get_rv_instret();
end_cycle = __get_rv_cycle(); instret_normal = end_instret - begin_instret;
cycle_normal = end_cycle - begin_cycle;
printf("\n\n"); printf("**********************************************\n");
printf("** begin to sum the array using nice add sum\n");
begin_instret = __get_rv_instret();
begin_cycle = __get_rv_cycle(); nice_case(array); end_instret = __get_rv_instret();
end_cycle = __get_rv_cycle(); instret_nice = end_instret - begin_instret;
cycle_nice = end_cycle - begin_cycle; printf("**********************************************\n");
printf("** performance list \n"); printf("\t normal: \n");
printf("\t instret: %d, cycle: %d \n", instret_normal, cycle_normal);
printf("\t nice : \n");
printf("\t instret: %d, cycle: %d \n", instret_nice , cycle_nice ); printf("**********************************************\n\n"); printf("* * * * ***** * ******* *** \n");
printf("** * * * * * * * * \n");
printf("* * * * * * * * * \n");
printf("* * * * * * * ***** * \n");
printf("* * * * * * * * * \n");
printf("* ** * * * * * * * \n");
printf("* * ***** ***** ******* ******* *** \n"); printf("\n\n**********************************************");
return 0;
}
- 实际测试:
法一:(不推荐)通过.c文件配置工程,参考这里(5.3. 无模板手动创建项目)
法二:(推荐)
- 创建HelloWorld例程,删除左侧相应工程目录下application/main.c文件

- 将我们所编写的软件驱动文件和测试文件放入该目录下

- 点击锤子进行编译,做好硬件连接后,点击️️绿色的三角运行。
采用NICE协处理器进行的累加所用的指令数和周期数都远小于普通情况,如下图所示。

一些疑惑:
- 对于NICE协处理器和普通的情况,均进行了诸如循环读寄存器数据之类的操作,那么实现NICE协处理器相较于普通情况的优化体现在什么方面,节约的是进行取数+计算的时间,还是其他诸如循环控制等的时间;
- 是否应该根据后续的系统及应用来判断进行什么样的扩展;
- 对于添加了NICE协处理器的内核,其跑分结果应该有所提高,那么该如何通过跑分的程序测试出来;
3.NucleiStudio+Vivado联合仿真教程
猜测后续的工作流程:
Benchmark:
Vivado中修改RTL设计-->NucleiStudio中跑分验证/Vivado中仿真验证(尝试跑通中);指令集扩展:
Vivado中添加RTL设计+IDE中添加软件驱动-->NucleiStudio中验证功能/Vivado中仿真验证功能(当前尝试的NICE协处理器可仿真验证)
编写了一个Nucleistudio+Vivado联合仿真的教程,或许会有用((。
手把手教你蜂鸟e203协处理器的扩展的更多相关文章
- 手把手教你蜂鸟e203移植(以Nexys4DDR为例)
准备工作:(网盘链接:) 1.蜂鸟e203的RTL源码: 2.一段分频代码: 3.顶层设计文件(system.v) 4.开发板文件: 5.Nexys4DDR电路图: 6.Nexys4DDR管脚约束模板 ...
- 手把手教你开发chrome扩展一:开发Chrome Extenstion其实很简单
手把手教你开发chrome扩展一:开发Chrome Extenstion其实很简单 手把手教你开发chrome扩展一:开发Chrome Extenstion其实很简单 手把手教你开发Chrome扩 ...
- 菜鸟-手把手教你把Acegi应用到实际项目中(8)-扩展UserDetailsService接口
一个能为DaoAuthenticationProvider提供存取认证库的的类,它必须要实现UserDetailsService接口: public UserDetails loadUserByUse ...
- 手把手教你开发chrome扩展
转载:http://www.cnblogs.com/walkingp/archive/2011/04/04/2003875.html 手把手教你开发chrome扩展一:开发Chrome Extenst ...
- 手把手教你Chrome扩展开发:本地存储篇
手把手教你开发chrome扩展一:开发Chrome Extenstion其实很简单 手把手教你开发Chrome扩展二:为html添加行为 手把手教你开发Chrome扩展三:关于本地存储数据 HTML5 ...
- 手把手教你开发Chrome扩展三:关于本地存储数据
手把手教你开发chrome扩展一:开发Chrome Extenstion其实很简单 手把手教你开发Chrome扩展二:为html添加行为 手把手教你开发Chrome扩展三:关于本地存储数据 HTML5 ...
- 手把手教你开发Chrome扩展二:为html添加行为
手把手教你开发chrome扩展一:开发Chrome Extenstion其实很简单 手把手教你开发Chrome扩展二:为html添加行为 手把手教你开发Chrome扩展三:关于本地存储数据 上一节我们 ...
- 手把手教从零开始在GitHub上使用Hexo搭建博客教程(二)-Hexo参数设置
前言 前文手把手教从零开始在GitHub上使用Hexo搭建博客教程(一)-附GitHub注册及配置介绍了github注册.git相关设置以及hexo基本操作. 本文主要介绍一下hexo的常用参数设置. ...
- 手把手教你写Sublime中的Snippet
手把手教你写Sublime中的Snippet Sublime Text号称最性感的编辑器, 并且越来越多人使用, 美观, 高效 关于如何使用Sublime text可以参考我的另一篇文章, 相信你会喜 ...
- 30分钟手把手教你学webpack实战
30分钟手把手教你学webpack实战 阅读目录 一:什么是webpack? 他有什么优点? 二:如何安装和配置 三:理解webpack加载器 四:理解less-loader加载器的使用 五:理解ba ...
随机推荐
- vue中v-show你不知道的用法 created computed mounted的执行顺序
我们都知道,v-show的值是一个布尔类型的. 我通过这个值进行显示或者隐藏. 但是有些时候,这个值是true还是false,我们需要去进行计算 此时我们就可以使用v-show="XXX() ...
- 情侣纪念日网站html5源码教程
个人名片: 对人间的热爱与歌颂,可抵岁月冗长 Github:念舒_C.ying CSDN主页️:念舒_C.ying 个人博客 :念舒_C.ying 预览图 直接进入我的网站吧 >> Z_ ...
- 什么是 Java 字节码?采用字节码的好处是什么?
在 Java 中,JVM 可以理解的代码就叫做字节码(即扩展名为 .class 的文件),它不面向任何特定的处理器,只面向虚拟机.Java 语言通过字节码的方式,在一定程度上解决了传统解释型语言执行效 ...
- 创建Vue项目,报错spawn yarn ENOENT
1. 使用 vue 创建项目的时候,报错 Error: spawn yarn ENOENT 1.1 用户自己设置了默认的包管理 yarn 1.2 没有安装 yarn 解决方式1: 打开 C盘 , 在 ...
- VB6各类源码开源 - 开源研究系列文章
今天把以前下载整理的关于VB6的一些代码进行了开源,覆盖了多个分类内容,需要的朋友请下载: VB6源码.part1 https://download.csdn.net/download/lzhdim/ ...
- uniapp面试题
.markdown-body { line-height: 1.75; font-weight: 400; font-size: 16px; overflow-x: hidden; color: rg ...
- Program文件的作用
Program.cs文件分析 Program.cs文件是至关重要的一个文件,它包含应用程序启动的代码,还可以配置所需要的服务和应用管道的中间件. 需要掌握: 6.0版本前后生成的Program.cs文 ...
- 用GPT4聊天制作AI绘画搞笑视频,播放量近10w,附GPT4开通教程
AI一天,人间一年 大家好,我是小卷,最近大家在视频号.抖音刷短视频时,是不是经常刷到那种用AI生成的聊天搞笑绘画视频.比如下面这个视频:南方小土豆来哈尔滨 又或者是AI眼中的各个大学 又或者是两个大 ...
- webrtc终极版(题外话)辛苦写文章分享,竟然遇到喷子狂喷,写篇文章回怼下,顺便发表下面对喷子的处理方式
webrtc终极版(题外话)辛苦写文章分享,竟然遇到喷子狂喷,写篇文章回怼下,顺便发表下面对喷子的处理方式 第一篇文章发过后,出人意料的是,收到了博客园某一位用户的狂喷[注:本系列文章会同步发布到cs ...
- 【进阶篇】Java 实际开发中积累的几个小技巧(一)
目录 前言 一.枚举类的注解 二.RESTful 接口 三.类属性转换 四.Stream 流 五.判空和断言 5.1判空部分 5.2断言部分 文章小结 前言 笔者目前从事一线 Java 开发今年是第 ...