CA 心智地圖

CA 心智地圖

計算機結構(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。

模型

  1. 硬體有兩樣:CPU(central processing unit)和 Mem(memory)。devices 在 OS 地圖第 0 章,CA 地圖不畫。
  2. Mem 是 byte-addressable:一個位址對應 1 byte。指令和資料都放在 Mem 裡。指令也是一串 bit,和資料放在同一個 memory。P&H 叫這個 stored-program concept。
  3. 這台電腦的 state 只有三個:PC(program counter:存這條指令的位址)、Reg(32 個 register,每個存一個 word = 32 bit;$0 永遠是 0)、Mem。
  4. CPU 不斷做三件事:讀 Mem[PC] 那個 word 當指令 → 執行:照指令改 Reg 或 Mem → 更新 PC(PC + 4,或跳到指令給的位址)。這和 OS 地圖第 0 章是同一句話。
  5. 所以一條指令 = 一次狀態轉移:(PC, Reg, Mem) → (PC', Reg', Mem')。算術和邏輯指令的資料只從 Reg 讀、寫回 Reg(同時也更新 PC)。只有 lw、sw 存取 Mem 裡的資料。
  6. 寫程式的人只看到這台機器:有哪些指令、每條指令怎麼改 state。這就是 ISA(instruction set architecture)。後面各章怎麼實作,都不能改變它的執行結果。
CPUcentral processing unit 讀 Mem[PC] → 執行(改 Reg 或 Mem) → 更新 PC PC 0x0040_0000 這條指令的位址 Reg 32 個 register,每個 32 bit $00永遠是 0 ⋮ $8$t0暫存的值 $18$s2h $19$s30x1000_0000A 的起點 ⋮ $31 Membyte-addressable:一個位址對應 1 byte 位址 內容(32 bit) 意思 指令 0x0040_0000 0x8E68_0020 lw $t0, 32($s3) 0x0040_0004 0x0248_4020 add $t0, $s2, $t0 0x0040_0008 0xAE68_0030 sw $t0, 48($s3) ⋮ 資料 0x1000_0020 A[8] lw 讀這一格 0x1000_0024 A[9] ⋮ 0x1000_0030 A[12] sw 寫這一格 位址由上往下遞增。一格是一個 word,相鄰兩格的位址差 4。 內容寫成 16 進位:一個 16 進位數字是 4 bit。 指令和資料都是一串 bit,放在同一個 Mem。 PC 指到這條 lw、sw 的位址 Reg[$s3] + imm

粗框灰底的是 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。

  • CPU time = 指令數 × CPI × clock cycle time。
    • 指令數:程式執行了幾條指令。由 ISA 和 compiler 決定。
    • CPI(clock cycles per instruction):每條指令平均要幾個 clock cycle。
    • clock cycle time:一個 clock cycle 的長度。由一個 cycle 內訊號要走的最長路徑決定。
  • 第 1–4 章:第 0 章的電腦怎麼用 bit 和電路做出來(P&H 第 2、3 章和第 4 章前半)。
  • 第 5 章起:怎麼變快。每章的問題寫成上式哪一個因子太大。
  • 限制:每一種加速,執行結果都要和第 0 章一條一條執行的結果一樣。P&H §4.5 說,pipelining 對寫程式的人是看不見的(invisible)。
  • 有些問題是前一章的解法帶來的。例:第 5 章的 pipeline 帶來第 6 章的 hazard。

定理

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,所以需要長常數的指令,要用另一種格式。

一條指令看兩個軸。兩個軸互不相干。

  • 軸 1:格式由「需要多大的常數」決定。
    • R-type:不需要常數,或只需要 5 bit 的 shamt。所有 operand(指令拿來運算的值)都是 register。例:add、sub、and、or、slt、sll、srl、jr。
    • I-type:需要一個 16 bit 的常數(imm)。例:addi、lw、sw、beq、bne、lui(load upper immediate)。
    • J-type:需要一個 26 bit 的 address。例:j、jal(jump and link)。
  • 軸 2:LHS(left-hand side:轉移式 <= 左邊,也就是要寫入的 state)由 op 和 funct 決定。
    • Reg:add、sll、addi、lw、lui。寫哪個 register 由格式決定:R-type 寫 rd,I-type 寫 rt。
    • Mem:sw。
    • PC:下一個 PC 可能不是 PC + 4 的指令:beq、bne(有條件)、j、jr。
    • Reg 和 PC 都寫:jal(固定寫 $31)。

你推出來的(模型的起點):「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 : 0
sll 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)」。表裡常數的顏色,就是這四種用法。

  • addi:常數就是值,= sign_extend(imm)。
  • lw、sw:常數加到 Reg[rs] 上,當作 Mem 的位址。
  • beq、bne:常數是 PC 的位移,目標 = PC + 4 + sign_extend(imm) × 4(imm 以 word 為單位)。
  • j、jal:26 bit 的 address 換掉 PC 的低 28 bit:{(PC + 4)[31:28], address, 00}。
  • jr 沒有常數:PC = Reg[rs]。

lw、sw 的 imm 以 byte 為單位,不乘 4。

4.問:control 看哪些欄位,決定一條指令做什麼?

答:看 op;R-type 再加看 funct。兩個軸都由它們決定。

5.問:MIPS 的哪些設計,各對應 P&H 的哪一條設計原則?

答:

  • Simplicity favors regularity:三種格式都是 32 bit,op 都在 [31:26],rs、rt 在 R-type 和 I-type 的位置也一樣。所以 control 看 op 就知道格式,Reg 可以先讀 rs、rt,不用等解碼完。
  • Smaller is faster:Reg 只有 32 個 register,所以一個 cycle 內讀得完。memory 階層(memory hierarchy,第 7 章)越往下越大,也越慢。所以資料放在小而快的 register 裡,少碰大而慢的 memory。
  • Make the common case fast:常數很常見,所以直接放進 16-bit immediate(addi、lw、sw 都用這個欄位),不用另外 load。branch 只做最常見的 beq、bne。
  • Good design demands good compromise:每種指令都想要更多 bit,但總長固定 32 bit。所以 immediate 只有 16 bit,大常數用 lui(load upper immediate)+ ori(or immediate)分兩步。j 的 address 只有 26 bit,高 4 bit 抄 PC。三種格式本身也是妥協。

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)。

  1. 整數用 n-bit 二補數(two's complement)。設 bit 樣式的無號值是 u。最高位 bit 是 0 ⇒ 值 = u。最高位 bit 是 1 ⇒ 值 = u − 2^n,也就是負數的絕對值 = 2^n − u。
  2. 浮點數(floating point)在 register 和 memory 裡也是一串 bit。IEEE 754(浮點數的標準)把它切成三個欄位:sign、exponent 欄位、fraction 欄位(圖的上面)。
  3. 值 = (−1)^s × 1.fraction × 2^(exponent 欄位 − bias)。bias = 2^(E−1) − 1,E 是 exponent 欄位的 bit 數。
  4. exponent 欄位全 0 和全 1 保留給特殊值。全 0 是 denormal:hidden bit 變 0,實際指數固定是 1 − bias。全 1 是 INF 和 NaN(not a number)。
  5. 圖的下面,是這些 bit 在數線上代表哪些數。
單精度 32 bit bias 127 s31 exponent(8)30–23 fraction(23)22–0 16 bit 例 · bias 31 s15 exponent(6)14–9 fraction(9)8–0 值 = (−1)^s × 1.fraction × 2^(exponent 欄位 − bias) bias = 2^(E−1) − 1,E 是 exponent 的 bit 數 正數的數線 denormal 間距相同 間距 ×2 間距 ×4 … 0 2^(1−bias) 2^(2−bias) 2^(3−bias) 2^(4−bias) 最大值之後:exponent 欄位全 1 → INF、NaN denormal:exponent 欄位 = 0,hidden bit 變 0,指數固定是 1 − bias。間距和第一段 normalized 一樣,所以 0 附近沒有空洞。

數線是示意圖:fraction 只畫 2 bit,所以每一段只有 4 個數。真的格式每一段有 2^(fraction 的 bit 數) 個數。上面的 16 bit 是一個例子:exponent 6 bit,fraction 9 bit。

exponent 欄位012…2^E − 22^E − 1
實際指數DeNorm(1 − bias)1 − bias2 − bias…biasINF/NaN
8 bit,bias 127DeNorm(−126)−126−125…127INF/NaN
6 bit,bias 31DeNorm(−30)−30−29…31INF/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 章

ALU 與 adder

問題(clock cycle time)

第 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)。

  1. 圖左上是 1-bit ALU(arithmetic logic unit)。每個 bit 先選 a 或 ¬a、b 或 ¬b,再用 operation 從 AND、OR、adder 三個結果選一個。32 個串起來就是 32-bit ALU。
  2. adder 每一位的 carry 照遞迴式算:cᵢ₊₁ = gᵢ + pᵢ·cᵢ。cᵢ 是進到第 i 位的 carry。gᵢ = aᵢ·bᵢ(generate)。pᵢ = aᵢ + bᵢ 或 aᵢ ⊕ bᵢ(propagate)。
  3. 圖右邊比較三種 adder:ripple carry adder、carry lookahead adder(CLA)、用 carry save adder(CSA)做的 Wallace tree。差別只在 carry 要等多久。
  4. 延遲用最長路徑算(圖左下的式子)。這是你建的模型。
1-bit ALU a b a_invert a 或 ¬a b_negate b 或 ¬b AND OR +full adder carry_in carry_out 0 1 2 operation(2 bit) result gate delay = 最長路徑(你建的模型) D[cᵢ₊₁] = D[OR] + max(D[gᵢ], D[pᵢ·cᵢ]) D[pᵢ·cᵢ] = D[AND] + max(D[pᵢ], D[cᵢ]) D[AND] = D[OR] = 1,D[p] = D[g] = 1,D[c₀] = 0 ripple:逐位累加 → D[cᵢ] = 1 + 2i cascaded CLA:block 的 G、P 是常數,只累加 block 之間的 carry carry 的延遲 ripple carry adder c₀ FA FA FA FA FA FA FA FA cᵢ₊₁ = gᵢ + pᵢ·cᵢ:每一位都要等前一位的 carry 延遲和 bit 數成正比 carry lookahead adder(4-bit block) CLA logic bit 0 bit 1 bit 2 bit 3 p g 所有 carry 同時算出 c₄ = g₃ + p₃g₂ + p₃p₂g₁ + p₃p₂p₁g₀ + p₃p₂p₁p₀c₀ 兩層 gate:先 AND,再 OR block 再算 P、G,串接各 block 展開遞迴式:每個 cᵢ 只看 p、g、c₀,不用等前一位 Wallace tree(16 個 partial products) 16 11 8 6 4 3 2 CPA 綠色每一步是一層 CSA:3 個數變成 2 個,共 6 層 紅色是唯一一次 carry 傳播:最後 2 個數用一個 CPA 相加 CSA:sum = a ⊕ b ⊕ c,carry = 多數決(a, b, c) a + b + c = sum + (carry << 1)

紅色箭頭是 carry 要等的地方,綠色是不用等的地方。

運算a_invertb_negatecarry_inoperation為什麼
AND00X0a·b
OR00X1a + b
add0002a + b(算術)
SUB0112a + ¬b + 1 = a − b
NOR11X0¬a·¬b = ¬(a + b)
NAND11X1¬a + ¬b = ¬(a·b)
NOT11X0NOR(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 三個結果。它還能做哪些運算?

答:

  • SUB:b_negate = 1,carry_in = 1,所以算的是 a + ¬b + 1 = a − b。這就是二補數的「取反加一」(第 2 章)。
  • NOR、NAND 靠 De Morgan's laws:¬a·¬b = ¬(a + b),¬a + ¬b = ¬(a·b)。NOT 是兩個輸入接同一個數的 NOR。
  • XOR 做不到。XOR = a·¬b + ¬a·b,要兩個乘積項再 OR。這個 ALU 每個 bit 只能選一個 gate 的結果,不能再把兩個結果接起來。

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 章

single-cycle datapath

問題

把第 0 章的狀態轉移做成硬體。最簡單的做法是一個 cycle 做完一條指令(CPI = 1)。

模型

出處:P&H §4.3(building a datapath)、§4.4(a simple implementation scheme)。

  1. IF 和 MEM 在同一個 cycle 都要存取 Mem,所以 Mem 要有兩個 port(P&H 畫成兩塊:Instruction memory、Data memory)。
  2. 模型分兩層。第一層是合併(combine,P&H 建 datapath 的方法):先寫出每類指令的轉移(步驟 1 的表),再合併成一套硬體(步驟 2 的表)。不同指令送進同一個位置的值不一樣 ⇒ 放 mux。有的指令不寫某個 state ⇒ 加 write enable。
  3. 第二層是合併的結果,用你在 0007 的說法寫成轉移式:combination block 讀現在的 state,算出這個 cycle 的 wire;always block 在 clock edge 把新值寫進 state(下面第一張圖)。
  4. 同一件事畫成 datapath(下面第二張圖),照期末 Q2 的圖畫。

你推出來的:「在 combination block 裏面:ALU = func(Read data 1, ALUSrc? Read data 2 : Imm, ALUOp) 之類的。而在 always block 裏面,就是狀態轉移式(LHS 是新狀態)」。式子的寫法照下面第一張圖。

state:粗框、灰底,名字大寫開頭。底邊的小三角形是 clock:clock edge 時寫入 combinational:細框、白底,不記值,名字小寫 wire:線,名字全小寫。橘色字是 control 送出的 wire

寫法(你在 0007 定的):state 的名字大寫開頭(PC、Reg、Mem),wire 和 combinational 元件的名字全小寫。考卷的 RegDst 就是 reg_dst,其他照同樣的規則改寫。

步驟 1:指令RegMemPC
add rd, rs, rtReg[rd] <= Reg[rs] + Reg[rt]不變PC + 4
addi rt, rs, immReg[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)
下一個 PCpc_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。

state 名字大寫開頭 Mem 指令 port,只讀 PC 這條指令的位址 Reg Registers,32 個 × 32 bit Mem 資料 port(和上面是同一個 Mem) 讀 combination block 讀現在的 state,算出這個 cycle 的 wire;不寫任何 state inst = Mem[PC] op, rs, rt, rd, imm = inst[31:26], inst[25:21], inst[20:16], inst[15:11], inst[15:0] reg_dst, alu_src, mem_to_reg, reg_write, mem_read, mem_write, branch, alu_op = control(op) read_data_1 = Reg[rs]  read_data_2 = Reg[rt]  imm32 = sign_extend(imm) alu_result = alu(alu_op, read_data_1, alu_src ? imm32 : read_data_2) zero = (alu_result == 0)  read_data = mem_read ? Mem[alu_result] : 不讀 write_reg = reg_dst ? rd : rt  write_data = mem_to_reg ? read_data : alu_result pc_plus_4 = PC + 4  branch_target = pc_plus_4 + (imm32 << 2) pc_src = branch & zero  next_pc = pc_src ? branch_target : pc_plus_4 wire 的值 always block clock edge 時寫入新的 state(LHS 是 state,RHS 是 wire) PC <= next_pc if (reg_write) Reg[write_reg] <= write_data if (mem_write) Mem[alu_result] <= read_data_2 寫:下一個 cycle 的 state
在轉移式裡的樣子意思wire(考卷的名字)
c ? x : ymux:c = 1 選 x,c = 0 選 yreg_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 時才讀 Memmem_read(MemRead)
control(op)只看 op 決定的 wire。pc_src 例外:它還看 alu 算出來的 zeropc_src 以外的 8 個
next_pc PC + 4 pc_plus_4 Mem 指令 port 只讀 inst [31–26] op control 輸出橘色字的 wire [25–21] rs [20–16] rt [15–11] rd [15–0] imm 0 1 reg_dst reg_write rs rt write_reg write_data read_data_1 read_data_2 Reg Registers sign_extend imm32 read_data_2 0 1 alu_src alu alu_control alu_op << 2 + branch_target 0 1 zero branch & pc_src mem_write mem_read alu_result read_data_2 read_data Mem 資料 port 0 1 mem_to_reg write_data

怎麼讀這張圖:粗框灰底的是 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?

答:

  1. 寫出這條指令那一列(步驟 1 的表)。
  2. mux 的選擇訊號:要送出哪個輸入,就填它的編號。
  3. mux 的選擇訊號是 X(don't care)⇔ 這個 mux 的輸出沒有寫進任何 state。
  4. write enable、read enable 只能填 0 或 1。

例: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 章

pipeline

問題(clock cycle time)

第 4 章裡,所有指令共用同一個 cycle。cycle 要長到最慢的指令(lw)走完整段 combinational 電路。其他指令用不到那麼久,也要等。

模型

出處:P&H §4.5(an overview of pipelining)、§4.6(pipelined datapath and control)。

  1. 第 4 章的 single-cycle 裡,從 state 的輸出到 state 的輸入,只有一段 combinational 電路。
  2. pipeline 在這段電路中間插進 4 個 pipeline register(它們也是 state),把它分成 5 段,每段是一個 stage:IF(instruction fetch:用 PC 拿指令)、ID(instruction decode:解碼、讀 Reg)、EX(execute:alu 運算)、MEM(memory access:存取 Mem)、WB(write back:寫回 Reg)。
  3. IF 和 MEM 在同一個 cycle 都要存取 Mem,所以 Mem 要有兩個 port(P&H 畫成兩塊:Instruction memory、Data memory)。
  4. clock edge 時所有 state 一起寫入。所以同一個 cycle 裡,5 個 stage 各做一條不同的指令。
state:粗框、灰底,名字大寫開頭。底邊的小三角形是 clock:clock edge 時寫入 combinational:細框、白底,不記值,名字小寫 wire:線,名字全小寫。橘色是 control 的 wire
pipeline:4 個 pipeline register 把 datapath 分成 5 段 PC IF_ID IRPC4 ID_EX A、BImmPC4Ctl EX_MEM ALUOut1ALUOut2Zero、BCtl MEM_WB ReadDataALUOut2Ctl Reg IF 讀 MemPC + 4 200 ps ID 讀 Regcontrol 100 ps EX alubranch adder 200 ps MEM 讀/寫 Mempc_src 200 ps WB mem_to_reg寫 Reg 100 ps 每段的 Time = 這段的 logic + t_reg。cycle 要等最長的一段:max(200, 100, 200, 200, 100) + t_reg = 200 ps + t_reg。 single-cycle(第 4 章):只有一段 PC IF → ID → EX → MEM → WB 是同一段:200 + 100 + 200 + 200 + 100 = 800 ps PCRegMem

所有 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讀的 statecombinational 算出的 wire這個 stage 結束時寫入的 state
IFPC、Mem(指令 port) inst = Mem[PC]
pc_plus_4 = PC + 4
IF_ID.IR <= inst
IF_ID.PC4 <= pc_plus_4
PC <= next_pc
IDIF_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
EXID_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
MEMEX_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
WBMEM_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。

EX_MEM.ALUOut1 回到 PC 前的 mux IF_ID ID_EX EX_MEM MEM_WB PC4 IR PC4 Ctl Imm A B Ctl ALUOut1 Zero ALUOut2 B Ctl ALUOut2 ReadData 0 1 pc_src PC 4 + pc_plus_4 Mem inst 指令 port op imm control sign_extend rs, rt read_data_1 read_data_2 Reg write_data << 2 + 0 1 alu_src alu zero branch & pc_src Mem 資料 port mem_to_reg 0 1 write_data

這張圖照期末 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 章

hazard

問題(限制、CPI)

第 5 章的 pipeline 裡,同一個 cycle 有 5 條指令在不同 stage。前一條指令在 WB 才把結果寫進 Reg,後一條指令在 ID 就要讀 Reg。branch 在 MEM 才決定跳不跳,在這之前已經拿了後面 3 條指令。不處理,執行結果就和第 0 章不一樣。用 stall 處理,CPI 就大於 1。

模型(data hazard)

出處:P&H §4.7。

  1. 時間點:每個 stage 的轉移式,在 stage 結束時寫入右邊的 pipeline register。用 stage 的名字代表這個時間點。例:「MEM」代表 MEM_WB 被求出的時間點,也就是 MEM 這個 stage 結束時。
  2. 依賴:一條指令求某個 state 時,轉移式 RHS 引用了前面某條指令求出的 state。被引用的 state 要先求出來,所以引用的時間點至少要晚 1 個 cycle。例外是 internal forwarding:Reg 在 WB 的前半個 clock 寫入,ID 在同一個 clock 的後半就讀得到。
  3. 沒有 forwarding:operand 在 ID 從 Reg 讀,所以依賴的是前一條指令的 WB。
  4. forwarding:把取 operand 的那一步從 ID 移到 EX,直接引用更早求出的同一個值。有兩種:EX → EX(值在 EX_MEM,P&H 叫 EX hazard)和 MEM → EX(值在 MEM_WB,P&H 叫 MEM hazard)。forwarding unit 決定 alu 的輸入用哪一個值。
  5. 計算步驟:① 每條指令列出它在求哪個 state 時引用了哪個 state,一個 dependency 一行。② 換成 forwarding 以後的版本。③ 畫時間軸,檢查每條 dependency 是不是至少晚 1 個 cycle;不夠就 stall(讓指令留在同一個 stage)。

你推出來的:「想著的是 pipeline state 之間的轉移式。……箭頭代表求出這個 state,需要依賴另一個 state。所以後者的時間至少需要晚一個 clock。internal forward 是例外……Forwarding,就是把這一行轉移式,晚一點做,引用更早的同個狀態。」

模型(control hazard)

出處:P&H §4.8。

  1. 下一條指令的 IF 依賴 PC。branch 在決定跳不跳的那個 stage 結束時寫入 PC。所以下一條的 IF 至少要比那個 stage 晚 1 個 cycle。損失的 cycle 數 = 決定的 stage 和 IF 差幾個 stage:在 MEM 決定損失 3 個,在 ID 決定損失 1 個。
  2. 三種處理:
    • stall:一直等到決定。每條 branch 都損失。
    • predict(猜):先照猜的拿。猜對沒有損失。猜錯就 flush:把拿錯的指令在 pipeline register 裡的 Ctl 清成 0(reg_write、mem_write = 0),讓它們變成 no-op(不做任何事的指令)。
    • 把決定提早到 ID:把比較 Reg[rs]、Reg[rt] 的電路和 branch adder 移到 ID。損失變成 1 個 cycle。代價:ID 要比較的值可能還沒算好,多出 data hazard。例:前一條是 R-type 而且緊接著 beq,beq 在 ID 要用它的結果,要 stall 1 個 cycle;前一條是 lw,要 stall 2 個 cycle。
  3. dynamic branch prediction:硬體用一張表(P&H 叫 branch prediction buffer),用 branch 指令位址的低位 bit 當 index,記這條 branch 過去有沒有跳。1-bit:記上一次的結果。2-bit:一個 0–3 的計數器;跳就 + 1,不跳就 − 1,到 0 或 3 停住;≥ 2 時猜跳。所以在 00 或 11 時,要連續猜錯兩次才改猜法。
data hazard:forwarding 和 load-use 改自 P&H §4.7 的 load-use 例子 1 2 3 4 5 6 7 8 9 cycle lw $2, 20($1) IF ID EX MEM WB and $4, $2, $5 IF ID stall EX MEM WB or $8, $4, $6 IF stall ID EX MEM WB add $9, $4, $2 IF ID EX MEM WB ① ② ③ 綠色箭頭是 forwarding: ① lw 的 MEM → and 的 EX(MEM → EX,stall 1 個 cycle 以後) ② and 的 EX → or 的 EX(EX → EX) ③ and 的 MEM → add 的 EX(MEM → EX;add 的 $4) 紅格是 stall:and 要的 $2,lw 在 MEM 才求出。 and 的 EX 不能和 lw 的 MEM 在同一個 clock, 所以 and 留在 ID 1 個 cycle,or 也留在 IF(load-use)。 add 的 $2 由 lw 在 WB 寫入,靠 Reg 讀,不畫箭頭。 beq 在 MEM 決定:後面 3 條被 flush,損失 3 個 cycle 1 2 3 4 5 6 7 beq IF ID EX MEM WB 下一條 IF ID EX flush 再下一條 IF ID flush 第 3 條 IF flush 目標 IF ID EX beq 在 ID 決定:後面 1 條被 flush,損失 1 個 cycle 1 2 3 4 5 6 7 beq IF ID EX MEM WB 下一條 IF flush 目標 IF ID EX 綠格是 PC 寫入以後,照決定拿到的指令。 2-bit 計數器:跳 + 1,不跳 − 1,到 0 或 3 停住 00 01 10 11 跳 不跳 跳 不跳 跳 不跳 跳 不跳 00、01:猜不跳 10、11(≥ 2):猜跳

左半的第 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 章

cache

問題(CPI)

第 4、5 章假設 Mem 一個 cycle 就存取完。但 memory 越大越慢:一個 cycle 存取得完的 memory 很小,放不下程式要的資料。

多核心:把整個 CPU 複製幾份,共用下面的 memory 階層 CPU 5-stage pipeline:同一個 cycle,五個 stage 各做一條不同的指令 拿掉 4 個 pipeline register 就是 single-cycle IF ID EX MEM WB IF_ID ID_EX EX_MEM MEM_WB PC Mem 的 指令 port = L1 I-cache TLBp → f control Reg 32 個 × 32 bit 讀 rs、rt 寫 rd 或 rt alu 整數與浮點運算 Mem 的 資料 port = L1 D-cache TLBp → f mux WB:結果寫回 Reg L1 miss 才往下找 L2 cache 比 L1 大,也比 L1 慢 指令和資料共用 block Main memory(DRAM) bank 0 bank 1 bank 2 bank 3 page table 也放在這裡(每個 process 一張) 約 100 ns page Disk swap 區:不在 memory 的 pages 約 10 ms page fault 由 OS 處理 越往右:越大、越慢、每個 byte 越便宜

這是第 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 地圖相同。

這章要回答的題目

  • 期末 Q5(AMAT:average memory access time)
  • 期末 Q6
  • 期末 Q8(a)(b)(d)
  • 順便講(考卷沒有):用 address trace 逐筆判斷 hit/miss、multi-level cache、memory stall 的 CPI

模型

0009 收課後補。下面先放 cache 的結構圖。

位址 tag拿來比對 index選哪一個 set block offset第幾個 byte index tag way 0 way 1 way 2 way 3 VDtagdata block VDtagdata block VDtagdata block VDtagdata block set 0 set 1 ⋮ set i ⋮ = = = = OR hit? mux:選出 hit 的那一個 way 再用 block offset 選出要的 byte 或 word,送回 CPU miss:到下一層拿一整個 block

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 章

DRAM

問題(CPI)

cache miss 時,要從 main memory 搬一個 block 進來。這段時間(miss penalty)由 main memory 用的 DRAM(dynamic random access memory)決定。

這章要回答的題目

  • 期末 Q7(c)(d)

模型

0010 收課後補。

定理

0010 收課後補。

第 9 章

virtual memory、TLB

問題(OS 地圖的保護、效率)

和 OS 地圖第 4、5 章相同:程式能讀寫任何 physical 位址;查 page table 讓每次存取多讀一次 memory。CA 寫 virtual 位址,OS 地圖寫 logical 位址,兩個指同一個東西。

這章要回答的題目

  • 期末 Q7(a)(b)
  • 期末 Q8(c)(e)
  • 順便講(考卷沒有):page table 大小

模型

0010 收課後補。下面先放位址轉換的圖。

CPU 發出 virtual 位址 virtual 位址 p d virtual page number page offset d 不變 用 p 查 TLB page table 的 cache valid tag f 12 17 0– hit physical 位址 f d physical page number page offset cache(第 7 章) 用 physical 位址查 miss TLB miss: 用 PTBR 讀 page table Main memory(DRAM) page table PTE:p → f、valid PTBR 指向它 bank 0 bank 1 bank 2 bank 3 valid = 0 Disk swap 區:不在 memory 的 pages page fault:trap 進 OS,從這裡搬一整頁進來 這是 OS 地圖第 5 章的 page fault 名詞對照(P&H ↔ OS 地圖) virtual address= logical 位址 virtual page number= p physical page number= f(frame number) page offset= d page table entry= PTE

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 章

ILP、multiprocessor

問題(CPI)

第 5 章的 pipeline 每個 cycle 至多做完一條指令,所以 CPI ≥ 1。

這章要回答的題目

考卷沒有。

模型

刷考古遇到再補。下面先放簡圖。

multiple issue:一個 cycle 發出 2 條 i1i2i3i4 IFIDEXMEMWB IFIDEXMEMWB IFIDEXMEMWB IFIDEXMEMWB cycle123456 static multiple issue:compiler 先把能一起發的指令排好(VLIW) dynamic multiple issue:硬體在執行時決定(superscalar) 同一組的兩條指令之間不能有 dependency multiprocessor:每個 core 有自己的 cache Core 0 L1 cache count = 5舊值 Core 1 L1 cache count = 7剛寫入 共用的 bus Main memory count = 5 cache coherence:同一個 block 在好幾個 cache 裡,大家要讀到一樣的值

考卷沒有這部分,但研究所考試常考。左邊是 multiple issue:一個 core 在一個 cycle 發出好幾條指令,用的是指令之間的 instruction-level parallelism(ILP)。右邊是 multiprocessor:好幾個 core 各有自己的 cache,共用同一個 memory。VLIW 是 very long instruction word。

定理

刷考古遇到再補。