# 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. ![](https://i.imgur.com/CM1Plcb.png) 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 ![](https://i.imgur.com/SbEfaFK.png) ![](https://i.imgur.com/uEfpoz6.png) ###### tags: `Computer archetecture`