# Spike, the RISC-V ISA Simulator: building and debugging a hart in software

> Spike implements a functional model of one or more RISC-V harts, from RV32I up to the hypervisor and vector extensions. It is aimed at toolchain, firmware and ISA-extension work, where you need a reference hart rather than speed.

**riscv-software-src/riscv-isa-sim** — Spike, a RISC-V ISA Simulator

- Repository: https://github.com/riscv-software-src/riscv-isa-sim
- Website: https://riscv.atlassian.net/browse/RVG-476
- Stars: 3,238 · Forks: 1,122
- Language: C
- License: NOASSERTION
- Published: 2026-09-24 · Updated: 2026-09-24 · Language: en
- Canonical page: https://hysenlabs.com/projects/riscv-software-src-riscv-isa-sim

## What Spike models, and who needs a functional hart

Spike is a functional model of one or more RISC-V harts. The README says so in one line, and that line is the whole design brief. A functional model reproduces architectural state and instruction results; it does not reproduce pipeline timing, cache behaviour or bus contention. If your question is "does this instruction compute the right value, and does this trap fire at the right point," Spike answers it. If your question is "how many cycles does this loop take," Spike is the wrong instrument, and no amount of flag-hunting will change that.

The audience follows from the extension list. The README enumerates RV32I and RV64I base ISAs at v2.1, RV32E and RV64E at v1.9, the M, A, F, D, Q, C and B extensions, a large set of scalar cryptography extensions (Zk, Zkn and Zks groups), the V vector extension at v1.0, the P extension at v0.9.2, the hypervisor extension at v1.0, and a long tail of smaller extensions including the cache-block maintenance group, Svnapot, Svpbmt, Svinval, Svadu, Svade, Smepmp, Smstateen, Ssdbltrp, Ssqosid, Zacas, Zabha, Zawrs, Zicfiss, Zicfilp, Zcmp, Zcmt and the vector crypto groups. That is a list written for people who read extension names the way other people read version numbers: compiler engineers adding an intrinsic, firmware authors bringing up a new hart, and hardware teams who want a reference to diff their RTL against.

One entry in that list matters more than the rest for planning. The README states that the V extension requires a 64-bit host. If you are on a 32-bit machine and your workload needs vectors, you are not one build flag away from success; you are on the wrong machine.

## How the simulator is put together: riscv, fesvr, softfloat and the front ends

The repository layout tells you most of the architecture. The riscv/ directory holds the core: instruction behaviour, the opcode table, and the build list that decides which instructions exist. softfloat/ is the floating-point library backing F, D, Q and the half-precision extensions. fesvr/ is the front-end server that handles the host-target boundary, which is how a program running inside Spike reaches the host for system calls. debug_rom/ holds the debug ROM used by the debug path. disasm/ and spike_dasm/ provide disassembly, and spike_main/ is the executable entry point. arch_test_target/ and ci-tests/ are the test scaffolding.

The data flow for a simple run is short. You compile a C program to a RISC-V ELF binary, then launch Spike with the proxy kernel as the first argument and your binary as the second. The proxy kernel (riscv-pk) is what gives the program an environment: it sets up what a bare hart does not have and forwards system calls through the front-end server to the host. Without a proxy kernel or an operating system, a program has no stack and no syscall path, which is why the README's gdb example program declares its buffer as a global and notes that the stack is not set up.

Adding an instruction touches four places, and the README is blunt about the failure mode if you skip one. You describe the behaviour in riscv/insns/<new_instruction_name>.h, add the opcode and mask to riscv/opcodes.h (or add the line to the separate riscv-opcodes package and let make install write it for you), add the instruction to riscv/riscv.mk.in, and rebuild. Miss the mk.in entry and the instruction is not compiled in; the simulator then treats it as an illegal instruction. That is a silent-looking failure if you are not watching for the trap, and it is the first thing to check when a new instruction "does not work."

## Installing Spike and running a first RISC-V program

The README assumes the RISCV environment variable points at your RISC-V tools install path, and it lists the build dependencies for a Debian-style system: device-tree-compiler, libboost-regex-dev and libboost-system-dev. On a yum-based system the README says to substitute yum install dtc for the first step. The build is an autoconf flow with an out-of-tree build directory.

```bash
apt-get install device-tree-compiler libboost-regex-dev libboost-system-dev
mkdir build
cd build
../configure --prefix=$RISCV
make
sudo make install
```

After make install, the spike binary lands under the prefix you configured. The README also documents an OpenBSD path, which needs bash, gmake and dtc installed through pkg_add, clang as the compiler, and gmake instead of make.

Running a program needs two more pieces: riscv-gnu-toolchain and riscv-pk. Write a short C file named hello.c, compile it with the toolchain, and then hand the resulting ELF binary to Spike with pk as the loader.

```bash
riscv64-unknown-elf-gcc -o hello hello.c
spike pk hello
```

What you should see is the program's output on your terminal, produced by a RISC-V binary that never touched RISC-V silicon. If the binary instead traps immediately, the usual cause is that it was built for a different ISA string than the one Spike was configured with, or that it expects an operating system that pk is not providing.

## Interactive debug mode and the gdb path

Spike ships two debuggers, and they suit different jobs. The built-in one is reached with -d at launch, or at any point during execution with control-C even if you did not pass -d. It is a small command language over the machine state: reg and fregs or fregd read integer, single-precision and double-precision registers, mem reads a physical address, and mem with a leading core number reads through a virtual address. Execution control is a bare enter key for one instruction, r to run on, until to stop when an equality becomes true, and while to keep going as long as one stays true. The equality forms cover the program counter, a register and a memory word, which is enough to set a crude breakpoint without any symbol information.

```bash
spike -d pk hello
```

At the prompt, the README's examples look like this: reg 0 a0 reads integer register a0 on core 0, mem 2020 reads a physical memory location given in hex, mem 0 2020 reads the same address through core 0's virtual mapping, and until pc 0 2020 runs until the program counter reaches that address. q ends the simulation.

The second path is gdb, and the README is explicit that Spike tries to behave like real hardware, so you also need OpenOCD to attach. That is a real cost: a gdb session against Spike is a two-process arrangement, not a single command. The built-in prompt is the lower-friction option for instruction-level questions, and gdb is the one to reach for when you want source-level stepping and symbols. Neither is a substitute for the other.

## Where Spike stops being the right tool

The README's versioning section contains the sharpest limitation, and it is about API stability rather than correctness. Spike follows SemVer for its principal public API, which the README identifies as the RISC-V ISA itself. The C++ interface to Spike's internals is explicitly not a public API, and the README states that backwards-incompatible changes to that interface will be made without incrementing the major version number. If you are writing a plugin, a custom device, or a harness that links against Spike's classes, you have no compatibility guarantee across commits. Pin a commit and expect to rebase.

The second limitation is the one implied by "functional model." There is no timing model to tune. Any performance number you extract from Spike is an artifact of your host, not a property of the hart you are modelling.

The third is coverage versus correctness. The extension list is long, and several entries are marked at pre-1.0 versions: the P extension at v0.9.2, Zvabd at v0.9, Zfbfmin, Zvfbfmin and Zvfbfwma at v0.6, Zvzip at v0.1, Zilx at v0.1. A version below 1.0 in the README is the project telling you the specification itself is still moving. Building a product decision on a v0.1 extension modelled by Spike is a different risk than building on RV64I.

Finally, the release cadence. The most recent tagged release in the repository metadata is v1.1.0 from 2021-12-17, with v1.0.0 before it in 2019. The extension list in the README is far longer than what those tags would suggest, which means the useful work is landing on master between releases. If your process requires a tagged version, you are choosing between a four-year-old tag and a moving branch. The last push to the repository was on 2026-09-22.

## Spike against QEMU and against RTL simulation

The natural alternative for running RISC-V software is QEMU's system emulation, and the difference is in what each is built to be. QEMU is a full-system emulator with a device model: it boots an operating system, presents disks, network interfaces and a display, and its RISC-V support is one target among many. Spike is a hart model with a minimal environment, and its extension coverage is the point. When a new RISC-V extension appears, Spike tends to model it for the purpose of testing the specification, and the README's list runs well past what a general-purpose emulator needs to boot Linux. If your goal is to run a distribution, QEMU is the shorter road. If your goal is to check that your compiler emits correct code for Zicond or Zvfbfwma, Spike is the instrument that exists for that.

The other alternative is RTL simulation of your own core. That gives you timing, which Spike cannot, at the cost of a much slower run and a dependency on a synthesizable design. The usual arrangement is to use Spike as the reference: run the same binary on Spike and on your RTL, and diff architectural state. Spike's value in that arrangement comes from being simple enough to trust, not from being fast.

## Licence, maintenance and what a Spike upgrade actually costs

The repository metadata reports the licence as NOASSERTION, and the top-level entry list includes a LICENSE file. That combination means the machine-readable classification did not resolve to a standard identifier. Read the LICENSE file in the tree before you ship anything derived from it, and treat the metadata field as a pointer rather than an answer. Nothing here is legal advice; the file is the source.

On maintenance, the repository is not archived, and the last push was on 2026-09-22. That is recent activity on the default branch. The release tags are a different story: v1.1.0 dates from 2021-12-17 and v1.0.0 from 2019-04-01. A team that tracks tags is effectively pinned to a 2021 snapshot, while a team that tracks master absorbs whatever lands. The versioning section makes the consequence concrete: the C++ internals can break without a major version bump, so a master-tracking integration has to be rebuilt and retested on every update, and the only thing that protects you is a pinned commit hash.

Upgrade cost also depends on your host. The README's build steps need device-tree-compiler and two Boost libraries, and the OpenBSD path needs a different shell, make and compiler. The V extension needs a 64-bit host. Those are the constraints to check before you promise a build on someone else's machine.

## Conclusion

Adopt Spike when you are validating an ISA extension, a boot loader, or a compiler backend against a reference hart, because its instruction coverage in the README runs from RV32I to the hypervisor, vector and crypto extension groups. Do not adopt it as a cycle-accurate performance model: the README describes a functional model, and the C++ internals are explicitly not a public API. Before committing, verify the extension list against the release you build, check that your host is 64-bit if you need the V extension, and confirm the licence text in the repository, since the metadata reports NOASSERTION rather than a named licence.

## FAQ

### Is there a RISC-V instruction set simulator available?

Yes. Spike, the RISC-V ISA Simulator, implements a functional model of one or more RISC-V harts, and the README lists support from RV32I and RV64I up through the hypervisor, vector and scalar cryptography extension groups.

### What is Spike, the RISC-V ISA simulator?

Spike is a functional model of one or more RISC-V harts, named after the golden spike used to celebrate the completion of the US transcontinental railway. Its principal public API is the RISC-V ISA itself.

### How do I install Spike and run a program with it?

Install device-tree-compiler, libboost-regex-dev and libboost-system-dev, then run configure with a prefix, make and make install from a build directory. You also need riscv-gnu-toolchain and riscv-pk; compile your C file with riscv64-unknown-elf-gcc and run it with spike pk hello.

### Can I debug a program running in Spike?

Yes, in two ways. Launch Spike with -d for the built-in interactive prompt, or press control-C during execution to enter it; the README also documents attaching gdb, which requires OpenOCD because Spike tries to behave like real hardware.

### Does Spike need a 64-bit host for the vector extension?

The README states that the V extension requires a 64-bit host. Other extensions in the list do not carry that note.

### Is Spike's C++ interface stable between versions?

No. The README states that the C++ interface to Spike's internals is not considered a public API and that backwards-incompatible changes to it will be made without incrementing the major version number.

## Sources

- [Issues](https://github.com/riscv-software-src/riscv-isa-sim/issues)
- [Project website](https://riscv.atlassian.net/browse/RVG-476)
- [README](https://github.com/riscv-software-src/riscv-isa-sim/blob/master/README.md)
- [Releases](https://github.com/riscv-software-src/riscv-isa-sim/releases)
- [riscv-software-src/riscv-isa-sim on GitHub](https://github.com/riscv-software-src/riscv-isa-sim)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/riscv-software-src-riscv-isa-sim
