为什么这两条指令被认为是数据相关的?

问题描述

所以,我了解到,当我们在 cpu 中使用流水线技术时,我们可能必须解决一些危险,例如两条指令之间的数据依赖性。 例如,我确实得到了这个数据依赖:

add $t0,$t1,$t2
lw $s1,0($t0)

lw 确实需要 $t0 的正确结果 但是,我也看到,我们将那些 2 指令视为数据相关的。 为什么?

    add $t0,$t2
    lw $s1,4($t0)

既然 lw 确实需要正确的 mem[$t0] + 4 值,这是一个不同的地址,为什么这被认为是一个依赖项?也许,我不明白,$lw 在那里做什么?
我是这么想的:
说吧

  addi $t0,$t0,5
  lw $s1,0($t0) # Now we loaded the value 5 to $s1
  
  #BUT WHAT ABOUT THAT
  li $t1,9
  addi $t0,5
  sw $t1,4($t0) # Now we go to &(mem[$t0]+4) and there we store the value of $t1,which is 9,

我们需要 t0 的地址而不是它的价值(或者至少我是这么理解的)

谁能给我解释一下?

解决方法

我们需要 t0 的地址

寄存器没有地址:它们有名字;它们在寄存器文件中有位置/索引,并且它们保存值。

只有内存有地址。

因为,lw 确实需要 mem[$t0] + 4 的正确值

那个 lw 访问 mem[$t0+4],它需要 $t0 的值才能执行 +


lwsw 指令计算有效地址:

ea = R[rs]+SignExtImm

这里,硬件使用索引 rs 对寄存器文件进行索引,该索引是从编码指令 rs 中名为 lw 的 5 位字段中获得的。寄存器中存储的值是 32 位,因此 5 位索引用于查找保存在那里的 32 位值。因此,这是对寄存器 rs 的值的读取。在将寄存器的 32 位值和立即数都提供给 ALU 加在一起之前,立即数从指令字段中的 16 位符号扩展到 32 位。

在计算 ea 后,负载:

R[rt] = M[ea]

在计算 ea 后,商店会

M[ea] = R[rt]

为了计算 ea,我们需要 R[rs] 的值,即保存在 rs 寄存器中的值。


这部分操作和顺序差不多:

add $t0,$t1,$t2   # $t0 is written here
addi $s1,$t0,4    # $t0 is read,ALU computes $t0+4 (result goes to $s1)
lw $s2,4($t0)      # $t0 is read,ALU computes $t0+4 (result is a memory address)
xori $s3,8    # $t0 is read,ALU computes $t0^8

addaddi 对已读取正确的数据依赖项。这是 ALU/ALU 依赖项还是 EX/EX,取决于我们是在谈论功能单元还是流水线阶段。这些是背靠背的危险。

由于寄存器读取通常发生在 ID(指令解码)阶段,如果 rs 的最后一次寄存器更新通过 WB(回写)阶段是 3 个周期前开始的指令,那么 rs 的这个 ID 读取{1}} 将获取正确的值。任何更少都意味着读入的 ID 不会看到正确的值,因为它尚未进入寄存器。

cycle#:       1  2  3  4  5  6  7  8
instruction #
i1:          IF ID EX MM WB           
i2:             IF ID EX MM WB
i3:                IF ID EX MM WB
i4:                   IF ID EX MM WB

这里 i4 可以毫无危险地读取 i1 的寄存器更新,因为这些操作都发生在周期 5 — i1 的 WB 发生在时钟 5 的开始,而 i4 的 ID 能够看到在同一时钟中写入的值。

但是如果 i2 或 i3 读取了 i1 所针对的寄存器,则存在风险,因为它们的 ID 阶段发生的时间早于 i1 的 WB 阶段(i2 的 ID 在周期 3 和 i3 的 ID 在周期 4,两者都为时过早,无法获得周期 5 时 i1 的 WB)。

所以,危险就是这样发生的。但是请注意,i2 的 EX 阶段(在周期 4 处)所需的正确值在 CPU 中,并且已经在周期 3 中由 i1 的 EX 阶段计算得出。前向或绕过会替换该适当值以覆盖在 i2 或 i3 的 ID 阶段中读取的过时值。


查看指令描述和编码的更多细节: https://inst.eecs.berkeley.edu/~cs61c/resources/MIPS_Green_Sheet.pdf

查看基本指令格式以查看字段编码,例如lwsw 都是 I 型指令,因此它们具有 rsrtimmediate 字段。

lw 指令有一个寄存器源和一个寄存器目标。 (它也有内存源,但我们不看内存中数据依赖的 Read-After-Write 危害,我们只看寄存器。)

sw 指令有两个寄存器源,没有寄存器目标。 (它也有一个内存目标,但我们不查看内存是否存在数据依赖的 Read-After-Write 危害,我们只查看寄存器。)