owned this note
owned this note
Published
Linked with GitHub
---
title: "Assignment3: Soft CPU"
---
# Assignment3: Soft CPU
###### tags: `Computer Architecture`
[TOC]
## Summarize RISC-V Compliance Tests and Signature
* Purpose of Compliance Tests[[1]](https://github.com/riscv/riscv-compliance/blob/master/doc/README.adoc#12-purpose-of-compliance-tests)
:::info
The goal of compliance tests is to check whether the processor under development meets the open RISC-V standards or not. It is considered as non-functional testing meaning that it doesn’t substitute for design verification. This can be interpreted as testing to check all important aspects of the specification but without focusing on details, for example, on all possible values of instruction operands or all combinations of possible registers.
The result that compliance tests provide to the user is an assurance that the specification has been interpreted correctly and the design under test (DUT) can be declared as RISC-V compliant.
Moreover, at the heart of the testing infrastructure is the detailed compliance test. This is the RISC-V assembler code that is executed on the processor and that provides results in a defined memory area (the signature). The test should only use the minimum of instructions and only those absolutely necessary. It should only use instructions and registers from the ISA instruction set on which it is targeted
:::
* Signature[[2]](https://github.com/riscv/riscv-compliance/blob/master/doc/README.adoc#25-the-test-signature)
:::info
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. It is expected that an implementation, at the end of a test, dumps the signature in to a file such that only 4-bytes are written per line, starting with the most-significant byte on the left.
In short, signature is the golden result of the test case.
:::
## Explain How Reindeer works with Verilator
:::info
In short, the `Reindeer/sim/verilator` directory contains `tb_PulseRain_RV2T.cpp`, which complies with the standard of Verilator simulator. Thus, after we use `make` instruction in `Reindeer/sim/verilator`, we would have the corresponding runnable simulation executable. The executable would be called when using `test` or `test_all`flag.
:::
## Benefit of 2 x 2 Pipeline[[3]](https://github.com/PulseRain/Reindeer#highlights---2-x-2-pipeline)
:::info
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.
:::
## Hold and Load And, how the simulation does for bootstraping?[[4]](https://github.com/PulseRain/Reindeer#highlights---hold-and-load)
:::info
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.
As the hold-and-load gets software images from an external host, it does not need any ROM to begin with. This makes it more portable across all FPGA platforms. If Flash is used to store the software image, the OCD can be modified a little bit to read from the flash instead of the external host.
:::
## Run Code from HW2 and Put It on Reindeer running on Verilator Simulator
### Source Code from HW2
Below is the source code I modified myself from [this document](https://hackmd.io/@WeiCheng14159/rkUifs2Hw), which serves a function that counts the leading zeros of a number.
```c=
unsigned char inline CLZ(unsigned int src){
unsigned char result;
unsigned int mask = 0x80000000;
for(result = 0; !(src & mask) && (result < 32); result ++){
mask >>= 1;
}
return result;
}
int _start(){
const unsigned int toCount = 0xf70;
unsigned char result = CLZ(toCount);
return 0;
}
```
### Compiled and Rewritten Dumped Assembly from HW2
```=clike
lui a4,0x80000
lui a2,0x1
addi a2,a2,-144 # f70 <_start-0xf0e4>
loop:
and a3,a4,a2
bnez a3,end
srli a4,a4,0x1
bnez a4,loop
end:
```