# 計算機組織 pipeline(data hazard)

## 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>)
  forward A/B ;*
改良後的電路圖如下:

**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>)
  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>)
  forward A/B ;*
改良後的電路圖如下(以第一張圖為例):

除了上述的兩個 hazard 以外,還有另一種無法靠 forwarding 解決的 hazard,必須要 stall 一個 cycle,稱之為 load-use Hazard,以下為例子:

我們可以上從圖中看到,在 cc4 結束後,第一級 pipeline 才會把資料從 Memory 讀進 MEM/WB register,但是第二級 pipeline 在 cc4 時就必須使用到 $2 的資料了,所以必須至少等到 cc4 結束後才能 forward 資料,因此電路必須 stall 一個 cycle。那我們再以下圖解釋電路是如何 stall 的(nop):

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>)
  forward ;*