計算機結構(CA,computer architecture)· 黃婷婷 11210 期中+期末 · 2026-11-06
這份地圖照故事分章,寫法和 OS(operating system)地圖一樣。第 0 章是最簡單的電腦。後面每一章,先寫這台電腦(或前一章的解法)碰到的問題,再寫解決它的模型,最後把從模型推出來的結論寫成問答。第 7–10 章現在只寫問題和要回答的題目。模型和定理在上完對應的課以後補。每一題的讀法,寫在 CA 資料夾 lessons 的考題表。
第 0 章
出處:P&H(Patterson & Hennessy 的課本《Computer Organization and Design》)§1.3、§2.5、§4.1。
粗框灰底的是 state,名字大寫開頭。例子是 P&H §2.3 的 A[12] = h + A[8]。h 在 $s2,陣列(array)A 的起點在 $s3。指令從 0x0040_0000 起放,資料從 0x1000_0000 起放,這是 P&H 寫 MIPS(P&H 用的 ISA)程式時的慣例。PC 指到第一條指令 lw。lw、sw 的位址是 Reg[$s3] + imm,指到資料。
1.問:PC 為什麼通常加 4?
答:每條指令是一個 word = 4 bytes,Mem 是 byte-addressable。所以下一條指令的位址是 PC + 4。
2.問:Mem 裡的一個 word 是指令還是資料,由誰決定?
答:由誰去存取它決定。PC 指到它,CPU 就把它當指令執行;lw、sw 的位址指到它,就把它當資料讀寫。bit 本身不分指令和資料。
出處:P&H §1.6(classic CPU performance equation)、§4.5。
1.問:程式裡有好幾類指令,每一類的 CPI 不同。平均 CPI 怎麼算?
答:加權平均。每一類指令的 CPI 乘上它佔指令數的比例,再加起來。
2.問:只改善一類指令,執行時間最多能減少多少?
答:最多減少那類指令原本花的時間。這是 Amdahl's law:改善後的時間 = 被改善的部分 ÷ 改善倍數 + 沒被改善的部分。所以總時間減少的比例,一定小於被改善的那類指令原本佔總時間的比例。反過來,只要小於這個比例,改善倍數夠大就做得到。
3.問:clock rate 變成 2 倍,程式就快 2 倍嗎?
答:不一定。speedup = 舊的執行時間 ÷ 新的執行時間。clock 變快時,每類指令的 cycle 數常常變多。所以三個因子要一起算,不能只看 clock rate。
第 1 章
第 0 章的 CPU 從 Mem[PC] 讀一個 word 當指令。所以一條指令的全部資訊都要放進 32 bit:做什麼運算、用哪幾個 register、常數或目標位址。
出處:P&H §2.5。第四條設計原則(Good design demands good compromises):所有指令都是 32 bit,所以需要長常數的指令,要用另一種格式。
一條指令看兩個軸。兩個軸互不相干。
<= 左邊,也就是要寫入的 state)由 op 和 funct 決定。
你推出來的(模型的起點):「R type iff 3 register --> LHS must be register etc / I type iff 2 register 1 imm --> further category: LHS is reg (includes RHS have Mem or RHS have Imm), LHS is PC, LHS is Mem」
| 軸 2:LHS \ 軸 1:格式 | R-type op 6 rs 5 rt 5 rd 5 shamt 5 funct 6 | I-type op 6 rs 5 rt 5 imm 16 | J-type op 6 address 26 |
|---|---|---|---|
| Reg | add Reg[rd] <= Reg[rs] + Reg[rt] sub、and、or 是同一種寫法slt Reg[rd] <= (Reg[rs] < Reg[rt]) ? 1 : 0sll Reg[rd] <= Reg[rt] << shamt |
addi Reg[rt] <= Reg[rs] + sign_extend(imm)lw Reg[rt] <= Mem[Reg[rs] + sign_extend(imm)]lui Reg[rt] <= {imm, 16 個 0} |
— |
| Mem | — | sw Mem[Reg[rs] + sign_extend(imm)] <= Reg[rt] |
— |
| PC | jr PC <= Reg[rs] |
beq PC <= PC + 4 + (Reg[rs] == Reg[rt] ? sign_extend(imm) × 4 : 0) bne 是同一種寫法,== 換成 != |
j PC <= {(PC + 4)[31:28], address, 00} |
| Reg 和 PC | — | — | jal Reg[31] <= PC + 4; PC <= {(PC + 4)[31:28], address, 00} |
沒有寫 PC 的指令,都另外做 PC <= PC + 4。
常數的顏色(定理 3 的四種定址):值:addi、lui;加到 Reg[rs] 的 byte 位移:lw、sw;加到 PC + 4 的 word 位移:beq、bne;換掉 PC 低 28 bit 的 address:j、jal;jr 沒有常數。
你提的:每條指令放進兩軸的一格,寫成轉移式。欄是軸 1(格式;表頭是它的欄位和 bit 數),列是軸 2(LHS:寫哪個 state)。
1.問:目的地 register 為什麼有時在 rd,有時在 rt?
答:軸 1 決定欄位的切法。I-type 把 rd 的位置拿去放 imm,所以目的地只能放在 rt(表頭:R-type 有 rd,I-type 沒有)。這就是第 4 章的 reg_dst mux:R-type 選 rd,I-type 選 rt。(你推出來的)
2.問:rt 什麼時候被寫,什麼時候被讀?
答:rt 被寫 ⇔ I-type 而且 LHS 是 Reg(addi、lw、lui)。其他指令的 rt 都是被讀的,包括 sw 要存的值和 beq、bne 要比較的值(表的 Reg 那一列,I-type 那一格)。(你推出來的)
3.問:四種定址從哪裡來?
答:都是「常數(軸 1)拿來做什麼(軸 2)」。表裡常數的顏色,就是這四種用法。
lw、sw 的 imm 以 byte 為單位,不乘 4。
4.問:control 看哪些欄位,決定一條指令做什麼?
答:看 op;R-type 再加看 funct。兩個軸都由它們決定。
5.問:MIPS 的哪些設計,各對應 P&H 的哪一條設計原則?
答:
6.問:j 能跳到任何位址嗎?
答:不能。j 只換低 28 bit,高 4 bit 照抄 PC。memory 依位址的高 4 bit 切成 16 塊,每塊 256 MB。所以 j 只能跳到同一塊裡。P&H 抄的其實是 PC + 4 的高 4 bit;只在 256 MB 的邊界上才有差別。
7.問:追蹤一段組合語言時,寫進 $0 的值、剛 sw 進 Mem 的值,之後會讀到什麼?
答:$0 永遠是 0,寫進去的值會被丟掉。sw 之後再 lw 同一個位址,會讀到剛寫進去的值。因為每條指令都是一次狀態轉移(第 0 章),sw 已經改了 Mem。
第 2 章
Reg 和 Mem 只存 bit。指令要算負數和小數,所以要規定一串 bit 代表哪一個數,而且要讓硬體好算。
出處:P&H §2.4(signed and unsigned numbers)、§3.5(floating point)。
數線是示意圖:fraction 只畫 2 bit,所以每一段只有 4 個數。真的格式每一段有 2^(fraction 的 bit 數) 個數。上面的 16 bit 是一個例子:exponent 6 bit,fraction 9 bit。
| exponent 欄位 | 0 | 1 | 2 | … | 2^E − 2 | 2^E − 1 |
|---|---|---|---|---|---|---|
| 實際指數 | DeNorm(1 − bias) | 1 − bias | 2 − bias | … | bias | INF/NaN |
| 8 bit,bias 127 | DeNorm(−126) | −126 | −125 | … | 127 | INF/NaN |
| 6 bit,bias 31 | DeNorm(−30) | −30 | −29 | … | 31 | INF/NaN |
你自己建的映射表。DeNorm 表示 hidden bit 是 0,實際指數是 1 − bias。
1.問:n-bit 二補數能表示哪些整數?
答:−2^(n−1) ~ 2^(n−1) − 1,負的比正的多一個。例:16 bit 的 0xFFFC,最高位 bit 是 1,所以是負數。絕對值 = 0x10000 − 0xFFFC = 4,值是 −4。P&H §2.4 用 32 bit 的同一個數當例子。
2.問:單精度的 fraction 欄位只有 23 bit。有效位數為什麼是 24 bit?
答:normalized 數的開頭一定是 1,所以不存。這個不存的 1 是 hidden bit。所以有效位數比 fraction 欄位多 1 bit。
3.問:exponent 欄位為什麼存「實際指數 + bias」?
答:這樣負的指數也能用無號數存。例:0x3F80_0000 = 1.0(exponent 欄位 127,實際指數 0)。normalized scientific notation 寫的是實際指數。寫回 32 bit 時,exponent 欄位才是實際指數 + bias。兩個不要混在一起。
4.問:exponent 欄位有 E bit 時,normalized 數的實際指數最大是多少?
答:exponent 欄位全 0 和全 1 保留給特殊值。所以 normalized 的實際指數是 1 − bias 到 bias,最大實際指數 = bias = 2^(E−1) − 1。要表示到 2^k,就要 2^(E−1) − 1 ≥ k。
5.問:浮點加法怎麼做?誤差從哪裡來?
答:三步:對齊、相加、normalize。對齊時,實際指數小的那個 mantissa 往右移。右移時,數學上的值沒有變。IEEE 754 規定先用無限精度算完,最後只 round 一次。所以誤差只來自最後那次 round。guard、round、sticky bit 是硬體多留的 3 個 bit,讓結果和「最後只 round 一次」一樣。
6.問:exponent 欄位 = 0 時(denormal),0 附近為什麼沒有空洞?最小正 denormal 是多少?
答:denormal 的 hidden bit 變 0,實際指數 = 1 − bias。這個指數和最小 normalized 數的實際指數一樣。所以 denormal 的間距和最小 normalized 那一段的間距相同。fraction 欄位最小的非 0 值是 2^−(fraction 欄位的 bit 數),所以最小正 denormal = 2^−(fraction 欄位的 bit 數) × 2^(1 − bias)。bias 要用這個格式自己的,不一定是 127。
第 3 章
第 1 章的指令要做加、減、AND、OR。ripple carry adder 的每一位都要等前一位的 carry,n bit 就要等 n 位。這段延遲在一個 cycle 裡,所以會拉長 clock cycle time。
出處:P&H 第 3 章(arithmetic for computers),和講 ALU(arithmetic logic unit)、carry lookahead 的附錄(第 5 版是附錄 B)。
紅色箭頭是 carry 要等的地方,綠色是不用等的地方。
| 運算 | a_invert | b_negate | carry_in | operation | 為什麼 |
|---|---|---|---|---|---|
| AND | 0 | 0 | X | 0 | a·b |
| OR | 0 | 0 | X | 1 | a + b |
| add | 0 | 0 | 0 | 2 | a + b(算術) |
| SUB | 0 | 1 | 1 | 2 | a + ¬b + 1 = a − b |
| NOR | 1 | 1 | X | 0 | ¬a·¬b = ¬(a + b) |
| NAND | 1 | 1 | X | 1 | ¬a + ¬b = ¬(a·b) |
| NOT | 1 | 1 | X | 0 | NOR(a, a):b 接同一個數 |
| XOR | 做不到 | 要 a·¬b 和 ¬a·b 兩個乘積再 OR | |||
表中的 X 是 don't care:填 0 或 1,結果都一樣。表頭是考卷的訊號名照 glossary 改寫的:Ainvert → a_invert,Bnegate → b_negate,CarryIn → carry_in,Operation → operation。
1.問:這個 1-bit ALU 只有 AND、OR、adder 三個結果。它還能做哪些運算?
答:
2.問:pᵢ 要用 OR 還是 XOR 定義?
答:兩種都讓 cᵢ₊₁ = gᵢ + pᵢ·cᵢ 成立。差別在 gᵢ = 1(aᵢ = bᵢ = 1)時:用 OR 定義,pᵢ = 1;用 XOR 定義,pᵢ = 0。所以題目給 pᵢ = 0、gᵢ = 1 時,只能是 XOR 定義。
3.問:ripple carry adder 為什麼慢?CLA 怎麼變快?代價是什麼?
答:ripple carry adder 的遞迴式,每一位都要等前一位的 carry。CLA 把遞迴式展開,每個 carry 兩層 gate(先 AND,再 OR)就算完。代價是 gate 的 fan-in(輸入個數)隨位數變大。所以切成 4-bit block,再用 block 的 P、G 算 block 之間的 carry(cascaded CLA)。
你推出來的:「ripple = 乖乖算遞迴;CLA = 展開轉移式;cascaded = 給轉移式加底標」
4.問:一個 carry 的 gate delay 怎麼算?
答:gate delay 就是最長路徑。D[x] 是 x 的延遲(幾個 gate delay)。從 c₀ 開始,用圖左下的式子逐位取 max。ripple carry adder 得到 D[cᵢ] = 1 + 2i。cascaded CLA 把 block 的 G、P 先算好當常數,只累加 block 之間的 carry。起算點有兩種慣例:pᵢ、gᵢ 算 1 層,或從 pᵢ、gᵢ 就緒才開始算。
5.問:carry save adder(CSA)為什麼不管幾 bit,都只要 1 個 full adder(FA)的延遲?
答:CSA 是 3:2 compressor:輸入 3 個數,輸出 2 個數(sum 和 carry),兩邊的和相同:a + b + c = sum + (carry << 1)。這裡的 c 是第三個數,不是 carry。carry 不傳給左邊那一位,而是左移 1 位,當成另一個輸出。所以每一位各自算,不用等別的位。
6.問:Wallace tree 為什麼是 minimum delay?要幾層 CSA?
答:Wallace tree 每一層把數 3 個一組送進 CSA,每組輸出 2 個,直到剩 2 個。最後用一個 carry propagate adder(CPA,例如 CLA)把 2 個數加起來。CSA 只能 3 → 2,不能 2 → 1。2 → 1 就是 carry 傳播。這一步一定要做,所以放到最後,只做一次。樹裡每層只有 1 個 FA 的延遲。層數 L 的下限:(數的個數) × (2/3)^L ≤ 2。圖右下畫的是 16 個 partial product 的例子。
第 4 章
把第 0 章的狀態轉移做成硬體。最簡單的做法是一個 cycle 做完一條指令(CPI = 1)。
出處:P&H §4.3(building a datapath)、§4.4(a simple implementation scheme)。
你推出來的:「在 combination block 裏面:ALU = func(Read data 1, ALUSrc? Read data 2 : Imm, ALUOp) 之類的。而在 always block 裏面,就是狀態轉移式(LHS 是新狀態)」。式子的寫法照下面第一張圖。
寫法(你在 0007 定的):state 的名字大寫開頭(PC、Reg、Mem),wire 和 combinational 元件的名字全小寫。考卷的 RegDst 就是 reg_dst,其他照同樣的規則改寫。
| 步驟 1:指令 | Reg | Mem | PC |
|---|---|---|---|
| add rd, rs, rt | Reg[rd] <= Reg[rs] + Reg[rt] | 不變 | PC + 4 |
| addi rt, rs, imm | Reg[rt] <= Reg[rs] + imm32 | 不變 | PC + 4 |
| lw rt, imm(rs) | Reg[rt] <= Mem[Reg[rs] + imm32] | 不變 | PC + 4 |
| sw rt, imm(rs) | 不變 | Mem[Reg[rs] + imm32] <= Reg[rt] | PC + 4 |
| beq rs, rt, L | 不變 | 不變 | Reg[rs] == Reg[rt] ? PC + 4 + (imm32 << 2) : PC + 4 |
| j L | 不變 | 不變 | {(PC + 4)[31:28], inst[25:0], 00} |
| 步驟 2:合併的地方 | 各指令送進的值 | control signal |
|---|---|---|
| Reg 寫到哪 | rd(add)、rt(addi、lw) | reg_dst:1 選 rd,0 選 rt |
| Reg 寫什麼 | alu_result(add、addi)、read_data(lw) | mem_to_reg:0 選 alu_result,1 選 read_data |
| Reg 寫不寫 | 寫(add、addi、lw)、不寫(sw、beq、j) | reg_write(write enable) |
| alu 的第二個輸入 | read_data_2(add、beq)、imm32(addi、lw、sw) | alu_src:0 選 read_data_2,1 選 imm32 |
| Mem | 讀(lw)、寫(sw)、不動(其他) | mem_read(read enable)、mem_write(write enable) |
| 下一個 PC | pc_plus_4、branch_target(beq 相等時)、jump_target(j) | pc_src = branch & zero;加 j 以後多一個 jump |
imm32 = sign_extend(imm)。j 是 P&H 4.4 節最後才合併進來的;下面的轉移式和 datapath 還沒有 j。合併 j 的結果寫在定理 6。
| 在轉移式裡的樣子 | 意思 | wire(考卷的名字) |
|---|---|---|
c ? x : y | mux:c = 1 選 x,c = 0 選 y | reg_dst、alu_src、mem_to_reg、pc_src(RegDst、ALUSrc、MemtoReg、PCSrc) |
if (c) State[…] <= … | write enable:c = 0 時,這個 state 不變 | reg_write、mem_write(RegWrite、MemWrite) |
c ? Mem[…] : 不讀 | read enable:c = 1 時才讀 Mem | mem_read(MemRead) |
control(op) | 只看 op 決定的 wire。pc_src 例外:它還看 alu 算出來的 zero | pc_src 以外的 8 個 |
怎麼讀這張圖:粗框灰底的是 state,方塊的名字和上面轉移式一樣;底邊的小三角形是 clock(Mem 的指令 port 只讀,所以沒有)。兩個 Mem 方塊是同一個 Mem 的兩個 port:左邊是指令 port,右邊是資料 port。細框白底的是 combinational。線是 wire:藍線是資料,橘色字是 control 送出的 wire,虛線箭頭指向它控制的 mux 或元件。state 方塊裡的藍色小字,是接到那個 port 的 wire。實心圓點是分岔。兩條線交叉但沒有接在一起時,其中一條畫成小半圓。每個 mux 的輸入都標了 0 或 1。mem_to_reg mux 的 0、1 上下位置和考卷相反,對應不變。和考卷的圖對照:Read register 1、2 接 rs、rt;Write register 接 write_reg;Write data 接 write_data;Data memory 的 Address 接 alu_result,Write data 接 read_data_2。alu_control 讀 alu_op 和 funct(inst[5:0]);funct 的線省略了。合併 j 多出的 jump mux 和 jump_target 也省略了。
1.問:datapath 為什麼有 7 個 control signal?轉移式要背嗎?
答:datapath 是合併出來的。同一個位置,不同指令送進的值不一樣 ⇒ 放 mux;有的指令不寫某個 state ⇒ 那個 state 加 write enable。7 個 control signal 就是 4 個 mux 和 3 個 enable(步驟 2 的表)。所以轉移式不用背,只要記得每類指令做什麼。
2.問:為什麼只有一個 alu,前面還要放 alu_src mux?
答:每類指令都剛好用一次 alu:add 算結果,addi 算加法,lw、sw 算位址,beq 相減看 zero。所以只有一個 alu。它的第二個輸入,add、beq 用 read_data_2,addi、lw、sw 用 imm32,所以前面放 alu_src mux。
3.問:給一條指令,怎麼推出它的 control signal?
答:
例:reg_write = 0 ⇒ write_reg 和 write_data 都沒有寫進 Reg ⇒ reg_dst = X,mem_to_reg = X。
4.問:不是 load 的指令,mem_read 為什麼填 0,不填 X?
答:mem_read 是 read enable,只能填 0 或 1(定理 3)。Mem 的資料 port 其實是 L1 D-cache(第 7 章)。用沒有意義的位址去讀,可能 cache miss,也可能 page fault。所以只有 load 是 1,其他指令填 0。
5.問:圖上的 datapath 能執行 bne 嗎?
答:不能直接執行。圖上的 pc_src = branch & zero 是給 beq 用的:beq 在 zero = 1 時跳。bne 要在 zero = 0 時跳,要多一條 control 的 wire(例如 branch_ne),讓 pc_src = branch_ne & ~zero。所以推 bne 的 pc_src 時,要看這次跳不跳,不能照抄圖上的 &。
6.問:怎麼把 j 合併進 datapath?
答:下一個 PC 多一種值 jump_target = {pc_plus_4[31:28], inst[25:0], 00},只要接線,不用 adder。在 pc_src mux 後面再加一個 mux(jump mux):next_pc = jump ? jump_target : (pc_src ? branch_target : pc_plus_4)。control 多送出 jump。加了 j 以後,pc_src = X ⇔ jump = 1。
第 5 章
第 4 章裡,所有指令共用同一個 cycle。cycle 要長到最慢的指令(lw)走完整段 combinational 電路。其他指令用不到那麼久,也要等。
出處:P&H §4.5(an overview of pipelining)、§4.6(pipelined datapath and control)。
所有 state 接同一個 clock(同一個 clock domain)。Time(x) 照你在 0007 的定義:x 的輸出穩定以後,要多久下一個 state 的輸入才穩定。t_reg 是 register 存資料要的時間:輸入要在 clock edge 前穩定一小段,clock edge 後輸出要過一小段才變。數字是 P&H 的例子,不是考卷的數字。Mem 在 MEM 這段結束時寫入;Reg 是例外,WB 這段的前半個 cycle 就寫,後半個 cycle 讓 ID 讀。
| stage | 讀的 state | combinational 算出的 wire | 這個 stage 結束時寫入的 state |
|---|---|---|---|
| IF | PC、Mem(指令 port) | inst = Mem[PC] pc_plus_4 = PC + 4 |
IF_ID.IR <= inst IF_ID.PC4 <= pc_plus_4 PC <= next_pc |
| ID | IF_ID、Reg | read_data_1 = Reg[IF_ID.IR.rs] read_data_2 = Reg[IF_ID.IR.rt] imm32 = sign_extend(IF_ID.IR.imm) control 的 wire = control(IF_ID.IR.op) |
ID_EX.A <= read_data_1 ID_EX.B <= read_data_2 ID_EX.Imm <= imm32 ID_EX.PC4 <= IF_ID.PC4 ID_EX.Ctl <= control 的 wire |
| EX | ID_EX | branch_target = ID_EX.PC4 + (ID_EX.Imm << 2) alu_result = alu(ID_EX.A, ID_EX.alu_src ? ID_EX.Imm : ID_EX.B) zero = (alu_result == 0) |
EX_MEM.ALUOut1 <= branch_target EX_MEM.ALUOut2 <= alu_result EX_MEM.Zero <= zero EX_MEM.B <= ID_EX.B EX_MEM.Ctl <= ID_EX.Ctl |
| MEM | EX_MEM、Mem(資料 port) | read_data = EX_MEM.mem_read ? Mem[EX_MEM.ALUOut2] : 不讀 pc_src = EX_MEM.branch & EX_MEM.Zero next_pc = pc_src ? EX_MEM.ALUOut1 : pc_plus_4 |
MEM_WB.ReadData <= read_data MEM_WB.ALUOut2 <= EX_MEM.ALUOut2 MEM_WB.Ctl <= EX_MEM.Ctl if (EX_MEM.mem_write) Mem[EX_MEM.ALUOut2] <= EX_MEM.B |
| WB | MEM_WB | write_data = MEM_WB.mem_to_reg ? MEM_WB.ReadData : MEM_WB.ALUOut2 | if (MEM_WB.reg_write) Reg[寫入編號] <= write_data (Reg 例外:前半個 cycle 就寫) |
粗體是 state,一般字是 wire,橘色是 control。ID_EX.alu_src、EX_MEM.branch 這種寫法,是存在那個 pipeline register 的 Ctl 裡的 control bit;開頭是 state 的名字,所以它是 state。PC 那一行寫在 IF,因為 PC 是 IF 讀的 state;它的 next_pc 用到這個 cycle IF 算的 pc_plus_4,和這個 cycle MEM 算的 pc_src。
這張圖照期末 Q3、Q4 的圖畫。粗框灰底的是 state:PC、Reg、Mem 和 4 個 pipeline register。兩個 Mem 方塊是同一個 Mem 的兩個 port:IF 用指令 port,MEM 用資料 port。pipeline register 裡的粗體小字是它存的欄位。Ctl(橘色虛線)是 control 的 wire 存進去的 bit,跟著指令往後走,每個 stage 用自己那一份。期末 Q4 的 top ALU 是 branch adder,結果存進 ALUOut1;bottom ALU 是 alu,結果存進 ALUOut2。pc_src 的線太長,用名字接起來:MEM 的 & 送出 pc_src,PC 前面的 mux 用它來選。寫進 Reg 的編號(rd 或 rt)也要跟著指令存進 ID_EX、EX_MEM、MEM_WB,考卷的圖省略了這條線。
1.問:pipeline 裡的 state,都在同一個 clock edge 寫入嗎?
答:pipeline register 也是 state。所有 state 接同一個 clock,在同一個 clock edge 寫入。Reg 例外:它在 cycle 中間寫入(前半寫、後半讀),用的還是同一個 clock。
你問過:「這裏的 state 都是同一個 clock domain 嗎?」
2.問:clock cycle time 怎麼算?
答:clock cycle time = 所有 Time 裡最大的那個。single-cycle 只有一段 ⇒ 各 stage 的時間相加。pipeline 有 5 段 ⇒ 每段 = logic + t_reg,取最大的。
你在 0007 的定義:「Time(x): x 穩定之後,要花多少時間才會使後續所有 signal 穩定」
3.問:register 存資料要的時間(t_reg),要加在哪裡?
答:t_reg 是 setup time + clock-to-Q。pipeline 的每一段都要加:可以當成每個 pipeline register 前面多了一段 logic。single-cycle 沒有 pipeline register;題目只給 pipeline register 的時間時,single-cycle 不加。
你問:「5ps store data 應該是 pipeline register 内部,當成在 register 前面多了一個 logic 需要 5ps 才能穩定?」
4.問:pipeline 有 5 個 stage。throughput 會變成 5 倍嗎?一條指令會變快嗎?
答:throughput 不到 5 倍:5 個 stage 的長度不同,cycle 要配合最長的一段;每段還要加 t_reg。一條指令不會變快:latency = 5 × clock cycle time,而 5 × 最長的一段 ≥ 5 段相加 = single-cycle 的 latency。pipeline 讓 throughput 變大,單一條指令反而變慢。例(圖上 P&H 的數字):single-cycle 的 cycle 是 800 ps,pipeline 是 200 ps + t_reg,所以 throughput 不到 4 倍;latency 是 5 × (200 ps + t_reg),比 800 ps 長。
5.問:一個 state 在哪個 stage 寫入?
答:pipeline register 在它左邊那個 stage 結束時寫入,例如 EX_MEM 在 EX 結束時寫入。一個 state 的新值,在轉移式 RHS 用到的值全部到齊的第一個 stage 算出來,那個 stage 結束時寫入。所以上面那張 stage 的表不用背。
6.問:beq 在哪個 stage 決定跳不跳?
答:MEM。ID_EX.A == ID_EX.B 由 EX 的 alu 比較。Zero 和 ALUOut1 都在 EX 結束時才寫進 EX_MEM,所以 MEM 才拿得到,MEM 結束時寫入 PC。把比較器和 adder 移到 ID,branch 就能在 ID 結束時決定(第 6 章的 control hazard)。
第 6 章
第 5 章的 pipeline 裡,同一個 cycle 有 5 條指令在不同 stage。前一條指令在 WB 才把結果寫進 Reg,後一條指令在 ID 就要讀 Reg。branch 在 MEM 才決定跳不跳,在這之前已經拿了後面 3 條指令。不處理,執行結果就和第 0 章不一樣。用 stall 處理,CPI 就大於 1。
出處:P&H §4.7。
你推出來的:「想著的是 pipeline state 之間的轉移式。……箭頭代表求出這個 state,需要依賴另一個 state。所以後者的時間至少需要晚一個 clock。internal forward 是例外……Forwarding,就是把這一行轉移式,晚一點做,引用更早的同個狀態。」
出處:P&H §4.8。
左半的第 3 條的 rs 從 $2 改成 $4,讓圖上也有 EX → EX。add 的 $2 由 lw 在 WB 寫入,靠 Reg 讀,不畫箭頭。左半的格子顏色和第 5 章一樣代表 stage。stall 的格子是紅色:這條指令留在同一個 stage。右上的紅格是被 flush 的指令:它們的 Ctl 被清成 0,變成 no-op。
1.問:沒有 forwarding 時,一個 dependency 要插幾個 no-op?
答:值在 WB 寫進 Reg,後一條指令在 ID 讀;internal forwarding 讓同一個 clock 也可以。所以兩條指令相鄰插 2 個,中間隔一條插 1 個,隔兩條以上不用插。
2.問:有 forwarding 時,哪些 dependency 不用 stall?
答:前提:後一條指令在 EX 用這個值。前一條是 R-type:值在 EX 求出,所以任何距離都不用 stall。相鄰的靠 EX → EX;隔一條的靠 MEM → EX;隔兩條以上的靠 internal forwarding 從 Reg 讀。前一條是 lw、中間至少隔一條:隔一條的靠 MEM → EX,也不用 stall。
3.問:有 forwarding,就能避開所有 data hazard 嗎?
答:不能。下一條指令在 EX 要用 lw 的值時,下一條的 EX 和 lw 的 MEM 在同一個 cycle,所以一定要 stall 1 個 cycle。P&H 叫這種 hazard load-use data hazard。例外:下一條是 sw,而且 lw 的值是 sw 要存的值(rt),這個值在 MEM 才用到。但 P&H 的 hazard detection unit 不分這種情況,照樣 stall。考題問「avoid all data hazards」,意思是一個 stall 都不用插。
4.問:branch 在 MEM 決定時,損失幾個 cycle?移到 ID 呢?
答:在 MEM 決定,損失 3 個:beq 在 cycle 1 做 IF,cycle 4 結束時才寫入 PC,所以下一條最早在 cycle 5 做 IF,本來是 cycle 2。移到 ID,損失 1 個:PC 在 cycle 2 結束時寫入,下一條在 cycle 3 做 IF。
5.問:猜錯時,為什麼 flush 就能讓結果和第 0 章一樣?
答:在 MEM 決定時,拿錯的指令最遠只到 EX,還沒到 MEM(寫 Mem)和 WB(寫 Reg)。把它們的 Ctl 清成 0,它們就不會改 Reg 和 Mem。在 ID 決定時,拿錯的只有 IF 那 1 條。
你推出來的:「只要計算 MEM 和 WB 的時候,必須先確保是猜對的,就可以。否則就不會有任何狀態改變」
6.問:一個迴圈跑 n 圈(n ≥ 2),前 n − 1 圈跳、最後一圈不跳。穩定以後,1-bit 和 2-bit 猜法每次迴圈各猜錯幾次?
答:1-bit 錯 2 次:最後一圈(出口)錯一次,留下「不跳」,下一次迴圈的第 1 圈(入口)又錯一次。2-bit 錯 1 次:出口錯一次,但計數器在 11,出口只降到 10,還是猜跳,所以入口猜對。
第 7 章
第 4、5 章假設 Mem 一個 cycle 就存取完。但 memory 越大越慢:一個 cycle 存取得完的 memory 很小,放不下程式要的資料。
這是第 5 章的 pipeline,加上 memory 階層(memory hierarchy)。第 4、5 章 Mem 的指令 port 和資料 port(P&H 圖上的 Instruction memory 和 Data memory),其實是 L1 I-cache 和 L1 D-cache。hit 時一個 cycle 內拿到;miss 才沿著紫線往下一層找。越往下越大、越慢、每個 byte 越便宜。藍線是資料,橘線是 control 送出的 wire,紫線是 memory 階層。兩個 L1 旁邊的 TLB 把 p(page number)換成 f(frame number),是第 9 章的內容。最上面的多核心是第 10 章的內容。時間是示意的量級,和 OS 地圖相同。
0009 收課後補。下面先放 cache 的結構圖。
CPU 送來一個位址,cache 把它切成三段:tag、index、block offset。index 選一個 set,tag 和這個 set 裡每個 way 存的 tag 比對,block offset 選 block 裡的哪個 byte。這張圖畫的是 4-way set associative。V 是 valid bit,D 是 dirty bit(write-back 才需要)。direct mapped 就是每個 set 只有 1 個 way;fully associative 就是只有 1 個 set、沒有 index。
0009 收課後補。
第 8 章
cache miss 時,要從 main memory 搬一個 block 進來。這段時間(miss penalty)由 main memory 用的 DRAM(dynamic random access memory)決定。
0010 收課後補。
0010 收課後補。
第 9 章
和 OS 地圖第 4、5 章相同:程式能讀寫任何 physical 位址;查 page table 讓每次存取多讀一次 memory。CA 寫 virtual 位址,OS 地圖寫 logical 位址,兩個指同一個東西。
0010 收課後補。下面先放位址轉換的圖。
CPU 發出的是 virtual 位址(OS 地圖叫 logical 位址)。TLB 把 p 換成 f,d(page 裡的第幾個 byte)原封不動。拿到 physical 位址以後,才去查 cache 和 DRAM。位址轉換的步驟和 OS 地圖第 4、5 章一樣。p、d、f、PTE(page table entry)、PTBR(page-table base register:存 page table 起點的 register)的名詞也和 OS 地圖一樣。TLB entry 裡的數字只是示意。TLB 也是一個 cache,所以第 7 章的 direct mapped、set associative 也適用於 TLB。DRAM 畫成 4 個 bank。
0010 收課後補。
第 10 章
第 5 章的 pipeline 每個 cycle 至多做完一條指令,所以 CPI ≥ 1。
考卷沒有。
刷考古遇到再補。下面先放簡圖。
考卷沒有這部分,但研究所考試常考。左邊是 multiple issue:一個 core 在一個 cycle 發出好幾條指令,用的是指令之間的 instruction-level parallelism(ILP)。右邊是 multiprocessor:好幾個 core 各有自己的 cache,共用同一個 memory。VLIW 是 very long instruction word。
刷考古遇到再補。