NICE协处理器的调用需要创建用户自定义RISC-V的指令,NICE 支持自定义硬件联合单元的集成,从而提高特定领域的性能,同时降低功耗[6]。
本设计开发了一个加法运算的协处理器用于加速累加运算操作,其中利用了DDR3数据存储器作为数据缓冲区(详见本论文4.1),将所需进行累加操作的三个数据输入到DDR3内部进行存储,利用NICE协处理器操作存储器提取所需数据到协处理器内部,处理后的数据通过rd寄存器输出,如图4-9所示。由于协处理器的运行是独立于处理器的内核,故可以独立于主处理器进行运算操作,可以减少运行的指令并减少流水线处理累加运算的时钟周期。

调用NICE接口有4个通道,请求通道、内存请求通道、响应通道、和内存响应通道。请求通道:主处理器在流水线的EXU级时,将指令的编码信息和源操作数传输到协处理器。反馈通道:协处理器告诉主处理器其已完成了该指令,并将结果反馈到主处理器。存储器请求通道:协处理器向主处理器发起存储器读写请求。存储器反馈通道:主处理器向协处理器写回存储器读写结果。各个通道信号说明如表4-2所示。
| 通道 | 方向 | 宽度 | 信号名 | 描述 |
|---|---|---|---|---|
| 请求通道 | Output | 1 | nice_req_valid | 主处理器发送指令请求信号给协处理器 |
| Input | 1 | nice_req_ready | 协处理器返回指令接收信号到主处理器 | |
| Output | 32 | nice_req_instr | 自定义指令的32位完整编码 | |
| Output | 32 | nice_req_rs1 | 源寄存器 1 的值 | |
| Output | 32 | nice_req_rs2 | 源寄存器 2 的值 | |
| 反馈通道 | Input | 1 | nice_rsp_valid | 协处理器发送反馈请求信号到主处理器 |
| Output | 1 | nice_rsp_ready | 主处理器返回反馈接收信号给协处理器 | |
| Input | 32 | nice_rsp_data | 返回指令的执行结果 | |
| Input | 1 | nice_rsp_err | 返回该指令的错误标志 | |
| 存储器请求通道 | Input | 1 | nice_icb_cmd_valid | 协处理器发送存储器读写的请求信号到主处理器 |
| Output | 1 | nice_icb_cmd_ready | 主处理器返回存储器读写的接收信号给协处理器 | |
| Input | 32 | nice_icb_cmd_addr | 内存访问请求地址 | |
| Input | 1 | nice_icb_cmd_read | 内存访问请求的写入或读取(0:写1:阅读) | |
| Input | 32 | nice_icb_cmd_wdata | 写入存储器的数据 | |
| Input | 2 | nice_icb_cmd_size | 读写数据的大小(2'b00:字节;2'b01:半字;2'b10:1位;2'b11:保留) | |
| 存储器反馈通道 | Output | 1 | nice_icb_rsp_valid | 主处理器发送存储器读写反馈请求信号到协处理器 |
| Input | 1 | nice_icb_rsp_ready | 协处理器返回存储器读写反馈接收信号给主处理器 | |
| Output | 32 | nice_icb_rsp_rdata | 存储器读反馈的数据 | |
| Output | 1 | nice_icb_rsp_err | 存储器读写反馈的错误标志 | |
| Input | 1 | nice_mem_holdup | 协处理器占用存储器的信号(防止主处理器的后续指令继续访问内存,主处理器和协处理器同时访问内存可能导致竞争性失锁) |
调用协处理器的方法:扩展一个用RTL级代码编写的协处理器,想个办法调用这个独立于流水线的计算单元,调用协处理器应用起来的方法是:在MCU层面,在编译器里编写C语言主函数中包含指定汇编指令的调用,完成驱动的配置。在nuclei-board-labs-master\e203_hbirdv2\common\demo_nice里的insc.h给了调用的示例。
// 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;
}
这里E203内核提供了NICE接口。通过自定义指令调用协处理器的过程如图4-9所示。

NICE指令的完整执行过程如下:
协处理器的功能模块在NICE协处理器内部,如图4-9所示。通过自定义指令调用协处理器后,协处理器的功能模块进行运算。本设计开发了一个累加运算模块用于累加运算,如图4-11所示。输入3个数时,先提取前两个数相加,再将第一次加法的和与第三个数相加,输出3个数的累加值[23]。

输入10、20、30三个数进入协处理器做累加运算,通过Nuclei Studio编译器的调试信息打印所运算的结果,如图4-12所示。为了对比使用协处理器对累加运算的加速效果,设置了一组不使用协处理器的累加对比项(normal),可以发现协处理器可以进行累加运算,运算结果为60。

因为关闭调试信息打印输出的情况下处理器可以节约一部分串口输出数据printf函数指令,这里便关闭了调试信息打印输出。可以发现:自定义指令调用NICE协处理器中的累加运算模块进行三个数的累加运算比普通C语言编写的累加运算读写减少了82条指令,同时减少了106个时钟周期,累加运算的性能提升了52%,如图4-13所示。可以预见的是,所涉及的累加运算越多,性能提升越明显。
