《自己动手写CPU》第五章--逻辑、移位操作与空指令的实现

5.1流水线数据相关问题

流水线中经常有一些被称为“相关”的情况发生,它使得指令序列中下一条指令无法按照设计的时钟周期执行,这些“相关”会降低流水线的性能。流水线中的线管分为以下三种类型。

(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,由上推知。

对于第四章建立的原始openMIPS五级流水线而言,从ori指令的实现过程可以知道,只有在流水线回写阶段才会写寄存器(实际上,其余指令也是一样的,在后面实现其余指令时,对这一点会更加清楚),因此不存在WAW相关。又因为只能在流水线译码阶段读寄存器、回写寄存器,不存在WAR相关,所以OpenMIPS的流水线只存在RAW相关。RAW相关有三种情况。

(1)相邻指令间存在数据相关   (五级流水:取指 -> 译码 -> 执行 -> 访存 -> 回写)

例:第一条ori指令就将写寄存器$1,随后的第二条ori指令需要读出$s1的数据,但是这一条ori指令在回写阶段才会将其运算结果写入$1,而第2条ori指令在译码阶段就需要读取$1,此时第一条ori指令还处在执行阶段,所以得到的必然不是第一条ori指令计算得出的结果,按这个值运算,必然出错。这种情况可以称为相邻指令间存在数据相关

(2)相隔一条指令的指令间存在数据相关。

 例:第1条ori指令将写寄存器$1,第三条ori指令在译码阶段需要读取寄存器$1,此时第一条ori指令还存在访存阶段,所以得到的必然也不是正确的值。

(3)相隔2条指令的指令间存在数据相关。

对于(1)、(2)这两种情况,有三种解决方法。

①插入暂停周期:当检测到相关时,在流水线中插入一些暂停周期。

②编译器调度:编译器检测到相关后,可以改变部分指令的执行顺序

③数据前推:将计算结果从其产生处直接送到其他指令需要处或所有需要的功能单元处,避免流水线暂停。前提就是新的寄存器的值可以在执行阶段计算出来。

5.2OpenMIPS对数据相关问题的解决措施

OPenMIPS处理器采用数据前推的方法来解决流水线数据相关问题。通过补充完善图4-4原始的数据流图,添加部分信号使得可以完成数据前推的工作,如果5-7所示。主要是将执行阶段的结果、访存阶段的结果前推到译码阶段,参与译码阶段选择运算源操作数的过程

《自己动手写CPU》第五章--逻辑、移位操作与空指令的实现

图5-8给出了为实现数据前推而对OpenMIPS系统结构所做的修改,具体有两个方面。

(1)将处于流水线执行阶段的指令的运算结果,包括:是否要写目的寄存器wreg_o、要写的目的寄存器地址wd_o、要写入目的寄存器的数据wdata_o等信息送到译码阶段,如图5-8中虚线所示。

(2)将处于流水线访存阶段的指令的运算结果,包括:是否要写目的寄存器wreg_o、要写的目的寄存器地址wd_o、要写入目的寄存器的数据wdata_o等信息送到译码阶段。 

《自己动手写CPU》第五章--逻辑、移位操作与空指令的实现

5.4逻辑、移位操作和空指令说明

MIPS指令集架构中定义的逻辑操作指令有8条:and、andi、or、ori、xor、nor/lui,其中ori指令已经实现了本章要实现的其余7条指令。

MIPS指令集架构中定义的移位操作指令有6条:sll、sllv、sra、srav、srl、srlv。

MIPS指令集架构中定义的空指令有2条:nop和ssnop。其中ssnop是一种特殊类型的空操作,在每个周期发射多条指令的CPU中,使用ssnop指令可以确保单独占用一个发射周期。OpenMIPS设计为标量处理器,也就是每个周期发射一条指令,所以ssnop的作用与nop相同,可以按照nop指令的处理方式来处理ssnop指令。

另外,MIPS32指令集架构中还定义了sync、pref这2条指令,其中sync指令用于保证加载、存储操作的顺序、对于OpenMIPS而言,是严格按照指令顺序执行的,加载、存储动作也是按照顺序进行的,所以可以将sync指令当作nop指令处理,在这里将其归纳为空指令。pref指令用于缓存预取,OpenMIPS没有实现缓存,所以也可以将pref指令当作nop指令处理,此处也将其归纳为空指令

以上17条指令按照格式,作用的不同,又可分为几类,分别说明如下。

1.and、or、xor、nor

这4条指令都是R类型指令,并且指令码都是6‘b000000,也就是MIPS32指令集架构中定义的SPECIAL类。此外,第6~10bit都为0需要根据指令中第0~5bit功能码的值进一步判断是哪一种指令。

·当功能码是6'b100100时,表示是and指令,逻辑“与”运算。

·指令用法为:and rd,rs,rt

·指令作用为:rd <-rs AND rt ,将地址为rs的通用寄存器和地址为rt的通用寄存器的值进行逻辑“与”运算,运算结果保持到地址为rd的通用寄存器中。

·当功能码是6'b100101时,表示是or指令,逻辑"或"运算。

·指令用法为:or rd, rs, rt

 ·指令作用为:rd <-rs OR rt ,将地址为rs的通用寄存器和地址为rt的通用寄存器的值进行逻辑“或”运算,运算结果保持到地址为rd的通用寄存器中。

·当功能码是6'b100110时,表示是xor指令,异或运算。

·指令用法为:xor rd, rs, rt ,将地址为rs的通用寄存器和地址为rt的通用寄存器的值进行逻辑“异或”运算,运算结果保持到地址为rd的通用寄存器中。

·当功能码是6'b100111时,将地址rs的通用寄存器的值与地址为rt的通用寄存器的值进行逻辑“或非”运算。指令用法为:nor rd , rd, rt

2.andi、xori指令

这2条指令都是I型指令,可以依据指令中第26~31bit指令码的值判断是哪一种指令。

·当指令码是:6'b001100,表示的是andi指令,逻辑"与"运算。

·指令用法:andi rt, rs, immediate

·当指令码是:6'b001110,表示是xori指令,异或运算。

·指令用法:xori rt, rs, immediate

3.lui指令

lui指令是I型指令。

·指令用法:lui rt, immediate

·指令作用:rt <- immediate ||0(16),将指令中的16bit立即数保存到地址为rt的通用寄存器的高16位。另外,地址为rt的通用寄存器的低16位使用0填充。

4.sll, sllv,sra,srav,srl,srlv指令。

这六条指令都是R型指令,并且指令码都是6'b000000,也就是说,都是SPECIAL类,需要依据指令中第0~5bit功能码的值进一步判断是哪一种指令。

-- 6'b000000 sll 逻辑左移。

        sll rd, rt, sa  指令作用是:rd<-rt<<sa(logic),将地址为rt的通用寄存器的值向左移sa位,空出来的位置使用0填充,结果保存到地址为rd的通用寄存器中。

--6'b000010 srl指令,逻辑右移。

        srl rd , rt, sa

--6'b000011,表示sra指令,算数右移。

        sra rd , rt, sa(arithmetic)

--6'b000100 , sllv指令, 逻辑左移。

       sllv rd , rt, rs.

        指令作用为:rd <-rt << rs[4:0](logic),将地址为rt的通用寄存器的值向左移位,空出来的位置使用0填充。移位位数由地址为rs的寄存器值的第0~4bit决定。

--6'b000110,表示是srlv指令,逻辑右移。

        srlv rd, rt, rs

--6'b000111, srav指令,算数右移

        srav rd , rt, rs

5.nop, ssnop, sync, pref指令

nop、ssnop、sync这3条指令都是R类型指令,并且指令码都是6'b000000,也就是说都是SPECIAL类 

《自己动手写CPU》第五章--逻辑、移位操作与空指令的实现

上一篇:Random随机数


下一篇:luogu P7446 [Ynoi2007] rfplca