Computer Organization and Design: RISC-V

RISC-V

RISC-V 處理器簡介

  • RISC-V 官網 -- https://riscv.org/
    • 軟體 -- https://riscv.org/exchange/software/
    • 開發板 -- https://riscv.org/exchange/
    • 處理器原始碼 -- https://riscv.org/exchange/cores-socs/
    • 技術手冊 -- https://riscv.org/technical/specifications/

RISC-V 處理器的架構

RISC-V 處理器內含 32 個整數暫存器 (x0-x31),若掛上浮點運算單元,則會再多出 32 個浮點暫存器 (f0-f31)。
這些暫存器通常有個比較好記的別名 (ABI Name),例如 x0 的別名為 Zero,因為該暫存器為唯讀,而且數值永遠都是 0。 x1 又稱 ra (return address) ,因為用來儲存返回位址。x2 又稱 sp (stack pointer) ,是堆疊暫存器。

另外有些暫存器的別名是一整群的,例如 t1-t6 (temporaries) 都是臨時變數暫存器。 a0-a7 為參數暫存器 (arguments),s0-s11 則是 Saved Registers。

RISC-V 的 PC 不屬於 x0-x31 ,而是一個獨立的暫存器,一般指令無法存取,想要讀取 PC 得用 auipc 這樣的特殊指令。

除了這些基本暫存器之外,RISC-V 還定義一群控制暫存器 CSR (Control Status Registers)

CSR 暫存器在設計作業系統時會很有用,例如我們可以透過讀取 time 得到目前的時間值。

RISC-V 指令格式

RISC-V 的指令格式共有六種
Immediate values are constants encoded directly within instructions.
Different instruction types (I-Type, S-Type, B-Type, U-Type, J-Type) use immediate values in different formats and for various purposes.
Immediate values allows the instruction to use or manipulate a constant without needing to load it from memory or another register.

RISC-V uses several formats for immediate values, depending on the instruction type:

  • I-Type (Immediate Type):
  • Used for immediate arithmetic and logical operations, load instructions, and system instructions.
    Immediate field: 12 bits.
    Instructions: ADDI, SLTI, ANDI, LW, LB, LH, LBU, LHU, JALR, ECALL, EBREAK, etc.
    For ex.,
    
      ADDI x1, x2, 10
      
    This instruction adds the value 10 (an immediate value) to the value in register x2 and stores the result in register x1.
  • S-Type (Store Type):
  • Used for store instructions.
    Immediate field: Split across two parts (5 bits in one field and 7 bits in another).
    Instructions: SW, SB, SH.
    For ex.,
    
      SW x1, 8(x2)
      
    This instruction stores the value in register x1 to the memory address obtained by adding 8 (an immediate value) to the value in register x2.
  • B-Type (Branch Type):
  • Used for conditional branch instructions.
    Immediate field: 12 bits (split across several fields).
    Instructions: BEQ, BNE, BLT, BGE, BLTU, BGEU.
    For ex.,
    
      BEQ x1, x2, 16
      
    This instruction compares the values in registers x1 and x2. If they are equal, it branches to the address PC + 16 (where PC is the address of the current instruction).
  • U-Type (Upper Immediate Type):
  • Used for instructions that require a larger immediate value.
    Immediate field: 20 bits.
    Instructions: LUI (Load Upper Immediate), AUIPC (Add Upper Immediate to PC).
    For ex.,
    
      This instruction loads the immediate value 0x12345000 (the immediate value shifted left by 12 bits) into register x1.
      
  • J-Type (Jump Type):
  • Used for jump instructions.
    Immediate field: 20 bits (split across several fields).
    Instruction: JAL (Jump and Link).
    For ex.,
    
      JAL x1, 1000
      
    This instruction jumps to the address PC + 1000 and stores the return address (PC + 4) in register x1.

RISC-V 指令集

RISC-V 的指令集可區分為很多群,最基礎的是 RV32I 整數指令集,若要納入整數乘除法,可加入 RV32M 指令集。
以下是較常見的 RISC-V 指令集。
  • RV32I:基础整数指令集 (固定不變了)
  • RV32M:乘法和除法
  • 由於兩個 32 位元整數相乘可能會變成 64 位元整數,因此會有超過 32 位元的高半部,所以有號數的乘法也分為 MUL, MULH 這兩種,其中 MULH 的結果為高半部,放入 rd 暫存器中。
    無號數的乘除法指令,最後會以 U 結尾,像是 MULHSU, MULHU, DIVU, REMU 等都是無號數的乘除法指令,其中的 REM 代表取餘數 (Remainder)。
  • RV32F:單精度浮点操作(和 RV32D:雙精度浮點操作)
  • RV32A:原子操作
  • RV32C:可选的压缩扩展 (對應 32 位元的 RV32G)
  • RV32B:基本擴展。
  • RV32V:向量扩展(SIMD)指令
  • RV64G:RISC-V 的 64 位地址版本。
RV32IM 代表 32 位元含乘除法的指令集 (RV32IM = RV32I + RV32M),RV32G 是 RV32IMAFD 的簡稱,這是一個常見的指令集組合,也就是包含《整數、乘除、原子、浮點 (單精+雙精) 》這樣的組合。

壓縮指令集

RISC-V 可以有 16, 32, 48, 64 等格式的指令,而且保留了更長指令的編碼空間。
RV32C is the compressed instruction set extension for the RISC-V RV32I base integer instruction set. This extension introduces compressed 16-bit instructions, which provide a more compact representation of commonly used instructions compared to the standard 32-bit instructions. The primary purpose of RV32C is to reduce the size of the code, which can lead to reduced memory usage and potentially improved performance due to better cache utilization.

RV32C 壓縮指令集為了縮減長度到 16 bit,除了縮減立即值 imm 的長度之外,也將 rd/rs1 用同一個欄位表示,這代表 rd/rs1 必須是同一個暫存器。

浮點指令集

浮點指令分為單精度 float (32 位元浮點數) 與雙精度 double (64 位元浮點數) 指令。

原子指令集

作業系統為了讓 thread 或 process 能共享變數卻不會產生《競爭情況》,必須創造出同步鎖定 (lock) 之類的運算,此時需要 RV32A《原子(Atomic)指令集》的支援

64 位元指令集

對於 64 位元的架構,其基本指令和 32 位元相同,指令也仍然是 32 位元的架構,但是暫存器卻是 64 位元的。
例如 64 位元的 sub 指令是將兩個 64 位元的暫存器相減(但在 32 位元的處理器中,sub 則是將兩個 32 位元的暫存器相減)。

結語

以下是 RISC-V 規格中,各指令集群是否已經《凍結》的簡表

RISC V 的中斷與異常處理

CSR 暫存器與指令

RISC-V 架構定義了許多暫存器,部分暫存器被定義為控制和狀態暫存器,也就是標題所指出的 CSR (Control and status registers) ,它被用於配置或是紀錄處理器的運作狀況。
RISC-V 架構中 (Machine Mode)與中斷、異常有關的暫存器:
  • CSR
    • mtvec
    • 當進入異常時, PC (Program counter) 會進入 mtvec 所指向的地址並繼續運行。
    • mcause
    • 紀載異常的原因
    • mtval
    • 紀載異常訊息
    • mepc
    • 進入異常前 PC 所指向的地址。若異常處理完畢, Program counter 可以讀取該位址並繼續執行。
    • mstatus
    • 進入異常時,硬體會更新 mstatus 寄存器的某些域值。
    • mie
    • 決定中斷是否被處理。
    • mip
    • 反映不同類型中斷的等待狀態。
  • Memory Address Mapped
    • mtime
    • 紀錄計時器的值。
    • mtimecmp
    • 儲存計時器的比較值。
    • msip
    • 產生或結束軟體中斷。
    • PLIC
RISC-V 定義了一系列的指令讓開發者能夠對 CSR 暫存器進行操作.
在處理各類的 Interrupt 都必須使用這些操作:
  • csrs 把 CSR 中指定的 bit 設為 1
  • 
      csrsi mstatus, (1 << 2)
      
  • csrc 把 CSR 中指定的 bit 設為 0
  • 
      
      
  • csrr[c|s] 將 CSR 的值讀入通用暫存器
  • 
      
      
  • csrw 將通用暫存器的值寫入 CSR
  • 
      csrw	mepc, a0
      
  • csrrw[i] 將 csr 的值寫入 rd 後,且將 rs1 的值寫入 CSR
  • 
      
      

異常

若處理器在執行指令流的時候遇到無法預期的情況,便稱之為異常
當異常發生時,處理器會停止手邊的工作,再將 Program counter 的位址指向 mtvec 所指的位址並開始執行

PicoRv32 -- RISC-V 處理器實作

rv32emu-next -- RISC-V 虛擬機實作


Computer Organization and Design The Hardware/Software Interface: RISC-V Edition

by David A. Patterson John L. Hennessy

留言

熱門文章