关于rocc的内容很多,我会分多章进行讲解。
初步规划以下面章节为划分。
1. 协议,自定义指令说明。
2. rocket-chip RoCC各模块的scala代码说明。
3. 软件代码编译实现。
4. rocket-chip RoCC各模块硬件实现和硬件仿真。
第一部分介绍的定制CSR寄存器和定制指令的协议内容。
1) CSR寄存器扩展
在The RISC-V Instruction Set Manual Volume II: Privileged Architecture中查找custom的时候可以找到table2.1。这个表是各种模式下CSR寄存器的地址划分。
The top two bits (csr[11:10]) indicate whether the register is read/write (00, 01, or 10) or read-only (11). The next two bits (csr[9:8]) encode the lowest privilege level that can access the CSR[1].
我们可以在不同的模式下添加自定义的CSR寄存器,但添加的CSR寄存器地址要符合协议的规定。
SiFive系列的CPU就有自定义CSR寄存器的例子:
2) msatus的XS域
在rocket处理器中有一个寄存器 mstatus,其中有一个XS域,该域的值只有为非零的时候,才可以执行自定义指令,否则会出现无效指令异常。默认情况下该域的值为零,需要通过程序修改该值[2]。
关于XS域的内容,可以查看RISC-V指令集卷II特权指令集,我在这列举一些重点的内容。
-
The XS field encodes the status of additional user-mode extensions and associated state.
-
These fields can be checked by a context switch routine to quickly determine whether a state save or restore is required. If a save or restore is required, additional instructions and CSRs are typically required to effect and optimize the process.
-
XS[1:0]的含义:
-
When an extension’s status is set to Off, any instruction that attempts to read or write the corresponding state will cause an illegal instruction exception. When the status is Initial, the corresponding state should have an initial constant value. When the status is Clean, the corresponding state is potentially different from the initial value, but matches the last value stored on a context swap. When the status is Dirty, the corresponding state has potentially been modified since the last context save.
-
XS[1:0]的转换状态情况:
对于XS[1:0]的含义,我的理解是在需要使用额外用户模式扩展时,对上下文(32个通用寄存器)的保存和装载起到指示作用,以此达到快速切换上下文的目的。
根据XS[1:0]的转换状态,可以知道:
- 当XS[1:0]=Off的时候,使用额外用户模式扩展会产生异常
- 当XS[1:0]=Off的时候,可以使用CSR配置指令修改XS[1:0]的状态,同时不会产生异常。
- 当XS[1:0]=Initial的时候,使用额外用户模式扩展,需要将XS[1:0]改为Dirty。
- 当XS[1:0]=Initial的时候,关闭额外用户模式扩展,需要将XS[1:0]改为Off。
- 当XS[1:0]=Clean的时候,使用额外用户模式扩展,需要将XS[1:0]改为Dirty。
- 当XS[1:0]=Clean的时候,不配置额外用户模式扩展,需要将XS[1:0]改为Initial。
- 当XS[1:0]=Clean的时候,关闭额外用户模式扩展,需要将XS[1:0]改为Off。
- 当XS[1:0]=Clean的时候,使能额外用户模式扩展,需要将XS[1:0]改为Initial。
- 当XS[1:0]=Dirty的时候,存储当前上下文情况,因为存完后memory和当前值是一致的,所以需要将XS[1:0]改为Clean。
- 当XS[1:0]=Dirty的时候,不应该存在装载操作,这样会覆盖当前的所有内容。
- 当XS[1:0]=Dirty的时候,不配置额外用户模式扩展,需要将XS[1:0]改为Initial。
- 当XS[1:0]=Dirty的时候,关闭额外用户模式扩展,需要将XS[1:0]改为Off。
- 当XS[1:0]=Dirty的时候,使能额外用户模式扩展,需要将XS[1:0]改为Initial。
我配置的rocket-chip只有单一的机器模式(M),用户模式(U)和管理模式(S)均没有带上,同时在软件程序方面没有过多的线程,都是直接运行在机器模式上的,不需要太多的上下文切换。而且在启动定制指令和rocc扩展接口后,两者在CPU运行期间均一直被使用,没有再次关闭的情况,所以我只需要解决“当XS[1:0]=Off的时候,使用额外用户模式扩展会产生异常”的情况,因此我在bootrom中直接将XS[1:0]由Off改为Dirty,且一直沿用不再改变。
3) 定制指令扩展
接下来介绍的是定制指令的格式。RISC-V协议已经预留了custom0~3这四条定制的指令。
可以扩展额外的定制指令,但需要避开RISC-V已经使用的opcode或者未来预留的opcode,同时在gcc编译的时候,需要使用底层汇编实现对应的扩展指令。rocket-chip是直接使用custom0~3作为rocc的扩展指令,因此为了方便,我会沿用custom0/1/2/3这几条预留的定制指令。
需要注意的是custom0~3均采用R类指令格式。RISC-V各指令类别如下图所示。
也就是说custom0~3指令使用了三个通用寄存器,rs1,rs2和rd。rs1和rs2作为目标寄存器,而rd作为返回寄存器,opcode是固定的,可以看table24.1,funct7和funct3是可以自由处理的,rocket-chip的accumulator模块就使用了funct7作为功能的区分,funct3也作为了特殊的使用,后面章节会对funct7和funct3作详细说明。
参考文献:
[1] A. Waterman, Y. Lee, R. Avizienis, D. A. Patterson, and K. Asanović. The RISC-V instruction set manual volume II: Privileged architecture version 1.7. Technical Report UCB/EECS-2015-49, UC Berkeley EECS, May 2015.
[2] 雷思磊. 开源处理器Rocket的自定义指令研究与测试[J]. 单片机与嵌入式系统应用, 2017(5).