好久没有研究微架构方面的东西了,最近正好A17要出了就研究一下。
Maynard Handley在他的m1逆向工程文档里测试ROB、Int/FP物理寄存器大小和History Queue里都使用了和Henry Wong不同的方法。
由于ROB是FIFO且只有最旧的指令retire了才会释放,所以我们需要用一条或者几条长延时dependence chain(这里他用的是FSQRT)来把ROB head堵住,后面再堆积nop指令。当堆积到一定数量时ROB会被占满,造成流水线stall,再后面的指令必须要等到前面delay chain指令retire才可以继续执行。通过观察在ROB被占满后的行为来判定ROB大小。

图上x轴是填充nop指令的数量 y轴是耗费的cycle。蓝色的线代表了有delay chain的情况,黄色代表了没有delay chain下nop的throughput。当填充指令达到~2200的时候执行周期明显变长了,为什么?我们先假设ROB大小没有容量限制,那么执行周期应该要到nop=32*13*8=3328的时候才会开始增长,因为 nop<3228的情况下 最少执行时间由FSQRT的延迟决定, nop>3228的情况下延迟由nop决定, 换句话说执行nop所消耗的时间会比 执行fsqrt消耗的时间更久 所以当fsqrt执行完后nop还没有执行完 如下图
红色的线代表了理论上如果ROB没有大小限制的情况。
所以在nop=2200的时候发生了什么导致了不符合理论的情况?
我们假设ROB大小是2200,如果填充指令的数量大于2200,比如说2300,那么在2200条指令后的nop都不可以执行因为当前ROB已经满了,必须要等到ROB head也就是delay chain(Fsqrt)指令retire并且释放ROB entry才可以继续执行。那么,执行2300条nop的时间=执行delay chain指令的时间+执行剩下100条nop指令的时间,作为对比假如ROB大小大于2300,那么执行的时间=执行delay chain指令的时间(也就是图上红色部分),因为假如机器没有stall, 在执行FSQRT的时候会并行的执行nop指令,nop执行完了FSQRT还没有执行完,所以执行时间等于FSQRT的执行时间。最终通过观察何时cycle 会突然增加并且不符合理论情况来确定ROB大小。为了更准确的观察你可以减少delay chain指令的数量,找到上述的现象可以复现下花费最少的延迟指令。如图下

最后提供一下测试序列的伪代码
start:
FSQRT r2, r2, r0
FSQRT r2, r2, r0
...
FSQRT r2, r2, r0
nop
nop
....
nop
counter--
branch start if not zero
循环是为了减少操作系统上下文切换所带来影响。
Maynard Handley在他的m1逆向工程文档里测试ROB、Int/FP物理寄存器大小和History Queue里都使用了和Henry Wong不同的方法。
由于ROB是FIFO且只有最旧的指令retire了才会释放,所以我们需要用一条或者几条长延时dependence chain(这里他用的是FSQRT)来把ROB head堵住,后面再堆积nop指令。当堆积到一定数量时ROB会被占满,造成流水线stall,再后面的指令必须要等到前面delay chain指令retire才可以继续执行。通过观察在ROB被占满后的行为来判定ROB大小。

图上x轴是填充nop指令的数量 y轴是耗费的cycle。蓝色的线代表了有delay chain的情况,黄色代表了没有delay chain下nop的throughput。当填充指令达到~2200的时候执行周期明显变长了,为什么?我们先假设ROB大小没有容量限制,那么执行周期应该要到nop=32*13*8=3328的时候才会开始增长,因为 nop<3228的情况下 最少执行时间由FSQRT的延迟决定, nop>3228的情况下延迟由nop决定, 换句话说执行nop所消耗的时间会比 执行fsqrt消耗的时间更久 所以当fsqrt执行完后nop还没有执行完 如下图

红色的线代表了理论上如果ROB没有大小限制的情况。
所以在nop=2200的时候发生了什么导致了不符合理论的情况?
我们假设ROB大小是2200,如果填充指令的数量大于2200,比如说2300,那么在2200条指令后的nop都不可以执行因为当前ROB已经满了,必须要等到ROB head也就是delay chain(Fsqrt)指令retire并且释放ROB entry才可以继续执行。那么,执行2300条nop的时间=执行delay chain指令的时间+执行剩下100条nop指令的时间,作为对比假如ROB大小大于2300,那么执行的时间=执行delay chain指令的时间(也就是图上红色部分),因为假如机器没有stall, 在执行FSQRT的时候会并行的执行nop指令,nop执行完了FSQRT还没有执行完,所以执行时间等于FSQRT的执行时间。最终通过观察何时cycle 会突然增加并且不符合理论情况来确定ROB大小。为了更准确的观察你可以减少delay chain指令的数量,找到上述的现象可以复现下花费最少的延迟指令。如图下

最后提供一下测试序列的伪代码
start:
FSQRT r2, r2, r0
FSQRT r2, r2, r0
...
FSQRT r2, r2, r0
nop
nop
....
nop
counter--
branch start if not zero
循环是为了减少操作系统上下文切换所带来影响。