取指级
取指 (Fetch) 阶段进行分支预测, 根据分支预测的结果更新程序计数器 PC, 同时向指令缓存 (ICache) 发出请求, 每一拍最多从 ICache 中读取一个 Cache Line (64bit) 的数据, 可换算为 2 条普通指令或者 4 条压缩指令. 指令缓存返回的结果会被压入到指令对齐缓冲 (IBF) 中, 由指令对齐缓冲识别指令边界并交给译码逻辑.
分支预测
NutShell 使用 Next-Line 分支预测器 (NLP). 它负责给出下一周期前端指令缓存请求的地址. 在 Next-Line 分支预测器预测跳转不会发生的情况下, 前端会发出当前程序计数器 (PC)+8 的取指请求. 默认的前端分支预测器使用两位饱和计数进行预测, 提供 512 项的跳转目标缓存 (BTB) 和 16 项的返回地址栈 (RAS). Next-Line 分支预测器在更新时会记录跳转指令的种类, 随后会根据跳转指令的种类来进行不同的预测. Next-Line 分支预测器在后端跳转指令写回时更新. 针对 64bit 的取指宽度, NLP 会返回 4bit 的跳转预测向量. 跳转预测向量标识在哪条指令处可能发生跳转, 指令对齐缓冲将使用跳转预测向量来选择有效的指令. 关于分支预测器更多的细节请参考 “分支预测单元” 这一节.
指令对齐缓冲
为了处理引入 RISC-V 压缩指令 RVC 后的指令对齐问题, 前端设置了单独的指令对齐缓冲, 它会判断指令的长度并将不同的指令分离. 如果有指令横跨两次 ICache 结果, 指令对齐缓冲会负责将其拼接成一条指令, 将拼接好的指令交给指令译码单元 (IDU) 进行译码.