跳转至

前端基础流水线

该处理器采取双取指的实现方式,前端的每一个流水级在每个周期内至多运输两条指令。下面对各个流水级进行介绍:

1 预取指阶段

预取指阶段包括程序计数器(PC)、取指地址转换单元(Inst-TLB)和分支预测器构成。

该阶段产生两个顺序指令地址送入流水线,并使用这两个地址对分支指令的方向和目标地址进行预测。

若PC当前对齐4字节但不对齐8字节,虽然在大多数情况下指令高速缓存仍然可以给出两条指令,但为减少分支预测器的延时和复杂度,在当前的设计中,这种情况下仅会存在一条有效指令,下个周期取指地址依然会回到8字节对齐的状态。

2 取指阶段

取指阶段主要由指令高速缓存(ICache)构成。

由于地址转换已经在预取指阶段完成,故ICache的访问是基于物理地址的。若ICache命中,则会给出地址相邻的两条指令,否则流水线的前两个阶段将陷入阻塞,直至缺失的缓存块从内存中读出。

3 预译码阶段

在预译码阶段,处理器会对指令进行跳转检查,即在分支预测器没有记录该指令时:

  • 若指令为直接必定跳转指令(BL、B),则预译码器会触发分支预测失败,并利用PC和指令中的立即数计算出正确地址,抹除前两个阶段的指令重新取指;
  • 若指令为分支指令,则预译码器会根据立即数最高位判断跳转方向:若立即数为负数,则认为该指令为循环跳转指令,并触发分支预测失败重新取指,否则认为该指令不予跳转。
  • 若指令不为任何跳转分支指令,则分支预测器一定将一条不为分支的指令判断为分支指令(这种情况在自修改程序中较为常见),此时预译码器触发分支预测失败,重新取指。

由于处理器的流水级较深,分支预测失败的代价过大。当分支预测器发生容量缺失时,预译码器可以及时纠正译码。在维护正确性方面,预译码器也阻止了“非跳转指令预测错误且不进入分支指令功能单元”这一影响正确性的情况发生。

经过预译码的指令会被送入取指队列。该队列由交叠实现的伪双端口FIFO实现,每个周期可以送入0~2条指令,并发射出0或2条指令。

4 译码阶段

译码阶段由译码器和空闲物理寄存器列表构成。

译码器借助Chisel中的BitPat自动生成组合逻辑,负责对从取指队列中发射出的至多2条指令进行译码,获得其寄存器、ALU操作数、访存类型、跳转类型等信号。

空闲物理寄存器列表为需要写寄存器堆的指令分配空闲物理寄存器,并从提交阶段获取待废除的物理寄存器。若空闲物理寄存器列表为空,则需要阻塞流水线前4个阶段,直至后端有待废除的物理寄存器提交至此。

5 重命名阶段

重命名阶段由寄存器映射表和分派器构成。

5.1 重命名系统

在重命名系统中,寄存器映射表由CRat构成,采用全相连的方式,利用逻辑寄存器的编号和每一个存储单元分别比较,并获取到对应的物理寄存器编号及其当前是否滞留在发射队列的信息。同时,对于需要目的寄存器的指令,当前周期还会将表中的有效位置位,并标记其为“滞留于发射队列”的状态。由于每个周期有两条指令需要重命名,因此可能出现写后读和写后写相关,需要对读出的源寄存器编号进行修缮,并决定写后写时将哪个逻辑寄存器写入映射表。

每条指令不仅需要读出两个源寄存器对应的物理寄存器编号,还需要读出目的寄存器曾经对应的物理寄存器编号,这个编号作为待废除的物理寄存器编号,将会在提交阶段提交给空闲物理寄存器列表。

由于重命名处在推断状态,因此在提交阶段,处理器维护了另一个绝对正确的映射有效位表,当发生分支预测失败时,重命名阶段的有效位表会被设置为提交阶段的有效位表,从而实现了映射关系的恢复。

5.2 分派器

分派器是连接处理器前端和后端的重要元件。这个单元会根据译码阶段给出的发射队列选择信号,为每一个发射队列提供如下信息:

  • 当前周期需要进入该发射队列的指令掩码
  • 当前周期需要进入该发射队列的指令处于这该指令组的哪个位置

对于功能相同的发射队列,分派器会比较当前这些发射队列中存在的指令总数,将指令送入总数较少的队列。

5.3 指令顺序的维护

在这个阶段,每一条指令会从重排序缓存(ROB)中获取1个顺序编号。这个编号将会伴随这条指令进入后端,直至其完成执行并顺序提交。若当前周期重排序缓存已满,则需要阻塞流水线前5个阶段,直至有指令提交。