????? Project Assignment 2 by HC120519101524

VIEWS: 10 PAGES: 7

									                計算機結構 Project Assignment 2
B91902073 黃于倫                    B91902082 馬智釗               B91902099 林松懋
1. Goal
  A simple pipelined processor simulator.
  Structural hazard: 使用不同的 Memory 儲存 Instruction 和 Data。
  Data hazard: Forwarding。(load word 之後的立即 access 仍需 stall)
  Control hazard: stall 1 cycle for branch and jump,decided in ID stage。
2. Structure
  以一個 Machine structure 代表整個 processor。
  struct Machine{
         unsigned int PC;                //記錄現在的 PC 值
         char Instruction[INSTR_SIZE];   //記錄讀入的 instructions(4K Bytes)
         int Register[32]                //記錄 32 個 Register 值
          char Data[MEM_SIZE];           //記錄 data memory 之值(4K Bytes)
          struct IF_IDstr IF_ID;         //IF/ID stage 之間的 buffer
          struct ID_EXstr ID_EX;         //ID/EX stage 之間的 buffer
          struct EX_MEMstr EX_MEM;       //EX/MEM stage 之間的 buffer
          struct MEM_WBstr MEM_WB; //MEM/WB stage 之間的 buffer
          struct CONTROLstr CONTROL //記錄 Control signal 之值


          int ForwardA,ForwardB;         //供 forwarding 使用的變數
  };
  其中,四個 buffer 的結構如下述:
  struct IF_IDstr{
         unsigned int PC;                //Instruction 的 PC+4,供 branch 計算
          int Instruction[32];           //Instruction 的內容,
                                         //為了方便 decode 而以 32 個 int 儲存
          int RegisterRs;                //Register rs 的編號
          int RegisterRt;                //Register rt 的編號
                                         //用以作 forwarding 和 stall 之判斷
  };


  struct ID_EXstr{
         int RegisterA;                  //Register rs 內的數值
          int RegisterB;                 //Register rt 內的數值
          int immediate;                 // Sign-extended immediate 值
          int RegisterRs;                //Register rs 的編號
      int RegisterRt;         //Register rt 的編號
      int RegisterRd;         //Register rd 的編號
                              //用以作 forwarding 和 stall 之判斷
      //以下為 control signals
      int MemtoReg;           //將傳至 MEM 和 WB stage
      int RegWrite;           //將傳至 MEM 和 WB stage
      int MemRead;            //將傳至 MEM stage
      int MemWrite;           //將傳至 MEM stage
      int RegDst;
      int ALUOp;              // 3 bits
                              //and=0,or=1,add=2,sub=6,slt=7,nor=8
      int ALUSrc;
};


struct EX_MEMstr{
       int ALUresult;         //ALU 計算結果
       int RegisterB;         //Register rt 內的數值
       int RegisterRd;        //Register rd 的編號
                      //I-type instruction 中此值為 rt 編號
(此值將一直傳至 WB stage,以標示出 write register 時欲寫入的 register 編號)


      //以下為 control signals
      int MemtoReg;           //將傳至 WB stage
      int RegWrite;           //將傳至 WB stage
      int MemRead;
      int MemWrite;
};


struct MEM_WBstr{
       int Data;              //從 memory 內取出的 Data
       int ALUresult;         //由 EX stage 傳來的 ALU 結果
       int RegisterRd;        //Register rd 的編號


      //以下為 control signals
      int MemtoReg;
      int RegWrite;
};
Control signal 之 structure 則包含七個數值:
 struct CONTROLstr{
        int MemtoReg;
        int RegWrite;
        int MemRead;
        int MemWrite;
        int RegDst;
        int ALUOp; // and=0, or=1, add=2, sub=6, slt=7, nor=8;
        int ALUSrc;
 };
 每個 structure 中仍有一些其他變數用以記錄並控制 processor 的運作,但並非
實體元件。


3. Data flow
  Main function:
                      ,       ,                 ,
   1. 取得 instruction 數 clock 數 以及所有的 instructions 並將其存入 processor
      的 instruction memory 中。
   2. 將 processor 初始化。
   3. 逆向執行一個 cycle 中的五個 stages,以 buffer 作為 stage 間傳遞資料的
      媒介。執行到要求的 cycle 數或是 program 完成時便停止。
                                    ,
      當下一個 PC 值恰好為總 instruction 數 x4 並且非因 branch 或 jump 而跳
      回時,代表程式已經執行至最後一個 instruction,此時通知 processor 此
      一訊息,待 processor 執行完殘存於其中數個 stages 內的 instructions 後,
      便停止此一步驟。
   4. 印出 processor 中的各項資訊,以及 IPC。


   步驟 3.由以下 code 所執行:
   for(i=0;i<num_clock;i++){     //執行特定數量的 clock cycles
        …………                     //一些在每個 cycle 開始前執行的設定
                                 //目的為用以正確偵測程式停止的時機
       writeback(&m);            //m 為 Machine structure
       mem_access(&m);
       execute(&m);
       decode(&m);
       fetch(&m);

       if(m.PC>=num_instr*4)     //檢查程式是否已執行至末端
            m.done[0]=1;         //若是,則將此訊息告知 processor
     if(m.complete==1)            //檢查程式是否已完全執行完畢
              break;              //跳離步驟 3.,進入步驟 4.
}

對於五個 stage 內所作的工作,則說明如下:
a. Instruction Fetch stage
    1.   從 Instruction memory 中依據 PC 值取出 instruction。
    2.   取出 instruction 中的 rs,rt 值並傳入 IF/ID buffer,供之後進行檢查。
    3.   增加 PC 值,將+4 後的值存入 processor 中,同時也將其傳至 IF/ID
         buffer,以供之後的 branch 做計算。


b. Instruction Decode stage
    1.   將 IF/ID buffer 中的 instruction 進行 decode,取出 opcode、rs、rt、rd、
         immediate 以及 jump value 等值。其中,R-type instruction 的 function
         code 可以從 immediate mod 64 取得(若為負數,則加上 64 即為正確
         值)。
    2.   判斷此 instruction 是否為 load word 之後的 register access(欲 access
         上一個 instruction load 出來的值),或是 write register 之後立即的
                                                   ,
         branch(branch 所比較的 register 尚未寫入正確的值 一部分情況下可
         以用 forward,但來不及時仍需 stall)。由於這些情況需要 stall
         pipeline,在 control signal 的輸出上會與正常情況不同,因此在實際
         將 control signal 送往 ID/EX buffer 前先做此檢查。
    3.   若此 instruction 是 branch 或 stall,並且並非在步驟 2.中被判定需要
         stall,則此時已經可以算出欲前往的 PC 值並且更新之(branch 的情
         況下,也已經可以比較兩 register 以判斷是否 taken)。
    4.   依據 opcode 設定符合該 instruction 的 control signals,R-type 的
         instruction(opcode=0)則以 funct 之值決定 ALUOp。最後,將這些
         control signals 傳入 ID/EX buffer,但在上述兩種必須 stall 的情況下,
         ID/EX buffer 中的所有 control signal 則傳入 0。並且記錄一些數值,
         通知同一個 clock cycle 中接下來的 Instruction Fetch stage 停止工
         作,不要把資料覆寫入 IF/ID buffer。
    5.   將 IF/ID buffer 中其他的數值傳入 ID/EX buffer,包括由 ID stage 中
         計算出的 RegisterA、RegisterB、immediate、RegisterRs、RegisterRt、
         以及 RegisterRd。
    6.   若此一 stage 中處理的是 beq、bne 或 j 這三個 instruction,則整個
         pipeline 必須填入一 bubble。此 bubble 會被放置於 IF stage,並且順
         著執行過程傳至 ID、EX、MEM 及 WB stage 後消失,將 pipeline 延
         遲一個 cycle。
c. Execution stage
  1.   Forwarding 判定。以 ID/EX、EX/MEM、MEM/WB 三個 buffer 中的
       Register 編號值做為是否使用 forwarding 以及何種 forwarding 的判
       斷。但是由於 Memory Access Stage 在 Execution stage 之前執行,導
       致此時 MEM/WB buffer 裡的值已經不是本 clock cycle 開始時真正的
       值。因此在 MEM stage 一開始時,便會在 RegisterRd 被覆寫前將其
                           ,
       存入一變數 LastRegisterRd 並且在 EX stage 的 forwarding 判斷時使
       用此值。其他的 Forwarding 或是 stall 的判斷也會遭遇到此一問題,
       故各 buffer 中增加了數個 Last-開頭的變數以應付此狀況。
  2.   決定 ALU input 0,一般是 ID/EX buffer 中 RegisterA 的值,若需要
       Forwarding,則可能為 EX/MEM buffer 中的 ALUresult,或是
       MEM/WB buffer 中的 Data/ALUresult(由 WB stage 中的 instruction 是
       否為一 Memory to Register 的 instruction 而定)。
  3.   決定 ALU input 1,一般是 ID/EX buffer 中 RegisterB/immediate 的值
       (由 ALUSrc 決定),若需要 Forwarding,則可能為 EX/MEM buffer
       中的 ALUresult,或是 MEM/WB buffer 中的 Data/ALUresult(由 WB
       stage 中的 instruction 是否為一 Memory to Register 的 instruction 而
       定)。
  4.   依據 ID/EX buffer 中 ALUOp 的值,將 ALU input 0 和 ALU input 1
       作運算,並將結果存入 EX/MEM buffer 中的 ALUresult。
  5.   將 ID/EX buffer 中其他的數值傳入 EX/MEM buffer,包括 control
       signal 中的 MemtoReg、RegWrite、MemRead 和 MemWrite,以及
       RegisterB 和 RegisterRd 等值。其中,由 control signal 中的 RegDst
       決定,要使用 ID/EX buffer 中 RegisterRt 還是 RegisterRd 的值,來
       做為 EX/MEM buffer 中 RegisterRd 的值。
d. Memory Access stage
                                                 ,
  此 stage 中的 Memory Read 和 Memory Write 不會同時執行 端看 Control
  Signal 中的數值而決定要執行哪一部分。
               ,                                ,
  1. Write Data 若 EX/MEM buffer 中 MemWrite 的值為 1 則將 EX/MEM
      buffer 內 RegisterB 的值,寫入由 EX/MEM buffer 內的 ALUresult 所
      標示的 Memory 位址。
  2. Read Data,若 EX/MEM buffer 中 MemRead 的值為 1,則將由
      EX/MEMbuffer 內的 ALUresult 所標示的 Memory 位址中儲存的值取
      出,並將其傳入 MEM/WB buffer,供 WB stage 完成 load word 的工
      作。
  3.   將 EX/MEM buffer 中其他的數值傳入 MEM/WB buffer,包括 control
       signal 中的 MemtoReg 和 RegWrite,以及由 EX stage 中得來的
       ALUresult 和 RegisterRd。
     e. Write Back stage
       1.   依據 MEM/WB buffer 中 MemtoReg 的值,決定要寫入的 data 是由
            MEM/WB buffer 中 ALUresult 還是從 memory 中取出的 Data。
       2.                                    ,
            若 MEM/WB buffer 中 RegWrite 的值為 1 則將 data 寫入由 MEM/WB
            buffer 內 Register Rd 作為編號的 Register。


     另外,每個 stage 在開始時皆會作一些檢查,若程式剛開始、即將結束、或
     是在進行 branch 或 lw 造成的 stall 時,皆會使某個或某些 stages 必須暫停或
     跳過原本欲執行的工作,以避免寫入不正確的數值。因此這些檢查會在該
     stage 執行任何工作之前執行,若符合條件,則在進行一些必要的設定後,
     立刻結束該 stage。


4. 心得
   本 project 中我們遇到的瓶頸主要有四:資料儲存的方式、程式開始和結束
的控制、以及 ID 和 EX stage 中,對於 forwarding 和是否 stall 的判斷。
1. 資料儲存:為了模擬 processor 的真實狀況,採用 char 的方式儲存 instruction
   和 data 以節省空間,因此欲取得 32 bit 的 instruction 和 memory word 時,皆
     需 將四個 char 的值組合成一個 word,問題出現在由 char 轉換成 int 的動
         ,                   ,
     作中 由於採用 sign-extended 數值為 128-255 的 char 皆會轉換成負數的 int    ,
     而導致 instruction decode 時的錯誤。但此問題並不嚴重,發現後立刻獲得解
     決。
2.   程式開始和結束的控制:程式剛開始時,後面的數個 stages 是沒有工作的。
     (就算後面的 stages 照常執行也不會影響到程式的執行結果,但由於本
     simulator 中 WB stage 同時負責計算 completed instruction 的個數,因此若照
     常執行會導致計算錯誤),為了達成此一效果,在初始化 processor 時,便在
     ID~WB 等四個 stage 皆塞入 bubbles,具有 bubble 的 stage 將不會執行任何
     原本的工作。
         程式結束時,為了讓其能正確停止,採用兩段式的通知。當 PC 值已經
     超過原本輸入的 instruction 範圍(例如:輸入 10 個 instuctions,但 PC 值已達
     40),並且非因 branch 或 jump 而在 ID stage 又跳回原本範圍時,代表程式已
     經不需再 fetch instruction,此時會先行通知 processor,之後的數個 cycle 便
     僅供 processor 將其中尚未完成的 instructions 執行完成,當這些 instructions
     皆完成後,processor 便正式停止執行,若輸入的 cycle 數大過此時的 cycle
     數,則在 IPC 計算時,採用此時實際花費的 cycle 數。
3.   Forwarding in EX stage:Forwarding 可說是寫作此 simulator 的最大難題,雖
     然課程中已經詳述了 forwarding 的方法,但實際應用上仍有容易出錯的地
     方。真正的 processor 是將所有 stages 一起執行,並用 clock edge 來控制,
     simulator 中則採用由後往前的方法,因此當 forwarding 必須使用該 clock
     cycle 開始時 buffer 中的值,而非在 stage 執行後被覆寫的值時,便需要額外
     的方法來記錄並獲取正確的數值。
          另外,EX/MEM buffer 中 RegisterB 的值(從 register rt 讀取出的數值)也
     要進行 forwarding,例如剛由 add 更新的 register 馬上用來 store word 時,若
     不採用 forwarding,則 sw 將會來不及將正確的 register 值存入。
4.   Forwarding and stall in ID stage:此 stage 中對 Forwarding 的需求來自 branch
     instruction,因其也可能必須獲取前一至二個 instruction 中剛進行更新的
     register 值,而當 forwarding 仍然來不及時,則只有 stall 一途。在 load word
     之後進行的 stall 也是因為時間上的不足而採用的最後手段。Stall 的採用會
     使某個特定的 stage 停止其原本的工作,但也必須因此採取一些特定的行
     動,以維護 processor 的正確性。
       由於整個 simulator 是採用 loop 以執行每個 cycle,因此若在某處設定錯
     誤,例如 stall 的處理上停止了某項不該停止的工作,則執行結果將產生連
     鎖性的錯誤。多半的錯誤都是來自使用數值的時間性不正確,如心得 3.中對
     Forwarding 的描述。由於此類錯誤不容易由外觀看見,因此在 Debug 上花費
     了不少時間,通常必須逐個 cycle 檢查錯誤的起源,甚至必須額外印出一些
     內部數值以找出從 PC、Register、以及 Control signal 上看不出來源的錯誤。

								
To top