一 流水线暂停机制的实现
因为乘累加、乘累减、除法指令在流水线执行阶段占用多个时钟周期,因此需要暂停流水线,以等待这些多周期指令执行完毕,一种直观的实现方法是:要暂停流水线,只需保持取指令地址PC的值不变,同时保持流水线各个阶段的寄存器(也就是IF/ID、ID/EX、EXMEM、MEM/WB模块的输出)不变。
OpenMIPS采用的是一-种改进的方法: 假如位于流水线第n阶段的指令需要多个时钟周.期,进而请求流水线暂停,那么需保持取指令地址PC的值不变,同时保持流水线第n阶段、第n阶段之前的各个阶段的寄存器不变,而第n阶段后面的指令继续运行。比如:流水线执行阶段的指令请求流水线暂停,那么保持PC不变,同时保持取指、译码、执行阶段的寄存器不变,但是可以允许访存、回写阶段的指令继续运行。
为此,设计添加CTRL模块,其作用是接收各阶段传递过来的流水线暂停请求信号,从而控制流水线各阶段的运行。
因为只有译码、执行阶段可能会有暂停请求,取指、访存阶段都没有暂停请求,因为指令读取、数据存储器的读/写操作都可以在--个时钟周期内完成。因此只有译码和执行阶段来输入暂停请求信号,那么CTRL对那些模块进行操作呢,首先要暂停PC信号,然后对各个寄存器也需要控制,因此还需要一个控制信号stall。故修改结构如下:
CTRL控制模块的实现
输出控制信号stall需要注意是六位信号,据此区分对各个阶段的暂停控制:
因此当译码阶段发来暂停请求时,stall为000111,执行阶段发来请求时为001111;
PC模块实现
我们控制PC信号暂停的具体实现方式为在PC暂停阶段不让PC累加就可以了,其余情况都长长累加即可:
IF/ID模块实现
修改此模块主要思考一下两点:
1.如何让寄存器模块实现暂停
给予赋值默认空地址,空指令,空字节即可
2.什么时候寄存器模块需要暂停
根据第一段我们知道想要实现的是让申请暂停阶段的前面的阶段暂停,后面的阶段继续,据此只需要判断前后一个阶段是否暂停即可,若后一个阶段暂停则此寄存器暂停,输出空即可;
ID/EX阶段
若前一个阶段即译码阶段暂停,则后面的寄存器正常运行,之前的寄存器保持不变就好了:
EX/MEM模块
同样的思考前一个阶段的模块执行阶段,如果暂停则发送空指令,如果不是则保持不变:
MEM/WB阶段
同上:
二 乘累加,乘累减指令说明
作用都是对两个操作数做乘法然后与特殊寄存器的{hi,lo}相加或相减,注意也会区分有无符号
实现思路:
之前说过这个指令需要两个时钟周期完成,第一个时钟周期进行乘法运算,第二个时钟周期把乘法运算的结果与特殊寄存器中的值相加,这就需要保存乘法运算与现在是第几个时钟周期。因为每个寄存器模块在一个时钟周期内必有输出,第一个时钟周期结束后乘法结果已经传到EX/MEM模块中了,因此需要再第二个时钟周期时回传回来,修改系统结构如下:
ID阶段实现
此阶段已经很熟悉了,从指令格式中就可以看出,都需要读两个寄存器,但是不写入通用寄存器:
EX阶段实现
在执行阶段需要做如下事情:
1.计算乘法运算结果
这个的数据通路在前一章已经有了,只需要把多余的指令加进来即可
2. 用两个时钟周期完成乘累加累减运算
把得到的乘法运算在第一个时钟周期里传输出去,并且更新时钟周期个数,并传输暂停信号;
在第二个时钟周期内把结果和hilo的值相加或相减,并且更新时钟周期个数,暂停传输暂停信号;
3.暂停流水线
即对输出请求暂停信号赋值,目前只有累加减乘指令有申请暂停信号,把它传输过去就行
4.写入特殊寄存器
如果是msub和madd信号,则写入hilo使能,高位hi地位lo。
EX/ME模块
主要用于传递执行阶段发来的乘法值和时钟周期信号,思考一下条件:执行阶段发起暂停
至此,乘累加累减已经完成。下一节会介绍除法指令的实现。