A 3D interactive WebGL visualization of a gem5 out-of-order (O3) CPU core executing a program — in the spirit of PGSimCity.
Watch instruction tokens flow through Fetch → Decode → Rename → ROB / RS(IQ) / LoadQueue / StoreQueue → INT/FP/LD·ST pipes → Writeback → Commit, with live occupancy gauges, physical-register scoreboard, RegFile writeback flashes, branch-predictor mispredict shockwaves, and cache/MSHR activity — all scrubbable cycle-by-cycle with a free-orbit 3D camera.
[demo/*.c] --aarch64-gcc--> static ARM64 binary
|
v
[gem5 + SimCity tracer patch] (SE mode, O3 CPU, LTAGE, L1I/L1D + L2)
| --debug-flags=SimCity --debug-file=simcity.log (NDJSON, "SC|{...}")
v
[tools/trace2json.py] (cycle-indexed compact trace)
| web/public/trace.json
v
[web/] React + Vite + three.js (react-three-fiber), Bloom post-processing
Adds a SimCity debug flag (src/cpu/o3/simcity.hh + hooks in
fetch.cc, bac.cc, decode.cc, rename.cc, iew.cc, inst_queue.cc, lsq_unit.cc, rob.cc, commit.cc, mem/cache/base.{cc,hh}, mshr_queue.hh).
Every hook emits one NDJSON line per microarchitectural event:
| event | meaning |
|---|---|
fetch/decode/rename/dispatch/iq_issue/complete/retire |
per-instruction stage ticks (rename carries arch→phys register mappings) |
rob_insert/rob_retire, iq_insert/iq_commit, lq_insert/lq_pop, sq_insert/sq_pop |
structure occupancy |
sb |
scoreboard ready/not-ready per phys reg |
bpred, bpmiss (stage dec/exe), memviol |
branch predictions and pipeline flushes |
ld_exec/st_exec/st_wb |
memory ops: address generation, store-buffer→D$ writeback |
cache, mshr |
L1I/L1D/L2 hits/misses and outstanding-miss occupancy |
The patch is read-only: zero functional impact, near-zero overhead unless
--debug-flags=SimCity is given.
# 0. clone gem5 next to this repo's files and apply the SimCity patch
# (the gem5/ directory is gitignored — it is NOT part of this repo)
git clone --depth 1 https://github.com/gem5/gem5.git gem5
cd gem5 && git apply ../gem5-simcity.patch && cd ..
# 1. build gem5 once (~20-40 min on an M-series Mac)
make gem5 # or: cd gem5 && scons build/ARM/gem5.opt -j
# 2. cross-compile the demo programs (needs aarch64-unknown-linux-gnu-gcc,
# e.g. brew install messense/macos-cross-toolchains/aarch64-unknown-linux-gnu)
# — prebuilt binaries are already committed in demo/, so this is optional
make demos
# 3. simulate + post-process + view
make all DEMO=mix_loop # writes web/public/trace-mix_loop.json
make web # http://localhost:5173Just want to look at it first? A small sample trace (8k cycles of
mix_loop) is committed — cd web && npm install && npm run dev works
out of the box. Full 60k-cycle traces for all four demos are generated
by make all DEMO=<name> (see above).
Demos: mix_loop (int+fp+mem mix), branch_storm (mispredictions),
mem_stream (cache misses/MSHR), fp_chain (long-latency FP overlap).
- drag / wheel / right-drag: orbit / zoom / pan (free camera)
- space: play/pause, ← / →: step one cycle, timeline: scrub
- hover a token: pc, disassembly, per-stage cycles
- click a building: occupancy panel
- bottom chart: ROB/IQ/LQ/SQ occupancy history + red branch-miss ticks
- Every instruction is a unique token born at the I-Cache and dying at Commit — it flies continuously between stages (no teleporting). Shapes: sphere = INT, cylinder = FP, pyramid = Load, cube = Store, tetrahedron = Branch.
- Execution lanes are shown separately: 3× INT ALU + INT MUL/DIV, 2× FP ALU + FP MUL/DIV, LOAD pipe, STORE pipe.
- The ROB sits after the pipes as an in-order ring: tokens occupy ring slots in program order and drain from the head (yellow triangle) — the reorder-then-retire behavior is directly visible.
- Phys RegFile: cyan flash = row read (at issue), orange = row written (at writeback), purple = row allocated by Rename (with animated Rename→RegFile beams). Scoreboard uses large cells: orange = value in flight, dim green = ready.
- L1I/L1D: one cell per cache line (128 sets × 4 ways): green = hit, red = miss, cyan = write.
- Left code panel: asm ↔ source side-by-side, auto-following the
commit PC, with the same shape/color chips as the 3D tokens
(needs
tools/dump_code.py, run viamake code DEMO=...).
gem5/ gem5 source (stable) with the SimCity patch applied
demo/ demo programs + Makefile (bare-metal syscalls, gem5 SE mode)
scripts/ run_simcity.py (stdlib SE board: O3 + LTAGE + L1/L2)
tools/ trace2json.py (simcity.log -> trace.json)
web/ React/three.js viewer
out/ gem5 output dirs (m5out style, one per demo)