owned this note
owned this note
Published
Linked with GitHub
# Lab3: Reindeer - RISCV RV32I[M] Soft CPU
###### tags: `RISC-V`
## Simply follow three steps to overcome this experiment
step1 generate VCD file
step2 put it into Reindeer
step3 analyze signals(compare with clk(clock))
First, I rewrite the code.
## Rewrite code
```
#include "compliance_test.h"
#include "compliance_io.h"
#include "test_macros.h"
RV_COMPLIANCE_RV32M
RV_COMPLIANCE_CODE_BEGIN
RVTEST_IO_INIT
RVTEST_IO_ASSERT_GPR_EQ(x31,x0,0x00000000)
RVTEST_IO_WRITE_STR(x31,"#test begin\n")
main:
la x1, test_res
li x2, -1 # //mul1=-1
li x4, -2 # //mul2=-2
li x5, 0 # //res=0
li x6, 0 # //i=0
loop:
slti x3, x6, 32 #//if i < 32
beqz x3, exit
srl x7, x4, x6
andi x7, x7, 1
beqz x7, out
sll x8, x2, x6
add x5, x5, x8
out:
addi x6, x6, 1 #//i++
j loop
exit:
sw x9, 0(x1)
RVTEST_IO_CHECK()
RVTEST_IO_ASSERT_GPR_EQ(x1,x9,0x00000051)
RVTEST_IO_WRITE_STR(x31,"#complete~~~~~~~~~~~~~~")
RV_COMPLIANCE_HALT
RV_COMPLIANCE_CODE_END
.data
RV_COMPLIANCE_DATA_BEGIN
.align 4
test_res:
.fill 1,4,-1
RV_COMPLIANCE_DATA_END
```
## Then do the deal with Reindeer
### Prvious work : Setup environment
It took long time to understand the relation between those folder and their work in compiling riscv. I also have analysed the I-ADD-01 file to get better understanding.
I had to modify some files in order to compile testcase file.
Few git file has been cloned in the system. So, the folder, ```/home/dc/riscv-compliance/riscv-test-suie/rv32i``` is where we will compile our testcase.
Modify the Makefile:
* TARGETDIR := /home/dc/riscv-compliance/riscv-target
* RISCV_TARGET := riscvOVPsim
* RISCV_DEVICE := rv32i
then move to other file: /home/dc/riscv-compliance/riscv-target/riscvOVPsim/device/rv32i/Makefile.include
Change TARGET_SIM to this.
```shell
TARGET_SIM ?= /home/dc/riscv-compliance/riscv-ovpsim/bin/Linux64/riscvOVPsim.exe
```
Then we could simply copy .elf and .objdump files and paste it in the Reindeer/sim/compliance/ folder.
Then test the testcase by ```make test multiplier``` command. Then we can see test case passed.
Now we can able to check gtk graph.
```shell
dc@dc:~/Reindeer/sim/verilator$ make test multiplier
====> Testing ./obj_dir/VPulseRain_RV2T_MCU
TEST CASE: multiplier
testing ../compliance/multiplier.elf -r ../compliance/references/multiplier.reference_output
elf file : ../compliance/multiplier.elf
reference : ../compliance/references/multiplier.reference_output
start address = 0x80000000
=============> reset...
=============> init stack ...
=============> load elf file...
=============> start running ...
0000 00000000 00000013
0001 00000000 00000013
0002 00000000 00000013
0003 00000000 00000013
0004 00000000 00000013
0005 80000000 00000003
0006 80000000 00000003
0007 80000004 00000003
0008 80000004 00000003
0009 80000004 00000003
=============================================================
Simulation exit ../compliance/multiplier.elf
Wave trace multiplier.vcd
=============================================================
====> Test PASSED, Total of 1 case(s)
```
### VCD files
After finishing all the procedure, we got .vcd file in the ```/Reindeer/sim/verilator/```
Start verilator by ```$ gtkwave multipiler.vcd```
### GTKWave form

credit the works all above to Suraj Pramanik & EE people.
### murmur
I guess something wrong cause it only got three kinds of signals. Or maybe my code is too simple.
## QA
### 1 Explain how [Reindeer](https://github.com/PulseRain/Reindeer) works with [Verilator](https://www.veripool.org/wiki/verilator).
Run the .elf file with the test branch with the ```tb_PulseRain_RV2T.cpp``` code. It will generate all signals and values which is vcd file. Put those values in the memory, then we can compare the signature from the reference output files. And I modify the parameter "TOTAL_RUN_CYCLE", default as 2000, to control the simulating signals.
In the cpp file, there has some important functions like-
void uut_memory_load -> which load data into the UUT memory
uut_memory_peek -> read uut memory and match with the reference output file whether match or not.
Initialize all the variables and set to 0. then call reset. Then initialize the stack as default.
Load .elf to the uut memory. Then start the cpu, run for TOTAL_RUN_CYCLES = 2000 times. It will generate all the memory peek addresses. Then reset the cpu for the second time and put it into hold state
Then we will compare those values with the reference_output files whethere they have matched or not.
### 2 What is "Hold and Load"? And, how the simulation does for bootstraping?
In Reindeer soft cpu OCD means on-chip debugger which is used to controll the mux connected to the memory.
In Reindeer soft cpu desing the soft CPU and the OCD can share the same UART port. 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.
After reset, the soft CPU will be put into a hold state, and it will have access to the UART TX port by default. But a valid debug frame sending from the host PC can let OCD to reconfigure the mux and switch the UART TX to OCD side, for which the memory can be accessed, and the control frames can be exchanged. A new software image can be loaded into the memory during the CPU hold state, which gives rise to the name "hold-and-load".
### 3 Can you show some signals/events inside [Reindeer](https://github.com/PulseRain/Reindeer) and describe?
Ps
Zephyrproject.org