contributed by < Risheng1128
>
參考 RISCOF - Introduction , RISCOF 是一個測試框架,主要是使用一系列的 RISC-V 組語測試檔來測試用硬體或是軟體實作的 RISC-V 處理器架構
而之前所使用的 riscv-arch-test 只能算是符合 RISC-V 架構的先決條件,通過這個測試並不能完全表示完全符合 RISC-V 的架構,因此這裡使用 RISCOF 可以做測試的交叉比對
可以開始來安裝 RISCOF 了,首先需要先安裝 python ,這裡使用的環境是 Ubuntu 20.04 ,而 python3 及 pip3 的版本如下所示,官方推薦的版本可以參考 Install Python
輸入以下命令安裝 RISCOF
使用命令 riscof --help
測試安裝是否成功,期望輸出如下
安裝 RISC-V toolchain ,這裡使用 riscv-gnu-toolchain ,安裝步驟如下
將 toolchain 加入到環境變數
安裝兩組 RISC-V 官方提供的 RISC-V 模擬器: SAIL 及 Spike ,以下是安裝 SAIL 的步驟,以這次的範例來說, Spike 為待測項且 SAIL 為參考項,以兩者的輸出相互對照,判斷是否會產生問題
接著安裝 Spike ,以下為安裝的步驟
安裝完後用命令 spike
測試有無安裝成功,以下為期望輸出
安裝一些檔案,詳細可參考 Create Neccesary Env Files
讓步驟簡化一點,可使用以下命令
會在目前的目錄產生以下的檔案結構
如果 SAIL 的檔案如 riscv_sim_RV32 沒有加到環境變數的話,在 config.ini
最後補上執行檔的目錄路徑,如下所示
接著繼續下載 architectural tests ,使用以下命令
經過了漫長的安裝,可以來執行 RISCOF 了,主要分成三個步驟,以下為第一個命令
期望輸出
接著使用以下命令產生要執行在模型上的測試檔列表
成功的話,會以以下輸出結束
測試檔列表可以在 riscof_work/test_list.yaml
中找到,以下為部份內容
最後一步是要對每個模組測試每個測試檔,並且判斷有無錯誤
最後可以看到測試的結果,以下擷取部份
到了這裡後就表示安裝成功!
參考 Understanding RISCOF Inputs 及 Building your Model Plugin 可以了解 RISCOF 的輸入代表什麼以及如何引入自己的模型
首先使用命令 riscof setup --refname=sail_cSim --dutname=rv32emu
建立對於 rv32emu 的設定檔,接著我們需要對建立的檔案進行修改,產生了以下的檔案結構
接著我們需要對檔案 riscof_rv32emu.py
進行修改,這個檔案就是用來設定編譯測試檔,並且執行 rv32emu 的檔案,第一步是先修改 rv32emu 執行檔的路徑,位於類別 class 的建立函式 __init__
,修改如下
在函式 build
裡,可以設定使用的編譯器,而這裡我選擇使用 riscv32-unknown-elf-gcc
,因此不需要做修改
接著在函式 build
有針對 spike 的輸入選項所做的實作,而我們的 rv32emu 不會使用到,因此可以移除
最後函式 runTests
裡,可以找到執行 rv32emu 的程式碼,而這裡需要改成 rv32emu 的輸入選項選項
接著很重要的一點,要記得修改預設的 rv32emu/env/model_test.h
的內容,這裡只要修改巨集 RVMODEL_HALT
即可,因為原本的實作會導致 rv32emu 進入無限迴圈
如此一來就可以正確的執行 rv32emu ,以下是 RISCOF 測試 rv32emu 後產生的測試報告
一共通過了 90 個測試資料,包含了 RV32IMC 、 Zifencei 及 privilege 的測試
以上測試的 riscv-arch-test 最新 commit 為 Merge pull request #286 from riscv-non-isa/clean-up ,於 2022/10/18 加入
雖然在 對 rv32emu 使用 RISCOF 通過了 90 個測試資料,但是所使用的 model_test.h
檔案是由 RISCOF 產生並且只修改修改巨集 RVMODEL_HALT
的部份,如果改成使用目前 rv32emu 所實作的檔案 model_test.h
,則會有以下的問題
發現 privilege 的 misaligned load 測試卻失敗了
要找到這個問題,先觀察兩者間檔案 model_test.h
的不同,可以發現 RISCOF 產生的檔案相比 rv32emu 多了以下的巨集 RVMODEL_DATA_SECTION
這個巨集除了新增 section .tohost
之外,也在 section .data
下加了 label begin_regstate
及 end_regstate
,同時這個巨集被放在巨集 RVMODEL_DATA_BEGIN
下,如下所示
從結果發現錯誤的部份是儲存暫存器 mtval
的部份,以下就利用反組譯研究 riscv-arch-test 儲存暫存器 mtval
的部份,以 misalign-lh
為例
由上述的程式碼,可以得知 riscv-arch-test 實際上是儲存 t2 - t3
的值
t2
: 暫存器 mtval
儲存的值,以 misaligned load 來說是發生 fault 的資料地址t3
: 經過測試後得知是 label mtrap_sigptr
的地址 (以這次的範例來說)接著回到反組譯的檔案,可以發現有無產生 label begin_regstate
及 end_regstate
其實是會導致 mtrap_sigptr
的地址不同,因此暫存器 t3
也會不同,也就導致了測試失敗
了解問題的原因,也得知不是模擬器的缺失,因此目前可以證明已經通過了 riscv-arch-test 的測試,測試版本為 Merge pull request #286 from riscv-non-isa/clean-up ,於 2022/10/18 加入
確定 rv32emu 可以通過最新版的 riscv-arch-test 後,可以將 rv32emu 裡原本的 riscv-arch-test 作更新的動作
在 commit Riscof dev 中,為了符合新的 RISCOF , riscv-arch-test 主要做了以下的更動
riscof_xxx.py
首先我們需要知道 RISCOF 的運作原理,簡單來說 RISCOF 是將待測物 (DUT) 及參考模型 (REF) 分別執行測試資料後將結果互相比較來決定測試是否通過的測試框架。其中最為重要的就是 config.ini
檔,裡頭包含了待測物以及參考模型的設定檔路徑,而設定檔的部份這邊著重在 ISA 的設定上,可以根據使用者的輸入來決定這次的測試要使用哪些指令集
config.ini
檔的部份可以參考範例,為 RISCOF 的通用版,而實際的結果可參考以下的範例,基本上就是紀錄待測物及參考模型會用到的檔案路徑
接著設定 ISA 的部份可以參考 model_isa.yaml ,而這次引入會修改 ISA 以及 misa
的數值,而在 RISCOF 裡預設的 ISA 為 RV32IMCZicsr_Zifencei
且 misa
(設定處理器支援的指令集) 的數值為 0x40001104
如下所示
而這裡 misa
的數值應該輸入多少,可以參考 Machine ISA Register ,以下為其 bit map
可以間單分成三個部份
MXL | XLEN |
---|---|
1 | 32 |
2 | 64 |
3 | 128 |
Bit | Character | Description |
---|---|---|
0 | A | Atomic extension |
1 | B | Tentatively reserved for Bit-Manipulation extension |
2 | C | Compressed extension |
3 | D | Double-precision floating-point extension |
4 | E | RV32E base ISA |
5 | F | Single-precision floating-point extension |
6 | G | Reserved |
7 | H | Hypervisor extension |
8 | I | RV32I/64I/128I base ISA |
9 | J | Tentatively reserved for Dynamically Translated Languages extension |
10 | K | Reserved |
11 | L | Tentatively reserved for Decimal Floating-Point extension |
12 | M | Integer Multiply/Divide extension |
13 | N | User-level interrupts supported |
14 | O | Reserved |
15 | P | Tentatively reserved for Packed-SIMD extension |
16 | Q | Quad-precision floating-point extension |
17 | R | Reserved |
18 | S | Supervisor mode implemented |
19 | T | Tentatively reserved for Transactional Memory extension |
20 | U | User mode implemented |
21 | V | Tentatively reserved for Vector extension |
22 | W | Reserved |
23 | X | Non-standard extensions present |
24 | Y | Reserved |
25 | Z | Reserved |
知道了以上的知識後,就可以來引入 RISCOF 了,目標是使用 riscof 讓 rv32emu 和 sail-riscv 分別執行 riscv-arch-test 並且互相比較,同時要保持原本 rv32emu 對於測試的實作,像是可指定要測試的指令集
這裡的解法是實作一個 python 檔,可以自動產生 config.ini
以及修改 ISA 設定檔,可參考 setup.py 的實作
而完整修改可以參考 Migrate to RISC-V Compatibility Framework (RISCOF)
RISCOF - The RISC-V Compatibility Framework
riscv-arch-test
riscv-tests