# 2017q1 Homework4 (microarch)
contributed by <`csielee`>
## 重新複習MIPS
上次這個小測驗一出,真的是備受打擊
居然把計算機組織忘光光了
了解 CPU 可是資工人的浪漫,複習之路 go!
重新把[計算機組織結構](https://hackmd.io/s/H1sZHv4R#)看過
真的覺得整理的很好
## 開始解題

### 分析題目
該題目是一個 piplining 的CPU
能夠偵測 Harazd並解決
Data Hazard
* forwarding
* 提早將 M or WB 階段的資料給 EX
* forwarding unit 會決定要不要 forwarding 跟要 forwarding 誰
* Stalling(Load and R-Type)
* 因為從 memory 取得資料需要等 M 階段結束,就算 forwarding 也來不及,因此讓 IF ID EX 都暫停一下
Control Hazard
* flush
* 同時在 IF/ID 跟 ID/EX 間就判斷是否要 branch,能夠猜錯也只要 flush 一個指令
## 修改 1
:::info
做了 1: Stuck at 0 left of cut 的修改,`sw $s1, 0($s2)` 能否運作?這樣的修改會使得哪些程式無法運作,請列出至少兩項組合語言列表
:::
:::success
`sw $s1, 0($s2)` 可以運作
:::
因為沒有需要存進暫存器,是要把資料存進記憶體
cut 掉這條線造成在 WriteBack(WB) 階段,無法告訴 register 要將資料存進暫存器,因為 RegWrite 永遠是 0
==無法運作的指令==
```
lw $s1, 0($s2)
add $s1,$2,$3
```
## 修改 2
:::info
做了 2 的修改後,以下程式能否運作?解釋並提出可運作的版本
add $s1, $s1, $s1
add $s1, $t0, $t1
:::
:::success
可以運作
:::
cut 掉這條線,會造成 Rs 的 forwarding 失效
但是在這個範例中
`add $s1, $t0, $t1` 的 `$s1` 是 Rd
所以沒有 Data hazard 的問題
## 修改 3
:::info
做了 3 的修改後,以下程式能否運作?
addi $s2, $zero, 2
addi $s1, $zero, 2
beq $s2, $s1, exit
:::
:::danger
不能運作
:::
~~把這條線 cut 掉,會造成所有 branch 指令失效
因為在 ID 階段,如果 condition 成立會將 label 的值加在 PC 上並給 PC
但是這部份被 cut 掉,所以當然就失效了~~
~~而且因為所有 branch 指令失效
基本上也不能使用 while、for、if 等結構~~
:::danger
這結論下太早了,並不是所有類型的 branch 都會失敗,試著將直接表示的數值變更,思考有沒有能夠運作的程式碼 --jserv
:::
> 抱歉,結論下的太早
> 我看到 PC 來源只有 PC+4 跟 PC+4+(imm*4)
> 就以為 cut 那條會讓所有 branch 指令失效 [name=東霖]

重新查詢一些資料
發現這張圖挺不錯的
其實 cut 掉這條線,最主要是會造成 __condition branch 失效__
也就是無法使用 beq 、 bne 指令
但是直接~~跳轉~~==跳躍==,或是從 $ra($31) 取得 addres 都是可行的
:::danger
"jump" 的繁體中文翻譯是「跳躍」,不是「跳轉」,請注意 --jserv
:::
因此上述的 code 能夠修改成
:::success
修改後的版本
cmp:
slt $t1, $s1, $s2
slt $t2, $s2, $s1
add $t1, $t1, $t2
sll $t1, $t1, 2
add $ra, $ra, $t1
jr $ra
addi $s2, $zero, 2
addi $s1, $zero, 2
jal cmp
j exit
:::
利用 jal 會把下一個指令位置存在 $ra 的特性
我們把 j exit 這個指令的位置存在 $ra
並且到 cmp 的部份去操作 $ra ,讓 PC 得到我們想要的結果
因為 `slt $t1, $s1, $2` 跟 `slt $t2, $s2, $s1`
最後會有三種結果
* if ($s1 = $s2), $t1 = 0 & $t2 = 0
* if ($s1 < $s2), $t1 = 1 & $t2 = 0
* if ($s2 < $s1), $t1 = 0 & $t2 = 1
經過 `add $t1, $t1, $t2` 剩兩種
* if ($s1 = $2), $t1 = 0
* if ($s1 != $2), $t1 = 1
因此把 $t1 乘上 4 之後加到 $ra 上
就能控制要不要跳過 `j exit` 這條指令
又不失去讓 $s1, $s2 比較的效果
> 這部份讓我思考很久,一直在想能不能夠直接取得 PC 的值
> 但是我觀察 32 個暫存器,沒有一個是 PC 的暫存器
> 所以我想應該是無法直接存取到 PC
> 不知道這部份的想法有沒有錯誤 [name=東霖]
> 老師提示說這個修改版本能夠更短 [name=東霖]
## 參考資料
[計算機組織結構](https://hackmd.io/s/H1sZHv4R#)
[淺入淺出計組之旅(15)MIPS 體系結構 (5) ](http://ithelp.ithome.com.tw/articles/10158857)
[ MIPS 指令集(共31条) ](http://blog.csdn.net/yixilee/article/details/4316617)