系列文章 : 使用 Verilog 實作 in-order CPU
hazard detection
hazard detection 負責
- 偵測 data hazard 有沒有發生
- 一旦發生了就發訊號 (
hz_stall_if_id ) 通知 fetch-stage 以及 decode-stage。
- fetch-stage 以及 decode-stage 收到訊號後,就將自己 stall 住,並往 ex-stage 插入一個 bubble
- 偵測 control hazard 有沒有發生
- 一旦發生了,就發訊號 (
hz_flush_if_id, hz_flush_id_ex, hz_flush_ex_mem ) 通知 pipeline_reg_if_id, pipeline_reg_id_ex pipeline_reg_ex_mem
- 各個 pipeline_reg 收到訊號後,會把 fetch-stage, decode-stage, ex-stage 的資訊通通 flush 掉
相關程式碼
完整的介紹可以看一下計算機組織的課本! 這邊簡單介紹一下三種 hazard。
- structure hazard
- 從下圖可以看到, cycle1 這個指令會想要取用 memory ( for data ),而 cycle4 這個指令也想要取用 memory ( for instruction )
- 假如我們的 fetch-stage 跟 mem-stage 用的是同一組訊號去取用資料的話,就會打架,變成可能要 stall ,讓彼此間錯開。
- 在這個小專案裡面,我們是直接切成兩份 memory ( data memory 以及 instruction memory ) 來解決 structure hazard。

- data hazard
- 當數據間彼此有相依性時,就可能出現 data hazard。
- 假定 cycle2 是 lw
r3, 4(r4)
- 假定 cycle3 是 add r4,
r3, r2
- 這時候 cycle3 依賴於 cycle2,因為 cycle3 需要知道 r3 的結果,變成 cycle3 需要等待 cycle2 的執行
- control hazard
- 這個設計要到 mem-stage 才能真正決定需不需要 branch,所以在這之前的指令都相依於這個 branch 指令。最簡單的策略就是等到 branch 真的發生的時候,把,fetch, decode, execute 都 flush 掉。
data hazard detection handling
以下是偵測 load-use data hazard 的方式。
- ex-stage 的指令需要讀取記憶體,並將結果載入到暫存器裡面。也就是執行
lw 指令。
- (
decode-stage 的 rs 等於 ex-stage 的 rt) 或是 ( decode-stage 的 rt 等於 ex-stage 的 rt)
- 當這個情況發生的時候,代表 decode-stage 會需要用到 ex-stage 即將載入的 register。
- 這導致 decode-stage 會需要等待 ex-stage 的結果。
那遇到了 load-use data hazard 該怎麼處理呢 ?
- data hazard detection unit 會發出訊號給 fetch-stage, decode-stage,讓 fetch-stage / decode-stage 凍結住,停止運行
- data hazard unit 會讓 pipeline_reg_id_ex 發出一個 bubble。
- 要怎麼發出一個 bubble 呢 ? 很簡單,只要讓 pipeline_reg_id_ex 給 ex-stage 的資料
通通都是 0 就可以了,這就會讓 ex-stage 拿到一個 nop ( 什麼也不做,不影響 CPU 狀態的指令 )
- forwarding unit 會在合適的時機點,把 wb-stage 的資料 forward 給 ex-stage 的資料
control hazard detection handling
以下是偵測 control hazard 的方式
- 其實只要觀察
mem_branch_and 這個訊號就可以了,只要 mem-stage 確定要發生 branch,就會 assert mem_branch_and。
遇到了 control hazard 該怎麼辦呢 ?
- 把 fetch-stage, decode-stage, ex-stage 通通 flush 掉 !
- 那具體上,什麼叫作
flush pipeline 呢 ? hazard detection unit 會發訊號給 pipeline_reg_if_id, pipeline_reg_id_ex, pipeline_ex_mem,讓他們把要交給下一個 stage 資料通通變成 0 ( 也就是插入 3 個 nop )。
參考連結