owned this note
owned this note
Published
Linked with GitHub
# Computer Architecture 2023: Term Project
[](https://hackmd.io/HdMEALKjTnSFF_d7QE3ESw)
<!-- This is a HackMD text block with slime green background-->
:::success
## **Goal**
- [ ] 完成RISC-V Atom中所有examples的debug,確保所有example都能成功編譯、運行。這是首要目標,有助於驗證處理器的穩定性和正確性。
- [ ] 使用Verilator對RISC-V Atom進行驗證,確保支援Dhrystone等專案。這有助於確保處理器在實際應用中的正常運作。
- [ ] 嘗試實作RV32M指令集,並使用內建SCAR進行全面的RV32I/RV32M指令測試,確保實作的指令集符合標準。
- [ ] 詳細記錄整個過程,包括遇到的技術問題。可以透過GitHub提交issue,與原開發者討論問題。參與整個過程並最終貢獻RV32M或相關實作將是一個更有價值的結果。
:::
[](https://hackmd.io/HdMEALKjTnSFF_d7QE3ESw)
For HackMD viewers, note that this documentation is synchronized between [GitHub](https://github.com/coding-ray/2023-ca-term-atom/blob/master/docs/readme.md) and HackMD.
All the code related to this project is in the following two repositories.
1. [coding-ray/2023-ca-term-atom](https://github.com/coding-ray/2023-ca-term-atom): All documentation related to this project goes here.
1. [coding-ray/riscv-atom](https://github.com/coding-ray/riscv-atom): The implementation of the M extension for [saursin/riscv-atom](https://github.com/saursin/riscv-atom) goes here.
This document consists of the following sections.
1. [Environment setup](#Environment-Setup): Building and installing RISC-V GNU toolchain, and building RISC-V Atom in a Docker container.
1. [To-do list](#To-do-List): Pending tasks.
## Environment Setup
In this section, we will guide you through the building and installation of RISC-V GNU toolchain and Verilator from source in a Docker container. After that, there will be the building procedure of RISC-V Atom. These steps are also verified to be applicable inside or outside a virtual machine.
### Install Docker Engine
Primary reference: [Install Docker Engine on Ubuntu | Docker Docs](https://docs.docker.com/engine/install/ubuntu/)
Docker will be used to wrap the entire project in a container. The following steps apply to Ubuntu Jammy 22.04.3, but it should be easy to customize them in the other Debian-based distributions with bash as the shell.
1. Uninstall all conflicting packages.
```shell
for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do
if [ ! -z "$(apt list --installed $pkg 2>&1 | grep installed)" ]; then
sudo apt purge -y $pkg;
else
echo "Not installed: $pkg"
fi
done
```
One-line and simplified version: `echo docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc | xargs sudo apt purge y $p`
1. Allow `apt` to fetch a repository over HTTPS.
```shell
sudo apt update && sudo apt install -y ca-certificates curl gnupg
```
1. Add Docker’s official GPG key.
```shell
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
```
1. Set up the repository.
```shell
echo \
"deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
"$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
```
1. Install the latest Docker engine and Docker Compose.
```shell
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
```
1. Add the current user to the `docker` group to access Docker commands without `sudo`.
```shell
sudo usermod -aG docker $USER
```
1. Re-login to take the effect, or enter `newgrp docker` to apply the changes in the current terminal.
### Set up a Docker Container
1. Launch an Ubuntu Jammy 22.04.3 container, with hostname `ca-term-ubuntu` (arbitrary) and container name `ca-term-ubuntu` (arbitrary) in the background (`-d` to detach from it, and `sleep infinity` to keep it running).
```shell
docker run --rm -d \
--name ca-term-ubuntu \
--hostname ca-term-ubuntu \
ubuntu:jammy-20231211.1 \
sleep infinity
```
1. Attach to the container.
```shell
docker exec -it ca-term-ubuntu /bin/bash
```
1. Un-minimize the environment, and install the `man` command and its docs.
```shell
unminimize
apt update
apt install man-db
```
1. Set the time zone to Asia/Taipei. ([Reference: bash - apt-get install tzdata noninteractive - Stack Overflow](https://stackoverflow.com/a/44333806))
```shell
ln -fs /usr/share/zoneinfo/Asia/Taipei /etc/localtime
echo Asia/Taipei > /etc/timezone
apt install -y tzdata
```
1. In the container, create a normal user `ray` (arbitrary) with password `0` (arbitrary) in group `sudo` (to use `sudo` as user `ray`). Note that the following commands are executed in the container as `root`.
```shell
apt update
apt install -y sudo
useradd -m ray
chsh -s /bin/bash ray
echo "ray:0" | chpasswd
echo "root:0" | chpasswd
usermod -aG sudo ray
```
1. Leave the container, and login as `ray` (the same as previously created user).
```shell
exit
docker exec -u ray -w /home/ray -it ca-term-ubuntu /bin/bash
```
1. Remove the login message, and remove the warning message from `sudo`. (Reference: [Giving yourself a quieter SSH login](https://web.archive.org/web/20200924150633/https://debian-administration.org/article/546/Giving_yourself_a_quieter_SSH_login))
```shell
touch ~/.hushlogin ~/.sudo_as_admin_successful
```
1. In the future, to stop the container, run the following command. Docker will automatically remove the stopped container since we added `--rm` in `docker run` previously. To keep the content but stopping the container, remove `--rm` in `docker run`.
```shell
docker stop ca-term-ubuntu
```
### Build and Install Verilator from Source
1. Install the dependencies to build or run [Verilator](https://github.com/verilator/verilator) from source. Verilator will be used by Atomsim to Verilate Verilog RTL into C++. (Primary reference: [Installation — Verilator Devel 5.021 documentation](https://veripool.org/guide/latest/install.html#package-manager-quick-install))
```shell
sudo apt install -y git help2man perl python3 make autoconf g++ flex bison ccache
sudo apt install -y libgoogle-perftools-dev numactl perl-doc
# Ubuntu only
sudo apt install libfl2 libfl-dev
# Ubuntu only (ignore since it gives error)
# sudo apt install zlibc zlib1g zlib1g-dev
```
1. Clone Verilator into `~/verilator`.
```shell
git clone https://github.com/verilator/verilator ~/verilator
cd ~/verilator
```
1. Build Verilator from the `stable` branch.
```shell
unset VERILATOR_ROOT
git pull # get the latest content
git checkout stable
autoconf # create ./configure script
./configure # configure and create Makefile
make -j `nproc`
make test # make sure all tests passes before continuing
```
1. Install Verilator, and check its version.
```shell
sudo make install
verilator --version
```
### Build and Install RISC-V GNU Toolchain from Source
1. Compile and install RISC-V GNU toolchain from source, for we found the script `install-toolchain.sh` provided by RISC-V Atom is buggy. The `configure` command targets RV64GC with glibc by default, so `--with-arch=rv64gc` is redundant. The entire repo (with its submodules and compiled objects) takes around 14 GiB of disk space, so be aware of the free spaces on the disk. After you issue `time make`, take a break. It took me 45 minutes.
```shell
git clone https://github.com/riscv/riscv-gnu-toolchain ~/toolchain
cd ~/toolchain
sudo apt install -y autoconf automake autotools-dev curl python3 python3-pip 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
./configure --prefix="$HOME/.local/share/riscv-gnu-toolchain" --enable-multilib
time make -j `nproc`
```
1. Add the binaries of the toolchain to PATH.
```shell
echo "export PATH=\"\$HOME/.local/share/riscv-gnu-toolchain/bin:\$PATH\"" >> ~/.bashrc
source ~/.bashrc
```
1. Check the version of `gcc` in the toolchain.
```shell
riscv64-unknown-elf-gcc --version
```
### Install the Other Dependencies of RISC-V Atom
Primary reference: [riscv-collab/riscv-gnu-toolchain: GNU toolchain for RISC-V, including GCC](https://github.com/riscv-collab/riscv-gnu-toolchain)
1. Install the dependencies to build or run RISC-V Atom. For more info about these packages, please check the official documentation provided above.
```shell
sudo apt install -y git python3 build-essential gtkwave screen libreadline-dev
```
1. Install the required Python packages. This step is not documented, but without the packages in `requirements.txt`, we cannot build the AtomSim simulator.
```shell
wget -O - https://raw.githubusercontent.com/saursin/riscv-atom/main/requirements.txt | xargs pip install
```
1. Add `~/.local/bin/` to path as the warning from `pip` instructs.
```shell
echo "export PATH=\"\$HOME/.local/bin:\$PATH\"" >> ~/.bashrc
source ~/.bashrc
```
### Build RISC-V Atom
Primary reference: [Building RISC-V Atom — RISC-V Atom v1.2 documentation](https://riscv-atom.readthedocs.io/en/latest/pages/getting_started/building.html)
1. Clone RISC-V Atom into ~/riscv-atom.
```shell
git clone https://github.com/saursin/riscv-atom.git ~/riscv-atom
cd ~/riscv-atom
```
1. Set the environment variables, and allow them to be automatically set on login.
```shell
source sourceme
echo -e "# set environment variables for RISC-V Atom\nsource \"$(pwd)/sourceme\"" >> ~/.bashrc
```
1. Build the AtomSim simulator.
```shell
make soctarget=atombones
```
1. Verify the build.
```shell
which atomsim
atomsim --help
```
1. Run through all examples. (Fixme: failed on lots of tests)
```shell
make soctarget=atombones run-all
```
## Collaboration on Both GitHub and HackMD
With some changes on HackMD, to synchronize changes from HackMD to GitHub, do the following steps.
1. Browse our [documentation on HackMD](https://hackmd.io/HdMEALKjTnSFF_d7QE3ESw). Desktop view of the HackMD page is easier to view than mobile view.
1. On the top right corner, click `...`, and the select `Versions and GitHub Sync`.
.
1. On the top right corner of the popup window, click `Push`.

1. Select a branch to commit changes. `develop` is more recommended than `master`.
1. Enter proper commit title and message according to [docs/commit-convention.md](commit-convention.md) and the changes.
To synchronize changes from GitHub to HackMD, follow the steps above, but click `Pull` instead in the popup window.

## **RISC-V Atom (Core)**
**RISCV-Atom** is an open-source 32-bit soft-core processor implemented in Verilog. It follows an embedded-class processor architecture and incorporates the open-source RISC-V instruction set architecture (RV32I), as outlined in the RISC-V unprivileged specification. Atom features a two-stage pipeline inspired by the ARM Cortex M0+.
The architecture of the RISC-V Atom core is illustrated in the following diagram.

The processor pipeline consists of two stages:
**Stage-1 Fetch :**
Responsible for fetching instructions from memory using the Instruction Bus. The Program Counter keeps track of the instruction address, incrementing by 4 after a successful fetch.
**Stage-2 Decode :**
Execute & Write-back
Decodes instructions, configures the data path for execution, fetches registers, generates a 32-bit immediate value, and executes the instruction using the ALU. Results are written back to the register file. Branch calculations occur here, with pipeline flushing if a branch is taken. The Comparator module handles comparison instructions like slt, slti, beq, bltu, etc.
## **Fix examples**
We found that several examples can't compile or run sucessfully. So, we fix the examples first.
### hello-asm
When we run the hello-asm for the first time, the following issue arises:
```clike!
Runtime exception: memory fetch failed: no mem block at given address (0x08000000)
```
After checking the map.lst, we did following modify:
```diff!
.global main
.text
#ifdef TARGET_ATOMBONES
+.equ TX_ADDRESS, 0x40000000
-.equ TX_ADDRESS, 0x08000000
#else
+.equ TX_ADDRESS, 0x08000000
-.equ TX_ADDRESS, 0x40000000
#endif
main:
la a0, msg
jal putstr
ebreak
...
```
Result :
```diff!
risv-atom@ubuntu:~/riscv-atom/sw/examples$ make soctarget=atombones ex=hello-asm run
► Running hello-asm/hello.elf
atomsim --maxitr=999999999 -uv hello-asm/hello.elf
___ __ _____
/ _ |/ /____ __ _ / __(_)_ _
/ __ / __/ _ \/ ' \_\ \/ / ' \
/_/ |_\__/\___/_/_/_/___/_/_/_/_/ v2.2
soctarget: atombones
Initializing bootrom
Loading 36 bytes at 0x00010000 from /home/risv-atom/riscv-atom/sw/bootloader/bootloader.hex
Initializing ram:
Loading segment 1 [base=0x20000000, sz= 5676 bytes, at=0x20000000] ... done
Loading segment 2 [base=0x2000162c, sz= 160 bytes, at=0x2000162c] ... done
Relaying uart-rx to stdout (Note: This mode does not support uart-tx)
Initialization complete!
----------8<-----------8<-----------8<-----------8<---------
Hello World!
-- from Assembly
EBreak hit at 0x20000148
Exiting..
```
## **Implement M extension**
To implement `M extension` in `riscv-atom`, we have to change the rtl code in `riscv-atom/rtl/core`. In [RISCV Instruction Set Manual](https://riscv.org/wp-content/uploads/2017/05/riscv-spec-v2.2.pdf), you can find the description of the M extension, including the strategy for handling division by zero and overflow.

### Modify `Defs.vh`
To include instructions for the `M extension`, different ALU operations are represented with four bits in the definition.
``` diff
// ALU
-`define ALU_FUNC_ADD 3'd0
-`define ALU_FUNC_SUB 3'd1
-`define ALU_FUNC_XOR 3'd2
-`define ALU_FUNC_OR 3'd3
-`define ALU_FUNC_AND 3'd4
-`define ALU_FUNC_SLL 3'd5
-`define ALU_FUNC_SRL 3'd6
-`define ALU_FUNC_SRA 3'd7
+`define ALU_FUNC_ADD 4'd0
+`define ALU_FUNC_SUB 4'd1
+`define ALU_FUNC_XOR 4'd2
+`define ALU_FUNC_OR 4'd3
+`define ALU_FUNC_AND 4'd4
+`define ALU_FUNC_SLL 4'd5
+`define ALU_FUNC_SRL 4'd6
+`define ALU_FUNC_SRA 4'd7
// ALU M extension
+`define ALU_FUNC_MUL 4'd8
+`define ALU_FUNC_MULH 4'd9
+`define ALU_FUNC_MULHSU 4'd10
+`define ALU_FUNC_MULHU 4'd11
+`define ALU_FUNC_DIV 4'd12
+`define ALU_FUNC_DIVU 4'd13
+`define ALU_FUNC_REM 4'd14
+`define ALU_FUNC_REMU 4'd15
```
### Modify `Decode.v`
The instructions in the image below pertain to the `M extension`, and they all fall under the R-type category. To enable the decoder to understand these instructions, refer to the machine code definitions in the table for the corresponding RTL code

```diff
+ /* MUL */
+ 17'b0100001_000_0110011:
+ begin
+ instr_scope = "MUL";
+ rf_we_o = 1'b1;
+ rf_din_sel_o = 3'd2;
+ a_op_sel_o = 1'b0;
+ b_op_sel_o = 1'b0;
+ alu_op_sel_o = `ALU_FUNC_MUL;
+ end
+
+ /* MULH */
+ 17'b0100001_001_0110011:
+ begin
+ instr_scope = "MULH";
+ rf_we_o = 1'b1;
+ rf_din_sel_o = 3'd2;
+ a_op_sel_o = 1'b0;
+ b_op_sel_o = 1'b0;
+ alu_op_sel_o = `ALU_FUNC_MULH;
+ end
+
+ /* MULHSU */
+ 17'b0100001_010_0110011:
+ begin
+ instr_scope = "MULHSU";
+ rf_we_o = 1'b1;
+ rf_din_sel_o = 3'd2;
+ a_op_sel_o = 1'b0;
+ b_op_sel_o = 1'b0;
+ alu_op_sel_o = `ALU_FUNC_MULHSU;
+ end
+
+ /* MULHU */
+ 17'b0100001_011_0110011:
+ begin
+ instr_scope = "MULHU";
+ rf_we_o = 1'b1;
+ rf_din_sel_o = 3'd2;
+ a_op_sel_o = 1'b0;
+ b_op_sel_o = 1'b0;
+ alu_op_sel_o = `ALU_FUNC_MULHU;
+ end
+
+ /* DIV */
+ 17'b0100001_100_0110011:
+ begin
+ instr_scope = "DIV";
+ rf_we_o = 1'b1;
+ rf_din_sel_o = 3'd2;
+ a_op_sel_o = 1'b0;
+ b_op_sel_o = 1'b0;
+ alu_op_sel_o = `ALU_FUNC_DIV;
+ end
+
+ /* DIVU */
+ 17'b0100001_101_0110011:
+ begin
+ instr_scope = "DIVU";
+ rf_we_o = 1'b1;
+ rf_din_sel_o = 3'd2;
+ a_op_sel_o = 1'b0;
+ b_op_sel_o = 1'b0;
+ alu_op_sel_o = `ALU_FUNC_DIVU;
+ end
+
+ /* REM */
+ 17'b0100001_110_0110011:
+ begin
+ instr_scope = "REM";
+ rf_we_o = 1'b1;
+ rf_din_sel_o = 3'd2;
+ a_op_sel_o = 1'b0;
+ b_op_sel_o = 1'b0;
+ alu_op_sel_o = `ALU_FUNC_REM;
+ end
+
+ /* REMU */
+ 17'b0100001_111_0110011:
+ begin
+ instr_scope = "REMU";
+ rf_we_o = 1'b1;
+ rf_din_sel_o = 3'd2;
+ a_op_sel_o = 1'b0;
+ b_op_sel_o = 1'b0;
+ alu_op_sel_o = `ALU_FUNC_REMU;
+ end
```
Also, change the `alu_op_sel` due to the adding one bit in `Defs.vh`
```diff=
-output reg [2:0] alu_op_sel_o,
+output reg [3:0] alu_op_sel_o,
```
### Modify `AtomRV.v`
change the wire `d-alu_op_sel` to 4 bit.
```diff
////// Instruction Decode //////
Instruction decode unit decodes instruction and sets various control
signals throughout the pipeline. Is also extracts immediate values
from instructions and sign extends them properly.
*/
wire [4:0] d_rd_sel;
wire [4:0] d_rs1_sel;
wire [4:0] d_rs2_sel;
wire [31:0] d_imm;
wire d_jump_en;
wire [2:0] d_comparison_type;
wire d_rf_we;
wire [2:0] d_rf_din_sel;
wire d_a_op_sel;
wire d_b_op_sel;
wire d_cmp_b_op_sel;
- wire [2:0] d_alu_op_sel;
+ wire [3:0] d_alu_op_sel;
wire [2:0] d_mem_access_width;
wire d_mem_load_store;
wire d_mem_we;
```
### Modify `alu.v`
Modify the input wire `sel_i` to be 4 bits and then integrate the circuitry to execute each instruction in the `M extension`
```diff
(
input wire [31:0] a_i,
input wire [31:0] b_i,
- input wire [2:0] sel_i,
+ input wire [3:0] sel_i,
output reg [31:0] result_o
);
+/////// m extension
+ wire sel_mul = (sel_i == `ALU_FUNC_MUL);
+ wire sel_mulh = (sel_i == `ALU_FUNC_MULH);
+ wire sel_mulhsu = (sel_i == `ALU_FUNC_MULHSU);
+ wire sel_mulhu = (sel_i == `ALU_FUNC_MULHU);
+ wire sel_div = (sel_i == `ALU_FUNC_DIV);
+ wire sel_divu = (sel_i == `ALU_FUNC_DIVU);
+ wire sel_rem = (sel_i == `ALU_FUNC_REM);
+ wire sel_remu = (sel_i == `ALU_FUNC_REMU);
+ /////// result of m extension
+ reg [63:0] mul_result;
+ reg [31:0] div_result;
+ reg [31:0] rem_result;
+ //mul,mulh,mulhsu,mulhu
+ always @(*) begin
+ if (sel_mul)
+ mul_result = $signed(a_i) * $signed(b_i);
+ else if (sel_mulhu)
+ mul_result = (a_i)*(b_i);
+ else if (sel_mulhsu)
+ mul_result = $signed(a_i)* (b_i);
+ else if (sel_mulh)
+ mul_result = $signed(a_i) * $signed(b_i);
+ else
+ mul_result= 64'h0 ;
+ end
+ //div divu
+ always @(*) begin
+ if (sel_div)
+ div_result = (b_i == 32'h0) ? 32'hffffffff:
+ (a_i == 32'h80000000 && b_i == 32'hffffffff) ? 32'h80000000:
+ $signed(a_i) / $signed(b_i);
+ else if (sel_divu)
+ div_result = (b_i == 32'h0) ? 32'hffffffff:
+ $unsigned($unsigned(a_i) / $unsigned(b_i));
+ else
+ div_result= 32'h0;
+ end
+ //rem remu
+ always @(*) begin
+ if (sel_rem)
+ rem_result = (b_i == 32'h0) ? a_i:
+ (a_i == 32'h80000000 && b_i == 32'hffffffff) ? 32'h0:
+ $signed(a_i) % $signed(b_i);
+ else if (sel_remu)
+ rem_result = (b_i == 32'h0) ? a_i:
+ $unsigned($unsigned(a_i) % $unsigned(b_i));
+ else
+ rem_result= 32'h0;
+ end
// output of universal shifter
reg [31:0] final_shift_output;
always @(*) begin
if (sel_sll)
final_shift_output = reverse(shift_output[31:0]);
else
final_shift_output = shift_output[31:0];
end
// Final output mux
always @(*) begin
if (sel_add | sel_sub)
result_o = arith_result;
else if (sel_sll | sel_srl | sel_sra)
result_o = final_shift_output;
else if (sel_xor)
result_o = a_i ^ b_i;
else if (sel_or)
result_o = a_i | b_i;
else if (sel_and)
result_o = a_i & b_i;
+ else if (sel_mul)
+ result_o = mul_result[31:0];
+ else if (sel_mulhu | sel_mulh | sel_mulhsu)
+ result_o = mul_result[63:32];
+ else if (sel_div | sel_divu)
+ result_o = div_result;
+ else if (sel_rem | sel_remu)
+ result_o = rem_result;
else
result_o = arith_result;
end
```
### M extension test
In `riscv-atom/test/scar`, the original author has already provided the environment to verify processor implementation.
[SCAR: Search Compile Assert Run](https://riscv-atom.readthedocs.io/en/latest/pages/documentation/scar.html#scar-search-compile-assert-run)
> SCAR performs a set of assembly level tests to verify the processor implementation. Each assembly test checks for one particular functionality of the processor. SCAR does this by examining a state dump file after the processor is done with executing a test code. This state dump file then checked assuming a set of assertions in the form of expected register values. These assertions are provided in the assembly file itself. SCAR is also used to verify the ISA-compliance.
```
$ cd test/scar
$ make
```
If all tests pass, the report should be as follows.
```verilog
+------------------------------------------------------------------------------+
| SCAR Verification Report |
+------------------------------------------------------------------------------+
Date: 2024-01-14 11:19:16
0). add64 - Passed All Assertions Passed
1). addi - Passed All Assertions Passed
2). add - Passed All Assertions Passed
3). andi - Passed All Assertions Passed
4). and - Passed All Assertions Passed
5). auipc - Passed All Assertions Passed
6). beq - Passed All Assertions Passed
7). bge - Passed All Assertions Passed
8). bgeu - Passed All Assertions Passed
9). blt - Passed All Assertions Passed
10). bltu - Passed All Assertions Passed
11). bne - Passed All Assertions Passed
12). function_call - Passed All Assertions Passed
13). jalr - Passed All Assertions Passed
14). jal - Passed All Assertions Passed
15). li - Passed All Assertions Passed
16). load_store_byte - Passed All Assertions Passed
17). load_store_hw - Passed All Assertions Passed
18). lui - Passed All Assertions Passed
19). lw - Passed All Assertions Passed
20). mv - Passed All Assertions Passed
21). ori - Passed All Assertions Passed
22). or - Passed All Assertions Passed
23). slli - Passed All Assertions Passed
24). sll - Passed All Assertions Passed
25). slti - Passed All Assertions Passed
26). sltiu - Passed All Assertions Passed
27). slt - Passed All Assertions Passed
28). sltu - Passed All Assertions Passed
29). srai - Passed All Assertions Passed
30). sra - Passed All Assertions Passed
31). srli - Passed All Assertions Passed
32). srl - Passed All Assertions Passed
33). stack - Passed All Assertions Passed
34). storew - Passed All Assertions Passed
35). sub - Passed All Assertions Passed
36). sw - Passed All Assertions Passed
37). xori - Passed All Assertions Passed
38). xor - Passed All Assertions Passed
================================================================================
Passed tests : 39 / 39
Ignored tests : 0 / 39
Failed tests : 0 / 39
```
To compile instructions with the `M extension`, we need to modify `scar.py` for compilation.
```diff
def compile_test(test:dict, save_objdump:bool=False):
# ---------- Configuration ----------
RVPREFIX = 'riscv64-unknown-elf-'
CC = 'gcc'
- CFLAGS = ['-march=rv32i', '-mabi=ilp32', '-nostartfiles']
+ CFLAGS = ['-march=rv32im', '-mabi=ilp32', '-nostartfiles']
LDFLAGS = []
# select linkerscript by auto detecting soctarget
try:
dump = run_cmd(['atomsim', '--soctarget'], print_dumps=False)
soctarget = dump.stdout.replace('\n', '')
LDFLAGS = ['-T', os.getenv('RVATOM')+'/sw/lib/link/link_'+soctarget+'.ld']
except Exception as e:
print(e)
print('Failed to get soctarget')
sys.exit(1)
```
Then add the test files in `tests.json`
```diff
[
{"name":"slt", "srcs":["tests/slt.S"], "assertion_file": "tests/slt.asrt"},
{"name":"sltu", "srcs":["tests/sltu.S"], "assertion_file": "tests/sltu.asrt"},
{"name":"srai", "srcs":["tests/srai.S"], "assertion_file": "tests/srai.asrt"},
{"name":"sra", "srcs":["tests/sra.S"], "assertion_file": "tests/sra.asrt"},
{"name":"srli", "srcs":["tests/srli.S"], "assertion_file": "tests/srli.asrt"},
{"name":"srl", "srcs":["tests/srl.S"], "assertion_file": "tests/srl.asrt"},
{"name":"stack", "srcs":["tests/stack.S"], "assertion_file": "tests/stack.asrt"},
{"name":"storew", "srcs":["tests/storew.S"], "assertion_file": "tests/storew.asrt"},
{"name":"sub", "srcs":["tests/sub.S"], "assertion_file": "tests/sub.asrt"},
{"name":"sw", "srcs":["tests/sw.S"], "assertion_file": "tests/sw.asrt"},
{"name":"xori", "srcs":["tests/xori.S"], "assertion_file": "tests/xori.asrt"},
{"name":"xor", "srcs":["tests/xor.S"], "assertion_file": "tests/xor.asrt"},
+ {"name":"mul", "srcs":["tests/mul.S"], "assertion_file": "tests/mul.asrt"},
+ {"name":"mulh", "srcs":["tests/mulh.S"], "assertion_file": "tests/mulh.asrt"},
+ {"name":"mulhsu", "srcs":["tests/mulhsu.S"], "assertion_file": "tests/mulhsu.asrt"},
+ {"name":"mulhu", "srcs":["tests/mulhu.S"], "assertion_file": "tests/mulhu.asrt"},
+ {"name":"div", "srcs":["tests/div.S"], "assertion_file": "tests/div.asrt"},
+ {"name":"divu", "srcs":["tests/divu.S"], "assertion_file": "tests/divu.asrt"},
+ {"name":"rem", "srcs":["tests/rem.S"], "assertion_file": "tests/rem.asrt"},
+ {"name":"remu", "srcs":["tests/remu.S"], "assertion_file": "tests/remu.asrt"}
]
```
Then make in `riscv-atom/test/scar`
```
$ make
```
All tests passed!
```verilog
> Generating report: work/scartest.report
+------------------------------------------------------------------------------+
| SCAR Verification Report |
+------------------------------------------------------------------------------+
Date: 2024-01-14 11:06:13
0). add64 - Passed All Assertions Passed
1). addi - Passed All Assertions Passed
2). add - Passed All Assertions Passed
3). andi - Passed All Assertions Passed
4). and - Passed All Assertions Passed
5). auipc - Passed All Assertions Passed
6). beq - Passed All Assertions Passed
7). bge - Passed All Assertions Passed
8). bgeu - Passed All Assertions Passed
9). blt - Passed All Assertions Passed
10). bltu - Passed All Assertions Passed
11). bne - Passed All Assertions Passed
12). function_call - Passed All Assertions Passed
13). jalr - Passed All Assertions Passed
14). jal - Passed All Assertions Passed
15). li - Passed All Assertions Passed
16). load_store_byte - Passed All Assertions Passed
17). load_store_hw - Passed All Assertions Passed
18). lui - Passed All Assertions Passed
19). lw - Passed All Assertions Passed
20). mv - Passed All Assertions Passed
21). ori - Passed All Assertions Passed
22). or - Passed All Assertions Passed
23). slli - Passed All Assertions Passed
24). sll - Passed All Assertions Passed
25). slti - Passed All Assertions Passed
26). sltiu - Passed All Assertions Passed
27). slt - Passed All Assertions Passed
28). sltu - Passed All Assertions Passed
29). srai - Passed All Assertions Passed
30). sra - Passed All Assertions Passed
31). srli - Passed All Assertions Passed
32). srl - Passed All Assertions Passed
33). stack - Passed All Assertions Passed
34). storew - Passed All Assertions Passed
35). sub - Passed All Assertions Passed
36). sw - Passed All Assertions Passed
37). xori - Passed All Assertions Passed
38). xor - Passed All Assertions Passed
39). mul - Passed All Assertions Passed
40). mulh - Passed All Assertions Passed
41). mulhsu - Passed All Assertions Passed
42). mulhu - Passed All Assertions Passed
43). div - Passed All Assertions Passed
44). divu - Passed All Assertions Passed
45). rem - Passed All Assertions Passed
46). remu - Passed All Assertions Passed
================================================================================
Passed tests : 47 / 47
Ignored tests : 0 / 47
Failed tests : 0 / 47
```
:::info
Are you going to submit pull request(s) for contributions?
:::
## Reference
* [RISC-V Atom Documentation & User Manual](https://riscv-atom.readthedocs.io/en/latest/index.html)
* [CA2022 Project: RISCV-Atom and implement RV32M](https://hackmd.io/@wanghanchi/riscv-atom)