五级流水线CPU的实现与改进 您所在的位置:网站首页 冒险带来的感想 五级流水线CPU的实现与改进

五级流水线CPU的实现与改进

2024-07-14 01:51| 来源: 网络整理| 查看: 265

实验报告二  流水线CPU

张涵诺 2019301894

实验三

流水线CPU(不考虑冒险)

实验要求:

    在单周期CPU的基础上增加流水线寄存器,在不考虑冒险的前提下,实现一个能够执行下列指令集的流水线CPU:

addu,subu,add,and,or,slt,addi,addiu,andi,ori,lui,lw,sw

设计思路:

把单周期CPU的数据通路进行分割,分成取指,指令译码,执行,数据存储器访问,写回这五部分。每部分用流水线寄存器进行分割。每条指令执行的过程是在每个时钟上升沿,由一个流水线寄存器传递到后一个流水线寄存器。从指令译码,读寄存器一级开始需要控制信号,每级需要的数据和不同控制信号由前面的部分产生并在每个时钟上升沿向后传递。

设计过程:

草图如下,橙色为控制信号,蓝色为数据

长条分节状物体为流水线寄存器,IM为指令存储器,IR为指令寄存器,ctrl为控制模块,左边的GPR代表读寄存器堆相关端口,因为这一级不写寄存器。最右侧写回级的GPR代表写寄存器堆相关端口。

extend为立即数扩展模块,NPC为下地址组合逻辑,DM为数据存储器。其中NPC模块的接法在实验四发现是不正确的,不过此处是对单周期CPU的划分,且只需要进行PC+4,没有影响。由于各个模块

已在单周期实现详细描述,此处重点解释各流水线寄存器的设计与运行。

   上图为执行与存储器访问两部分之间的流水线寄存器,各寄存器仅在位宽上有区别。在时钟上升沿读入所有在输入端的数据和控制信号。接收CPU复位信号,同样进行异步复位。因为如果不进行复位,则开始运行时每个流水线寄存器的值是随机的。即刚开始就有五条随机的指令。

  

如上图所示,译码与执行级之间的流水线寄存器的输入有控制模块输出的ALU操作控制信号,数据选择器控制信号,写存储器控制信号,立即数扩展模式控制信号,寄存器读出的a,b操作数,扩展后的立即数,部分指令。其中部分数据与信号并非EX级所用,若不传递,则随着下一指令的进入所需控制信号和数据会流失。

遇到的问题与解决方法:

第一个实验未通过,编写如下汇编代码进行测试:

Testbench中时钟周期为100ns,在20ns处复位信号有一下降沿,因为此后所有流水线寄存器的值是

确定的(0),所有以流水线寄存器的值为输入的组合逻辑信号值也应当是确定的,而下图中可见MUX_extend_b数据选择器,ALU等组合逻辑的输入输出值均不定,至第一个时钟上升沿才确定。

如下图所示,进一步观察发现,id变为_ex_out(整个id_ex流水线寄存器的值)在复位信号有效后并没有变为定值。

继续观察,如下图所示,该流水线寄存器的输入信号在复位信号有效后均变为定值,所以问题出在该寄存器。

阅读代码发现。该寄存器虽然有输入reset信号,但并没有起作用,它不在敏感列表中,

Always语句也没有相关的清零操作,导致该问题出现。添加negedge reset和在if(reset == 0)

时的清零操作得以解决问题。

处理EXE级数据冒险

实验要求:在流水线CPU(不考虑冒险)的基础上处理以下EXE级数据冒险

设计思路:

第一条指令写的目的寄存器是第二三条指令的源寄存器,对于第二条指令对第一条指令的依赖,

当第二条指令进入执行级,所需操作数已存在于EX_MEM流水线寄存器中;对于第三条指令对第一条指令的依赖,当第三条指令进入EXE级,所需操作数已存在于MEM_WB寄存器中,需要合适的硬件在适当时刻选择流水线寄存器中数据作为运算操作数

设计过程:

冒险检测/冒险条件判断

仅考虑R型指令,有四种条件

运行至MEM级的指令的Rd寄存器与运行至EX级指令的Rs寄存器为同一寄存器

运行至MEM级的指令的Rd寄存器与运行至EX级指令的Rt寄存器为同一寄存器

运行至WB级的指令的Rd寄存器与运行至EX级指令的Rs寄存器为同一寄存器

运行至WB级的指令的Rd寄存器与运行至EX级指令的Rt寄存器为同一寄存器

事实上我在ID级对向后面流水级传的写目的寄存器进行了判断,它可能是R型的

Rd字段,也可能是I型的Rt字段,也可能是Jal要求的31号寄存器。

通过一个三输入数据选择器,根据控制器产生的s_num_write信号判断目的寄存器并将寄存器字段输入流水线寄存器。这样做的意义在于,简便地实现了多种指令间的数据依赖问题,不仅是R型和R型。

构建数据/控制通路

草图如下:

需要冒险检测单元检测WB级,MEM级的写控制信号,比较WB级,MEM级,EX级的寄存器号并输出数据选择器的控制信号。需要两级数据选择器,一级是选择数据来源是EX级还是旁路来的,

一级选择旁路来源是MEM还是WB级。

编写旁路策略

         先单独考虑MEM或WB一级对EX级的影响:若该级的regwrite信号为有效,且目的寄存器号与EX的源操作数的寄存器号相同,则极可能要旁路。除非源和目的相同且为$0寄存器,此时旁路则发生错误。

       考虑重叠的数据冒险:当MEM和WB级写目的寄存器相同且均非0,则旁路较新的MEM级数据。

上图为考虑更细化的条件的控制策略的一部分。

遇到的问题及解决方法:

   没有真正理解“双重数据冒险”,忽略了一种情况:运行至WB级和MEM级分别写不同的寄存器,

但又分别和运行至EX级的Rs和Rt字段相同。则前两条指令带来的冒险均需处理。

   我的错误是只有一个选择旁路来源的数据选择器,即rs和rt都用旁路来的一个数据代替。应当增加多选器以实现将WB级或MEM级的数据代替任意一个运算的操作数。

   改正后进行测试:

最后三条指令出现了题目要求的情况,期望最后$26寄存器,$25寄存器,$24寄存器依次被写入7.

仿真符合预期

3.

实验要求

在流水线CPU(EXE级数据冒险1)的基础上处理以下EXE级数据冒险

设计思路:

若某条指令上一条指令为lw,且它的源寄存器和lw的目的寄存器相同,则当lw运行至WB级,该指令运行至MEM级时才能得到结果,即该指令必须阻塞一个周期,才能在进入EX级时使用流水线寄存器中的数据。阻塞的方式是插入一个什么都不做的“气泡”并保持PC和指令寄存器不变,防止丢失已取的指令。

   设计过程:

冒险检测

这类冒险发生必有一条装载指令lw在先。为检测该条件,教材上的做法是检测Memread信号,

      而我们的实现没有这个信号,改为检测Opcode字段是否为lw,为达到该目的,必须增加各级寄存器位宽,

   逐级传输Opcode至ID_EX流水线寄存器用于检测。

id_ex ID_EX(hold, {instr_out_[31:26], instr_out_[20:16], instr_out_[25:21], op, sb, reg_write, mem_write, sel, s_npc, rd_rt_ID, a, b, imm32, instr_out_}, id_ex_out, clock, reset);

顶层模块中id_ex输入部分改为上示代码。instr_out_[31:26]即为ID的高位部分,opcode。

     另一个条件为lw的Rt字段与下一条指令的Rt字段相等或lw的Rt字段与下一条指令的Rs字段相等。该条件由冒险检测单元实现。

2) PC与IR保持不变,插入气泡的实现

       气泡即不改变计算机“状态”的一条指令,不改变状态即不对内存与寄存器进行写入,由于所有控制信号都是高电平有效,将所有控制信号置零,甚至指令所有位置0即可。

       如上图所示,我的实现是冒险检测单元检测到响应条件后,输出”插入气泡”信号 hold,

   并修改ID_EX寄存器的端口,使其接收hold,hold为高电平,则在最近一个时钟上升沿写入

   全0。

       为使PC和IR值不变,修改其端口,使其接收hold信号,hold为高电平则在下一个时钟

   上升沿保持不变。因为一个时钟沿过后冒险条件必然不满足,hold会变为0,所以这样的实现

方式不会造成状态卡死。

如上图所示,hold为高电平,前往else分支,在时钟上升沿输入全0。

上图为冒险检测的具体实现。阻塞一次后,即可用上个实验实现的bypass将数据从

WB级旁路回来。

仿真验证:

如上图所示,在插入气泡后,数据选择器控制信号sel_bypassA,sel_source,sel_source_B信号变为高电平,将WB级的运算结果旁路至EX级,仿真结果符合预期。

实验四

实验要求:在流水线CPU(EXE级数据冒险2)的基础上处理如下EXE级数据冒险

      设计思路与过程:

冒险检测:

  运行至WB级的指令需要写寄存器;

  写入的寄存器号与ID级读取的寄存器寄存器号相同;

  写入的寄存器号非0;

  对两种特殊情况的讨论:

      运行至WB级的指令不是运行至ID级指令之前最新的一条更改ID级指令所读寄存器的指令。

   此时会将“旧值”旁路至ID_EX寄存器,但接下来实验三第二个实验对数据冒险的处理就会起作用。

   所以没有关系。

      对I型指令的目的寄存器字段Rt进行不必要的旁路。由于I型指令的目的寄存器寄存器号已经经数据选择器写入ID_EX字段,所以该旁路对目的寄存器号没有影响,同时虽然旁路后的值进入了ID_EX

寄存器,对于I型指令,数据选择器会选择扩展后的立即数字段。所以对I型指令没有影响。

硬件实现

草图如下

需冒险检测单元和数据选择器,冒险检测单元检测IR寄存器的rs和·rt字段,MEM_WB寄存器的regwrite信号和写寄存器号,若检测到冒险条件,则该单元输出的数据选择器控制信号置相应的值。

原先读取寄存器值输入ID_EX寄存器的部分增加数据选择器,两个数据源分别是寄存器堆输出值和MEM_WB寄存器的相应值。

冒险检测的实现如上图所示,若写0寄存器则直接不考虑旁路,若此时ID级Rs,Rt字段相等且需要旁路,则两个数据选择器均选择来自ID_WB寄存器的数据。

加在ID_EX寄存器前的两个数据选择器如上图所示。

仿真验证:

           

               使用上图所示汇编代码进行验证。第一条与最后一条指令形成本实验所要求处理的冒险。

            期望依次对$31至$28寄存器写入 7, 1, 1, 7。

                下图为仿真时寄存器值的波形

            

实验结果符合预期

2.

实验要求:

能够处理J,JAL,JR指令引入的控制冒险

设计思路与过程:

设计草图如下

   之前把NPC模块放在EX级是出于BEQ需要使用ALU的考虑,本实验的要求使得部分或全部的

下地址产生应当在ID级进行。本实验先对j,jr,jal进行处理,故另设一个下地址模块NPC_1完成这三条指令下地址的产生与IR.Flush信号的产生,其位于ID级。对NPC_1输入不同指令下的控制信号,IR输出(指令)的地址部分,产生flush信号及下地址。

   Ctrl模块多输出一控制信号,用于选择使用哪个NPC模块,PC的下地址输入端增加一数据选择器,其选择信号即为新增的控制信号。其两个数据源分别为NPC_1和NPC的地址输出。

   NPC_1的实现如下图所示

控制信号s_npc为 2,3,4时分别代表进行j, jr, jal指令。这三条J型指令将目标地址写入PC时,若不进行清零操作,则无效的PC+4指向的指令会被取到IR寄存器。所以这三种情况flush信号均为1。目标地址值为PC高四位,立即数字段左移二位拼接的结果或寄存器堆a输出端的值。

如上图所示,which_npc数据选择器选择下地址,sel_pc为新增控制信号。

如上图所示,if_id_flush信号为IR寄存器新增信号,高电平时,在最近的时钟上升沿进行清零,产生前文所述“气泡”。

遇到的问题与解决方案:

对JAL指令所保存的PC+4值的意义理解有误。

若不更改蓝色部分数据通路,则JAL指令所保存的PC+4值是JAL运行至WB级时的当前PC值+4,而JAL

的意义应当是JAL在im的地址+4,以便之后进行返回。于是通过增加从IR到MEM_WB各级流水线寄存器的位宽,并在取指时一并向IR的高位传递PC+4,逐级传递至WB级,去掉WB级的加法器并将原来加法器输出端连接至新增的32位上解决问题。

如上图所示,ex_mem_out[104:73]即为新增的PC+4

仿真测试:

使用上图所示汇编代码进行测试。

期望$31号寄存器保存了第二条OR指令的地址3018。

$31号寄存器保存了第二条OR指令的地址

如上图所示,观察到取jal指令时,sel信号选择了npc_1,符合预期

3.

实验要求:

采用以下方法处理BEQ指令的控制冒险:

 增加硬件,将比较提前到ID级。静态预测,假设分支不发生。

设计思路与过程:

设计草图如下

将beq提前至ID级需要增加硬件——比较器。比较器的输入端位两个寄存器读出端,若相等,则输出1,否则输出0。同时需要将比较器输出值,IR寄存器的一段,符号扩展的立即数送入在ID级产生下地址的NPC_1模块。此时NPC_1实际上可承担所有下地址任务,调试中为方便起见,将选择下地址的信号设为恒定值。

比较器的实现如上图。实际比较器可通过异或和所有位取与构造。

npc_1模块的修改,fpc为当前pc值,即为beq指令对应的地址+4。若分支,

则静态预测失败,意味着取了一条无用/错误的指令,需要对IR进行flush,所以该信号

为1。预测正确,则对当前PC进行+4更新即可。

仿真测试:

使用上图所示汇编代码进行测试。

期望执行至最后一条beq指令时跳转到第一条指令

如上图所示,pc值在最后确实更新为0x3000,·第一条指令地址,符合预期。

如上图所示,跳转的同时,NPC_1产生的flush信号为高电平,符合预期。

4.

实验要求:

因为beq指令的比较操作提前到ID级,所以引入了如下图所示的ID级数据冒险。请处理以下ID级数据冒险:

实验思路与过程:

若beq指令的上一条指令的目的操作数为beq指令的源操作数,则计算出判断分支所需数值时,beq指令已经进入EX级。因为在ID级进行分支计算,所以需要对beq阻塞一个周期。

设计草图如下

冒险检测:

  EX级指令regwrite有效

  EX级指令目的寄存器非$0

  IR级指令为beq;

  IR级Rs字段与EX级目的寄存器编号字段相同

如上图所示,若检测到冒险条件,则输出hold_2控制信号,使IR,pc值保持,并将一气泡送入ID_EX寄存器。

如上图所示,若hold_2为高电平,则不进入 if 和 elif分支,保持不变。

在处理了该冒险后,还要增加一旁路,使分支所需值从MEM级旁路至ID级。

旁路发生的条件:

MEM级指令regwrite有效

  MEM级指令目的寄存器非$0

  IR级指令为beq;

  IR级Rs字段与MEM级目的寄存器编号字段相同;

旁路检测单元的实现如下图所示

如下图所示,增加数据选择器以在冒险发生时进行旁路

仿真测试:

上图代码最后两条指令有本实验所要求的数据冒险,期望执行beq时pc多保持一个周期不变并成功跳转。

如上图所示,pc在301c确实多保持了一个周期不变,并成功跳转回第一条指令的地址。符合预期。

实验总结:

后半部分实验从用寄存器划分一个单周期CPU开始,逐渐进行数据冒险的旁路,再进行阻塞的处理,

最后学习控制冒险的处理。理解流水线的波形图使我对流水线CPU的工作机制有了更深入的了解。而且

我掌握了从不同角度理解流水线的工作方式。在理解单条指令的执行时,跟踪一条指令在各个流水线寄 存器间状态的变化较方便。进行旁路时,从静态的视角观察不同流水级寄存器的联系更容易理解,另一种理解方式是每到来一个上升沿则各级指令前进一步。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有