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