Skip to main content

High-performance RISC-V cycle-accurate system simulator

Project description

rvsim

Cycle-accurate RISC-V 64-bit simulator · Written in Rust · Python API

ISA Tests ISA License

Models a full out-of-order superscalar processor — physical register file, CAM-style issue queue with wakeup/select, reorder buffer, load queue, non-blocking caches, DRAM timing — and exposes everything through a composable Python API for architecture research and design-space exploration.

from rvsim import Config, BranchPredictor, Cache, Backend, Environment

config = Config(
    width=4,
    backend=Backend.OutOfOrder(rob_size=128, issue_queue_size=32, prf_gpr_size=256),
    branch_predictor=BranchPredictor.TAGE(),
    l1i=Cache("32KB", ways=8, latency=1),
    l1d=Cache("32KB", ways=8, latency=1),
    l2=Cache("256KB", ways=8, latency=10),
)

result = Environment(binary="software/bin/programs/qsort.elf", config=config).run()
print(result.stats.query("ipc|branch|miss"))

Out-of-Order Pipeline

flowchart LR
    subgraph Frontend
        F1[Fetch1] --> F2[Fetch2] --> D[Decode] --> RN["Rename<br/>PRF · Free List"]
    end

    subgraph Backend
        RN --> IQ["Issue Queue<br/>CAM wakeup / select"]

        IQ --> ALU["IntALU ×4"]
        IQ --> MUL["IntMul"]
        IQ --> FPU["FPU<br/>Add · Mul · FMA"]
        IQ --> BRU["Branch"]
        IQ --> LSU["Load / Store"]

        ALU & MUL & FPU & BRU --> WB["Writeback<br/>PRF broadcast"]
        LSU --> M1["Mem1<br/>L1D · TLB"] --> M2[Mem2] --> WB

        WB -->|wakeup| IQ
        WB --> ROB["ROB<br/>in-order commit"]
        ROB -->|"mispredict / trap → flush<br/>rebuild rename map"| RN
    end

    subgraph Memory
        M1 <-->|miss| MSHR["MSHRs<br/>non-blocking"]
        MSHR <--> L2[L2 Cache] <--> DRAM["DRAM<br/>row-buffer timing"]
    end
  • Physical register file with free list and speculative rename map — committed map restored on trap
  • CAM-style issue queue with wakeup/select: results broadcast on writeback, dependents wake and issue the next cycle
  • Reorder buffer for in-order commit with precise exception support
  • Load queue for memory ordering violation detection and replay
  • Store buffer with store-to-load forwarding and speculative draining
  • Configurable FU pool — counts and latencies per unit type, structural hazard modeling
  • Speculative load wakeup when MSHRs are available: dependents issue optimistically, cancelled on L1D miss
  • Branch misprediction recovery: rename map rebuilt from committed state + surviving ROB entries

The in-order backend uses the same frontend and shared pipeline stages, making both modes directly comparable.


Memory System

  • SV39 virtual memory — separate iTLB and dTLB, shared L2 TLB, full hardware page table walker
  • Non-blocking caches via MSHRs — L1D misses park while the pipeline continues; waiters resume when the line arrives
  • L1i · L1d · L2 · L3 — configurable size, associativity, and replacement policy (LRU / PLRU / FIFO / Random / MRU)
  • Prefetchers — next-line, stride, stream, tagged; configurable per cache level
  • Inclusive / exclusive cache policies with eviction tracking
  • DRAM controller — row-buffer aware timing: tCAS, tRAS, tPRE, row miss latency

ISA

RV64IMAFDC — base integer, multiply/divide, atomics, single/double-precision float, compressed instructions. Privileged ISA with M/S/U modes, full CSR set, trap delegation, and a CLINT timer.

Passes all 134 tests in riscv-software-src/riscv-tests — rv64ui, rv64um, rv64ua, rv64uf, rv64ud, rv64uc, rv64mi, rv64si.


Python API

pip install rvsim

Configuration

Everything is composable. Mix and match backends, predictors, caches, and FU configs:

from rvsim import Config, Cache, Backend, BranchPredictor, Prefetcher, MemoryController, Fu

config = Config(
    width=4,
    backend=Backend.OutOfOrder(
        rob_size=128,
        issue_queue_size=32,
        load_queue_size=32,
        store_buffer_size=32,
        prf_gpr_size=256,
        prf_fpr_size=128,
        load_ports=2,
        store_ports=1,
        fu_config=Fu([
            Fu.IntAlu(count=4, latency=1),
            Fu.IntMul(count=1, latency=3),
            Fu.FpFma(count=2, latency=5),
            Fu.Branch(count=2, latency=1),
            Fu.Mem(count=2, latency=1),
        ]),
    ),
    branch_predictor=BranchPredictor.TAGE(num_banks=4, table_size=2048),
    l1i=Cache("32KB", ways=8, latency=1, prefetcher=Prefetcher.NextLine()),
    l1d=Cache("32KB", ways=8, latency=1, mshr_count=8, prefetcher=Prefetcher.Stride()),
    l2=Cache("256KB", ways=8, latency=10),
    memory_controller=MemoryController.DRAM(t_cas=14, t_ras=14, row_miss_latency=120),
)

Running and inspecting

from rvsim import Environment, Simulator, reg, csr

# High-level: run a binary, get stats
result = Environment(binary="software/bin/programs/mandelbrot.elf", config=config).run()
print(result.stats.query("ipc|branch|miss"))

# Low-level: tick the pipeline manually and watch it
cpu = Simulator().config(config).binary("software/bin/programs/qsort.elf").build()

for _ in range(1000):
    cpu.tick()
    cpu.pipeline_snapshot().visualize()   # live pipeline diagram

# Run until a specific PC or privilege level
cpu.run_until(pc=0x80001234)
cpu.run_until(privilege="U")

# Inspect architectural state by name
print(hex(cpu.regs[reg.A0]))
print(hex(cpu.regs[reg.SP]))
print(hex(cpu.csrs[csr.MSTATUS]))
print(hex(cpu.csrs[csr.SEPC]))
print(cpu.mem64[0x80001000])

Comparing configurations

from rvsim import BranchPredictor, Config, Environment, Stats

rows = {}
for name, bp in [("GShare", BranchPredictor.GShare()), ("TAGE", BranchPredictor.TAGE())]:
    r = Environment("software/bin/programs/maze.elf", Config(width=4, branch_predictor=bp)).run()
    rows[name] = r.stats.query("ipc|branch_accuracy|mispredictions")

print(Stats.tabulate(rows, title="Branch Predictor Comparison"))

Parallel sweeps

Sweep distributes all (binary, config) combinations across CPU cores:

from rvsim import Sweep, Config, Cache

results = Sweep(
    binaries=[
        "software/bin/programs/mandelbrot.elf",
        "software/bin/programs/qsort.elf",
        "software/bin/programs/maze.elf",
    ],
    configs={
        f"L1={size}": Config(width=4, l1d=Cache(size, ways=8), uart_quiet=True)
        for size in ["8KB", "16KB", "32KB", "64KB"]
    },
).run(parallel=True)

results.compare(metrics=["ipc", "l1d_miss_rate"], baseline="L1=8KB")

Checkpointing

cpu.run_until(pc=0x80002000)
cpu.save("checkpoint.bin")

cpu.restore("checkpoint.bin")
cpu.run(limit=10_000_000)

Analysis Scripts

scripts/analysis/ — ready-to-run design-space exploration:

Script What it does
width_scaling.py IPC vs superscalar width across programs
branch_predict.py Accuracy and misprediction rate for all predictors
cache_sweep.py L1D size vs miss rate across workloads
inst_mix.py Instruction class breakdown (ALU / FP / load / store / branch)
stall_breakdown.py Stall cycle attribution: memory · control · data · structural
top_down.py Top-down microarchitecture analysis
o3_inorder.py Out-of-order vs in-order IPC comparison
design_space.py Full multi-dimensional design-space sweep
python scripts/analysis/width_scaling.py --bp TAGE --widths 1 2 4 8
python scripts/analysis/branch_predict.py --width 4 --programs maze qsort mandelbrot
python scripts/analysis/o3_inorder.py

Machine model configs in scripts/benchmarks/ (P550, M1, Cortex-A72):

python scripts/benchmarks/p550/run.py
python scripts/benchmarks/tests/compare_p550_m1.py

Building from Source

Requirements: Rust 2024 edition · Python 3.10+ · maturin · riscv64-unknown-elf-gcc

make build        # Compile Rust core and install Python bindings (editable)
make software     # Build libc and example programs
make test         # Run Rust test suite
make lint         # fmt-check + clippy

Linux Boot (Experimental)

The simulator can boot Linux through OpenSBI. Full boot is still in progress.

make linux        # Download and build Linux + rootfs via Buildroot
make run-linux    # Boot Linux

License

Licensed under either of MIT or Apache-2.0, at your option.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

rvsim-0.12.0.tar.gz (365.3 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

rvsim-0.12.0-cp310-abi3-win_amd64.whl (467.7 kB view details)

Uploaded CPython 3.10+Windows x86-64

rvsim-0.12.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (619.5 kB view details)

Uploaded CPython 3.10+manylinux: glibc 2.17+ x86-64

rvsim-0.12.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (589.3 kB view details)

Uploaded CPython 3.10+manylinux: glibc 2.17+ ARM64

rvsim-0.12.0-cp310-abi3-macosx_11_0_arm64.whl (542.9 kB view details)

Uploaded CPython 3.10+macOS 11.0+ ARM64

rvsim-0.12.0-cp310-abi3-macosx_10_12_x86_64.whl (576.8 kB view details)

Uploaded CPython 3.10+macOS 10.12+ x86-64

File details

Details for the file rvsim-0.12.0.tar.gz.

File metadata

  • Download URL: rvsim-0.12.0.tar.gz
  • Upload date:
  • Size: 365.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for rvsim-0.12.0.tar.gz
Algorithm Hash digest
SHA256 40118429b8509ed48b3615e2ccbb9bb15f580b5dd9571df80be15c502d3727b8
MD5 57ff1d39751cb6f3a3341876e33431f6
BLAKE2b-256 db6742dda8607107f3ce7be6531046484cc24ae3ad7aff475f9725e4299b3d32

See more details on using hashes here.

Provenance

The following attestation bundles were made for rvsim-0.12.0.tar.gz:

Publisher: release.yml on willmccallion/rvsim

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rvsim-0.12.0-cp310-abi3-win_amd64.whl.

File metadata

  • Download URL: rvsim-0.12.0-cp310-abi3-win_amd64.whl
  • Upload date:
  • Size: 467.7 kB
  • Tags: CPython 3.10+, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for rvsim-0.12.0-cp310-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 f0e694e898f531be3ec3dcbd66ae4d2c3c1259f23142953bd6f0f8aa8d09f496
MD5 b4a0f2f2f3bead2a379a41ac574dc89d
BLAKE2b-256 bcea12ae620076441c69adcbeb7412d69b654730749b568d684c2fd888566db2

See more details on using hashes here.

Provenance

The following attestation bundles were made for rvsim-0.12.0-cp310-abi3-win_amd64.whl:

Publisher: release.yml on willmccallion/rvsim

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rvsim-0.12.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for rvsim-0.12.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 71ab3a5595af052dc65849e37905dc2ed63ee926c654785f92c0a209a99b6951
MD5 2b7b39004f5892eecfedd41b2697fa09
BLAKE2b-256 e68dea3305640c8f1dfe96954df94218496ca4980ed160d9401acfa5669a35f7

See more details on using hashes here.

Provenance

The following attestation bundles were made for rvsim-0.12.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on willmccallion/rvsim

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rvsim-0.12.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for rvsim-0.12.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 06273eeb11ebe3fa575d84e1f6e13272e442e2ae32fab9dc4591cf57d0c462f2
MD5 899080ca6d6dd9d25a188415e7f90df1
BLAKE2b-256 6f7e7c572557eb04bc531dcdffcf2aca7ddec626397b4984a78f0186f641a41a

See more details on using hashes here.

Provenance

The following attestation bundles were made for rvsim-0.12.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: release.yml on willmccallion/rvsim

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rvsim-0.12.0-cp310-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for rvsim-0.12.0-cp310-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 8344a2a93a09eef62f5f65809e023dcfce8bb1c89767cf78c016c1c73bfe56a3
MD5 089b8bc978a0d00dedb2b0209290f97e
BLAKE2b-256 ede2aeef9ed1008f5a780f3aa97577b895ee8b574af6843a8ac558eef8dfc52e

See more details on using hashes here.

Provenance

The following attestation bundles were made for rvsim-0.12.0-cp310-abi3-macosx_11_0_arm64.whl:

Publisher: release.yml on willmccallion/rvsim

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rvsim-0.12.0-cp310-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for rvsim-0.12.0-cp310-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 1cbc5a3eeb9825604f068172198fed53dab906c460fc124e12f0efb7eccab692
MD5 b68cb7c9a53c10ec024e8e71c2fbb401
BLAKE2b-256 3b1e14bf31ca39af8c04622a574276f5349158eacf8560b2499a97eeda331b2d

See more details on using hashes here.

Provenance

The following attestation bundles were made for rvsim-0.12.0-cp310-abi3-macosx_10_12_x86_64.whl:

Publisher: release.yml on willmccallion/rvsim

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page