---
tags: computer-arch
---
# Lab3: Reindeer - RISCV `RV32I[M]` Soft CPU
## [Reindeer](https://github.com/PulseRain/Reindeer) - RISCV `RV32I[M]` Soft CPU
PulseRain [Reindeer](https://github.com/PulseRain/Reindeer) is a soft CPU of Von Neumann architecture. It supports RISC-V `RV32I[M]` instruction set, and features a 2 x 2 pipeline. It strives to make a balance between speed and area, and offers a flexible choice for soft CPU across all FPGA platforms.
## 2 x 2 Pipeline
Reindeer's pipeline is composed of 4 stages:
1. Instruction Fetch (IF)
2. Instruction Decode (ID)
3. Instruction Execution (IE)
4. Register Write Back and Memory Access (MEM)
However, unlike traditional pipelines, Reindeer's pipeline stages are mapped to a 2 x 2 layout, as illustrated below:
![](https://i.imgur.com/b3r4WWe.png)
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.
## Hold and Load
Bootstrapping a soft CPU tends to be a headache. The traditional approach is more or less like the following:
1. Making a boot loader in software
2. Store the boot loader in a ROM
3. After power on reset, the boot loader is supposed to be executed first, for which it will move the rest of the code/data into RAM. And the PC will be set to the _start address of the new image afterwards.
The drawbacks of the above approach are:
1. The bootloader will be more or less intrusive, as it takes memory spaces.
2. The implementation of ROM is not consistent across all FPGA platforms. For some FPGAs, like Intel Cyclone or Xilinx Artix, the memory initial data can be stored in FPGA bitstream, but other platforms might choose to use external flash for the ROM data. The boot loader itself could be executed in place, or loaded with a small preloader implemented in FPGA fabric. And when it comes to SoC + FPGA, like the Microsemi Smartfusion2, a hardcore processor could also be involved in the boot-loading. In other words, the soft CPU might have to improvise a little bit to work on various platforms.
To break the status quo, the PulseRain Reindeer takes a different approach called "hold and load", which brings a hardware based OCD (on-chip debugger) into the fore, as illustrated below:
![](https://i.imgur.com/NryvNUo.png)
## Simulation with [Verilator](https://www.veripool.org/wiki/verilator)
- [ ] Prerequisites
1. Install Ubuntu GNU/Linux 18.04 or later;
2. Install [Verilator](https://www.veripool.org/wiki/verilator)
```shell
$ sudo apt install verilator
```
3. Ensure the version of [Verilator](https://www.veripool.org/wiki/verilator) > `4.0`
```shell
$ verilator --version
```
Expected: `Verilator 4.028 2020-02-06 rev v4.026-92-g890cecc1` (or later)
4. Install GNU Toolchain for RISC-V as [Lab2](https://hackmd.io/@sysprog/rJAufgHYS) mentioned
Check `$PATH`
```shell
$ riscv-none-embed-gcc --version | head -1
```
Expected result: `riscv-none-embed-gcc (xPack GNU RISC-V Embedded GCC x86_64) 10.2.0`
5. Install [GTKwave](http://gtkwave.sourceforge.net/)
```shell
$ sudo apt install gtkwave
```
- [ ] Build from source code
```shell
$ git clone https://github.com/PulseRain/Reindeer.git
$ cd Reindeer/sim/verilator
$ make
```
![](https://i.imgur.com/t1x17fO.png)
- [ ] Build/Run targets
1. Run compliance test for [all 55 cases](https://github.com/riscv-non-isa/riscv-arch-test/tree/master/riscv-test-suite/rv32i_m)
```shell
$ make test_all
```
2. Run compliance test for individual case. For example, [I-ADD-01](https://github.com/riscv/riscv-compliance/blob/master/riscv-test-suite/rv32i/src/I-ADD-01.S)
```shell
$ make test I-ADD-01
```
3. Run simulator on an ELF file for 2000 cycles
```shell
$ make run ../../bitstream_and_binary/zephyr/hello_world.elf
```
## View waveform dumps with GTKwave
* [Brief introduction](http://programmermagazine.github.io/201311/htm/message2.html)
```shell
$ gtkwave
```
Open `I-ADD-01.vcd` generated by [Verilator](https://www.veripool.org/wiki/verilator):
* signal: clk
![](https://i.imgur.com/612Zus9.png)
* signal: clk, start, load_active, mem_access_addr
![](https://i.imgur.com/SsPCibv.png)
Reference: [PicoSoC: How we created a RISC-V based ASIC processor using a full open-source foundry](https://content.riscv.org/wp-content/uploads/2017/12/Wed-1142-RISCV-Tim-Edwards.pdf)