# Pipeline
###### tags: `IT鐵人`
### Clock Cycle Time

Clock Cycle Time又稱為時脈週期,代表電腦裡面計時器一個Cycle的時間。在上一回的內容中,我們將CPU組裝起來,這時候所有的零件連接在一起,代表要做完所有步驟才會輪到下一個指令,所以一個Cycle的時間就要訂成最長的指令時間,也就是說假設每個指令需要的時間為:
|指令類型|時間|
|--|--|
|R-type|400ps|
|Load word|600ps|
|Store word|550ps|
|Branch|350ps|
|Jump|200ps|
那麼我們就要挑最長的600ps當作一個Cycle的時間。
那麼每600ps我們就只能完成一個指令,太慢了。

## Pipeline
假設現在有四個人要洗衣服,步驟有洗衣服 30min、烘衣服 40min、摺衣服 20min,如果大家輪流做,並且全部做完才輪到下一個人,那麼就會發生:

不僅時間會拖很久,中間洗衣機及烘衣機都會有很大的時間處於閒置狀態,如果我們能夠讓機器在閒置的時候就交給下一個人使用,那麼時間軸就會變成:

如此一來就可以大幅減少時間,這就是Pipeline的觀念,將過程拆成多個Stage來執行,前一個Stage結束後就交給下一個指令進行該Stage。
## MIPS Stage
對於MIPS我們拆成5個Stage,分別為
|Stage縮寫|全名|作用|
|-|-|-|
|IF|Instruction Fetch|取得指令|
|ID|Instruction Decode & Register Read|指令解碼和讀取Register|
|EX|Execution or Address Calculation|執行或位址運算|
|MEM|Data Memory Access|記憶體讀取|
|WB|Write Back|寫回Register|
以下用5個Stage劃分了Datapath:

由於每個階段做完不會剛好能馬上進行下一階段,可能發生該Stage已經做完但下一個Stage尚未執行完,所以我們需要在中間加入Pipeline Register來暫時存取前一個結果,加上去後的結果如下圖:

如此一來我們能夠更快速的執行多個指令,並且一個Cycle的時間也可以取最久的步驟即可,不用取所有的過程,用數字來討論的話就是:
> 假設每個步驟的時間為:
> |IF|ID|EX|MEM|WB|
> |-|-|-|-|-|
> |300ps|400ps|350ps|500ps|100ps|
>
> 如此一來我們的Cycle Time要取500ps,那麼執行一個指令過了五個步驟後,耗費時間為:
> 500 x 5 = 2500ps
> 假設我們用原先一個Cycle執行一個指令,以R-type來說,不會用到MEM部分,所需時間為:
> 300 + 400 + 350 + 100 = 1150ps
>
> 雖然看起來Pipeline比較久,不過如果把指令數量放大來看,假設兩邊都有N個R-type指令:
> 對於Pipeline來說,除了最前面4個Cycle沒有完成指令外,後面每個Cycle各完成了一個指令,時間為:500 x 4 + 500 x N (ps)
> 對於沒有Pipeline來說,時間為1150 x N (ps)
> 假設N趨近無限大,Pipeline速度會是Non-Pipeline的兩倍以上。
## Control Unit
對照前面的圖會發現今天的圖片還沒有Control Unit,接下來就要討論到了。
|上一篇的datapath|今天的|
|-|-|
|||
Control Unit要注意的是,在Control Unit判斷的事項,可能在後面的Stage才會用到,比如說Register, Memory是否要寫入,ALUop的值是多少等等,所以這些Control bits也要塞進去Pipeline Register中,一個Stage一個Stage的傳下去,最後的結果會像是這樣:

## What's next?
夠難了吧~不過這還不夠,因為Pipeline還會有另一個問題等著我們去解決,那就是Hazard。這部分就留到下一個部分再來煩惱ㄅ,就這樣ㄅㄅ。
|上一篇|下一篇|
|--|--|
| [Build a CPU](https://hackmd.io/@dZfCcN4hT8aUuDPv3B8CWQ/SJjc9CPyF) |[Hazard](https://hackmd.io/@dZfCcN4hT8aUuDPv3B8CWQ/rk7NPf2kK)|
