RISC-V GNU Toolchain 是一個用於在 x86_64 上建立 RISC-V 程式的 GNU Toolchain。SPIKE 是 RISC-V 的 Instruction Set Simulator (ISS),用以在 x86_64 上模擬 RISC-V 的指令集。Proxy Kernel 是一個用於在 SPIKE 上執行 RISC-V 程式的 Proxy Kernel。本文將紀錄筆者安裝 RISC-V GNU Toolchain、SPIKE 及 Proxy Kernel 的步驟。

安裝 RISC-V GNU Toolchain

本文根據 RISC-V GNU Toolchain 官方文件1 的步驟,示範在 Ubuntu 上安裝 RISC-V GNU Toolchain。

  1. 根據 Readme 的指示,先安裝相依套件

     sudo apt-get install autoconf automake autotools-dev curl python3 python3-pip python3-tomli libmpc-dev libmpfr-dev libgmp-dev gawk build-essential bison flex texinfo gperf libtool patchutils bc zlib1g-dev libexpat-dev ninja-build git cmake libglib2.0-dev libslirp-dev
    
  2. 將 RISC-V GNU Toolchain 的安裝路徑加入 PATH 環境變數

    本文示範將 RISC-V GNU Toolchain 安裝在 /opt/riscv 目錄下,並將其加入 PATH 環境變數中。

    在預設的情況下,/opt/riscv 目錄需要 root 權限才能寫入,因此在以下步驟中牽涉到 /opt/riscv 目錄的操作,可能需要使用 sudo 權限。以下將使用 [sudo] 來表示可能需要使用 sudo 權限的指令。

    ~/.bashrc~/.bash_profile 中加入以下設定

     export RISCV=/opt/riscv  # Path to install RISC-V toolchain
     export PATH=$PATH:$RISCV/bin
    

    記得重新載入設定,使設定生效

     source ~/.bashrc
    
  3. 取得 RISC-V GNU Toolchain 的原始碼,並進入目錄

     git clone https://github.com/riscv/riscv-gnu-toolchain
     cd riscv-gnu-toolchain
    
  4. 為了將編譯的生成檔案與原始碼分開,建立一個 build 目錄,我們將在這個目錄下進行編譯

     mkdir build && cd build
    
  5. 若您在 Ubuntu 20.04 上執行編譯,可能會遇到無法取得 Submodule 的問題2,如下所示

    Ubuntu 22.04 以後的版本請忽略此步驟

     error: Server does not allow request for unadvertised object 26f7004bf73c421c3fd5e5a6ccf470d05337b435
     Fetched in submodule path 'newlib', but it did not contain 26f7004bf73c421c3fd5e5a6ccf470d05337b435. Direct fetching of that commit failed.
     error: Server does not allow request for unadvertised object 23c84db5b3cb4e8a0d555c76e1a0ab56dc8355f3
     Fetched in submodule path 'gdb', but it did not contain 23c84db5b3cb4e8a0d555c76e1a0ab56dc8355f3. Direct fetching of that commit failed.
     error: Server does not allow request for unadvertised object 04696df09633baf97cdbbdd6e9929b9d472161d3
     Fetched in submodule path 'gcc', but it did not contain 04696df09633baf97cdbbdd6e9929b9d472161d3. Direct fetching of that commit failed.
    

    這是由於 Ubuntu 20.04 的 Git 版本 (2.25.1) 使用的預設 Git Protocol 為 v0,而自 Ubuntu 22.04 以後的 Git 版本所使用的預設 Git Protocol 為 v2,因此在 Ubuntu 20.04 上執行編譯時會遇到無法取得 Submodule 的問題。解決方法是將 Git Protocol 設為 v2

     [sudo] git config --global protocol.version 2
    

    在使用 make 進行編譯時使用 root 身份,會自動以 root的身份抓取 Submodule,因此需要在上方指令前加上 [sudo],修改 root 身份的 Git Protocol 設定

  6. 生成編譯設定檔

     ../configure --prefix=$RISCV
    
    • --prefix:指定安裝路徑,本文示範安裝在 /opt/riscv 目錄下
    • 32-bit 和 64-bit 編譯3
      • 預設編譯 RV64GC (64-bit)
      • 若要編譯 RV32GC (32-bit),則使用

        ../configure --prefix=$RISCV --with-arch=rv32gc --with-abi=ilp32
        
      • 若需要同時可以編譯 32-bit 和 64-bit RISC-V 程式,則使用 Multilib 選項 (本文會使用此選項)進行示範

        ../configure --prefix=$RISCV --enable-multilib
        
  7. 進行編譯

    Makefile 會在編譯後自動將 Toolchain 安裝在 $RISCV 目錄下,因此可能需要使用 sudo 權限進行安裝

    編譯 Newlib 的 Cross-Compiler

     [sudo] make -j$(nproc)
    

    編譯 Linux 的 Cross-Compiler

     [sudo] make linux -j$(nproc)
    

    使用 -j$(nproc) 參數可以加速編譯,將編譯工作分散到多個 CPU 核心上進行

    編譯完成後,會在 /opt/riscv/bin 目錄下看到編譯好的 RISC-V GNU Toolchain

安裝 SPIKE

SPIKE 是 RISC-V 的 Instruction Set Simulator (ISS),用以在 x86_64 上模擬 RISC-V 的指令集。在安裝完 SPIKE 後,我們可以使用 SPIKE 來執行 bare-metal 的 RISC-V 程式。

  1. 安裝相依套件

     sudo apt-get install device-tree-compiler libboost-regex-dev libboost-system-dev
    
  2. 取得 SPIKE 的原始碼

     git clone https://github.com/riscv-software-src/riscv-isa-sim.git
     cd riscv-isa-sim
    
  3. 建立 build 目錄,並進入該目錄以進行編譯

     mkdir build && cd build
    
  4. 生成編譯設定檔並進行編譯

     ../configure --prefix=$RISCV
     make -j$(nproc) # compile only
     [sudo] make install # install to /opt/riscv
    

安裝 Proxy Kernel

若 RISC-V 程式需要使用 System Call,則需要安裝 Proxy Kernel 來提供這些 System Call,並將其轉換成 SPIKE 可以理解的指令。

  1. 取得 Proxy Kernel 的原始碼,並進入目錄

     git clone https://github.com/riscv-software-src/riscv-pk.git
     cd riscv-pk
    
  2. 建立 build 目錄,並進入該目錄以進行編譯

     mkdir build && cd build
    
  3. 生成編譯設定檔並進行編譯

     ../configure --prefix=$RISCV --host=riscv64-unknown-elf
     make -j$(nproc)
     [sudo] make install
    

測試

  1. 撰寫一個簡單的 C 程式

     #include <stdio.h>
    
     int main() {
         printf("Hello, RISC-V!\n");
         return 0;
     }
    
  2. 編譯 C 程式

     riscv64-unknown-elf-gcc -o hello hello.c
    
  3. 執行編譯好的 RISC-V 程式

     spike pk hello
    

    若一切正常,應該可以看到 Hello, RISC-V! 的輸出

參考資料