microarch 相關背景知識、在限制中實做
===
contributed by <`PeterTing`>、<`jack81306`>
## 整體作業
- [ ] 背景知識
- [x] 基本指令
- [x] 基本架構
- [x] pipeline 架構
- [ ] Hazard
- [x] 解析 [B09 microarch](https://hackmd.io/s/r1Olsp_og)
- [x] 第一部影片
- [ ] 實作程式碼
## MIPS 背景知識
### 指令介紹
#### R type 指令
* R 型指令是<b>不會使用到記憶體或者是一般常數</b>運算類型的指令.
* 指令架構如下
![](https://i.imgur.com/Ywrex83.png)
* op : 全名為 operation code,這六個 bit 是拿來指定處理器內部各個部件的行為,也是拿來辨別這個指令的功能.
* rs,rt :兩個 register 來源.
* rd :目的地 register.
* shamt :shift amount.
* funct : 一樣是拿來指定處理器內部的行為.
#### I type 指令
* I 型指令是<b>讀寫記憶體或者是包含常數運算</b>的指令.
* 指令架構如下
![](https://i.imgur.com/DdD7b28.png)
* rt,rs: 和 R 型指令不同的是 I 型指令中的 rt 通常是拿來當作目的地,rs 則是來源或者是偏移地止的起點.
#### J type 指令
* J 型指令是<b>對下一條指令的地址進行跳轉</b>的指令.
* 指令架構如下
![](https://i.imgur.com/oPFbB3S.png)
* J 型指令,裡儲存地址的 bit 雖然只有26個,卻可以儲存 28 個 bits 的地址,是因為<b>每一條指令都是 4 個 byte ,因此每一條指令地址都是 4 的倍數,也就是說末兩位為 0,所以就可以把它省略掉嚕.</b>
* 而另外四個 bits 則是在 program counter 內
### MIPS 的抽象架構
![](https://i.imgur.com/pgaHOcR.png)
* Data 可能來自 ALU 的結果,或者是 Data memory,但是在紅圈1處形成一個交叉,這時就必須加入 multiplexor 來處理資料的流向.
* multiplexor: 從多個輸入中,根據控制信號來決定輸出.
* 控制信號被放在指令裡,會根據指令的不同來傳遞不同的信號給各個 multiplexor.
* PC 是指向指令的地址,處理器在運作時,如果這條指令是非 j type 型的指令,則下一條指令的地址就是 PC+4.如果這條指令是 branch 的指令,則下一條指令的地址是 PC+4 再加上偏移地址.這時會在紅圈2產一個交叉,一樣要加入 multiplexor 來處理資料的流向.
### CPU 元件介紹
#### 加入 control lines 的 mips 抽象架構
![](https://i.imgur.com/aOmNc3g.png)
#### Decoder 介紹 (第一階 control unit)
* Decoder 位於紅圈 1 的地方,Decoder 是根據指令裡的 opcode 來控制各個元件的行為
* RegDst:1 是寫入[15 : 11]的reg、0是寫入[20 : 16]的* reg,只有在把值寫入register裡時才有用
* ALUSrc:1 是用sign-extend 立即值、0是用register的值(ALU source
* MemtoReg:1 是取input讀入的位址的值、0是直接用ALU result 的值,只有在把值寫回register裡時才有用
* Regwrite:1 是將計算結果寫回register
* MemRead:1 唯有Read memory使用 (lw)
* MemWrite:1 唯有Write memory使用 (sw)
* Branch:1 唯有branch使用 (beq)
* 各種指令的 opcode
![](https://i.imgur.com/EEsiW70.png)
#### ALU 介紹
* ALU,即算術邏輯單元,位於紅圈 2,可以根據 ALU Control 送過來的控制訊號,對兩個輸入值做 ADD、SUB、AND、OR、SLT 等基本的運算,然後將運算的結果輸出.
* ALU 放大圖
![](https://i.imgur.com/ZaRzUrK.png)
#### ALU Control 介紹
* ALU Control 位於紅圈 3,負責輸出控制信號給 ALU,它接收了指令中的 Function code 部份及由 Control 送出的 ALUOp 兩個信號輸入,詳細數值如下圖.
![](http://i.imgur.com/UNLRjeB.png)
### 分析指令 datapath
#### R type 指令執行路徑
![](https://i.imgur.com/5AtnZIA.png)
* 上圖是 R type 指令的 datapath ,可以觀察到 R type 指令並部會使用到整個處理器.
* 在 1 號位置被截斷的原因在於說,R type 指令把應要寫入的 register 地址存放在 rd (也就是第 11 到 15 bit),而不是第 20 到 16 bit.
* 2 號位置被截斷的原因是資料是儲存在 register 而不是指令裡,3 號位置同理.
* R type 指令沒有使用到記憶體(4 號位置).
* R type 指令不進行跳轉(5 號位置).
#### Memory access 指令執行路徑
![](https://i.imgur.com/c5TTFKJ.png)
* 上圖是有使用記憶體指令的 datapath.(e.g. lw,rw)
* 因為 lw 或 rw 是 I type 指令,所以儲存需要寫入或讀取的 register 是放在第 16 到 11 個 bit(1 號位置).
![](https://i.imgur.com/DdD7b28.png)
* 2 號位置會根據讀取或寫入指令的不同而截斷其中一個,如果是讀取就不會使用到 write data,反之則不會使用到 read data.
* Memory access 指令不進行跳轉(3 號位置).
#### Branch 指令執行路徑
![](https://i.imgur.com/G8x0m0d.png)
* Branch 指令為依照比較結果來決定是否要跳轉.(e.g. beq,bne)
* 比較不需要進行寫入(1,2 號位置).
* 也不需要使用到記憶體(3 號位置).
* Branch 計算跳轉地址的方式是把 pc+4 和偏移地止進行相加.
![](https://i.imgur.com/DIkuAgO.png)
#### J type 指令執行路徑
![](https://i.imgur.com/ABwFVf9.png)
* j type 指令是直接跳轉到該地址,因此只會使用到上半部的元件.
* 地址的組成方式是取 pc+4 前面 4 個 bit 再加上指令內儲存的偏移地址(一樣要 shift 2 bit).
![](https://i.imgur.com/2oZ6aDU.png)
### Pipeline 介紹
* Pipeline:多道指令以重疊(overlapped)方式執行,可增加一個程式單位時間內可完成的指令,但無法減少每個指令的執行時間。下圖以一個洗衣房的流程講解.
![](https://i.imgur.com/sSSWwYG.png)
* 來講解以上以上那張圖的概念,現在我們有四件事情要做,分別為洗衣服,烘乾衣服,摺衣服,和放進衣櫃。當沒有 pipeline 時我們需要等四件事情全部都做完,才能進行下一個輪迴,若現在可以進行 pipeline , 則可以在別人烘衣服的時候使用洗衣機,在別人摺衣服的時候使用烘衣機,讓道程序都不會空下來,可以有效地進行利用,這樣將可以提升設備使用率.
* 再 mips 裡,instruction 可以分成五個步驟來執行.
* **IF** : 指令抓取 (Instruction fetch)
* **ID** : 指令解碼 (Instruction Decode)
* **EX** : 執行 (Execution)
* **MEM** : 記憶體存取 (Memory Acess)
* **WB** : 寫回運算結果或是記憶體中的資料 (Write Back)
#### MIPS Pipeline Datapath with Control
![](https://i.imgur.com/wCyIgma.png)
* Pipeline register(位於紅圈處):用來分開每一個pipeline stage,以便儲存它所對應stage所產生的資料,也可以用來緩衝各stage間運算速度之不一致,而在指令解碼時(ID)產生的訊號,並不是直接送到各元件,而是送到 pipeline register,一階一階往後送.
### Hazard 介紹
#### Hazard 有三種
* **Stucture Hazard** : 需要的硬體正在被其他的指令使用。
* **Data Hazard** : 兩道指令具有相依性,即下一道指令需要上一道指令的運算結果。
* 例如:有兩條指令,相加和相減,而相減指令的其中一個數值需要相加後的結果,相減的指令就會需要等待相加的指令。
![](https://i.imgur.com/Cvox8n2.png)
![](https://i.imgur.com/harROZA.png)
* 圖中有兩行 bubble ,即代表要 stall 兩個 cycles
* **Control Hazard** : 條件分支造成等待延遲
* 下一條指令的位置取決於條件分支之運算結果
#### 解決方案
* **Structure Hazard** : 在 mips 裡,將指令和資料放在不同的記憶體中.
![](https://i.imgur.com/gVmgHf7.png)
* **Data Hazard**
* **Forwarding** : 不要等資料存到 register 中,直接把資料送進 ALU 的其中一個來源.
![](https://i.imgur.com/3MphsmP.png)
* 需要多一條 wire
* **load-use data hazard** : 即使使用 forwarding ,還是會 stall 一個 cycle
* ![](https://i.imgur.com/eLlK0j7.png)
* **Code Scheduling** : 重新安排程式碼之間的順序.
* ![](https://i.imgur.com/owsSXA0.png)
* **Control Hazard**
* **Stall** : 先等分支結果出來再抓取下一條指令
* **Predict** : 只有猜錯時會造成 pipeline stall
* **untaken**
* **static Branch Prediction** : 根據跳躍類型預測,ex : loop 猜往回跳,if 猜往前跳
* **Dynamic Branch Prediction** : 根據硬體內所存之最近預測結果,來猜測最有可能之結果。
## 題目解析
![](https://i.imgur.com/ezJU2cz.png)
### 1.Stuck at 0 left of cut
>做了 1: Stuck at 0 left of cut 的修改,sw $s1, 0($s2) 能否運作?這樣的修改會使得哪些程式無法運作,請列出至少兩項組合語言列表
* 截斷的這條線路是傳送 regwrite 訊號的線路,因此無法告訴 register 要把資料存進去,這樣會使要存資料進 register 的指令通通失效.
* e.g.
```
add $t0,$t1,$t2
lw $t0,0($t1)
```
### 2
>做了 2 的修改後,以下程式能否運作?解釋並提出可運作的版本
```
add $s1, $s1, $s1
add $s1, $t0, $t1
```
* 截斷這條線路,會讓 rs 的 forward 失效,但是在這支程式裡,並不需要 forward data,因此這支程式可以運作.
### 3
>做了 3 的修改後,以下程式能否運作?
```
addi $s2, $zero, 2
addi $s1, $zero, 2
beq $s2, $s1, exit
```
* 這條線路是把偏移地址和 pc+4 相加的線路,如果截斷這條線路的話,就不能執行 condition branch(e.g. beq,bne),所以上述程式無法運作.
* 但是仍然可以使用 j type 指令.可以修改成
```mips
cmp:
slt $t0,$s1,$s2
slt $t1,$s2,$s1
xor $t0,$t0,$t1
sll $t0,$t0,2
add $ra,$ra,$t0
jr $ra
addi $s2, $zero, 2
addi $s1, $zero, 2
jal cmp
j exit
...
```
* 利用了 jal 會記錄當前位置的特性,如果兩者相等就跳回 pc+4,不相等就跳到 pc+8,而 pc+4 則會在跳到 exit.
## MIPS 主要缺陷
* 分支延遲
* 在所有的 MIPS 處理器中,跟在分支指令之後的指令,即使在與前一個分支 指令流向分歧之後,依然會被處理器所執行,因此在之後的 MIPSII體系中,加 入了 Branch-likely 指令,在處理類似的狀況時,在分支指令其後的指令只 有在前一個分支被接受時,才會被執行,不過除非自行指定分之後的指令,在 加強後的編譯器的處理下,分支所帶來的延遲將顯得不明顯。
* 載入延遲
* 在 MIPS I指令集中,load 指令將無法再次載入才剛被 load 指令本身所載 入的資料,若是有需要再度載入,那麼必須在兩個 load 流程之間,使用其他 指令來區隔,甚至是使用空指令來空轉一週,以便讓 load 指令可再度進行載 入。
* 浮點運算單元的問題
* 由於浮點運算需要耗費多個處理器時脈週期來進行,因此在 MIPS 處理器架 構中,大多會有獨立的浮點運算處理管線,構成內部的輔助處理器架構,由於浮 點運算單元可以與其後的指令並行處理,因此當並行處理的指令要去存取尚未計 算完成的浮點運算結果暫存器時,處理器便會停止執行,因此這部份的處理也需 要大量的編譯器最佳化。
## 架構比較
### Pipeline
- **MIPS**
最簡單的體系結構之一,體積小、耗能比低。但MIPS有"分支延遲" 以及"載入延遲"兩個明顯的缺點,MIPS 使用編譯器来解决上面的兩個問題。因为 MIPS 最初的設計思想是使用簡單的 RISC 及其他軟體技術,来達成 RISC 的完整概念。
- **ARM’s Shifter**
shifter 是 ARM 中很重要的概念,他可以提高運算邏輯的速度,跟同樣功能的 adder/shift register 相比,效率更高,但是也占用更多的芯片面積
### 指令結構
MIPS 有 32bit 及 64bit architecture,但是 ARM 只有 32bit architecture (ARM11 局部 64 位)
MIPS 是開放式的架構,可在開發的內核中建立自己的指令,而 ARM 是在每個指令結構以 4bit 的 condition code 決定。
### Register
由於 MIPS 內核中有 32 個 register,相對於 ARM 只有 16 個,設計天生上的優勢使得同等性能下, MIPS 的芯片面積及功耗比較小。ARM 有一组特殊用途 register cp0-cp15,可以使用 MCR,MRC 等指令控制;相對應的, MIPS 也有 cp0-cp30,使用 mfc0,mtc0 指令控制。
### 地址空間
MIPS 起始地址是 0xbfc00000,會有 4Mbyte 的大小限制,但一般 MIPS 芯 片都會採取一些方法解决這個問題。而 ARM 没有這種問題。在新版的 MIPS24K 起始地址往後移,有了 16byte 的大小。
## 參考資料
- [講義](http://www.cs.utexas.edu/users/mckinley/352/lectures/12.pdf)