数据冒险与控制冒险

不清楚概念的话,先看王道书,或者看这篇:

计算机组成原理(11)----指令流水线_store指令的时空图-CSDN博客

结构冒险:

对于结构冒险,通常采用指令Cache和数据Cache分离的方法就能解决。

数据冒险:

在学习的指令中,Load指令和运算类指令会写寄存器,如果在没有写回寄存器之前,其他指令就尝试读这一指令,那么就会发生数据冒险。

控制冒险:

在学习的指令中,只有转移类指令可能会更改PC值,那么下一条要执行的指令就不是流水线中的下一条指令,则引起控制冒险。


判断是否存在数据冒险:

从第一条指令开始,结合注释,观察该指令"写"了某个寄存器,并观察后续相邻的3条指令是否"读"了同一个寄存器。若发现此类情况,则存在数据冒险。为什么只用看后面3条,看下面的图就懂了。

例题1:

I1写的是R1,观察后面3条指令,没有读R1,I1与其他3条指令不存在数据冒险;第二条指令写了R5,观察后续3条指令有没有读R5,I3读了R5,所以I2与I3存在数据冒险。

数据冒险的解决方法:

① 硬件阻塞 ② 转发(旁路)技术,转发旁路技术能解决大部分数据冒险,不能解决由 Load 指令写寄存器引起的 Load-use数据冒险(后面讲)

用硬件阻塞的方法解决如下:

由于阻塞期间I2一直占用IF段的硬件资源,所以只有I2段进入到了ID,下一段才能进入IF

例题2:

答案为C,自己分析一遍,以下为解决方法:


分析是否存在控制冒险:

只有转移类指令的执行才会引发控制冒险。因此只需观察指令序列中是否包含"转移类指令"即可。

解决方法:将转移类指令后一条指令的IF段硬件阻塞3个时钟。 这样就能保证后一条指令取指的操作,在转移类指令的第4段(M)之后在开始,这样才能保证后一条指令取指,取的是修改完PC后正确地址的指令。

例题:

第1条指令写了R4,而后面的2,3条指令都读了R4,所以需要确保第2条和第3条指令的ID段在第1条指令的WB段之后:

第2条指令与第3条指令之间也会产生数据冒险:

其余同理分析,会由于数据相关而产生阻塞的是2,3,4,6

很显然,第6条指令是转移类指令,所以会产生控制冒险。

为什么第1条指令和第5条指令存在数据相关?不是只有与后面3条指令才可以产生数据相关吗?

这是因为第6条指令是一条转移类指令,如果执行I6指令后,跳转到I1继续执行,那么I5和I1就有可能产生数据相关。

I5指令需要写R2,而I1需要读R2,所以I1的ID段需要在I5的WB段之后:

由于题目给了,分支指令的执行均引起3个时钟周期的阻塞,也就是后一个指令的IF段会推后3个时钟。看到下图,I1段的ID已经在WB段后面很多了,所以即使有数据相关,但是因为有3个时钟周期的阻塞,所以I1和I5不会因为数据相关而阻塞。


总结:

关于数据冒险:后一条指令的ID段要在前一条指令的WB段之后

判断是否会产生数据冒险,则看该条指令的后3条指令有没有读 该条指令写的寄存器

关于控制冒险:后一条指令的IF段要在前一条指令的M段之后


转发技术处理数据冒险:

以 I1 举例,在通常的指令流水线中,执行(EX)阶段得到的结果,需要到WB阶段才能写回,而采用转发技术,可以直接将I1的EX的结果(放到EX/MEM流水段寄存器的结果)从流水段寄存器中取出,直接送到第2条指令的ALU输入端。

也就是说,即使I2的ID段取得数据是错误的,但是EX执行操作阶段,使用的数据是正确的,所以ID不需要进行阻塞3个时钟周期的操作。

为什么转发技术不能解决由 Load 指令写寄存器引起的 Load-use数据冒险

Load-use:Load指令将数据加载到寄存器中,下一条指令就需要使用寄存器中的值。例如下图的I2,I3指令:

Load指令会在M段结束后,才能在内存中获得最终的数据,然后在WB段才写回R[s3]

而下一条指令要在EX段就使用Load指令读出来的数据。

所以必须要让EX段阻塞一个时钟,阻塞一个时钟之后就可以使用转发技术将上一条指令M段的数据转发到下一条指令的EX段

由于I3指令阻塞了一个时钟,那么后一条指令I4,就必须阻塞4个时钟周期,使得后一条指令的IF段在前一条指令的M段之后:

完整解答:

总结:

① 对于控制冒险,如果采用硬件阻塞的方法,就要确保后一条指令的IF段在前一条指令的M段(修改PC值)之后。

② 对于数据冒险,可以使用硬件阻塞,也可以使用转发技术。如果采用转发技术,就不需要进行任何阻塞。但是转发技术不能解决由 Load 指令写寄存器引起的 Load-use数据冒险。对于Load-use指令,需要在EX段前进行一个时钟周期的阻塞。

相关推荐
懒大王爱吃狼26 分钟前
Python教程:python枚举类定义和使用
开发语言·前端·javascript·python·python基础·python编程·python书籍
秃头佛爷1 小时前
Python学习大纲总结及注意事项
开发语言·python·学习
阿伟*rui1 小时前
配置管理,雪崩问题分析,sentinel的使用
java·spring boot·sentinel
待磨的钝刨1 小时前
【格式化查看JSON文件】coco的json文件内容都在一行如何按照json格式查看
开发语言·javascript·json
XiaoLeisj3 小时前
【JavaEE初阶 — 多线程】单例模式 & 指令重排序问题
java·开发语言·java-ee
paopaokaka_luck3 小时前
【360】基于springboot的志愿服务管理系统
java·spring boot·后端·spring·毕业设计
dayouziei3 小时前
java的类加载机制的学习
java·学习
励志成为嵌入式工程师4 小时前
c语言简单编程练习9
c语言·开发语言·算法·vim
捕鲸叉5 小时前
创建线程时传递参数给线程
开发语言·c++·算法
A charmer5 小时前
【C++】vector 类深度解析:探索动态数组的奥秘
开发语言·c++·算法