---
tags: 2022 computer architecture
---
# 使用 [RISCOF](https://riscof.readthedocs.io/en/latest/) 測試 [rv32emu](https://github.com/sysprog21/rv32emu)
contributed by < [`Risheng1128`](https://github.com/Risheng1128) >
## [RISCOF](https://riscof.readthedocs.io/en/latest/) - The RISC-V Compatibility Framework
參考 [RISCOF - Introduction](https://riscof.readthedocs.io/en/latest/intro.html) , RISCOF 是一個測試框架,主要是使用一系列的 RISC-V 組語測試檔來測試用硬體或是軟體實作的 RISC-V 處理器架構
而之前所使用的 [riscv-arch-test](https://github.com/riscv-non-isa/riscv-arch-test) 只能算是符合 RISC-V 架構的先決條件,通過這個測試並不能完全表示完全符合 RISC-V 的架構,因此這裡使用 RISCOF 可以做測試的交叉比對
### 環境設定
可以開始來安裝 RISCOF 了,首先需要先安裝 python ,這裡使用的環境是 Ubuntu 20.04 ,而 python3 及 pip3 的版本如下所示,官方推薦的版本可以參考 [Install Python](https://riscof.readthedocs.io/en/latest/installation.html#install-python)
```shell
$ python3 --version
Python 3.8.10
$ pip3 --version
pip 20.0.2 from /usr/lib/python3/dist-packages/pip (python 3.8)
```
輸入以下命令安裝 RISCOF
```
$ pip3 install git+https://github.com/riscv/riscof.git
```
使用命令 `riscof --help` 測試安裝是否成功,期望輸出如下
```shell
Usage: riscof [OPTIONS] COMMAND [ARGS]...
Options:
--version Show the version and exit.
-v, --verbose [info|error|debug]
Set verbose level
--help Show this message and exit.
Commands:
arch-test Setup and maintenance for Architectural TestSuite.
coverage Run the tests on DUT and reference and compare signatures
gendb Generate Database for the Suite.
run Run the tests on DUT and reference and compare signatures
setup Initiate Setup for riscof.
testlist Generate the test list for the given DUT and suite.
validateyaml Validate the Input YAMLs using riscv-config.
```
安裝 RISC-V toolchain ,這裡使用 [riscv-gnu-toolchain](https://github.com/riscv-collab/riscv-gnu-toolchain) ,安裝步驟如下
```shell
$ sudo apt-get install autoconf automake autotools-dev curl python3 libmpc-dev libmpfr-dev libgmp-dev gawk build-essential bison flex texinfo gperf libtool patchutils bc zlib1g-dev libexpat-dev
$ git clone --recursive https://github.com/riscv/riscv-gnu-toolchain
$ git clone --recursive https://github.com/riscv/riscv-opcodes.git
$ cd riscv-gnu-toolchain
$ ./configure --prefix=/path/to/install --with-arch=rv32gc --with-abi=ilp32d # for 32-bit toolchain
$ [sudo] make # sudo is required depending on the path chosen in the previous setup
```
將 toolchain 加入到環境變數
```
$ vim ~/.bashrc
# 在最後一行加入
export PATH=$PATH:/path/to/install/bin
```
安裝兩組 RISC-V 官方提供的 RISC-V 模擬器: [SAIL](https://github.com/riscv/sail-riscv) 及 [Spike](https://github.com/riscv-software-src/riscv-isa-sim) ,以下是安裝 SAIL 的步驟,以這次的範例來說, Spike 為待測項且 SAIL 為參考項,以兩者的輸出相互對照,判斷是否會產生問題
```
$ sudo apt-get install opam build-essential libgmp-dev z3 pkg-config zlib1g-dev
$ opam init -y --disable-sandboxing
$ opam switch create ocaml-base-compiler.4.06.1
$ opam install sail -y
$ eval $(opam config env)
$ git clone https://github.com/riscv/sail-riscv.git
$ cd sail-riscv
$ make
$ ARCH=RV32 make
$ ARCH=RV64 make
$ [sudo] ln -s sail-riscv/c_emulator/riscv_sim_RV64 /usr/bin/riscv_sim_RV64
$ [sudo] ln -s sail-riscv/c_emulator/riscv_sim_RV32 /usr/bin/riscv_sim_RV32
```
接著安裝 Spike ,以下為安裝的步驟
```
$ sudo apt-get install device-tree-compiler
$ git clone https://github.com/riscv-software-src/riscv-isa-sim.git
$ cd riscv-isa-sim
$ mkdir build
$ cd build
$ ../configure --prefix=/path/to/install/spike
$ make
$ [sudo] make install #sudo is required depending on the path chosen in the previous setup
```
安裝完後用命令 `spike` 測試有無安裝成功,以下為期望輸出
```shell
Spike RISC-V ISA Simulator 1.1.1-dev
usage: spike [host options] <target program> [target options]
Host Options:
-p<n> Simulate <n> processors [default 1]
-m<n> Provide <n> MiB of target memory [default 2048]
-m<a:m,b:n,...> Provide memory regions of size m and n bytes
at base addresses a and b (with 4 KiB alignment)
-d Interactive debug mode
...
```
安裝一些檔案,詳細可參考 [Create Neccesary Env Files](https://riscof.readthedocs.io/en/latest/installation.html)
讓步驟簡化一點,可使用以下命令
```
$ riscof setup --dutname=spike
```
會在目前的目錄產生以下的檔案結構
```
├──config.ini # configuration file for riscof
├──spike/ # DUT plugin templates
├── env
│ ├── link.ld # DUT linker script
│ └── model_test.h # DUT specific header file
├── riscof_spike.py # DUT python plugin
├── spike_isa.yaml # DUT ISA yaml based on riscv-config
└── spike_platform.yaml # DUT Platform yaml based on riscv-config
├──sail_cSim/ # reference plugin templates
├── env
│ ├── link.ld # Reference linker script
│ └── model_test.h # Reference model specific header file
├── __init__.py
└── riscof_sail_cSim.py # Reference model python plugin.
```
如果 SAIL 的檔案如 riscv_sim_RV32 沒有加到環境變數的話,在 `config.ini` 最後補上執行檔的目錄路徑,如下所示
```
path=/home/benson/riscvof/sail-riscv/c_emulator/
```
接著繼續下載 architectural tests ,使用以下命令
```
$ riscof --verbose info arch-test --clone
```
經過了漫長的安裝,可以來執行 RISCOF 了,主要分成三個步驟,以下為第一個命令
```
$ riscof validateyaml --config=config.ini
```
期望輸出
```shell
INFO | ****** RISCOF: RISC-V Architectural Test Framework 1.25.2 *******
INFO | using riscv_isac version : 0.15.0
INFO | using riscv_config version : 3.4.0
INFO | Reading configuration from: /home/benson/config.ini
INFO | Preparing Models
INFO | Input-ISA file
INFO | Loading input file: /home/benson/spike/spike_isa.yaml
INFO | Load Schema /home/benson/.local/lib/python3.8/site-packages/riscv_config/schemas/schema_isa.yaml
INFO | Processing Hart: hart0
INFO | Initiating Validation
INFO | No errors for Hart: 0 :)
INFO | Initiating WARL legality checks.
INFO | Initiating post processing and reset value checks.
INFO | Performing Checks on PMP CSRs
INFO | Dumping out Normalized Checked YAML: /home/benson/riscof_work/spike_isa_checked.yaml
INFO | Input-Platform file
INFO | Loading input file: /home/benson/spike/spike_platform.yaml
INFO | Load Schema /home/benson/.local/lib/python3.8/site-packages/riscv_config/schemas/schema_platform.yaml
INFO | Initiating Validation
INFO | No Syntax errors in Input Platform Yaml. :)
INFO | Dumping out Normalized Checked YAML: /home/benson/riscof_work/spike_platform_checked.yaml
```
接著使用以下命令產生要執行在模型上的測試檔列表
```
$ riscof testlist --config=config.ini --suite=riscv-arch-test/riscv-test-suite/ --env=riscv-arch-test/riscv-test-suite/env
```
成功的話,會以以下輸出結束
```shell
[INFO] : Selecting Tests.
```
測試檔列表可以在 `riscof_work/test_list.yaml` 中找到,以下為部份內容
```shell
suite/rv32i_m/C/C-ADD.S:
work_dir: /scratch/git-repo/incoresemi/riscof/riscof_work/rv32i_m/C/C-ADD.S
macros: [TEST_CASE_1=True, XLEN=32]
isa: RV32IC
test_path: /home/neel/.pyenv/versions/3.7.0/envs/venv/lib/python3.7/site-packages/riscof/suite/rv32i_m/C/C-ADD.S
suite/rv32i_m/C/C-ADDI.S:
work_dir: /scratch/git-repo/incoresemi/riscof/riscof_work/rv32i_m/C/C-ADDI.S
macros: [TEST_CASE_1=True, XLEN=32]
isa: RV32IC
test_path: /home/neel/.pyenv/versions/3.7.0/envs/venv/lib/python3.7/site-packages/riscof/suite/rv32i_m/C/C-ADDI.S
suite/rv32i_m/C/C-ADDI16SP.S:
work_dir: /scratch/git-repo/incoresemi/riscof/riscof_work/rv32i_m/C/C-ADDI16SP.S
macros: [TEST_CASE_1=True, XLEN=32]
isa: RV32IC
...
```
最後一步是要對每個模組測試每個測試檔,並且判斷有無錯誤
```
$ riscof run --config=config.ini --suite=riscv-arch-test/riscv-test-suite/ --env=riscv-arch-test/riscv-test-suite/env
```
最後可以看到測試的結果,以下擷取部份
```shell
INFO | /home/benson/riscvof/riscv-arch-test/riscv-test-suite/rv32i_m/Zifencei/src/Fencei.S : ff9358edda915263426801f485b5be24f788862c : Passed
INFO | /home/benson/riscvof/riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/ebreak.S : 0e77784916ed9c07842883ba6c62db2555a8335f : Passed
INFO | /home/benson/riscvof/riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/ecall.S : 2c53665403e472c95f81e23bf4351ee5c8bd0990 : Passed
INFO | /home/benson/riscvof/riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/misalign-beq-01.S : 6ba8712973dade81eaf1182d1050e5799a7ef2a0 : Passed
INFO | /home/benson/riscvof/riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/misalign-bge-01.S : 6ba8712973dade81eaf1182d1050e5799a7ef2a0 : Passed
INFO | /home/benson/riscvof/riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/misalign-bgeu-01.S : 6ba8712973dade81eaf1182d1050e5799a7ef2a0 : Passed
INFO | /home/benson/riscvof/riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/misalign-blt-01.S : 6ba8712973dade81eaf1182d1050e5799a7ef2a0 : Passed
INFO | /home/benson/riscvof/riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/misalign-bltu-01.S : 6ba8712973dade81eaf1182d1050e5799a7ef2a0 : Passed
INFO | /home/benson/riscvof/riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/misalign-bne-01.S : 6ba8712973dade81eaf1182d1050e5799a7ef2a0 : Passed
INFO | /home/benson/riscvof/riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/misalign-jal-01.S : 6ba8712973dade81eaf1182d1050e5799a7ef2a0 : Passed
INFO | /home/benson/riscvof/riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/misalign-lh-01.S : 6ba8712973dade81eaf1182d1050e5799a7ef2a0 : Passed
INFO | /home/benson/riscvof/riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/misalign-lhu-01.S : 6ba8712973dade81eaf1182d1050e5799a7ef2a0 : Passed
INFO | /home/benson/riscvof/riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/misalign-lw-01.S : 6ba8712973dade81eaf1182d1050e5799a7ef2a0 : Passed
INFO | /home/benson/riscvof/riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/misalign-sh-01.S : 6ba8712973dade81eaf1182d1050e5799a7ef2a0 : Passed
INFO | /home/benson/riscvof/riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/misalign-sw-01.S : 6ba8712973dade81eaf1182d1050e5799a7ef2a0 : Passed
INFO | /home/benson/riscvof/riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/misalign1-jalr-01.S : 6ba8712973dade81eaf1182d1050e5799a7ef2a0 : Passed
INFO | /home/benson/riscvof/riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/misalign2-jalr-01.S : 6ba8712973dade81eaf1182d1050e5799a7ef2a0 : Passed
```
到了這裡後就表示安裝成功!
### 藉由 RISCOF 使用 riscv-arch-test 測試 rv32emu
參考 [Understanding RISCOF Inputs](https://riscof.readthedocs.io/en/stable/inputs.html) 及 [Building your Model Plugin](https://riscof.readthedocs.io/en/stable/plugins.html) 可以了解 RISCOF 的輸入代表什麼以及如何引入自己的模型
首先使用命令 `riscof setup --refname=sail_cSim --dutname=rv32emu` 建立對於 rv32emu 的設定檔,接著我們需要對建立的檔案進行修改,產生了以下的檔案結構
```
├──config.ini # configuration file for riscof
├──rv32emu/ # DUT plugin templates
├── env
│ ├── link.ld # DUT linker script
│ └── model_test.h # DUT specific header file
├── riscof_rv32emu.py # DUT python plugin
├── rv32emu_isa.yaml # DUT ISA yaml based on riscv-config
└── rv32emu_platform.yaml # DUT Platform yaml based on riscv-config
├──sail_cSim/ # reference plugin templates
├── env
│ ├── link.ld # Reference linker script
│ └── model_test.h # Reference model specific header file
├── __init__.py
└── riscof_sail_cSim.py # Reference model python plugin.
```
接著我們需要對檔案 `riscof_rv32emu.py` 進行修改,這個檔案就是用來設定編譯測試檔,並且執行 rv32emu 的檔案,第一步是先修改 rv32emu 執行檔的路徑,位於類別 class 的建立函式 `__init__` ,修改如下
```diff
# In case of an RTL based DUT, this would be point to the final binary executable of your
# test-bench produced by a simulator (like verilator, vcs, incisive, etc). In case of an iss or
# emulator, this variable could point to where the iss binary is located. If 'PATH variable
# is missing in the config.ini we can hardcode the alternate here.
- self.dut_exe = os.path.join(config['PATH'] if 'PATH' in config else "","rv32emu")
+ self.dut_exe = '/home/benson/rv32emu/build/rv32emu'
```
在函式 `build` 裡,可以設定使用的編譯器,而這裡我選擇使用 `riscv32-unknown-elf-gcc` ,因此不需要做修改
```python
# Note the march is not hardwired here, because it will change for each
# test. Similarly the output elf name and compile macros will be assigned later in the
# runTests function
self.compile_cmd = 'riscv{1}-unknown-elf-gcc -march={0} \
-static -mcmodel=medany -fvisibility=hidden -nostdlib -nostartfiles -g\
-T '+self.pluginpath+'/env/link.ld\
-I '+self.pluginpath+'/env/\
-I ' + archtest_env + ' {2} -o {3} {4}'
```
接著在函式 `build` 有針對 spike 的輸入選項所做的實作,而我們的 rv32emu 不會使用到,因此可以移除
```diff
- # for rv32emu start building the '--isa' argument. the self.isa is dutnmae specific and may not be
- # useful for all DUTs
- self.isa = 'rv' + self.xlen
- if "I" in ispec["ISA"]:
- self.isa += 'i'
- if "M" in ispec["ISA"]:
- self.isa += 'm'
- if "F" in ispec["ISA"]:
- self.isa += 'f'
- if "D" in ispec["ISA"]:
- self.isa += 'd'
- if "C" in ispec["ISA"]:
- self.isa += 'c'
```
最後函式 `runTests` 裡,可以找到執行 rv32emu 的程式碼,而這裡需要改成 rv32emu 的輸入選項選項
```diff
# set up the simulation command. Template is for spike. Please change.
- simcmd = self.dut_exe + ' --isa={0} +signature={1} +signature-granularity=4 {2}'.format(self.isa, sig_file, elf)
# 等同於 「 rv32emu 執行檔路徑 --arch-test 輸出檔路徑 輸入執行檔路徑 」
+ simcmd = self.dut_exe + ' --arch-test {0} {1}'.format(sig_file, elf)
```
接著很重要的一點,要記得修改預設的 `rv32emu/env/model_test.h` 的內容,這裡只要修改巨集 `RVMODEL_HALT` 即可,因為原本的實作會導致 rv32emu 進入無限迴圈
```diff
#define RVMODEL_HALT \
- li x1, 1; \
- write_tohost: \
- sw x1, tohost, t5; \
- j write_tohost;
+ add a7, x0, 93; \
+ add a0, x0, 0; \
+ ecall
```
如此一來就可以正確的執行 rv32emu ,以下是 RISCOF 測試 rv32emu 後產生的測試報告
```
riscof run --config=config.ini --suite=riscv-arch-test/riscv-test-suite/ --env=riscv-arch-test/riscv-test-suite/env
```
{%youtube -epaesVZWtE%}
一共通過了 90 個測試資料,包含了 RV32IMC 、 Zifencei 及 privilege 的測試
:::info
以上測試的 [riscv-arch-test](https://github.com/riscv-non-isa/riscv-arch-test) 最新 commit 為 [Merge pull request #286 from riscv-non-isa/clean-up](https://github.com/riscv-non-isa/riscv-arch-test/commit/e4d1f3250e6371b730e36fb9106640901e605ae0) ,於 2022/10/18 加入
:::
### rv32emu 的實作缺失猜測
雖然在 [對 rv32emu 使用 RISCOF](#對-rv32emu-使用-RISCOF) 通過了 90 個測試資料,但是所使用的 `model_test.h` 檔案是由 RISCOF 產生並且只修改修改巨集 `RVMODEL_HALT` 的部份,如果改成使用目前 rv32emu 所實作的檔案 `model_test.h` ,則會有以下的問題
```shell
ERROR | /home/benson/riscvof/riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/misalign-lh-01.S : 6ba8712973dade81eaf1182d1050e5799a7ef2a0 : Failed
ERROR | /home/benson/riscvof/riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/misalign-lhu-01.S : 6ba8712973dade81eaf1182d1050e5799a7ef2a0 : Failed
ERROR | /home/benson/riscvof/riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/misalign-lw-01.S : 6ba8712973dade81eaf1182d1050e5799a7ef2a0 : Failed
```
發現 privilege 的 misaligned load 測試卻失敗了
要找到這個問題,先觀察兩者間檔案 `model_test.h` 的不同,可以發現 RISCOF 產生的檔案相比 rv32emu 多了以下的巨集 `RVMODEL_DATA_SECTION`
```c
#define RVMODEL_DATA_SECTION \
.pushsection .tohost,"aw",@progbits; \
.align 8; .global tohost; tohost: .dword 0; \
.align 8; .global fromhost; fromhost: .dword 0; \
.popsection; \
.align 8; .global begin_regstate; begin_regstate: \
.word 128; \
.align 8; .global end_regstate; end_regstate: \
.word 4;
```
這個巨集除了新增 section `.tohost` 之外,也在 section `.data` 下加了 label `begin_regstate` 及 `end_regstate` ,同時這個巨集被放在巨集 `RVMODEL_DATA_BEGIN` 下,如下所示
```c
#define RVMODEL_DATA_BEGIN \
RVMODEL_DATA_SECTION \
.align 4;\
.global begin_signature; begin_signature:`
```
從結果發現錯誤的部份是儲存暫存器 `mtval` 的部份,以下就利用反組譯研究 riscv-arch-test 儲存暫存器 `mtval` 的部份,以 `misalign-lh` 為例
```
80000400 <sv_mtval>:
80000400: 343023f3 csrr t2,mtval
80000404: 41c383b3 sub t2,t2,t3
80000408: 00732623 sw t2,12(t1)
```
由上述的程式碼,可以得知 riscv-arch-test 實際上是儲存 `t2 - t3` 的值
- `t2`: 暫存器 `mtval` 儲存的值,以 misaligned load 來說是發生 fault 的資料地址
- `t3`: 經過測試後得知是 label `mtrap_sigptr` 的地址 (以這次的範例來說)
接著回到反組譯的檔案,可以發現有無產生 label `begin_regstate` 及 `end_regstate` 其實是會導致 `mtrap_sigptr` 的地址不同,因此暫存器 `t3` 也會不同,也就導致了測試失敗
```
80001100 <begin_regstate>:
80001100: 0080 .2byte 0x80
...
80001200 <end_regstate>:
80001200: 0004 .2byte 0x4
...
80001210 <begin_signature>:
80001210: deadbeef jal t4,7ffdc7fa <value+0x7ffdc7ea>
80001214 <mtrap_sigptr>:
80001214: deadbeef jal t4,7ffdc7fe <value+0x7ffdc7ee>
```
了解問題的原因,也得知不是模擬器的缺失,因此目前可以證明已經通過了 riscv-arch-test 的測試,測試版本為 [Merge pull request #286 from riscv-non-isa/clean-up](https://github.com/riscv-non-isa/riscv-arch-test/commit/e4d1f3250e6371b730e36fb9106640901e605ae0) ,於 2022/10/18 加入
## 更新 rv32emu 裡的 riscv-arch-test
確定 rv32emu 可以通過最新版的 riscv-arch-test 後,可以將 rv32emu 裡原本的 riscv-arch-test 作更新的動作
- 舊版本: 分支 [old-framework-2.x](https://github.com/riscv-non-isa/riscv-arch-test/tree/old-framework-2.x)
- 新版本: 分支 [main](https://github.com/riscv-non-isa/riscv-arch-test/) 且 commit 為 [Merge pull request #302 from riscv-non-isa/canary-patch](https://github.com/riscv-non-isa/riscv-arch-test/commit/933ddddff896453dec83b6ca1ca2453b6f584d0b)
在 commit [Riscof dev](https://github.com/riscv-non-isa/riscv-arch-test/pull/255) 中,為了符合新的 RISCOF , riscv-arch-test 主要做了以下的更動
- 移除所有的 Makefile ,導致在原本 rv32emu 的實作中,呼叫 riscv-arch-test 的 Makefile 時會出現錯誤,因此需要實作新的檔案來編譯各種的測試檔,這裡參考 RISCOF 產生的檔案 `riscof_xxx.py`
- 移除所有的 Referece Signatures ,也就是參考的解答,改成由其他的模擬器作為參考提供
## 引入 RISCOF 到 rv32emu
首先我們需要知道 RISCOF 的運作原理,簡單來說 RISCOF 是將待測物 (DUT) 及參考模型 (REF) 分別執行測試資料後將結果互相比較來決定測試是否通過的測試框架。其中最為重要的就是 `config.ini` 檔,裡頭包含了待測物以及參考模型的設定檔路徑,而設定檔的部份這邊著重在 ISA 的設定上,可以根據使用者的輸入來決定這次的測試要使用哪些指令集
`config.ini` 檔的部份可以參考[範例](https://github.com/Risheng1128/riscof/blob/master/riscof/Templates/setup/config.ini),為 RISCOF 的通用版,而實際的結果可參考以下的範例,基本上就是紀錄待測物及參考模型會用到的檔案路徑
```
[RISCOF]
ReferencePlugin=sail_cSim
ReferencePluginPath=/home/benson/rv32emu/tests/arch-test-target/sail_cSim
DUTPlugin=rv32emu
DUTPluginPath=/home/benson/rv32emu/tests/arch-test-target/rv32emu
[rv32emu]
pluginpath=/home/benson/rv32emu/tests/arch-test-target/rv32emu
ispec=/home/benson/rv32emu/tests/arch-test-target/rv32emu/rv32emu_isa.yaml
pspec=/home/benson/rv32emu/tests/arch-test-target/rv32emu/rv32emu_platform.yaml
path=/home/benson/rv32emu/build
target_run=1
[sail_cSim]
pluginpath=/home/benson/rv32emu/tests/arch-test-target/sail_cSim
path=/home/benson/rv32emu/tests/arch-test-target/sail_cSim
```
接著設定 ISA 的部份可以參考 [model_isa.yaml](https://github.com/Risheng1128/riscof/blob/master/riscof/Templates/setup/model/model_isa.yaml) ,而這次引入會修改 ISA 以及 `misa` 的數值,而在 RISCOF 裡預設的 ISA 為 `RV32IMCZicsr_Zifencei` 且 `misa` (設定處理器支援的指令集) 的數值為 `0x40001104` 如下所示
```
hart_ids: [0]
hart0:
ISA: RV32IMCZicsr_Zifencei
physical_addr_sz: 32
User_Spec_Version: '2.3'
supported_xlen: [32]
misa:
reset-val: 0x40001104
...
```
而這裡 `misa` 的數值應該輸入多少,可以參考 [Machine ISA Register](https://www.five-embeddev.com/riscv-isa-manual/latest/machine.html) ,以下為其 bit map

可以間單分成三個部份
- MXL(Machine XLEN): 決定 XLEN 的數值
| MXL | XLEN |
| --- | ---- |
| 1 | 32 |
| 2 | 64 |
| 3 | 128 |
- Write/Read Only Legal Values (WLRL)
- Extensions: 設定支援的指令集
| 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](https://github.com/riscv/sail-riscv) 分別執行 riscv-arch-test 並且互相比較,同時要保持原本 rv32emu 對於測試的實作,像是可指定要測試的指令集
這裡的解法是實作一個 python 檔,可以自動產生 `config.ini` 以及修改 ISA 設定檔,可參考 [setup.py](https://github.com/sysprog21/rv32emu/blob/master/tests/arch-test-target/setup.py) 的實作
而完整修改可以參考 [Migrate to RISC-V Compatibility Framework (RISCOF)](https://github.com/sysprog21/rv32emu/commit/01b00b6f175f57ef39ffd1f4fa6a611891e36df3)
## 參考資料
[RISCOF - The RISC-V Compatibility Framework](https://riscof.readthedocs.io/en/latest/)
[riscv-arch-test](https://github.com/riscv-non-isa/riscv-arch-test)
[riscv-tests](https://github.com/riscv-software-src/riscv-tests)