KaiSpace
tech

MIPS pipelining

什么是pipelining

pipelining的概念很像统筹规划,例如一个零件有需要五个机器依次工作。我们并不需要等一个零件完全做完后再开始下一个零件加工,而是可以第一个零件进入第二步时第二个零件就开始加工,这样可以节省很多时间。

image-20250401151354047

mips将一个instruction的运行拆分成了五个步骤:

image-20250401151606041

每两个步骤中间我们会加入一个pipeline registers(多个register的集合,包含data和control signals)

image-20250401152459164

其作用是:

阶段隔离与时序稳定

流水线寄存器隔离了各个流水线阶段,使得每个阶段的数据和控制信号在时钟边沿被“锁定”,从而在整个时钟周期内保持稳定。这种稳定性确保了数据不会因信号传递延时或噪声而受到干扰。

辅助冒险检测和解决

通过将数据和控制信息保存到各个阶段的流水线寄存器中,冒险检测逻辑可以准确地分析和比较相邻阶段之间的信号,从而识别数据冒险、结构冒险或控制冒险。没有这些隔离寄存器,相关信号可能混合或不稳定,使得冒险检测变得更加复杂或不准确。

降低设计复杂性

使用流水线寄存器将每个阶段的操作独立开来,可以简化时序分析和设计验证工作,同时为系统提供更强的抗干扰能力和鲁棒性。

这样设计后,每一个步骤只需要读取前一个pipeline registers的数值,然后在处理后传给后一个pipeline registers。

有些信息如write register会在前面被覆盖掉,所以这个需要一同传给MEM/WB pipeline registers。

对于control signal,我们可以derive以下diagram:

image-20250401152951574

image-20250401153013658

加入使用时序后,可以得出以下diagram:

image-20250401153127224

pipelining的问题(Pipeline hazards)

1. structural hazards

Simultaneous use of a hardware resource

image-20250401153334652

同一个时钟周期使用mem。

Solution1: Inst3 delay(stall) 3 cycles

Solution2: 我们需要将mem的访问分成两个部分:Data memory和Instruction Memory。

同样地,我们可以将reg的重叠分成半个clock cycle的write和read:
image-20250401153703819

2. Data Hazards

这个和下一个control hazards本质上都是data dependency的问题,如果RAW (Read After Write)访问同一个register,则会出现data hazards,如果一个指令 depends on 另一个指令,则会出现Control hazards (beq, bne) 。

如果第二个Instruction需要立刻使用上一个instruction的结果,我们就需要将上一个的execution(ALU) result 传递给下一个instruction的ALU,并覆盖(by pass)掉从reg读取的data。这个过程称为forwarding。
image-20250401154050422

但是load instruction是必须结束DM才能够得到register的数值,这种情况下我们就需要stall。

image-20250401154214816

对于同一个register,WB和ID可以同时进行,lw的情况下,下一个instruction的EX会获取MEM的结果(不需要等WB),并覆盖ID的register value。

3. Control Hazards

beq和bne语句需要跳转,但是如果我们继续使用pipelining可能会execute顺序错误。这时我们用三个方法保证pipelining的正确性:

  1. Early Branch Resolution:
    我们为beq和bne语句特殊快速处理。这样我们可以在reg stage结束就能得到结果。image-20250401154644156

    image-20250401154744324

    如果beq紧跟在beq所需register赋值后面,或者lw后面,需要stall更多时间。(无法继续优化)

  2. branch prediction

    假设不会跳转,接着执行后续命令。如果猜错了,跳转了,那么将后面instruction之后的步骤全部清空不做了。

    image-20250401160632680

    这个优化其实不多,因为在循环中,branch一般是taken的。

  3. delayed branch

    可以独立进行的在beq和bne前面的操作可以放到紧接着beq和bne做,这样无论是否take都不需要flush,通常能节省50%的时间。(compiler must be smart enough to pre-execute the ordering problem)

    image-20250401160956587

本文图片大量借鉴NUS CS2100 slides

Comments

No comments yet.