为了记录和帮助后人学习和修改Rocket Core的源代码,我计划写一个“Rocket Core源代码笔记”系列。这个系列主要解释UCB的rocket-chip中Rocket核心的代码,即src/main/scala/rocket/RocketCore.scala
代码(在不同的版本中,文件的命名不同。)。这个系列可以帮助你理解和修改Rocket核心。
因为我并不是硬件设计专业出身,可能会有很多错误,欢迎联系我指出错误和交流。Email:assasaki@163.com,或者通过评论等联系方式联系我。很多部分我并没有关注或者不懂,欢迎一同完善。
之后还会公开一个整个核心的原理图,等待完成会将会在这里更新。
update:正在进行的原理图 预览,如果你想参与进来,请联系我。
前置技能
- 了解RISCV基础
- RISCV用户指令手册
- Chisel
- 计算机体系结构,CPU流水相关概念
这一些列假设你了解CPU的多级流水的构造,我更多的希望把代码中如何和理论上对应讲清楚,而不是讲CPU本身的原理。
总览
Rocket是一个5级流水(IF,ID,EX,MEM,WB)的单发射精简指令集CPU,在Rocket Chip中,Rocket Core只包括CPU核心的逻辑,需要配合其他功能模块一起使用(Cache,乘法器,加法器,RoCC等)。我们只讨论核心自身的逻辑,基本不讨论其他模块的功能。
在开始细节前,我们大概浏览一下整体结构和需要关注的一些原理。这基本上是之后可能写的一个大致的目录。
五级流水
我们先简述一下五级流水分别的功能。
- IF
- 取指阶段主要由ibuf部件来实现,具体的实现在ibuf.scala中。在Rocket Core中没有过多的逻辑。
- ID
- Decode阶段主要对ibuf提供的指令进行解码,即解析出控制线的信息,存放到id_ctrl(控制寄存器)中,和一些其他的信息。
- Decode的解码逻辑在decode.scala中,映射关系在idecode.scala中。
- ID阶段还会对读取寄存器的值,供EX阶段使用,但这个值并不一定正确,需要经过bypass等逻辑才是正确的值。
- EX
- EX阶段是执行的阶段,不同的指令会决定使用何种部件。
- ALU执行加法运算和分支指令的比较等,源码在alu.scala中。
- DIV执行乘除法运算,源码在div.scals中。
- 访存指令会在EX阶段准备好Cache的request值。
- MEM
- MEM阶段是访存阶段,访存部件是dmem,源码在DCache.scala中。
- MEM阶段还会计算一个分支指令和跳转指令的目的地址。
- WB
- 写回阶段主要是将结果写回寄存器。
- 在Rocket Core中,写回部分包括加法器,乘法器,访存和RoCC等需要写回的操作,每个周期只能写回一个寄存器,存在优先级问题。
- RoCC的指令发送阶段也在WB阶段,因为WB阶段才能确定好发送给RoCC的寄存器值。(这里其实MEM阶段应该也准备好了,为什么不在MEM阶段发送指令我也不知道。)
功能部件
- IO
- interrupts
- imem:连接一级指令Cache
- dmem:连接一级数据Cache
- ptw
- fpu
- rocc
- trace
- 功能部件
- rf:RegFile,32个寄存器,其中0位恒等于0。
- FPU:浮点运算
- CSR
- BPU:breakpoints
- RoCC:指令扩展核心
- ALU:加法器
- DIV:乘法器
- sboard:记分牌,这里的记分牌是最简单的二值记分牌
需要关注的机制
打算讨论的:
- bypass:旁路在代码中如何实现?
- sboard:记分牌在Rocket Core中是如何使用的?
- 控制流:下一条指令是如何产生的?
- Exception:异常如何产生和处理
- 多周期指令如何处理?(Cache Miss,乘法等)
没关注/不懂的/看心情的:
- CSR
- replay
- stall