---
# System prepended metadata

title: 'Assignment3: Your Own RISC-V CPU'

---

# Assignment3: Your Own RISC-V CPU
contributed by < [zz1888](https://github.com/zz1888/ca2025-mycpu) >
STILL WORKING ON IT !!!!!
## Environment
- #### Ubuntu 22.04
- #### virtual environment`venv`
```C++
source .venv/bin/activate
```
- #### RISC-V GNU Toolchain  
  Used to compile compliance test programs and extract ELF signatures via `readelf` .
- #### RISCOF  
  Python-based compliance framework that orchestrates architectural tests and compares DUT signatures with a reference model.
- #### rv32emu  
  Reference RISC-V emulator used to generate golden signatures.
- #### use everytime
```
export PATH=/home/mediacore/riscv-none-elf-gcc/bin:$PATH
export CROSS_COMPILE=riscv-none-elf-
export RISCV=/home/mediacore/riscv-none-elf-gcc
export PATH=$RISCV/bin:$PATH
```
## Common Sense that I don't know
This section documents the common sense I learned during this project that was not obvious to me at first, in order to help with future review and learning.
- Chisel Tests (`sbt test`)
used to verify the correctness of individual hardware modules and the CPU at Chisel-based RTL (Register-Transfer Level).
`sbt test` is like check the algorithm is right or not.
- Verilator Simulation (`make verilaton`, `make sim`)
used to simulate the generated Verilog RTL as a complete hardware system.
`make verilaton`is like create an empty CPU.
and `.asmbin`file is more like what algorithm I run in this CPU.
then `make sim`to run it.
## Error that  I encountered
```clike
   ERROR | Error evaluating verify condition (PMP['implemented']): name 'PMP' is not defined
```
#### Physical Memory Protection (PMP) 
A RISC-V privileged architecture feature that allows the processor to define access permissions (read, write, execute) for different physical memory regions.
#### Why does the PMP error appear?
During `make compliance`, the RISC-V compliance framework checks whether PMP is implemented by reading the ISA configuration (YAML).
In this project, PMP is not implemented in the CPU design, and no PMP-related CSRs are provided.
#### How to fix it?
set`spike_simple_isa.ymal`in RV32 and RV64 implemented to false.
```clike
PMP:
  implemented: false
```
## 0-minimal
### Test
```clike
[info] welcome to sbt 1.10.7 (Eclipse Adoptium Java 11.0.29)
[info] loading project definition from /home/mediacore/ca2025-mycpu/project
[info] loading settings for project root from build.sbt...
[info] set current project to mycpu-root (in build file:/home/mediacore/ca2025-mycpu/)
[info] set current project to mycpu-minimal (in build file:/home/mediacore/ca2025-mycpu/)
[info] JITTest:
[info] Minimal CPU - JIT Test
[info] - should correctly execute jit.asmbin and set a0 to 42
[info] Run completed in 54 seconds, 190 milliseconds.
[info] Total number of tests run: 1
[info] Suites: completed 1, aborted 0
[info] Tests: succeeded 1, failed 0, canceled 0, ignored 0, pending 0
[info] All tests passed.
[success] Total time: 55 s, completed Dec 23, 2025, 2:12:45 AM
```
## 1-singleCycle
### Test
- Test Instruction Decode
```clike
[info] InstructionDecoderTest:
[info] InstructionDecoder
[info] - should decode RV32I instructions and generate correct control signals
[info] Run completed in 7 seconds, 94 milliseconds.
[info] Total number of tests run: 1
[info] Suites: completed 1, aborted 0
[info] Tests: succeeded 1, failed 0, canceled 0, ignored 0, pending 0
[info] All tests passed.
[success] Total time: 13 s, completed Dec 17, 2025, 8:21:58 PM
```
- Test Excute
```clike
[info] ExecuteTest:
[info] Execute
[info] - should execute ALU operations and branch logic correctly
[info] Run completed in 6 seconds, 592 milliseconds.
[info] Total number of tests run: 1
[info] Suites: completed 1, aborted 0
[info] Tests: succeeded 1, failed 0, canceled 0, ignored 0, pending 0
[info] All tests passed.
[success] Total time: 7 s, completed Dec 17, 2025, 8:28:26 PM
```
- Test
```clike
[info] InstructionDecoderTest:
[info] InstructionDecoder
[info] - should decode RV32I instructions and generate correct control signals
[info] ByteAccessTest:
[info] Single Cycle CPU - Integration Tests
[info] - should correctly handle byte-level store/load operations (SB/LB)
[info] InstructionFetchTest:
[info] InstructionFetch
[info] - should correctly update PC and handle jumps
[info] ExecuteTest:
[info] Execute
[info] - should execute ALU operations and branch logic correctly
[info] FibonacciTest:
[info] Single Cycle CPU - Integration Tests
[info] - should correctly execute recursive Fibonacci(10) program
[info] RegisterFileTest:
[info] RegisterFile
[info] - should correctly read previously written register values
[info] - should keep x0 hardwired to zero (RISC-V compliance)
[info] - should support write-through (read during write cycle)
[info] QuicksortTest:
[info] Single Cycle CPU - Integration Tests
[info] - should correctly execute Quicksort algorithm on 10 numbers
[info] Run completed in 43 seconds, 181 milliseconds.
[info] Total number of tests run: 9
[info] Suites: completed 7, aborted 0
[info] Tests: succeeded 9, failed 0, canceled 0, ignored 0, pending 0
[info] All tests passed.
[success] Total time: 43 s, completed Dec 17, 2025, 8:29:48 PM
```
### Compliance
```clike
    INFO | /home/mediacore/ca2025-mycpu/tests/riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/misalign1-jalr-01.S : -                                        : Passed
    INFO | Test report generated at /home/mediacore/ca2025-mycpu/tests/riscof_work_1sc/report.html.
    INFO | Opening test report in web-browser
gio: file:///home/mediacore/ca2025-mycpu/tests/riscof_work_1sc/report.html: Failed to find default application for content type ?text/html?

✅ Compliance tests complete. Results in riscof_work_1sc/
Completion time: Thu Dec 18 01:01:48 CST 2025

Copying results to results/ directory...
Cleaning up auto-generated RISCOF test files...
✅ Compliance tests complete. Results in results/
📊 View report: results/report.html
```
![image](https://hackmd.io/_uploads/rJ6JwDemZe.png)
## 2-MMIO-TRAP
### Overview
CSR stores CPU state and control rules, CLINT decides when to enter a trap, a trap is the forced control-flow transition, and the trap handler is software that handles the event and returns execution.
### CSR (Control and Status Registers) 
CSR is a set of internal CPU registers used to record state and control privileged behavior.
#### What CSR does:
- Records:
Where execution was interrupted (`mepc`).
Why it was interrupted (`mcause`).
- Controls:
Whether interrupts are allowed (`mstatus.mie`).
Where to jump on a trap (`mtvec`).
### CLINT (Core-Local Interrupt Controller)

CLINT is hardware logic that manages interrupt and exception entry,like when to enter it's a decision maker.
#### What CLINT does:
- Receives interrupt signals (timer, external, etc.).
- Checks:
Global interrupt enable (`mstatus.mie`).
Pending interrupt signals.
- If conditions are met:
1.Triggers trap entry.
2.Initiates CSR updates (`mepc`, `mcause`, `mstatus`).
3.Redirects PC to the trap vector.
### Full Flow
```
Normal program execution
↓
CLINT detects interrupt / exception
↓
Check mstatus.mie == 1
↓
Enter trap
↓
CSR updates (mepc, mcause, mstatus)
↓
PC jumps to mtvec
↓
Trap handler executes (software)
↓
mret
↓
Resume original program
```
### Test
```clike
[info] ByteAccessTest:
[info] [CPU] Byte access program
[info] - should store and load single byte
[info] CLINTCSRTest:
[info] [CLINT] Machine-mode interrupt flow
[info] - should handle external interrupt
[info] - should handle environmental instructions
[info] UartMMIOTest:
[info] [UART] Comprehensive TX+RX test
[info] - should pass all TX and RX tests
[info] ExecuteTest:
[info] [Execute] CSR write-back
[info] - should produce correct data for csr write
[info] FibonacciTest:
[info] [CPU] Fibonacci program
[info] - should calculate recursively fibonacci(10)
[info] TimerTest:
[info] [Timer] MMIO registers
[info] - should read and write the limit
[info] InterruptTrapTest:
[info] [CPU] Interrupt trap flow
[info] - should jump to trap handler and then return
[info] QuicksortTest:
[info] [CPU] Quicksort program
[info] - should quicksort 10 numbers
[info] Run completed in 47 seconds, 518 milliseconds.
[info] Total number of tests run: 9
[info] Suites: completed 8, aborted 0
[info] Tests: succeeded 9, failed 0, canceled 0, ignored 0, pending 0
[info] All tests passed.
[success] Total time: 54 s, completed Dec 19, 2025, 12:26:48 AM
```
### Compliance
```clike
    INFO | /home/mediacore/ca2025-mycpu/tests/riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/misalign2-jalr-01.S : -                                        : Passed
    INFO | Test report generated at /home/mediacore/ca2025-mycpu/tests/riscof_work_2mt/report.html.
    INFO | Opening test report in web-browser
gio: file:///home/mediacore/ca2025-mycpu/tests/riscof_work_2mt/report.html: Failed to find default application for content type ?text/html?

✅ Compliance tests complete. Results in riscof_work_2mt/
Completion time: Fri Dec 19 00:45:34 CST 2025

Copying results to results/ directory...
Cleaning up auto-generated RISCOF test files...
✅ Compliance tests complete. Results in results/
📊 View report: results/report.html
```
![image](https://hackmd.io/_uploads/B12Wt3ZXZe.png)
### VGA Display Demo
Ubuntu : `sudo apt install libsdl2-dev`
![image](https://hackmd.io/_uploads/SJvVdWD7Wl.png)
`✅ Demo complete! You should have seen animated nyancat.`
## 3-pipeline
### Exercise 21
#### Q1: Why do we need to stall for load-use hazards?
A: Because the data loaded from memory is not available until the MEM stage,and cannot be forwarded to the EX stage in the next cycle.
##### Without stall
| Instruction    | C1 | C2 | C3 | C4  | C5  |
| -------------- | -- | -- | -- | --- | --- |
| LW x1, 0(x2)   | IF | ID | EX | MEM | WB  |
| ADD x3, x1, x4 |    | IF | ID | EX  | MEM |
##### With stall
| Instruction        | C1 | C2 | C3 | C4  | C5  | C6  |
| ------------------ | -- | -- | -- | --- | --- | --- |
| LW x1, 0(x2)       | IF | ID | EX | MEM | WB  |     |
| **stall** |    | IF | ID | EX  | MEM | WB  |
| ADD x3, x1, x4     |    |    | IF | ID  | EX  | MEM |
#### Q2: What is the difference between "stall" and "flush"?
A stall pauses pipeline progress to wait for correct data, while a flush removes incorrect instructions that have already entered the pipeline.
##### Flush example (branch taken)
```
BEQ x1, x2, target
ADD x3, x4, x5   // wrong path
```
| Instruction | C1 | C2 | C3 | C4        |
| ----------- | -- | -- | -- | --------- |
| BEQ         | IF | ID | EX |           |
| ADD         |    | IF | ID | ❌ flushed |
#### Q3: Why does jump instruction with register dependency need stall?
A:because the jump target address depends on a register value that may not be available yet.
```
ADD  x1, x2, x3
JALR x0, x1, 0
```
##### Without stall
| Instruction | C1 | C2 | C3 | C4  |
| ----------- | -- | -- | -- | --- |
| ADD         | IF | ID | EX | MEM |
| JALR        |    | IF | ID | EX  |
##### With stall
| Instruction | C1 | C2 | C3 | C4  | C5  |
| ----------- | -- | -- | -- | --- | --- |
| ADD         | IF | ID | EX | MEM | WB  |
| stall       |    | IF | ID | EX  | MEM |
| JALR        |    |    | IF | ID  | EX  |
#### Q4: Why is branch penalty only 1 cycle instead of 2?
A:because branch decision and target address are resolved in the EX stage, so only one incorrect instruction needs to be flushed.
```
BEQ x1, x2, target
ADD x3, x4, x5
```
| Instruction | C1 | C2 | C3 | C4        |
| ----------- | -- | -- | -- | --------- |
| BEQ         | IF | ID | EX |           |
| ADD         |    | IF | ID | ❌ flushed |

Branch resolved at EX and Only one wrong instruction
→ 1-cycle penalty
#### Q5: What would happen if we removed hazard detection logic entirely?
A:the CPU would execute instructions with incorrect data or wrong control flow, leading to incorrect program behavior.
```
LW  x1, 0(x2)
ADD x3, x1, x4
```
| Instruction | C1 | C2 | C3 | C4  |
| ----------- | -- | -- | -- | --- |
| LW          | IF | ID | EX | MEM |
| ADD         |    | IF | ID | EX  |

`ADD` reads Old `x1`
#### Q6: Complete the stall / flush condition summary
**Stall is needed when**: 
1. EX stage instruction is LW and ID stage instruction uses the loaded register
 2. MEM stage instruction writes a register and EX stage JALR or BEQ depends on it

**Flush is needed when**:
1. A BEQ/BNE/BLT/BGE branch is taken or a JAL/JALR instruction changes the PC
### Test
```clike
[info] PipelineProgramTest:
[info] Three-stage Pipelined CPU
[info] - should calculate recursively fibonacci(10)
[info] - should quicksort 10 numbers
[info] - should store and load single byte
[info] - should solve data and control hazards
[info] - should handle all hazard types comprehensively
[info] - should handle machine-mode traps
[info] Five-stage Pipelined CPU with Stalling
[info] - should calculate recursively fibonacci(10)
[info] - should quicksort 10 numbers
[info] - should store and load single byte
[info] - should solve data and control hazards
[info] - should handle all hazard types comprehensively
[info] - should handle machine-mode traps
[info] Five-stage Pipelined CPU with Forwarding
[info] - should calculate recursively fibonacci(10)
[info] - should quicksort 10 numbers
[info] - should store and load single byte
[info] - should solve data and control hazards
[info] - should handle all hazard types comprehensively
[info] - should handle machine-mode traps
[info] Five-stage Pipelined CPU with Reduced Branch Delay
[info] - should calculate recursively fibonacci(10)
[info] - should quicksort 10 numbers
[info] - should store and load single byte
[info] - should solve data and control hazards
[info] - should handle all hazard types comprehensively
[info] - should handle machine-mode traps
[info] PipelineUartTest:
[info] Three-stage Pipelined CPU UART Comprehensive Test
[info] - should pass all TX and RX tests
[info] Five-stage Pipelined CPU with Stalling UART Comprehensive Test
[info] - should pass all TX and RX tests
[info] Five-stage Pipelined CPU with Forwarding UART Comprehensive Test
[info] - should pass all TX and RX tests
[info] Five-stage Pipelined CPU with Reduced Branch Delay UART Comprehensive Test
[info] - should pass all TX and RX tests
[info] PipelineRegisterTest:
[info] Pipeline Register
[info] - should be able to stall and flush
[info] Run completed in 2 minutes, 40 seconds.
[info] Total number of tests run: 29
[info] Suites: completed 3, aborted 0
[info] Tests: succeeded 29, failed 0, canceled 0, ignored 0, pending 0
[info] All tests passed.
[success] Total time: 179 s (02:59), completed Dec 22, 2025, 11:39:12 PM
```
### Make Complian
```clike
    INFO | /home/mediacore/ca2025-mycpu/tests/riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/misalign2-jalr-01.S : -                                        : Passed
    INFO | Test report generated at /home/mediacore/ca2025-mycpu/tests/riscof_work_3pl/report.html.
    INFO | Opening test report in web-browser
gio: file:///home/mediacore/ca2025-mycpu/tests/riscof_work_3pl/report.html: Failed to find default application for content type ?text/html?

✅ Compliance tests complete. Results in riscof_work_3pl/
Completion time: Mon Dec 22 23:52:58 CST 2025

Copying results to results/ directory...
Cleaning up auto-generated RISCOF test files...
✅ Compliance tests complete. Results in results/
📊 View report: results/report.html
```
![image](https://hackmd.io/_uploads/Sy5h9JvX-x.png)
