自己动手写CPU之第五阶段(1)——流水线数据相关问题
将陆续上传本人写的新书《自己动手写CPU》(尚未出版),今天是第15篇,我尽量每周四篇
上一章建立了原始的OpenMIPS五级流水线结构,可是仅仅实现了一条ori指令,从本章開始,将逐步完好。
本章首先讨论了流水线数据相关问题。然后改动OpenMIPS以解决该问题。并在5.3节验证了解决效果。接着对逻辑、移位操作与空指令的指令格式、使用方法、作用进行了一一说明。在5.5节通过扩展OpenMIPS实现了这些指令,最后编写測试程序,对实现效果进行了检验。
5.1 流水线数据相关问题
我们在第4章实现的五级流水线结构非常easy。假设依照“简单即美(Simple is Beautiful)的标准,那么我们的流水线是美的,可是不完美,由于现实往往是复杂的,一个简单的流水线是解决不了如此多的现实问题的,本节探讨的数据相关问题就是当中一个问题。在我们实现逻辑、移位操作等其他指令之前。必须先讨论这个问题,由于这个问题已经影响到測试程序的编写了。
流水线中常常有一些被称为“相关”的情况发生,它使得指令序列中下一条指令无法依照设计的时钟周期运行,这些“相关”会减少流水线的性能。
流水线中的相关分为三种类型。
(1)结构相关:指的是在指令运行的过程中,因为硬件资源满足不了指令运行的要求,发生硬件资源冲突而产生的相关。
比方:指令和数据都共享一个存储器。在某个时钟周期,流水线既要完毕某条指令对存储器中数据的訪问操作,又要完毕兴许的取指令操作。这样就会发生存储器訪问冲突。产生结构相关。
(2)数据相关:指在流水线中运行的几条指令中。一条指令依赖于前面指令的运行结果。
(3)控制相关:指流水线中的分支指令或者其它须要改写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之前写该寄存器,将使得该寄存器的值不是最新值。
对于第4章建立的原始OpenMIPS五级流水线而言,从ori指令的实现过程能够知道,仅仅有在流水线回写阶段才会写寄存器(实际上其余指令也是一样的,在后面实现其余指令时,对这一点会更加清楚),因此不存在WAW相关。又由于仅仅能在流水线译码阶段读寄存器、回写阶段写寄存器,所以不存在WAR相关。所以OpenMIPS的流水线仅仅存在RAW相关。RAW相关有三种情况。
(1)相邻指令间存在数据相关
考虑例如以下代码。
1 ori $1,$0,0x1100 # $1 = $0 | 0x1100 = 0x1100
2 ori $2,$1,0x0020 # $2 = $1 | 0x0020 = 0x1120
第1条ori指令会写寄存器$1。随后的第2条ori指令须要读出$1的数据,可是第1条ori指令在回写阶段才会将其运算结果写入$1,而第2条ori指令在译码阶段就须要读取$1的值。此时第1条ori指令还处于运行阶段,所以得到的必定不是第1条ori指令计算得出的结果,按这个值运算,必定会出错。
如图5-1所看到的。
这样的情况能够称为相邻指令间存在数据相关。针对OpenMIPS详细情况。也能够称为流水线译码、运行阶段存在数据相关。
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbGVpc2hhbmd3ZW4=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">
(2)相隔1条指令的指令间存在数据相关
考虑例如以下代码。
1 ori $1,$0,0x1100 # $1 = $0 | 0x1100 = 0x1100
2 ori $3,$0,0xffff # $3 = $0 | 0xffff = 0xffff
3 ori $2,$1,0x0020 # $2 = $1 | 0x0020 = 0x1120
第1条ori指令会写寄存器$1。第3条ori指令在译码阶段须要读取寄存器$1,此时第1条ori指令还处于訪存阶段。所以得到的必定也不是正确的值。
如图5-2所看到的。这样的情况能够称为相隔1条指令的指令间存在数据相关。针对OpenMIPS详细情况。也能够称为流水线译码、訪存阶段存在数据相关。
(3)相隔2条指令的指令间存在数据相关
考虑例如以下代码。
1 ori $1,$0,0x1100 # $1 = $0 | 0x1100 = 0x1100
2 ori $3,$0,0xffff # $3 = $0 | 0xffff = 0xffff
3 ori $4,$0,0xffff # $4 = $0 | 0xffff = 0xffff
4 ori $2,$1,0x0020 # $2 = $1 | 0x0020 = 0x1120
第1条ori指令会写寄存器$1,第4条ori指令在译码阶段须要读取寄存器$1。此时第1条指令处于回写阶段,在回写阶段最后的时钟上升沿才会将运算结果写入$1,所以第4条ori指令得到的不是正确的寄存器$1的值。如图5-3所看到的。这样的情况能够称为相隔2条指令的指令间存在数据相关,针对OpenMIPS详细情况,也能够称为流水线译码、回写阶段存在数据相关。
当中相隔2条指令存在数据相关(即流水线译码、回写阶段存在数据相关)这样的情况,在第4章设计的Regfile模块中已经得到了解决,Regfile模块部分代码例如以下。
module regfile(
......
); ...... /****************************************************************
*********** 第三段:读port1的读操作 *********
*****************************************************************/ // raddr1是读地址、waddr是写地址、we是写使能、wdata是要写入的数据
always @ (*) begin ...... end else if((raddr1 == waddr) && (we == `WriteEnable)
&& (re1 == `ReadEnable)) begin
rdata1 <= wdata; ...... end /****************************************************************
*********** 第四段:读port2的读操作 *********
*****************************************************************/ // raddr2是读地址、waddr是写地址、we是写使能、wdata是要写入的数据
always @ (*) begin ...... end else if((raddr2 == waddr) && (we == `WriteEnable)
&& (re2 == `ReadEnable)) begin
rdata2 <= wdata; ...... end endmodule
在读操作中有一个推断,假设要读取的寄存器。是在下一个时钟上升沿要写入的寄存器。那么就将要写入的数据直接作为结果输出。如此就攻克了相隔2条指令存在数据相关的情况。
对于相邻指令间存在数据相关、相隔1条指令的指令间存在数据相关这两种情况。有三种解决方法。
(1)插入暂停周期:当检測到相关时,在流水线中插入一些暂停周期,如图5-4所看到的。
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbGVpc2hhbmd3ZW4=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">
(2)编译器调度:编译器检測到相关后,能够改变部分指令的运行顺序,如图5-5所看到的。
(3)数据前推:将计算结果从其产生处直接送到其它指令须要处或全部须要的功能单元处,避免流水线暂停。如图5-6所看到的的样例,新的$1值实际在第1条ori指令的运行阶段已经计算出来了。能够直接将该值从第1条ori指令的运行阶段送入第2条ori指令的译码阶段,从而使得第2条ori指令在译码阶段得到$1的新值。也能够直接将该值从第1条ori指令的訪存阶段送入第3条ori指令的译码阶段,从而使得第3条ori指令在译码阶段也得到$1的新值。
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbGVpc2hhbmd3ZW4=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">
读者须要注意,第(3)种方法有一个前提就是新的寄存器的值能够在运行阶段计算出来,假设是载入指令,那么就不满足这个前提,由于载入指令在訪存阶段才干获得终于结果。这是一种load相关,本书将在实现载入存储指令的时候考虑这样的情况,本章暂不考虑。
下一次将介绍OpenMIPS对数据相关问题的解决措施,敬请关注!
自己动手写CPU之第五阶段(1)——流水线数据相关问题的更多相关文章
- 自己动手写CPU之第五阶段(2)——OpenMIPS对数据相关问题的解决措施
将陆续上传本人写的新书<自己动手写CPU>(尚未出版).今天是第16篇.我尽量每周四篇 5.2 OpenMIPS对数据相关问题的解决措施 OpenMIPS处理器採用数据前推的方法来解决流水 ...
- 自己动手写CPU之第五阶段(3)——MIPS指令集中的逻辑、移位与空指令
将陆续上传本人写的新书<自己动手写CPU>(尚未出版),今天是第17篇.我尽量每周四篇 5.4 逻辑.移位操作与空指令说明 MIPS32指令集架构中定义的逻辑操作指令有8条:and.and ...
- 自己动手写CPU之第七阶段(7)——乘累加指令的实现
将陆续上传本人写的新书<自己动手写CPU>.今天是第30篇.我尽量每周四篇 亚马逊的销售地址例如以下.欢迎大家围观呵! http://www.amazon.cn/dp/b00mqkrlg8 ...
- 自己动手写CPU之第六阶段(2)——移动操作指令实现思路
将陆续上传本人写的新书<自己动手写CPU>(尚未出版),今天是第21篇,我尽量每周四篇 6.2 移动操作指令实现思路 6.2.1 实现思路 这6条移动操作指令能够分为两类:一类是不涉及特殊 ...
- 自己动手写CPU之第四阶段(3)——MIPS编译环境的建立
将陆续上传本人写的新书<自己动手写CPU>(尚未出版).今天是第13篇.我尽量每周四篇 4.4 MIPS编译环境的建立 OpenMIPS处理器在设计的时候就计划与MIPS32指令集架构兼容 ...
- 自己动手写CPU之第七阶段(2)——简单算术操作指令实现过程
将陆续上传本人写的新书<自己动手写CPU>.今天是第25篇.我尽量每周四篇 亚马逊的预售地址例如以下,欢迎大家围观呵! http://www.amazon.cn/dp/b00mqkrlg8 ...
- 自己动手写CPU之第七阶段(5)——流水线暂停机制的设计与实现
将陆续上传本人写的新书<自己动手写CPU>,今天是第28篇.我尽量每周四篇 China-pub的预售地址例如以下(有文件夹.内容简单介绍.前言): http://product.china ...
- 自己动手写CPU之第八阶段(4)——转移指令实现过程2
将陆续上传本人写的新书<自己动手写CPU>,今天是第36篇,我尽量每周四篇 开展晒书评送书活动,在亚马逊.京东.当当三大图书站点上,发表<自己动手写CPU>书评的前十名读者,均 ...
- 自己动手写CPU之第七阶段(6)——乘累加指令实现思路
将陆续上传本人写的新书<自己动手写CPU>.今天是第29篇.我尽量每周四篇 亚马逊的销售地址例如以下,欢迎大家围观呵! http://www.amazon.cn/dp/b00mqkrlg8 ...
随机推荐
- Yii2 框架下bootstrap 弹窗预览视频等~
Yii2 本身已经引用了'yii\bootstrap\BootstrapAsset',所以使用bootstrap 非常简洁. 1 在PHP页面引用命名空间 use app\assets\AppAsse ...
- 通过项目逐步深入了解Mybatis<三>
Mybatis 高级知识 安排:对订单商品数据模型进行分析 订单商品数据模型 数据模型分析思路: 1.每张表记录的数据内容(分模块对每张表记录的内容进行熟悉,相当于学习系统需求的过程) 2.每张表重要 ...
- iOS 7 改变Status Bar 颜色
Set the UIViewControllerBasedStatusBarAppearance to NO in the Info.plist. In ViewDidLoad method or a ...
- Android 属性动画(Property Animation) 全然解析 (下)
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/38092093 上一篇Android 属性动画(Property Animatio ...
- 一种基于Qt的可伸缩的全异步C/S架构server实现(二) 网络传输
二.网络传输模块 模块相应代码命名空间 (namespace ZPNetwork) 模块相应代码存储目录 (\ZoomPipeline_FuncSvr\network) 2.1 模块结构 ...
- Java获取客户端真实IP地址的两种方法
在JSP里,获取客户端的IP地址的方法是:request.getRemoteAddr(),这种方法在大部分情况下都是有效的.但是在通过了Apache,Squid等反向代理软件就不能获取到客户端的真实I ...
- .net web api 一
web api可以提供方便简单可靠的web服务,可以大量的用于不需要提供复杂的soap协议的环境,以简单明了的形式返回数据,在不太复杂的环境中web api可以做为wcf等重级web服务的一种可替代方 ...
- oc内存管理总结(一)
**内存管理 问题 1.什么是ios内存管理? 就是在对象不再被使用的时候,把它即时的从内存中清除掉 2.为什么要使用内存管理? 1.严格的内存管理,能够是我们的应用程在性能上有很大的提高 2.如果忽 ...
- Struts2 校验
Struts2校验格式: actionName-methodName-invalidation.xml 该配置文件必须和action类在同一个包下. <?xml version="1 ...
- 理解javascript 回调函数
##回调函数定义 百度百科:回调函数 回调函数就是一个通过函数指针调用的函数.如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用为调用它所指向的函数时,我们就说这是回调函数.回调函数不 ...