The idea
A processor must preserve the meaning of a program while instructions overlap and memory takes an unpredictable amount of time. This project makes that correctness problem visible across four independent RISC-V integer pipelines.
The approach
Each hart uses IF, ID, EX, MEM, and WB stages. Forwarding handles arithmetic dependencies, a load-use interlock inserts bubbles, and branch resolution flushes younger work. A locked round-robin arbiter serializes shared-memory transactions without changing a stalled request.
Engineering work
- Implemented the RV32I integer datapath, subword loads and stores, branch/jump control, and a hard-wired zero register.
- Preserved WB forwarding values when an older memory operation freezes EX; drained WB exactly once during stalls.
- Added terminal illegal-instruction, misalignment, ECALL, and EBREAK handling, including a younger-store squash check.
- Built an independent Python instruction interpreter and compared every retirement event and every final byte of RAM.
What the results show
Adding cores increases available compute, but does not create shared-memory bandwidth. With always-ready memory in seed 0, the single hart completes in 430 clocks; four contending harts complete in 508–511 clocks each. These are mixed-program completion times, not an application speedup benchmark.
Verification evidence
| Program/core configurations | 32 |
|---|---|
| Retirement events compared | 25,668 |
| Tested core counts | 1 and 4 |
| Generic synthesis | 35,644 cells |
Each project includes a documented test plan and coverage gaps. Simulation checks the supplied workloads; generic cell counts are not physical area, timing, or power measurements.
Reproduce the result
Download the source, install the open-source tools, and run from the collection root:
make cpu
make lint
make synth
make report