Rocket Core源代码笔记——入门

开始一个系列,记录一下对Rocket Core源代码的学习。

Posted by Readm on February 19, 2018

为了记录和帮助后人学习和修改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

To be continued :)