# 指令流水线

# 流水线数据通路和控制器

# load 指令的 5 个阶段

image-20240114162856503

# 单周期指令模型和流水线模型性能

image-20240114163103806

流水线方式下,单条指令的执行时间不能缩短,但能大大提高指令的吞吐量

# 流水线指令集的设计

具有什么特征的指令集有利于流水线执行呢

  • 指令长度尽量一致,有利于简化取指令和指令译码操作

    • MIPS 指令都是 32 位,每次取四个单元的指令,且下址计算方便: PC+4

    • X86 指令从 1 字节到 17 字节不等,使取指部件及其复杂

  • 指令格式少,且源寄存器位置相同,有利于在指令未知时就可取操作数

    • MIPS 指令的 Rs 和 Rt 位置一定,在指令译码时就可读 Rs 和 Rt 的值(若位置随指令不同而不同,则需先译码确定指令后才能取寄存器编号)
  • 只有 load / Store 指令才能访问存储器,有利于减少操作步骤,规整流水线

    • 可以把 lw/sw 指令的地址计算和运算指令的执行步骤规整在同一个周期
    • X86 运算类指令的操作数可以是内存数据,故需计算地址、访存、执行
  • 数据和指令在内存中要” 对齐” 存放,有利于减少访存次数和流水线的规整
    总之,规整、简单和一致等特性有利于指令的流水线执行

# R 型指令的 4 个阶段

image-20240114164135883

含有 R-Type 和 load 指令的流水线存在问题

同一个功能部件会同时被多个指令使用,发生结构冒险

为此我们规定:

  • 每个功能部件每条指令只能用一次(如:写口不能用两次或以上)
  • 每个功能部件必须在相同的阶段被使用(如:写口总是在第五阶段被使用)

解决方案:

  • 加一个 NOP 阶段以延迟 “写” 操作:把 “写” 操作安排在第 5 阶段,这样使 R-Type 的 Mem 阶段为空 NOP

# 五阶段指令流水线数据通路

image-20240114165519445

为什么需要寄存器

  • 保存每个周期执行的结果!
  • 不同于 PC,属于内部寄存器,对程序员透明,不需作为现场保存

# 取指令阶段

流水段寄存器用来存放每个阶段(一个时钟内)的执行结果
总是在下个时钟到来后的 Clock-to-Q 写入,应保存后面阶段要用到的指令和 PC+4 的值!

不需要控制信号,因为每条指令所执行的功能都一样,是确定的操作,无需根据指令的不同来控制执行不同的操作

# 流水线控制信号

只有在执行、读存储器、写寄存器三个阶段存在控制信号

因为 IF、ID 阶段功能对每条指令都是一样的。

通过对前面流水线数据通路的分析,得知:

  • 因为每个时钟都会改变 PC 的值,所以 PC 不需要写控制信号
  • 流水段寄存器每个时钟都会写入一次,也不需要写控制信号
  • Ifecth 阶段和 Dec/Reg 阶段都没有控制信号
  • Exec 阶段的控制信号有四个
    • ExtOp (扩展器操作):1- 符号扩展;0- 零扩展
    • ALUSrc (ALU 的 B 口来源):1- 来源于扩展器;0- 来源于 BusB
    • ALUOp (主控制器输出,用于辅助局部 ALU 控制逻辑来决定 ALUCtrl)
    • RegDst (指定目的寄存器):1- Rd;0- Rt
  • Mem 阶段的控制信号有两个
    • MemWr (DM 的写信号):Store 指令时为 1,其他指令为 0
    • Branch (是否为分支指令):分支指令时为 1,其他指令为 0
  • Wr 阶段的控制信号有两个
    • MemtoReg (寄存器的写入源):1- DM 输出;0- ALU 输出
    • RegWr (寄存器堆写信号):结果写寄存器的指令都为 1,其他指令为 0

# 流水线冒险处理

# 结构冒险

将 Instruction Memory (Im) 和 Data Memory (Dm) 分开
将寄存器读口和写口独立开来

# 数据冒险

RAW: 写后读冒险

解决方法

  • 流水线阻塞 (气泡 Bubble):硬件上通过阻塞 (stall) 方式阻止后续指令执行,延迟到有新值以后
    • 需要改数据通路
  • 插入 NOP 指令
  • 转发技术:流水段寄存器中值直接取到 ALU 输入端,若是 ALU 相关结果,可以通过转发解决;若是 DM 相关结果,需要延迟一个周期
  • 编译优化:调整指令顺序,但不能解决所有数据冒险

# Load 指令引起的延迟现象

image-20240114172943729

image-20240114172957176

  • 实际上,在第四周期结束时,数据在流水段寄存器中已经有值。
  • 采用数据转发技术可以使 load 指令后面第二条指令得到所需的值
  • 但不能解决 load 指令和随后的第一条指令间的数据冒险,要延迟执行一条指令

# 控制冒险

当流水线遇到条件转移指令和其他改变 PC 值的指令而造成断流

虽然 Beq 指令在第四周期取出,但:

  • 目标地址在第七周期才被送到 PC 的输入端
  • 第八周期才能取出目标地址处的指令执行
  • 结果:在取目标指令之前,已有三条指令被取出,取错了三条指令!

# 指令流水线总结

# 指令流水线的局限性

  • 并不是每条指令都有相同多个流水段
  • 并不是每个流水段都一样长
  • 随着流水线深度的增加,流水线寄存器的额外开销比例也增大
  • 指令在资源冲突、数据相关或控制相关时会发生流水线冒险

# 指令流水线的执行效率

  • 吞吐率:比非流水线方式下大大提高
  • 指令执行时间:相对于非流水线方式,一条指令的执行时间延长了

#