Assembly MIPS中的数据危害(真实相关性)

Assembly MIPS中的数据危害(真实相关性),assembly,dependencies,mips,cpu-architecture,cpu-hazard,Assembly,Dependencies,Mips,Cpu Architecture,Cpu Hazard,在上面的MIPS代码中,在解决方案表中,R3的真正依赖项标记为I3->I4。据我所知,真正的依赖关系是原始(写后读)危险或流危险。我很确定这是一个写后再写的危险,因此不是一个真正的依赖。我这样说对吗 写后再写危险 不,这不是一个先写后写的危险。虽然从微体系结构的角度来看,I4似乎是一个写操作——相对于内存而言,它确实是一个写操作,即仅在处理器内部,管道级和寄存器所在的位置和操作,存储指令有两个源操作数,没有寄存器目标 因此,R3在被I3写入后被I4读取。(换句话说,store指令需要R3的值,作

在上面的MIPS代码中,在解决方案表中,R3的真正依赖项标记为I3->I4。据我所知,真正的依赖关系是原始(写后读)危险或流危险。我很确定这是一个写后再写的危险,因此不是一个真正的依赖。我这样说对吗

写后再写危险

不,这不是一个先写后写的危险。虽然从微体系结构的角度来看,I4似乎是一个写操作——相对于内存而言,它确实是一个写操作,即仅在处理器内部,管道级和寄存器所在的位置和操作,存储指令有两个源操作数,没有寄存器目标

因此,R3在被I3写入后被I4读取。(换句话说,store指令需要R3的值,作为执行内存存储的输入值;R3的值与存储位置的地址和大小一起输入数据内存,这里是4)。因此,这是一个写后读取的危险

写后再写危险

不,这不是一个先写后写的危险。虽然从微体系结构的角度来看,I4似乎是一个写操作——相对于内存而言,它确实是一个写操作,即仅在处理器内部,管道级和寄存器所在的位置和操作,存储指令有两个源操作数,没有寄存器目标


因此,R3在被I3写入后由I4读取。(换句话说,store指令需要R3的值,作为执行内存存储的输入值;R3的值与要存储的地址和大小一起输入到数据内存中,这里是4)。因此,这是一种先读后写的危险。

在一个稍微高级一些的带有存储缓冲区的管道中,存储和加载必须确保它们正确地看到对方。但是,如果加载和存储在同一管道阶段进行内存访问,则通过探测存储缓冲区进行存储转发意味着您永远不必在标量管道(每个时钟1 insn)中暂停存储/重新加载(内存位置的原始数据),假设存储转发延迟仅为1个周期。与寄存器文件不同,寄存器文件由解码读取,由写回阶段写入,这使得原始危险成为一个问题。存储确实有一个内存目标,这在某些设计中可能很重要。但不是注册目的地;这就是为什么我在那句话中添加了那个限定词。@PeterCordes,谢谢你的额外见解(和改进的措辞)!我忘了链接和。进一步阅读:在无序存储执行的情况下保留程序顺序,并避免存储暂停->使用OoO exec重新加载。(当存储地址可能在稍后的加载地址之后才准备好时,这会变得非常棘手;现代x86 CPU动态预测加载是否是未知地址存储的重新加载,如果猜错了,可能需要刷新管道。)在一个稍微高级的带存储缓冲区的管道中,仓库和货物必须确保彼此正确相见。但是,如果加载和存储在同一管道阶段进行内存访问,则通过探测存储缓冲区进行存储转发意味着您永远不必在标量管道(每个时钟1 insn)中暂停存储/重新加载(内存位置的原始数据),假设存储转发延迟仅为1个周期。与寄存器文件不同,寄存器文件由解码读取,由写回阶段写入,这使得原始危险成为一个问题。存储确实有一个内存目标,这在某些设计中可能很重要。但不是注册目的地;这就是为什么我在那句话中添加了那个限定词。@PeterCordes,谢谢你的额外见解(和改进的措辞)!我忘了链接和。进一步阅读:在无序存储执行的情况下保留程序顺序,并避免存储暂停->使用OoO exec重新加载。(当存储地址可能在稍后的加载地址之后才准备就绪时,这会变得非常棘手;现代x86 CPU动态预测加载是否是未知地址存储的重新加载,如果猜错了,可能需要刷新管道。)
I1:LW R1, 0(R4) ; R1 ← address (0+R4)
I2:ADDI R2, R1, #8 ; R2 ← R1+8
I3:MULT R3, R1, R1 ; R3 ← R1*R1
I4:SW R3, 4(R2) ; address(4+R2) ← R3