0%

OOO CPU Issue Stage: Wake Up

任务:将功能单元计算出的结果通知到发射队列当中所有等待该数据的指令

Tomasulo 算法唤醒

当指令执行完之后才将相关指令进行唤醒。

back-to-back 背靠背执行唤醒

对于单周期指令

  • 被仲裁电路选中的指令将其目的寄存器编号发送的对应的总线上广播 (tag bus)
  • 发射队列当中的所有指令将 tag bus 上的编号和自己的源寄存器编号对比,如匹配则标记为 ready
    通过旁路网络获得寄存器值(这样才能背靠背执行)
  • 发射队列当中的指令如果源操作数均 ready ,则可以向仲裁电路发出请求
    • 一条指令可以轮流向多个仲裁电路发送请求,直到找到愿意响应的仲裁电路(平衡负载)
  • 仲裁电路对所有发送请求的指令进行仲裁选择发射
    • 未发射的指令需要在下个 cycle 继续发送请求
    • 发射的指令会收到仲裁电路的响应信号,并将其目的寄存器编号广播(第 1 步)
      不会马上离开发射队列:对于访存指令而言可能出现访存违例

发射队列对单周期指令唤醒电路的影响:

  1. 如果使用多个小容量的发射队列(分布式)
    • 由于总容量并不变,所以 tag bus 总体的复杂度不变(由于布局布线的问题,可能复杂度会上升)
    • 但每个发射队列上仲裁电路的请求端变少,可以加快仲裁电路

对于多周期指令

将唤醒划分为 2 个主要阶段:

  1. 广播:被仲裁电路选中的指令的目的寄存器编号被送到 tag bus 上
  2. 唤醒:将 tag bus 上的寄存器编号和发射队列中所有指令的源寄存器编号比较

多周期指令的唤醒,需要根据其在功能单元中执行的周期数将唤醒过程延迟,所以就有 2 种延迟方法:

  1. 延迟广播 (delayed tag broadcast)
  2. 延迟唤醒 (delayed wake-up)

延迟广播 (delayed tag broadcast)

指令被选中的当前周期,并不将指令的目的寄存器编号立刻送到 tag bus 上,而是延迟 (N - 1) 个周期后送到总线上(对于执行周期为 N 的指令)

问题:可能导致 tag bus 冲突

tag bus 冲突解决方案:

  1. 方案1: 增加这个功能单元对应的 tag bus 数
    不具有可扩展性:需要大量总线,唤醒电路复杂度大幅上升
  2. 方案2: 使用表格记录每条指令的执行周期
    后续指令通过查表发现冲突后延时到下个 cycle 继续仲裁
    • 关于表格的实现方案:(trade-off)
      • 访问表格和仲裁电路并行工作
        • 不会增加延时,但造成性能损失:在基于 oldest-first 的仲裁规则下, tag bus 冲突会导致后续可被仲裁的指令都被延时
        • 如果不遵循 oldest-first 呢?
      • 访问表格和仲裁电路串行工作:指令首先查找表格,没有冲突后再向仲裁电路发出请求
        • 后续的指令不会受到前面冲突的影响(站在仲裁电路的角度看,前面冲突的第二条指令其实是未 ready 的)
        • 缺点是串行访问会增大延时

延迟唤醒(delayed wake-up)

指令被选中的当前周期,就将指令的目的寄存器编号立刻送到 tag bus 上并和所有指令的源寄存器编号比较。但匹配项并不立即置位 ready ,延时 (N-1) 个周期后再置位 ready

  • 不存在 tag bus 的冲突问题
  • 本质是在发射队列的每条指令的 ready 位前增加延时寄存器

实现方案1:移位寄存器

  • 发射队列中每条指令的目的寄存器对应一个 DELAY 值
    • DELAY 值位宽由 FU 中最多需要周期数决定:8 位 4 周期编码 11111000
    • DELAY 值同分配电路一同写入发射队列
    • 指令被仲裁电路选中后广播时,同时将 DELAY 值广播到总线 DELAY bus
  • 发射队列的每条指令的源寄存器添加一个移位寄存器和移位使能位
    • 广播匹配后,使能位拉高,移位寄存器初始值置为DELAY bus上的值
    • 使能位拉高后,移位寄存器每周期算术右移1位,其最后一位表示进入ready状态
    • 当指令被仲裁电路选中并收到响应信号后将使能位和移位寄存器清零

可以使用功能单元完成计算的 valid 信号作为指令 ready 唤醒的条件吗?

使用指定周期延迟的目的是为了实现背靠背执行,tomusolu 算法本身就是以指令执行完作为置位 ready 的条件,但这样对于 RAW 相关的指令不能实现背靠背执行

如果有多条使用相同功能单元的指令均延迟唤醒,第一条收到响应后后续其他几条不能置位 ready ,所以可以在功能单元中维护一个 valid 表(移位寄存器 or FIFO),每开始执行一条指令就移位一次(移位值 0 ),同时有一个指针指向第一个 0 项,执行结束前一个周期就将指针处置 1 并下移到下一条 0 项

同时,发射队列中延迟唤醒的指令可以记录功能单元中 valid 表的地址,来匹配指定的 valid 信号

推测唤醒 (speculative wake-up)

针对执行周期数不确定的指令,如 load 指令、除法指令等

  • 最简单的处理方法是:等指令执行完再进行唤醒
    • tomasulo算法
    • 问题: RAW 相关的指令不能背靠背执行
  • 对于 load 指令,其延迟取决于 DCache 和 TLB 的命中情况
    • hit 则周期数确定

Load指令的推测唤醒

  • 总是预测 hit ,因为 DCache 的命中率很高
  • 按照 DCache hit 的周期数进行延迟唤醒
  • 预测错误的处理
    • 状态恢复
      • 发射队列中被Load指令唤醒的所有寄存器置为 not ready 状态
      • 被 Load 唤醒并且离开发射队列的指令需要从流水线中清除,重新放回发射队列
    • 之后 Load 指令可以继续按照 L2Cache hit 继续进行预测,一直到 DRAM
  • 对于支持虚拟存储的 DCache , TLB miss也需要按照预测错误进行处理
    • 对于软件处理TLB miss ,按照异常的方式处理
  • 对于不同结构的 DCache, 预测执行的方式不同:
    to be continued …