# Lab3: Reindeer - RISCV RV32I[M] Soft CPU ###### tags: `CA2020` ### 1. How RISC-V Compliance Tests works? Purpose : Check whether the processor under development meets the open RISC-V standards or not. This is the RISC-V assembler code that is executed on the processor and that provides results in a defined memory area (the signature). ### 2. Why the signature should be matched? The test signature is defined as reference data written into memory during the execution of the test. It should record values and results of the operation of the Test. ### 3. How Reindeer works with 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. ![](https://i.imgur.com/nKmpB60.png) ### 4. What is 2 x 2 Pipeline? How can we benefit from such pipeline design? The Instruction Fetch and Memory Access always happen on different clock cycles, thus to **avoid the structural hazard** caused by the single port memory. ![](https://i.imgur.com/HOMDhPv.png) ### 5. What is “Hold and Load”? And, how the simulation does for bootstraping? 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. 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". After the memory is loaded with the new image, the OCD can setup the start-address of the soft CPU, and send start pulse to make the soft CPU active. At that point, the OCD can switch the UART TX back to the CPU side for CPU's output. ![](https://i.imgur.com/x6QraD0.png) ## Code for Reindeer reference [Lab1 : IsPrime](https://hackmd.io/@Zong55555/rkPsQPPrP) ```= #include "riscv_test_macros.h" #include "compliance_test.h" #include "compliance_io.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") # address for test results la x5, test_1_res addi sp,sp,-12 #prologue sw s0,8(sp) #prologue addi s0,sp,12 #prologue li a5,19 #n sw a5,-4(s0) #store n in -4(s0) li a5,1 #prime = 1 sw a5,-8(s0) #store prime in -8(s0) li a5,2 #i = 2 sw a5,0(s0) #store i in -0(s0) lw a4,-4(s0) #a4 = n j for if: lw a5,0(s0) #a5 = i rem a5,a4,a5 #n%i bne a5,zero,i++ #whether n is divided by i sw zero,-8(s0) #if n can be divided by i, prime = 0 j epilogue i++: lw a5,0(s0) #a5 = i addi a5,a5,1 sw a5,0(s0) for: lw a5,0(s0) #a5 = i mul a5,a5,a5 #a5 = i*i bge a4,a5,if #for loop condition epilogue: lw a0,argument #a5 = n (for print) lw a4,-8(s0) #a4 = prime lw s0,8(sp) #epilogue addi sp,sp,12 #epilogue bne a4,zero,print1 #if(prime) print1: addi x0,x0,0 RVTEST_IO_WRITE_STR(x31, "Test End\n") RV_COMPLIANCE_HALT RV_COMPLIANCE_CODE_END # Input data section. .data # Output data section. RV_COMPLIANCE_DATA_BEGIN test_1_res: .fill 5, 4, -1 RV_COMPLIANCE_DATA_END ```