# Assignment3: SoftCPU
## Modify the assembly programs for Reindeer Simulation with Verilator.
### A new Makefile
In order to run the assembly program with Verilator, we have to generate the `.elf` file, and we can find some clues in the `Makefile` of `riscv-compliance` for generating `.elf` file.
There are the messages when i command `make` in `riscv-compliance` folder.

In this picture we can find some path of libraries and `link` file we need when compiling. Hence, i copy those necessary libraries to a new folder and make a new `Makefile` for compiling the assembly program to `.elf` file, the following is a new `Makefile`.
```cpp
CC = gcc
#flag
RISCV_DEVICE ?= rv32i
RISCV_ARC ?= ilp32
RISCV_PREFIX ?= riscv32-unknown-elf-
LK_SCRIPT ?= link.ld
flag = -march=$(RISCV_DEVICE) -mabi=$(RISCV_ARC) -nostdlib -nostartfiles -static -mcmodel=medany -fvisibility=hidden -T$(LK_SCRIPT)
#target
target = .
all: $(target)
$(RISCV_PREFIX)$(CC) $(flag) $(target) -o out.elf
clean:
rm *.elf
```
### The new assembly file
The following is the `C` code of `bit reverse` program which i choose to implement in this homework.
```cpp
int main()
{
unsigned int example = 0x12345678;
unsigned int shift[5];
shift[4] = 0xffff0000;
shift[3] = 0xff00ff00;
shift[2] = 0xf0f0f0f0;
shift[1] = 0xcccccccc;
shift[0] = 0xaaaaaaaa;
unsigned int tmp;
for(int i = 4; i >= 0 ; i--){
tmp = example & shift[i];
tmp >>= (1U << i);
shift[i] >>= (1U << i);
example &= shift[i];
example <<= (1U << i);
example |= tmp;
}
return 0;
}
```
> You can refer [Assignment2: RISC-V Toolchain](https://hackmd.io/fiI_RYNfSsWOlbS4-UUA-w) to know how the above program work
>
The following is the assembly code of `bit reverse` program.
```cpp
#include "compliance_test.h"
#include "compliance_io.h"
#include "test_macros.h"
# Test Virtual Machine (TVM) used by program.
RV_COMPLIANCE_RV32M
# Test code region.
RV_COMPLIANCE_CODE_BEGIN
RVTEST_IO_INIT
RVTEST_IO_ASSERT_GPR_EQ(x31, x0, 0x00000000)
RVTEST_IO_WRITE_STR(x31, "# Test Begin\n")
# ---------------------------------------------------------------------------------------------
RVTEST_IO_WRITE_STR(x31, "# Test part A1 - general test of value 0 with 0, 1, -1, MIN, MAX register values\n");
# Addresses for test data and results and load test data
la x12, test_data //input_data's addr
la x20, result
lw x1, 0(x12) // x1 is input data
# Load mask1
la x2, mask // mask's addr
# loop index 'i' initialization, and load 1u to x21
li x4, 4 // x4 = i
li x21, 1
LOOP:
lw x3, 0(x2) // load mask
and x10, x1, x3 // tmp = input & mask
sll x5, x21, x4 // x5 = (1U << i)
srl x10, x10, x5 // tmp >>= (1U << i)
srl x3, x3, x5 // mask >>= (1U << i)
and x1, x1, x3 // input &= mask
sll x1, x1, x5 // input <<= (1U << i)
or x1, x1, x10 // input |= tmp
addi x4, x4, -1 // i--
addi x2, x2, 4 // load mask_n
bge x4, x0, LOOP // i >= 0
END:
sw x1, 0(x20)
# ---------------------------------------------------------------------------------------------
# HALT
RV_COMPLIANCE_HALT
RV_COMPLIANCE_CODE_END
# Input data section.
.data
test_data:
.word 0x12345678
mask:
.word 0xFFFF0000
.word 0xFF00FF00
.word 0xF0F0F0F0
.word 0xCCCCCCCC
.word 0xAAAAAAAA
# Output data section.
RV_COMPLIANCE_DATA_BEGIN
result:
.fill 1, 4, -1
RV_COMPLIANCE_DATA_END
```
The followings are the register i use
- x1: test data
- x2: address of mask
- x3: mask
- x4: i
- x5: (1U << i)
- x10: tmp
- x12: address of test data
- x20: result
- x21: 1
### Generate `.elf` file and run with verilator
1. Generate `.elf` file
Command:
```
$make target=bit_reverse.S
```
2. Move the `.elf` file to `Reindeer/sim/compliance` folder
3. Make a new golden file in `Reindeer/sim/compliance/references/` to check the output.
4. Check the output and generate `.vcd` wave file.
Command:
```
$make test bit_reverse
```
```
========> Matching signature ...
80002020 1e6a2c48 PASS
======> Signature ALL MATCH!!!
```
5. Check whe wave file


###### tags: `Computer archetecture`