# 計算機組織 pipeline(data hazard) ![](https://i.imgur.com/XKg2lu3.png) ## EX/MEM Data Hazard * <font color="#1D5EA1">(1a)EX/MEM. RegisterRd = ID/EX. RegisterRs </font> <font color="f59745">第n+1級</font> pipeline 要取用的register [25:21] 跟<font color="f59745">第n級</font> pipeline 寫入的 resgister 是一樣的,就會造成此hazard。可參考圖中的 *sub* 跟 *and*。 * <font color="#1D5EA1">(1b)EX/MEM. RegisterRd = ID/EX. RegisterRt </font> 與 1a 一樣,但是source為 [20:16]。 * <font color="#1D5EA1">(2a)MEM/WB. RegisterRd = ID/EX. RegisterRs </font> <font color="f59745">第n+2級</font> pipeline 要取用的register[25:21]跟<font color="f59745">第n級</font> pipeline 寫入的 resgister 是一樣的,就會造成此hazard。可參考圖中的 *sub* 跟 *or*。 * <font color="#1D5EA1">(2b)MEM/WB. RegisterRd = ID/EX. RegisterRt </font> 與 2a 一樣,但是source為[20:16]。 當然,要在控制訊號<font color="1DA14D">EX/MEM. RegsiterWrite = 1</font>以及<font color="1DA14D">MEM/WB. RegsiterWrite = 1</font>(有需要把資料寫入register的時候)才會發生Data Hazard。 同時,如果寫入的register address是 $0(it's valid!),因為$0的讀出值應永遠為0,所以不會產生Data Hazard。 總結一下,當以下條件成立時,會發生 **EX Data Hazard:** *if (<font color="1DA14D">EX/MEM. RegWrite</font> & <font color="1DA14D">EX/MEM. RegRd != 0</font> & <font color="1DA14D">EX/MEM. RegRd == ID/EX. RegRs/Rt</font>) &emsp;&emsp;forward A/B ;* 改良後的電路圖如下: ![](https://i.imgur.com/mFTTEpz.png) **MEM Data Hazard:** 與 EX Hazard 相似: *if (<font color="1DA14D">MEM/WB. RegWrite</font> & <font color="1DA14D">MEM/WB. RegRd != 0</font> & <font color="1DA14D">EX/MEM. RegRd == ID/EX. RegRs/Rt</font>) &emsp;&emsp;forward A/B ;* 但是,如果電路同時出現 EX 與 MEM Data Hazard 的話,那到底要成立哪一個條件呢? 請看舉例: ```MIPS= add $1, $1, $2 add $1, $1, $3 add $1, $1, $4 ``` 可以觀察第三個與其他兩個 add 的關係。第二個跟第三個 add 出現了 EX Data Hazard,而第一個跟第三個 add 出則是出現了 MEM Data Hazard。如果將 pipeline 展開的話,就是在 cc5 的時候會同時發生這兩個Hazard。而解決方法就是在 MEM Data Hazazrd 的條件中再加入「不能發生 EX Data Hazard 」,也就是: *if (<font color="1DA14D">MEM/WB. RegWrite</font> & <font color="1DA14D">MEM/WB. RegRd != 0</font> & <font color="1DA14D">EX/MEM. RegRd == ID/EX. RegRs/Rt</font> & <font color="f59745">!EX Data Hazard</font>) &emsp;&emsp;forward A/B ;* 改良後的電路圖如下(以第一張圖為例): ![](https://i.imgur.com/ETuV5OA.jpg) 除了上述的兩個 hazard 以外,還有另一種無法靠 forwarding 解決的 hazard,必須要 stall 一個 cycle,稱之為 load-use Hazard,以下為例子: ![](https://i.imgur.com/VAZqKeW.png) 我們可以上從圖中看到,在 cc4 結束後,第一級 pipeline 才會把資料從 Memory 讀進 MEM/WB register,但是第二級 pipeline 在 cc4 時就必須使用到 $2 的資料了,所以必須至少等到 cc4 結束後才能 forward 資料,因此電路必須 stall 一個 cycle。那我們再以下圖解釋電路是如何 stall 的(nop): ![](https://i.imgur.com/UKVftPe.png) 1. 在 cc3 時,偵測 IF/ID 和 ID/EX 所要讀的 address 是否相同 2. 如果第一點成立的話,則在 EX stage 之前的電路插入 nop,同時讓 lw 指令繼續執行 3. 最後,再將 data 從 MEM/WB register forward 到 EX stage,所以load-use Hazazrd 成立的條件為: *if (<font color="1DA14D">ID/EX. MemRead</font> & <font color="1DA14D">IF/ID. RegRs/Rt == ID/EX. RegRt</font>) &emsp;&emsp;forward ;*