自己动手写CPU之第七阶段(5)——流水线暂停机制的设计与实现
將陸續(xù)上傳本人寫的新書《自己動(dòng)手寫CPU》,今天是第28篇。我盡量每周四篇
China-pub的預(yù)售地址例如以下(有文件夾、內(nèi)容簡(jiǎn)單介紹、前言):
http://product.china-pub.com/3804025
亞馬遜的預(yù)售地址例如以下,歡迎大家圍觀呵。
http://www.amazon.cn/dp/b00mqkrlg8/ref=cm_sw_r_si_dp_5kq8tb1gyhja4
7.5 流水線暫停機(jī)制的設(shè)計(jì)與實(shí)現(xiàn)
7.5.1 流水線暫停機(jī)制設(shè)計(jì)
? ? ? 由于OpenMIPS設(shè)計(jì)乘累加、乘累減、除法指令在流水線運(yùn)行階段占用多個(gè)時(shí)鐘周期,因此須要暫停流水線,以等待這些多周期指令運(yùn)行完成。一種直觀的實(shí)現(xiàn)方法是:要暫停流水線,僅僅需保持取指令地址PC的值不變。同一時(shí)候保持流水線各個(gè)階段的寄存器(也就是IF/ID、ID/EX、EX/MEM、MEM/WB模塊的輸出)不變。
? ? ? OpenMIPS採(cǎi)用的是一種改進(jìn)的方法:假如位于流水線第n階段的指令須要多個(gè)時(shí)鐘周期,進(jìn)而請(qǐng)求流水線暫停,那么需保持取指令地址PC的值不變。同一時(shí)候保持流水線第n階段、第n階段之前的各個(gè)階段的寄存器不變,而第n階段后面的指令繼續(xù)執(zhí)行。
比方:流水線執(zhí)行階段的指令請(qǐng)求流水線暫停,那么保持PC不變,同一時(shí)候保持取指、譯碼、執(zhí)行階段的寄存器不變。可是能夠同意訪存、回寫階段的指令繼續(xù)執(zhí)行。
? ? ? 為此,設(shè)計(jì)加入CTRL模塊。其作用是接收各個(gè)階段傳遞過來(lái)的流水線暫停請(qǐng)求信號(hào),從而控制流水線各個(gè)階段的執(zhí)行。
? ? ? 為了實(shí)現(xiàn)流水線暫停機(jī)制,對(duì)系統(tǒng)結(jié)構(gòu)做如圖7-10所看到的的改動(dòng)。
? ? ? CTRL模塊的輸入來(lái)自ID、EX模塊的請(qǐng)求暫停信號(hào)stallreq。對(duì)于OpenMIPS教學(xué)版而言,僅僅有譯碼、運(yùn)行階段可能會(huì)有暫停請(qǐng)求。取指、訪存階段都沒有暫停請(qǐng)求。由于指令讀取、數(shù)據(jù)存儲(chǔ)器的讀寫操作都能夠在一個(gè)時(shí)鐘周期完畢。?
? ? ? CTRL模塊對(duì)暫停請(qǐng)求信號(hào)進(jìn)行推斷,然后輸出流水線暫停信號(hào)stall。從圖7-10中可知,stall輸出到PC、IF/ID、ID/EX、EX/MEM、MEM/WB等模塊。從而控制PC的值,以及流水線各個(gè)階段的寄存器。
7.5.2 流水線暫停機(jī)制實(shí)現(xiàn)
? ? ? 1、CTRL模塊的實(shí)現(xiàn)
? ? ? CTRL模塊的接口如圖7-10中所看到的,各接口作用如表7-1所看到的。
? ? ? 讀者須要注意:輸出信號(hào)stall是一個(gè)寬度為6的信號(hào)。其含義例如以下。
- ?stall[0]表示取指地址PC是否保持不變。為1表示保持不變
- ?stall[1]表示流水線取指階段是否暫停,為1表示暫停
- ?stall[2]表示流水線譯碼階段是否暫停。為1表示暫停
- ?stall[3]表示流水線運(yùn)行階段是否暫停,為1表示暫停
- ?stall[4]表示流水線訪存階段是否暫停,為1表示暫停
- ?stall[5]表示流水線回寫階段是否暫停,為1表示暫停
? ? ? CTRL模塊的代碼例如以下。源文件是本書附帶光盤Code\Chapter7_2文件夾下的ctrl.v。
module ctrl(input wire rst,input wire stallreq_from_id, // 來(lái)自譯碼階段的暫停請(qǐng)求input wire stallreq_from_ex, // 來(lái)自運(yùn)行階段的暫停請(qǐng)求output reg[5:0] stall );always @ (*) beginif(rst == `RstEnable) beginstall <= 6'b000000;end else if(stallreq_from_ex == `Stop) beginstall <= 6'b001111;end else if(stallreq_from_id == `Stop) beginstall <= 6'b000111;end else beginstall <= 6'b000000;endendendmodule當(dāng)中宏定義Stop在defines.v中定義。例如以下: `define Stop 1'b1 // 流水線暫停 `define NoStop 1'b0 // 流水線繼續(xù)? ? ? 能夠從下面三點(diǎn)理解。
? ? ? (1)當(dāng)處于流水線運(yùn)行階段的指令請(qǐng)求暫停時(shí)(即stallreq_from_ex等于Stop),依照OpenMIPS流水線暫停機(jī)制的設(shè)計(jì)。要求取指、譯碼、運(yùn)行階段暫停。而訪存、回寫階段繼續(xù),所以設(shè)置stall為6'b001111。
? ? ? (2)當(dāng)處于流水線譯碼階段的指令請(qǐng)求暫停時(shí)(即stallreq_from_id等于Stop),依照OpenMIPS流水線暫停機(jī)制的設(shè)計(jì)。要求取指、譯碼階段暫停,而運(yùn)行、訪存、回寫階段繼續(xù),所以設(shè)置stall為6'b000111。
? ? ? (3)其余情況下。設(shè)置stall為6'b000000,表示不暫停流水線。
? ? ? 2、改動(dòng)取指階段
? ? ? (1)改動(dòng)PC模塊
? ? ? 從圖7-10中可知,PC模塊新添加了一個(gè)輸入信號(hào)stall,其值就是CTRL模塊的接口stall。改動(dòng)取指階段PC模塊的代碼例如以下,當(dāng)中改動(dòng)的代碼使用加粗、斜體標(biāo)識(shí)。
源文件是本書附帶光盤Code\Chapter7_2文件夾下的pc_reg.v。
module pc_reg(input wire clk,input wire rst,input wire[5:0] stall, // 來(lái)自控制模塊CTRLoutput reg[`InstAddrBus] pc ,output reg ce );always @ (posedge clk) beginif (rst == `RstEnable) begince <= `ChipDisable;end else begince <= `ChipEnable;endend// 當(dāng)stall[0]為NoStop時(shí),pc加4,否則,保持pc不變always @ (posedge clk) beginif (ce == `ChipDisable) beginpc <= 32'h00000000;end else if(stall[0] == `NoStop) beginpc <= pc + 4'h4;endendendmodule? ? ? (2)改動(dòng)IF/ID模塊
? ? ? 參考圖7-10,IF/ID模塊也新增了一個(gè)輸入信號(hào)stall,主要改動(dòng)例如以下,改動(dòng)的代碼使用加粗、斜體標(biāo)識(shí)。完整代碼參考本書附帶光盤Code\Chapter7_2文件夾下的if_id.v文件。
module if_id( ......input wire[5:0] stall, );//(1)當(dāng)stall[1]為Stop,stall[2]為NoStop時(shí)。表示取指階段暫停,// 而譯碼階段繼續(xù),所以使用空指令作為下一個(gè)周期進(jìn)入譯碼階段的指令。//(2)當(dāng)stall[1]為NoStop時(shí),取指階段繼續(xù)。取得的指令進(jìn)入譯碼階段。//(3)其余情況下。保持譯碼階段的寄存器id_pc、id_inst不變。 always @ (posedge clk) begin if (rst == `RstEnable) begin id_pc <= `ZeroWord; id_inst <= `ZeroWord; end else if(stall[1] == `Stop && stall[2] == `NoStop) begin id_pc <= `ZeroWord; id_inst <= `ZeroWord; end else if(stall[1] == `NoStop) begin id_pc <= if_pc; id_inst <= if_inst; end end endmodule
? ? ? 3、改動(dòng)譯碼階段
? ? ? (1)改動(dòng)ID模塊
? ? ? 參考圖7-10,ID模塊新增了一個(gè)輸出信號(hào)stallreq,在實(shí)現(xiàn)載入、存儲(chǔ)指令的時(shí)候會(huì)給該信號(hào)賦值,眼下臨時(shí)設(shè)置這個(gè)輸出就是NoStop,詳細(xì)代碼不再給出。讀者能夠參考本書附帶光盤Code\Chapter7_2文件夾下的id.v文件。
? ? ? (2)改動(dòng)ID/EX模塊
? ? ? 參考圖7-10,ID/EX模塊新增了一個(gè)輸入信號(hào)stall,主要改動(dòng)例如以下,改動(dòng)的代碼使用加粗、斜體標(biāo)識(shí)。完整代碼位于本書附帶光盤Code\Chapter7_2文件夾下的id_ex.v文件。
module id_ex( ......//來(lái)自控制模塊的信息input wire[5:0] stall,...... );//(1)當(dāng)stall[2]為Stop,stall[3]為NoStop時(shí)。表示譯碼階段暫停,// 而運(yùn)行階段繼續(xù),所以使用空指令作為下一個(gè)周期進(jìn)入運(yùn)行階段的指令。//(2)當(dāng)stall[2]為NoStop時(shí)。譯碼階段繼續(xù)。譯碼后的指令進(jìn)入運(yùn)行階段。
//(3)其余情況下,保持運(yùn)行階段的寄存器ex_aluop、ex_alusel、ex_reg1、 // ex_reg2、ex_wd、ex_wreg不變。
always @ (posedge clk) begin if (rst == `RstEnable) begin ...... end else if(stall[2] == `Stop && stall[3] == `NoStop) begin ex_aluop <= `EXE_NOP_OP; ex_alusel <= `EXE_RES_NOP; ex_reg1 <= `ZeroWord; ex_reg2 <= `ZeroWord; ex_wd <= `NOPRegAddr; ex_wreg <= `WriteDisable; end else if(stall[2] == `NoStop) begin ex_aluop <= id_aluop; ex_alusel <= id_alusel; ex_reg1 <= id_reg1; ex_reg2 <= id_reg2; ex_wd <= id_wd; ex_wreg <= id_wreg; end end endmodule
? ? ? 4、改動(dòng)運(yùn)行階段
? ? ? (1)改動(dòng)EX模塊
? ? ? 參考圖7-10,EX模塊新增了一個(gè)輸出信號(hào)stallreq_from_ex,在本章后面實(shí)現(xiàn)乘累加、乘累減、除法指令的時(shí)候會(huì)給該信號(hào)賦值。
? ? ?(2)改動(dòng)EX/MEM模塊
? ? ?參考圖7-10,EX/MEM模塊新增了一個(gè)輸入信號(hào)stall,主要改動(dòng)例如以下。改動(dòng)的代碼使用加粗、斜體標(biāo)識(shí)。完整代碼位于本書附帶光盤Code\Chapter7_2文件夾下的ex_mem.v文件。//(2)當(dāng)stall[3]為NoStop時(shí),運(yùn)行階段繼續(xù),運(yùn)行后的指令進(jìn)入訪存階段。 //(3)其余情況下。保持訪存階段的寄存器mem_wb、mem_wreg、mwm_wdata、 // mem_hi、mem_lo、mem_whilo不變。 always @ (posedge clk) begin if(rst == `RstEnable) begin ...... end else if(stall[3] == `Stop && stall[4] == `NoStop) begin mem_wd <= `NOPRegAddr; mem_wreg <= `WriteDisable; mem_wdata <= `ZeroWord; mem_hi <= `ZeroWord; mem_lo <= `ZeroWord; mem_whilo <= `WriteDisable; end else if(stall[3] == `NoStop) begin mem_wd <= ex_wd; mem_wreg <= ex_wreg; mem_wdata <= ex_wdata; mem_hi <= ex_hi; mem_lo <= ex_lo; mem_whilo <= ex_whilo; end //if end //always endmodule
? ? ? 5、改動(dòng)訪存階段
? ? ? 訪存階段僅僅要改動(dòng)MEM/WB模塊。參考圖7-10,MEM/WB模塊也新增了一個(gè)輸入信號(hào)stall。主要改動(dòng)例如以下,改動(dòng)的代碼使用加粗、斜體標(biāo)識(shí)。
完整代碼位于本書附帶光盤Code\Chapter7_2文件夾下的mem_wb.v文件。
module mem_wb( ...... //來(lái)自控制模塊的信息input wire[5:0] stall, ...... );//(1)當(dāng)stall[4]為Stop。stall[5]為NoStop時(shí),表示訪存階段暫停,// 而回寫階段繼續(xù)。所以使用空指令作為下一個(gè)周期進(jìn)入回寫階段的指令。//(2)當(dāng)stall[4]為NoStop時(shí)。訪存階段繼續(xù),訪存后的指令進(jìn)入回寫階段。//(3)其余情況下,保持回寫階段的寄存器wb_wd、wb_wreg、wb_wdata、 // wb_hi、wb_lo、wb_whilo不變。 always @ (posedge clk) begin if(rst == `RstEnable) begin ...... end else if(stall[4] == `Stop && stall[5] == `NoStop) begin wb_wd <= `NOPRegAddr; wb_wreg <= `WriteDisable; wb_wdata <= `ZeroWord; wb_hi <= `ZeroWord; wb_lo <= `ZeroWord; wb_whilo <= `WriteDisable; end else if(stall[4] == `NoStop) begin wb_wd <= mem_wd; wb_wreg <= mem_wreg; wb_wdata <= mem_wdata; wb_hi <= mem_hi; wb_lo <= mem_lo; wb_whilo <= mem_whilo; end //if end //always endmodule
? ? ? 6、改動(dòng)頂層模塊OpenMIPS
? ? ? 由于上面加入了CTRL模塊,并且對(duì)流水線各個(gè)階段的模塊也都添加了對(duì)應(yīng)的接口。所以要改動(dòng)OpenMIPS模塊。以將新增接口與CTRL模塊連接起來(lái),連接關(guān)系如圖7-10所看到的,詳細(xì)代碼不在書中列出,讀者能夠參考本書附帶光盤Code\Chapter7_2文件夾下的openmips.v文件。
下一次將利用上面實(shí)現(xiàn)的流水線暫停機(jī)制實(shí)現(xiàn)乘累加、乘累減指令,敬請(qǐng)關(guān)注!總結(jié)
以上是生活随笔為你收集整理的自己动手写CPU之第七阶段(5)——流水线暂停机制的设计与实现的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: css实现元素水平垂直居中
- 下一篇: 枚举当前环境中打开的所有IE