Skip to content

PeterDessev/Ferrite

Repository files navigation

Ferrite

Ferrite is a CPU microarchitectural simulator written in Rust: components communicate only through typed, backpressured ports over links with declared latency, systems are assembled at runtime from a pure-data ConfigGraph (no recompilation), and every run is deterministic and testable. This repository currently implements Milestones 0.1 ("First Light") and 0.2 (trace fidelity + RISC-V ingestion): a deterministic single-shard event kernel with smart ticking, a component registry, a trace frontend reading ChampSim, STF (plain .stf and zstd-compressed .zstf — the RISC-V tooling standard), and synthetic streams, a trace-fidelity verifier (ferrite trace-verify) with a 100%-detection corruption-corpus gate, a one-IPC trace-driven core, a set-associative LRU cache with MSHRs, a fixed-latency DRAM model, and a CLI that runs a config end-to-end and dumps stats. The full architecture and multi-year roadmap are in PLAN.md; the market rationale is in MARKET.md; the normative engineering specs are docs/milestone-0.md and docs/milestone-0.2.md.

Quickstart

Requires Rust (edition 2021+ toolchain via rustup).

# Build everything
cargo build --release

# Run the demo: 1M synthetic instructions through core -> L1D -> DRAM
./target/release/ferrite run configs/demo-1core.json

Expected output (stats on stdout, deterministic and byte-stable across runs; timing summary on stderr):

core0.insts  1000000
core0.loads  300083
...
l1d.hits  25088
l1d.misses  374873
...
derived.ipc  0.015887
derived.ticks  31472739500
ferrite: 1000000 insts, 62945479 cycles (31472739500 ticks) in 0.42s wall = 2.4 MIPS; ...

(The demo's 512 KiB footprint deliberately thrashes the 32 KiB L1D, so IPC is low — it exists to exercise the miss path.)

Other commands:

# List registered component models and their ports
./target/release/ferrite info            # or: ferrite info mem.cache

# Generate a ChampSim-format synthetic trace file
./target/release/ferrite gen-trace --insts 100000 --seed 7 --footprint-kb 64 -o my.trace

# Run with JSON stats, also written to a file
./target/release/ferrite run configs/demo-1core.json --json --stats-out stats.json

# Verify a trace's fidelity: fingerprint + invariant checks, optionally
# compared field-by-field against a reference (exit 0 clean / 1 errors / 2 diverged)
./target/release/ferrite trace-verify my.trace --against converted.stf

Traces: "trace" params (and trace-verify arguments) accept a file path — ChampSim input_instr binary (64-byte records; decompress .xz externally via xz -dc), STF .stf, or zstd-compressed .zstf, detected by extension or magic — or a synthetic:insts=N,seed=S,footprint_kb=K[,load_pct=..,store_pct=..,branch_pct=..,taken_pct=..] spec.

Documentation

The wiki at docs/wiki/ is the reference for how the simulator works: start at the Home page for the system overview and crate map, follow the per-crate pages for internals, use the reference pages for the config schema, CLI, determinism contract, and trace formats, and work through the tutorial to make your first modification end to end. API-level documentation is rustdoc: cargo doc --workspace --no-deps --open.

The wiki describes the current state of the simulator only — it is not a changelog or history — and it is updated in the same change as the code it describes, never bulk-updated later. The policy is normative in CONTRIBUTING.

Workspace map

configs/              example configs (demo-1core.json)
docs/milestone-0.md   normative spec for this milestone
crates/
  ferrite-time        Tick (1 ps) and ClockPeriod types
  ferrite-if-cpu      instruction IR (TraceInst) + TraceSource trait
  ferrite-if-mem      memory messages (MemReq/MemResp) + line_addr
  ferrite-kernel      deterministic event engine: Component trait, ports/links,
                      credit backpressure, smart ticking, seeds (SplitMix64)
  ferrite-stats       flat counters behind handles; text/JSON dumps
  ferrite-config      ConfigGraph serde model + validation with near-miss hints
  ferrite-comp        model registry (linkme) + ConfigGraph -> Engine instantiation
  ferrite-trace       ChampSim reader/writer, STF/.zstf reader, synthetic
                      generator, and the fidelity module (fingerprints,
                      invariant checks, corruption-corpus gate)
  core-1ipc           `cpu.1ipc`  one-IPC trace-driven core (blocking loads)
  mem-cache           `mem.cache` set-associative, true-LRU, MSHR cache
  mem-dram            `mem.dram`  fixed-latency, bounded-inflight memory
  ferrite-models      registration hub (link_all keeps model crates linked)
  ferrite-cli         the `ferrite` binary: run / info / trace-verify / gen-trace

Model crates never depend on each other; only ferrite-models and ferrite-cli link the world.

Tests

cargo test --workspace          # all unit + integration + e2e tests

End-to-end tests live in crates/ferrite-cli/tests/e2e.rs: a frozen golden stats dump for configs/demo-1core.json and a determinism gate (two runs must be byte-identical). The perf smoke (5M-instruction run, prints wall time and MIPS) is ignored by default:

cargo test -p ferrite-cli --test e2e --release -- --ignored --nocapture

Reference numbers (4-core host, release): ~2.4 MIPS / ~12M events/s on the miss-heavy demo topology.

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

About

Deterministic CPU microarchitecture simulator in Rust. untime-configured, trace-driven (ChampSim + RISC-V STF), with built-in trace-fidelity verification.

Topics

Resources

Contributing

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages