<超標量處理器概覽> 第 6 章 - 指令解碼
在 pipeline 中,decode stage 的任務是將指令中的資訊提取出來,CPU 使用這些資訊控制後續的 pipeline 來執行這條指令 影響 decode 的複雜度因素有: 指令集的複雜度: CISC vs. RISC 每個 cycle 可以 decode 的指令個數: 每個 cycle 可以 decode N 條指令,那就需要 N 個 decode 電路 6.1 - 指令緩存 現代處理器可以在 fetch stage 從 I-Cache 讀出大於每個 cycle 可以 decode 指令個數的指令,因此需要在 fetch stage 和 decode stage 之間加一個 buffer,用來將 I-Cache 讀出的所有指令保存起來,這個 buffer 就稱為 Instruction Buffer Fetch stage 最終會輸出兩個主要的內容給 Instruction Buffer: 從 I-Cache 讀出的 N 條指令 (並非所有指令都是有效的) 有效的指令個數 1 instruction fetch 位址不是 cache aligned 時,或是 fetch group 中包含預測為 taken 的指令,會導致 fetch stage 沒辦法寫入 N 條指令進 Instruction Buffer 此時需要告知 Instruction Buffer,有效的指令個數 現在 superscalar CPU 需要 Instruction Buffer 的原因: Superscalar CPU 可以每個 cycle 可以 fetch 的指令個數大於每個 cycle 可以 decode 的指令個數,這樣即使在發生 I-Cache miss 時,Instruction Buffer 中仍有可能還有保存尚未 decode 的指令,因此不需要 stall pipeline,可以繼續 decode 指令,增加 CPU 的性能 Superscalar CPU 中即使每個 cycle 可以 decode 的指令個數與每個 cycle 所 fetch 的指令個數相等,在 decode stage 仍會有一些特殊的指令需要處理,導致在 fetch stage 所 fetch 的指令沒有辦法全部被 decode 如 ARM 的 multiply-accumulate 指令 (UMAAL RdLo, RdHi, Rn, Rm),會有兩個 destination registers,為了減少對 register renaming 的影響,會將其拆分成兩條普通的指令,每條指令只有一個 destination register 因此,如果在 decode stage 沒有特別的處理,會導致 decode 的指令個數大於 fetch 指令的個數,但後續的 pipeline 都是依照原先的指令個數來設計的,不可能因為這些不常見的指令而增加後續 pipeline 的處理能力 (因為會增加硬體面積,且使用率也不高) 為了解決此問題,就需要加入 Instruction Buffer,讓 multiply-accumulate 後面的指令,可以等到下一個 cycle 再 decode 由於 Instruction Buffer 可以在一個 cycle 內寫入多條的指令,也可以讀出多條的指令,因此也是一個 multi-port 的 FIFIO;但在實際設計上,並不會使用真的 multi-port 的 SRAM 來實現這樣的 FIFO,而是會採用 interleaving 的方式 (參考:2.3.1 - True Multi-port),使用多個 single-port 的 SRAM 來實現,從而避免使用 multi-port SRAM 所導致的硬體速度上的限制 6.2 - 一般情況 ARM 的 CPSR,只有 4 個 bits (N、C、Z、V),但其他的暫存器都是 32 bits 的;如果將 CPSR 跟其他的暫存器統一對待,會造成很多暫存器無法有效的被利用,因為 32 bits 的暫存器,只存了 4 bits 的資料 因此,一般都是將 CPSR 單獨處理,對 CPSR 單獨使用一套 register renaming 的流程,這樣就可以根據 CPSR 的特性來訂製 register renaming 的流程 且考慮到條件執行的指令只是少部份,所以所使用的 register file 可以很小,例如只需只用 16 個 physical registers 就足夠了 指令所攜帶的 source registers 和 destination registers 的個數直接決定了 register renaming 電路在實現上的難易度: 像是 register renaming mapping tables 的 ports 數、指令間相關性檢查電路的複雜度 由於 RISC 架構的指令比較整齊劃一,很容易解析出指令中的 opcode 和 operands,在 decode stage 產生的 pipeline 控制訊號也比較少,因此 RISC 架構的 instruction decoding 通常都可以在 1 個 cycle 完成 一般情況下,RISC 處理器在 decode stage 完成的任務可以概括為: What type:例如指令是算術指令還是分支指令 What operation:例如當指令是算術指令時,是進行什麼運算;是分支指令時,它的跳轉條件是什麼樣的 What resource:例如對算術指令時來說,其 source 和 destination registers 是哪些,有沒有 immediate value 6.3 - 特殊情況 即使在 RISC 指令集中,也存在一些特殊的指令;這些指令不能按照一般的方法處理 例如:ARM 的 LDM / STM 指令,需要多個 cycles 才能完成;而且它們的 source 和 destination registers 有多個,如果在 superscalar CPU 中對它們跟普通指令一樣來處理的話,會需要增加 register renaming mapping table、issue queue 和 ROB 所需的 ports 數,增加硬體的面積,並降低處理效能 因此在 superscalar CPU 中,並不會直接處理 LDM / STM 這樣的指令,而是會將其轉換為多條普通的指令 (µops),每條普通的指令就是一般的 load / store 指令,這樣就可以用普通指令的方式來處理 6.3.1 - 分支指令的處理 先前提到,採用 checkpoint 的方式對 mis-prediction 的分支指令恢復 CPU 的狀態,為了減少分支指令編號分配電路的複雜度,需要限制每個 cycle 能 decode 的分支指令個數,例如每個 cycle 只能 decode 一條分支指令 (參考:4.4 - 分支預測失敗時的恢復) 但是,每個 cycle 從 Instruction Buffer 讀取的指令中,有可能存在多條的分支指令,需要在 decode stage 做特別的處理 簡單的作法: ...