流水线中经常有一些被称为"相关"的情况发生,它使得指令序列中下一条指令无法按照设计的时钟周期执行,这些“相关”会降低流水线的性能。流水线中的相关分为以下三种类型:
- 结构相关:指的是在指令执行的过程中,由于硬件资源满足不了指令执行的要求,发生硬件资源冲突而产生的相关。比如:指令和数据都共享-一个存储器,在某个时钟周期,流水线既要完成某条指令对存储器中数据的访问操作,又要完成后续的取指令操作,这样就会发生存储器访问冲突,产生结构相关。
- 数据相关:指的是在流水线中执行的几条指令中,一条指令依赖于前面指令的执行结果。
- 控制相关:指的是流水线中的分支指令或者其他需要改写PC的指令造成的相关。结构相关、控制相关将在后续指令分析中讨论,本节重点讨论数据相关的问题。流水线数据相关又分为三种情况: RAW、WAR、WAW。
流水线数据相关又分为:
- RAW:即Read After Write,假设指令j是在指令i后面执行的指令,RAW表示指令i将数据写入寄存器后,指令j才能从这个寄存器读取数据。如果指令j在指令i写入寄存器前尝试读出该寄存器的内容,将得到不正确的数据。
- WAR:即Write After Read,假设指令j是在指令i后面执行的指令,WAR表示指令i读出数据后,指令j才能写这个寄存器。如果指令j在指令i读出数据前就写该寄存备,将使得指令i读出的数据不正确。
- WAW:即Write After Write,假设指令j是在指令i后面执行的指令,WAW表示指令i将数据写入寄存器后,指令j才能将数据写入这个寄存器。如果指令j在指令i之前写该寄存器,将使得该寄存器的值不是最新值。
如下图是实现逻辑或操作的简单五级流水线各模块连接图,从下图可以看出只有在回写阶段才会写入数据到寄存器中。
这样就能看出问题:
- 相邻指令间存在数据相关
>2. 相隔1条指令的指令间存在数据相关
>3. 相隔2条指令的指令间存在数据相关
解决办法:
数据前推:将计算结果从其产生处直接送到其他指令需要处或所有需要的功能单元处,避免流水线暂停。如下图所示的例子中,新的$1值实际上在第1条ori指令的执行阶段已经计算出来了,可以直接将该值从第1条ori指令的执行阶段送入第2条ori指令的译码阶段,从而使第2条ori指令在译码阶段得到$1的新值。也可以直接将该值从第1条ori指令的访存阶段送入第3条ori指令的译码阶段,从而使第3条ori指令在译码阶段也得到$1的新值。
对于相邻指令和相隔1条指令的指令间的数据相关可以通过数据前推的方式解决:
对于相隔2条指令的指令间的数据相关,可以在回写阶段写入寄存器时做个判断,如果读取的寄存器地址和回写阶段要写入的寄存器地址相同,则直接把回写阶段要写入的数据读出