A Python simulation of a MIPS-like processor, built for the CS104 Computer Architecture portfolio project. It models the fetch–decode–execute cycle, a write-through cache, and a memory bus — and reports cache performance at the end of every run.
The simulator reads a plain-text assembly program, loads initial values into a simulated memory bus, then executes the program one instruction at a time, printing every stage as it goes:
[FETCH ] PC=28 -> LW R5,0(R1)
[DECODE] LW
[Cache] HIT address 4 -> 7
[EXEC ] R5 = MEM[4] = 7
| Component | File | Responsibility |
|---|---|---|
MemoryBus |
memory_bus.py |
Main memory. Converts binary addresses to integers on load. |
Cache |
cache.py |
Write-through cache sitting between the CPU and memory. Tracks hits and misses. |
CPU |
cpu.py |
8 registers, a program counter, and the instruction set. |
| Entry point | main.py |
Wires the three together and runs the program. |
The CPU never talks to the memory bus directly — every read and write goes through the cache, which decides whether to serve the request itself or pass it down. When the cache is disabled it becomes a transparent pass-through.
| Instruction | Operands | Meaning |
|---|---|---|
ADD |
Rd, Rs, Rt |
Rd = Rs + Rt |
ADDI |
Rt, Rs, immd |
Rt = Rs + immd |
SUB |
Rd, Rs, Rt |
Rd = Rs - Rt |
SLT |
Rd, Rs, Rt |
Rd = 1 if Rs < Rt else 0 |
BNE |
Rs, Rt, offset |
Branch to (PC + 4) + offset * 4 if Rs != Rt |
J |
target |
Jump to target * 4 |
JAL |
target |
Save return address in R7, then jump |
LW |
Rt, offset(Rs) |
Rt = MEM[Rs + offset] |
SW |
Rt, offset(Rs) |
MEM[Rs + offset] = Rt |
CACHE |
code |
0 off, 1 on, 2 flush |
HALT |
— | Stop execution |
R0 is hardwired to zero, following the MIPS convention — writes to it are
silently discarded.
python main.py # runs data/instruction_input.txt
python main.py data/my_program.txt # runs a specific programdata/instruction_input.txt — the provided sample: enables the cache,
performs two additions, then jumps past the end of the program. The simulator
detects that the program counter has left valid memory and halts cleanly
rather than crashing.
data/my_program.txt — a loop that sums the seven values in memory
addresses 1–7 and stores the result at address 100. It exercises the full
instruction set and produces a 42.9% cache hit rate:
R3 : 36
100 : 36
[Cache] Hits: 6 | Misses: 8 | Hit rate: 42.9%
The program counter advances before execution, not after. Real hardware
increments the PC during the fetch stage, while the instruction is still being
decoded. Branch offsets are therefore relative to PC + 4, not to the branch
instruction itself — an off-by-one here silently skips an instruction instead
of raising an error.
Jumps that land outside the program are treated as a halt. The provided sample program jumps to an address with no instruction behind it. Rather than crash on an index error, the CPU reports the out-of-range program counter and stops — the closest reasonable analogue to a real processor faulting.