# Lab3: Reindeer - RISCV RV32I[M] Soft CPU
###### tags: `RISC-V`
## Modify the assembly code from HW1/HW2 for Reindeer
We can use the [riscv-compliance](https://github.com/riscv/riscv-compliance) and [imperas-riscv-tests](https://github.com/riscv-ovpsim/imperas-riscv-tests) to get the ELF file. I need to modify the configuration, so risc-v can run it.
- /imperas-riscv-tests/Makefile
```
export RISCV_DEVICE ?= rv32i
export RISCV_PREFIX ?= riscv-none-embed-
export RISCV_TARGET_FLAGS ?=
export RISCV_ASSERT ?= 0
export TARGET_SIM ?= /home/ccs100203/Desktop/imperas-riscv-tests/riscv-ovpsim/bin/Linux64/riscvOVPsim.exe
```
- /riscv-target/riscvOVPsim/device/rv32i/Makefile.include
```
ROOTDIR ?= /home/ccs100203/Desktop/imperas-riscv-tests
TARGET_SIM ?= /home/ccs100203/Desktop/imperas-riscv-tests/riscv-ovpsim/bin/Linux64/riscvOVPsim.exe
```
- /riscv-test-suite/rv32i/Makefile
```
ROOTDIR ?= /home/ccs100203/Desktop/imperas-riscv-tests
TARGET_DIR := $(ROOTDIR)/riscv-target
RISCV_TARGET := riscvOVPsim
RISCV_DEVICE := rv32i
```
:::warning
I haven't finish the code modification.
:::
```c
#include "riscv_test_macros.h"
#include "compliance_test.h"
#include "compliance_io.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")
main:
lw s0, x # Set s0 equal to the parameter x
lw s1, y # Set s1 equal to the parameter y
mv a0, s0 # Set arguments
mv a1, s1
jal power # return the result a0
mv s2, a0 # Set s2 equal to the result
j print
power:
addi sp, sp, -12
sw ra, 0(sp)
sw s0, 4(sp)
sw s1, 8(sp)
mv s0, a0 # s0 -> parameter x
mv s1, a1 # s1 -> parameter y
li s2, 1 # s2 -> res, init = 1
loop:
bge x0, s1, Ret # if (0 >= y) break
andi t0, s1, 0x1 # t0 -> y & 0x1
li t1, 0x1 # t1 -> 0x1
li ra, 0x54 # Set ra equal to srli s1, s1, 1
beq t0, t1, odd # y is odd
srli s1, s1, 1 # y_u >> 1, y /= 2
mul s0, s0, s0 # x = x * x
j loop # goto loop
odd:
mul s2, s2, s0 # res = res * x
jr ra # goto srli s1, s1, 1
Ret:
mv a0, s2 # Set return reg a0
lw ra, 0(sp) # Restore ra
lw s0, 4(sp) # Restore s0
lw s1, 8(sp) # Restore s1
addi sp, sp, 12 # Free space on the stack for the 3 words
jr ra # Return to the caller
.data
x: .word 3
y: .word 5 # unsigned
RV_COMPLIANCE_DATA_END
```
## GTKWAVE
## Explain how Reindeer works with Verilator.
From [Verilator](https://en.wikipedia.org/wiki/Verilator)
> Verilator is a free and open-source software tool which converts Verilog (a hardware description language) to a cycle-accurate behavioral model in C++ or SystemC.
## What is 2 x 2 Pipeline? How can we benefit from such pipeline design?

from [2 x 2 Pipeline](https://github.com/PulseRain/Reindeer#highlights---2-x-2-pipeline)
> In the 2 x 2 layout, each stage is active every other clock cycle. For the even cycle, only IF and IE stages are active, while for the odd cycle, only ID and MEM stages are active. In this way, the Instruction Fetch and Memory Access always happen on different clock cycles, thus to avoid the structural hazard caused by the single port memory.
Thanks to using single port memory to store both code and data, the Reindeer soft CPU is quite portable and flexible across all FPGA platforms. Some FPGA platforms, like the Lattice iCE40 UltraPlus family, carry a large amount of SPRAM with very little EBR RAM. And those platforms will find themselves a good match with the PulseRain Reindeer when it comes to soft CPU.
We knew this design has some benefits.
1. Avoid the structural hazard caused by the single port memory.
If IF and MEM need to access the memory in same cycle, it will lead to structural hazard. In other design, We need to separate the IM and DM to avoid this hazard. however in this way, IF and MEM access memory in different cycles. Thus, it can avoid this hazard.
2. The Reindeer soft CPU is quite portable and flexible across all FPGA platforms.
Because this design don't need extra memory, it will be more flexible.
## What is “Hold and Load”? And, how the simulation does for bootstraping?

from [Hold and Load](https://github.com/PulseRain/Reindeer#highlights---hold-and-load)
The soft CPU and the OCD can share the same UART port, as illustrated above. The RX signal goes to both the soft CPU and OCD, while the TX signal has to go through a mux. And that mux is controlled by the OCD.
## Can you show some signals/events inside Reindeer and describe?
## Summarize how RISC-V Compliance Tests works and why the signature should be matched.