# 2017q1 Homework04 (microarch) contriduted by <`king1224`> ###### tags: `king1224` ## 複習[計算機組織](https://hackmd.io/s/H1sZHv4R) * $CPU\ Time = \frac{Seconds}{Program} = \frac{Instructions}{Program} \times \frac{Clock\ Cycles}{Instruction} \times \frac{Seconds}{Clock\ Cycle}$ * 真心每次都會搞錯 MIPS 和 MIPS * Millions of Instruction Per Second * Microprocessor without Interlocked Pipeline Stages * [MIPS 指令集](http://blog.xuite.net/tzeng015/twblog/113272086-MIPS+%E6%8C%87%E4%BB%A4%E9%9B%86),有寫出下指令時 rs, rt, rd 的位置順序,常常記不起來 rs, rt 的位置呢 * MIPS Division 我想放一下這個,因為~~我完全忘光光了~~,老師說不會就不會,不要說忘記。 __devide algorithm__ ![](https://i.imgur.com/BzcDA9q.png) >問題: 為什麼在步驟一要先左移一個 bit? >回答: 不論正負,都先以無號數計算 >[name=洪正皇][color=#ea4331] __divide hardware__ ![](https://i.imgur.com/WimvYTZ.png) * IEEE 表示法 這些特殊值很有趣,因為我不知道 special value: |Exponent|Significand|Object| |--------|-----------|------| |0|0|+/- 0| |0|nonzero|denormalized underflow| |1-254|anything|normalized floating number| |255|0|+/- infinity| |255|nonzero|NaN| * ALU control 下面的 ALUop 是不是該改成 ALU control |ALUop|Function| |----|----| |0000|and| |0001|or| |0010|add| |0110|subtract| |0111|set on less than| |1100|nor| * logic equation: 從來沒有這樣想過,都只是死背的 opcode + function 得到的 ALUcontrol * ALUctr2 = ALUop0 + ALUop1‧func2’‧func1‧func0’ ![](https://i.imgur.com/Z14qHdd.png) * ALUctr1 = ALUop1’ + ALUop1‧func2’‧func0’ ![](https://i.imgur.com/iixcwpD.png) * ALUctr0 = ALUop1‧func3’‧func2‧func1’‧func0 + ALUop1’‧func3‧func2’‧func1‧func0’ ![](https://i.imgur.com/jFKyGXB.png) 提問: 為什麼 func3, func2, func1, func0 不是 don't care? 回答: 如果設成 don't care 的話,就不能分辨是哪一項 R type * internal forwarding * write in first half clock and read in second half * 原來這個方式叫這個名字 ## 問題討論 考慮以下 MIPS 實作,其 data path 如下: ![](https://i.imgur.com/Y80lxhP.png) 上圖紅色的 `1`, `2`, `3` 對 MIPS 做了對應的修改,請考慮以下狀況,分別解釋對應的程式碼是否能運作: ## 修改1 做了 `1: Stuck at 0 left of cut` 的修改,`sw $s1, 0($s2)` 能否運作?這樣的修改會使得哪些程式無法運作,請列出至少兩項組合語言列表 ![](https://i.imgur.com/s9bYQ24.png) * __可以運作__ 從圖中可以看到 WB 是控制著 MemtoReg, RegWr 這兩條訊號線的,切掉之後 register block 會一直以為訊號線的值為 0,因此無法將資料寫回 register,而 `sw $s1, 0($s2)` 是將資料寫入記憶體,__因此可以運作__。 * __不能運作的情況__ `lw $s1, 0($s2)` `add $s1, $t1, $t2` ## 修改2 做了 `2` 的修改後,以下程式能否運作?解釋並提出可運作的版本 ``` add $s1, $s1, $s1 add $s1, $t0, $t1 ``` * 可以運作 這條線是 rs 的 forwarding 資料線,而從[這裡](http://blog.xuite.net/tzeng015/twblog/113272086-MIPS+%E6%8C%87%E4%BB%A4%E9%9B%86)可以看到第二行 add 指令的 $s1 是 rd,根本不會造成 forwarding 阿!!! > 差點被騙了 >hazard conditions: >1. EX/MEM.RegisterRd = ID/EX.registerRs >2. EX/MEM.RegisterRd = ID/EX.registerRt >3. MEM/WB.RegisterRd = ID/EX.registerRs >4. MEM/WB.RegisterRd = ID/EX.registerRt >[name=洪正皇][color=#ef7c9f] ## 修改3 做了 `3` 的修改後,以下程式能否運作? ``` addi $s2, $zero, 2 addi $s1, $zero, 2 beq $s2, $s1, exit ``` 這條線所傳遞的值為 PC+4+(imm*4),需要將目標 address 經過 sign-extend 的 branch 指令將會無法計算要跳去的目的地,如圖中的表格第三行 ![](https://i.imgur.com/1WsCX72.png) > 但這張圖是還沒提前判斷 branch 的架構 > 原題目中將是否 equal 提前到 ID 階段判斷,也另外用一個加法器來提早得到目標位址 > [name=洪正皇][color=#db6ba1] 因此 beq, bnq ...等 branch 指令皆無法運作,而 jump 的指令如 j, jr ...等可以正常運作 #### 修改過後的 code ``` addi $s2, $zero, 2 addi $s1, $zero, 2 j exit ``` 經過我人工 assembler 後,s1 跟 s2 不是本來就一樣的嗎... __正常版 beq 改寫,看過 [csielee 大大](https://hackmd.io/s/Byl8yvFse#)的版本後就回不去了,目前我想不到更好的解法,但~~直接抄過來~~似乎也不太好__ 改善 csielee 大大的暫時版: 將 slt 改成 xor,可以少判斷一行,xor 有值代表不同,沒值代表相同,而 slt 需要做兩次才能判斷是否相同,但 xor 的值出來不知道怎麼處理 ``` cmp: xor $t1, $s1, $s2 or $t1, $t1, $zero sll $t1, $t1, 2 add $ra, $ra, $t1 jr $ra addi $s2, $zero, 2 addi $s1, $zero, 2 jal cmp j exit ```