自己动手写CPU(6)流水线暂停、乘累加减与除法器的实现
自己動(dòng)手寫(xiě)CPU(6)流水線暫停、乘累加減與除法器的實(shí)現(xiàn)
流水線暫停
因?yàn)镺penMIPS設(shè)計(jì)乘累加、乘累減、除法指令在流水線執(zhí)行階段占用多個(gè)時(shí)鐘周期,因此需要暫停流水線,以等待這些多周期指令執(zhí)行完畢。OpenMIPS采用的是一種改進(jìn)的方法:假如位于流水線第n階段的指令需要多個(gè)時(shí)鐘周期,進(jìn)而請(qǐng)求流水線暫停,那么需保持取指令地址PC的值不變,同時(shí)保持流水線第n階段、第n階段之前的各個(gè)階段的寄存器不變,而第n階段后面的指令繼續(xù)運(yùn)行。
為實(shí)現(xiàn)CPU的流水線暫停功能,我們?cè)O(shè)計(jì)添加了CTRL模塊,其作用是接收各階段傳遞過(guò)來(lái)的流水線暫停請(qǐng)求信號(hào),從而控制流水線各階段的運(yùn)行。CTRL模塊對(duì)譯碼和執(zhí)行階段的暫停請(qǐng)求信號(hào)進(jìn)行判斷,然后輸出流水線暫停信號(hào)stall。下圖是為了實(shí)現(xiàn)流水線暫停機(jī)制而對(duì)系統(tǒng)結(jié)構(gòu)所做的修改。具體代碼修改之處見(jiàn)文末的項(xiàng)目鏈接。
指令介紹
乘累加、乘累減指令共有4條,包括: madd、maddu、msub、msubu,各指令的格式如下圖所示。從圖中可知,這4條指令的指令碼都是SPECIAL2,第6~15bit都為0,可以依據(jù)第0~5bit的功能碼確定是哪一種指令。
- 當(dāng)功能碼是6’b000000時(shí),表示是madd指令,有符號(hào)乘累加運(yùn)算。指令用法為:madd rs, rt。指令作用為:{HI, LO}<-{HI, LO}+ rs x rt,將地址為rs的通用寄存器的值與地址為rt的通用寄存器的值作為有符號(hào)數(shù)進(jìn)行乘法運(yùn)算,運(yùn)算結(jié)果與{HI, LO}相加,相加的結(jié)果保存到{HI, LO}中。此處{HI, LO}表示 HI、LO寄存器連接形成的64位數(shù),HI是高32位,LO是低32位。
- 當(dāng)功能碼是6’b000001時(shí),表示是 maddu指令,無(wú)符號(hào)乘累加運(yùn)算。指令用法為:maddu rs, rt。指令作用為: {HI, LO} <- {HI, LO} + rs × rt,將地址為rs的通用寄存器的值與地址為rt的通用寄存器的值作為無(wú)符號(hào)數(shù)進(jìn)行乘法運(yùn)算,運(yùn)算結(jié)果與{HI, LO}相加,相加的結(jié)果保存到{HI,LO}中。
- 當(dāng)功能碼是6’b000100時(shí),表示是msub指令,有符號(hào)乘累減運(yùn)算。指令用法為:msub rs, rt。指令作用為:{HI, LO}<-{HI,LO} - rs × rt,將地址為rs 的通用寄存器的值與地址為rt的通用寄存器的值作為有符號(hào)數(shù)進(jìn)行乘法運(yùn)算。然后使用{HI,LO}減去乘法結(jié)果,相減的結(jié)果保存到{HI,LO}中。
- 當(dāng)功能碼是6’b000101時(shí),表示是 msubu指令,無(wú)符號(hào)乘累減運(yùn)算。指令用法為:msubu rs, rt。指令作用為:{HI, LO} <-{HI, LO} - rs × rt,將地址為rs的通用寄存器的值與地址為rt的通用寄存器的值作為無(wú)符號(hào)數(shù)進(jìn)行乘法運(yùn)算。然后使用{HI,LO}減去乘法結(jié)果,相減的結(jié)果保存到{HI,LO}中。
修改之處
實(shí)現(xiàn)思路
乘累加與乘累減指令計(jì)劃在流水線階段采用兩個(gè)時(shí)鐘周期完成運(yùn)算,所以必須要保存兩個(gè)信息:(1)、當(dāng)前是第幾個(gè)時(shí)鐘周期;(2)、乘法結(jié)果。所以O(shè)penMIPS通過(guò)在EX/MEM模塊添加兩個(gè)寄存器cnt、hilo,分別保存上述信息。修改系統(tǒng)結(jié)構(gòu)框圖如下所示:
1.修改譯碼階段的ID模塊
譯碼階段的ID模塊要添加對(duì)乘累加、乘累減指令的分析,根據(jù)給出的指令格式可知,這4條指令都是 SPECIAL2類指令,可以依據(jù)功能碼確定是哪一種指令。確定指令的過(guò)程如下圖所示。
涉及的宏定義如下(因?yàn)椴簧婕皩?duì)通用寄存器的回寫(xiě),所以無(wú)需“_OP”的宏定義)
`define EXE_MADD 6'b000000 `define EXE_MADDU 6'b000001 `define EXE_MSUB 6'b000100 `define EXE_MSUBU 6'b000101這4條指令的譯碼過(guò)程都是相似的,簡(jiǎn)單說(shuō)明如下。
2.修改執(zhí)行階段的EX模塊
3.修改EX/MEM模塊
增加兩個(gè)輸入接口hilo_i,cnt_i,增加兩個(gè)輸出接口hilo_o,cnt_o,在流水線執(zhí)行階段暫停的時(shí)候,將輸入信號(hào)hilo_i通過(guò)輸出接口hilo_o送出,輸入信號(hào)cnt i通過(guò)輸出接口cnt_o送出。其余時(shí)刻,hilo_o為0,cnt_o也為0。
除法器
采用"試商法"實(shí)現(xiàn)除法運(yùn)算,對(duì)于32位的除法,至少需要32個(gè)時(shí)鐘周期才能得到除法結(jié)果。
實(shí)現(xiàn)思路
新建一個(gè)模塊 DIV,在其中實(shí)現(xiàn)采用試商法的32位除法運(yùn)算。當(dāng)流水線執(zhí)行階段的EX模塊發(fā)現(xiàn)當(dāng)前指令是除法指令時(shí),首先暫停流水線,然后將被除數(shù)、除數(shù)等信息送到DIV模塊,開(kāi)始除法運(yùn)算。DIV模塊在除法運(yùn)算結(jié)束后,通知EX模塊,并將除法結(jié)果送到EX模塊,后者依據(jù)除法結(jié)果設(shè)置HI、LO寄存器的寫(xiě)信息,同時(shí)取消暫停流水線。
修改后的系統(tǒng)部分框圖如下
DIV模塊的主要部分是一個(gè)狀態(tài)機(jī),共有四個(gè)狀態(tài)
- DivFree:除法模塊空閑;
- DivByZero:除數(shù)是0;
- DivOn:除法運(yùn)算進(jìn)行中;
- DivEnd:除法運(yùn)算結(jié)束;
作者使用的是一段式的狀態(tài)機(jī),里面阻塞和非阻塞賦值交替使用,對(duì)于我這個(gè)硬件小白來(lái)說(shuō)還是難度太高,我還是老老實(shí)實(shí)用三段式重新實(shí)現(xiàn)了,中間過(guò)程還算有點(diǎn)復(fù)雜,輸出的邏輯既有組合邏輯也有時(shí)序邏輯,好在調(diào)試了一會(huì)之后總算通過(guò)了。
仿真結(jié)果
乘累加、乘累減測(cè)試指令
.org 0x0.set noat.global _start _start:ori $1,$0,0xffff sll $1,$1,16ori $1,$1,0xfffb # $1 = -5ori $2,$0,6 # $2 = 6mult $1,$2 # hi = 0xffffffff# lo = 0xffffffe2madd $1,$2 # hi = 0xffffffff# lo = 0xffffffc4maddu $1,$2 # hi = 0x5# lo = 0xffffffa6msub $1,$2 # hi = 0x5# lo = 0xffffffc4 msubu $1,$2 # hi = 0xffffffff# lo = 0xffffffe2由波形圖可見(jiàn),乘累加、乘累減指令實(shí)現(xiàn)正確,同時(shí)觀察到乘累加、乘累減指令都需要兩個(gè)時(shí)鐘周期來(lái)完成,且兩個(gè)時(shí)鐘周期內(nèi)的PC值都保持不變。
除法模塊測(cè)試指令
.org 0x0.set noat.global _start _start:ori $2,$0,0xffffsll $2,$2,16ori $2,$2,0xfff1 # $2 = -15ori $3,$0,0x11 # $3 = 17div $zero,$2,$3 # hi = 0xfffffff1,lo = 0x0divu $zero,$2,$3 # hi = 0x00000003,lo = 0x0f0f0f0ediv $zero,$3,$2 # hi = 2,lo = 0xffffffff實(shí)驗(yàn)心得
執(zhí)行階段的EX模塊對(duì)HI、LO寄存器的寫(xiě)操作為什么不引入cnt_i來(lái)進(jìn)行判斷呢?即cnt_i=2’b01(執(zhí)行階段的第二個(gè)周期)再加上功能碼的定義來(lái)進(jìn)行對(duì)HI、LO寄存器是否寫(xiě)入的決策呢?
聯(lián)系前后模塊發(fā)現(xiàn),EX模塊發(fā)出暫停流水線的請(qǐng)求后,EX_MEM模塊收到來(lái)自EX模塊的暫停流水線請(qǐng)求后就把HI、LO寄存器的寫(xiě)使能關(guān)閉了,也就是說(shuō)我們?cè)诔死奂印⒊死蹨p的第一階段的寫(xiě)指令是傳不到HILO寄存器堆的,所以就不用加上cnt_i這個(gè)冗余指令的判斷過(guò)程了。
三段式狀態(tài)機(jī)還需多多訓(xùn)練,多注意時(shí)序上的問(wèn)題,哪些變量在上升沿賦值,哪些變量是組合邏輯賦值。
乘累加、乘累減項(xiàng)目
除法運(yùn)算項(xiàng)目
總結(jié)
以上是生活随笔為你收集整理的自己动手写CPU(6)流水线暂停、乘累加减与除法器的实现的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 自己动手写CPU(5)简单算术操作指令实
- 下一篇: 自己动手写CPU(7)转移指令的实现