旁路网路
需要旁路网络的原因
比如两条指令RAW,最保守的方式是前面一条指令 FU 计算完成后,dst 写回了PRF,然后后面一条指令 是如此idx再去读PRF,费时,影响pipelie效率,所以需要旁路电路,从前一个指令计算出结果的时候,就fwd到新指令的入口。
简单设计的旁路网络
左边图没有旁路网络的时候,所有的寄存器的值从PRF来。右边那个比如FU0的值可以从PRF来,也可以从上一次FU0自己算出来的值来,还可以从FU1的计算的结果来。
旁路电路冲突的解决
- 产生conflict的原因
如下图,如果一个FU中有几个计算模块,比如第一个FU,可以同时执行Add和shift,add latency=2,shift latency=1,则下下张图的时序,有可能出现add和shift的运算同时算出来,都需要fwd(forward),这就出现了旁路电路fwd的冲突 - 解决旁路电路conflict方式
根据是否进行推测,有两种方案(前提:我们知道指令的执行latency)
推测:假设所有的都不会出现conflict,当要开始执行的时候,再检查是否会和同FU的其他指令产生conflitc,如果产生conflict就放回issue queue.
不推测:在选择指令的时候,就算好,如果会和前面的指令发生conflict,这个周期就不把指令送到FU
复杂设计的旁路网络
复杂电路引起增加流水级数
在现实的处理器里,FU比较多,布线复杂,从PRF读的数据需要很长的传输才能到达FU的数据端,而且数据来源不止从PRF来,有可能还要做mux,所以把这个阶段单拿一个周期,叫source drive。如果没有这个阶段,复杂的准备工作和冒险处理将和执行阶段抢时间,导致cycle拉长。
同理,计算的数据到写入PRF也要很长的时间,所以单拎出来一个周期 result drive
增加流水级数引起旁路电路的复杂度快速提升
指令在result drive和write back阶段可以发起forward,在source drive阶段和execute阶段可以接收forward,导致forward的组合急剧增多
简化旁路电路采取的方式(cluster)
- cluster bypass
把不同的FU放在不同的cluster中(一个cluster放>=1)FU,同cluster内的FU之间可以快速forward,没有source drive和result drive的环节,不同的cluster之间数据如果有依赖,只能通过读取PRF的方式获取
存储器指令的加速
影响存储指令速度的原因
1. load/store指令之间也会出现和寄存器类似的WAW/WAR/RAW hazard
解决hazard的方式
完全顺序执行
缺点:存储的速度慢;优点:可靠部分乱序执行
store和store之间保持顺序,两个store之间的load可以乱序
当指令A被select的时候,就可以wake up 指令B/C/D,当B/C/D的地址算出来的时候,A的已经算出来了,因此B/C/D 可以和A比较是否发生地址冲突,如果不发生,load就可以发出去,如果发生,load就可以等到store的回来直接用store的数据。
指令B/C/D并不阻塞下一条store 指令E,因为对于AXI来说是不同的channel,而且即使指令A没有AXI的bresp回来,指令E也可以发出去,但是指令F/G检查冲突的时候要不仅要和指令E做地址比较,也要和指令A做地址比较。
那么哪些load指令需要和前一个store做比较,哪些需要和前前…个store指令做比较,这就需要记录load和store 之间的顺序,可以用ROB来做辅助标记。所有的store的指令相关的数据都放在store buffer里,如果load有匹配的上的,就去store buffer取数据,就不向AXI去read了。完全乱序执行
只要load的操作数准备好了,就发送
2.数据放在不同层级cache中,取数据慢
解决方式:D-cache缺失的时候,处理器继续执行后面的load/store,使用非阻塞的fetch方式