Sparsr Docs

Tooling and CLI Reference

The SDK includes two command-line programs, both in bin/.

Program What it does
spasm Turns assembly source into a .spex kernel image
sparsr-vm Runs a kernel, with no host program needed

Most kernels skip both programs. A kernel written in C is built by a stock RISC-V GCC, from three files the SDK provides, and your host program runs it. See Writing a Kernel in C. Reach for spasm when you want to write the instruction stream yourself.

spasm, the assembler

spasm [--target=rv32i] <assembly-file.S>

spasm reads one RV32I assembly source file and writes one .spex kernel image. Writing a Kernel in RISC-V Assembly shows how to write the source.

Input

spasm takes a .S or .s file. The source is RV32I assembly, and it includes sparsr.S for the wide instructions. spasm runs the system's riscv64-unknown-elf-as and ld on it. The image is little-endian.

--target=rv32i names the instruction set explicitly. rv32 and riscv are accepted too, in any case. -t is the short form of --target. You only need the flag for a source file with some other extension.

spasm refuses the older MIPS format. A .spasm source, or --target=mips, stops with an error, because no Sparsr device decodes that format. Rewrite such a kernel as a .S file that includes sparsr.S, or in C.

What it needs

  • include/sparsr.S and ldscripts/sparsr.ld from the SDK. spasm looks for them next to its own binary, so an unpacked SDK just works. If you have moved things around, point SPARSR_SDK_ROOT at the directory holding include/ and ldscripts/.
  • RISC-V binutils on your PATH, from the binutils-riscv64-unknown-elf package.

spasm appends no terminator. A kernel ends by returning, with ret.

Output file and location

The output is always written to the current working directory, with the input's base name and a .spex extension.

cd build
spasm ../kernel/my_kernel.S      # writes ./my_kernel.spex

Exit status

Code Meaning
0 The image was written
1 Bad arguments, a missing source file, a refused format, or an assembly error

Diagnostics go to standard error. spasm prints the RISC-V assembler's own messages unchanged. Messages from spasm itself include:

Usage: spasm [--target=rv32i] <assembly-file.S>
Assembly file not found: /path/to/file.S
Unknown target 'x86'. Expected 'rv32i'.
The MIPS Sparsr Assembly format (.spasm) is no longer supported: no Sparsr device decodes it. Write the kernel as RV32I assembly in a .S file that includes "sparsr.S", or in C.

sparsr-vm, the processor as a program

sparsr-vm is the Sparsr VM as a standalone program rather than a library. It is self-contained and about 2 MB, so running a kernel needs nothing else installed.

sparsr-vm run <kernel.spex> [options]   load a kernel and run it
sparsr-vm serve [options]               hold devices and answer the wire protocol
sparsr-vm info [--endpoint PATH]        what a running endpoint is and can do
sparsr-vm ping [--endpoint PATH]        measure the round trip to an endpoint
sparsr-vm shutdown [--endpoint PATH]    ask a running endpoint to stop
sparsr-vm version
sparsr-vm help

sparsr-vm help prints every option.

Running a kernel on its own

This is the reason to reach for the tool. You supply a kernel image and nothing else:

sparsr-vm run kernel.spex --dmem=41 --print-dmem=2 --trace

--trace prints every instruction the kernel retired and what it changed, which is the fastest way to find out why a kernel did the wrong thing.

Exit status

The exit code says what happened to the kernel, not only to the program:

Code Meaning
0 The kernel ran and finished
1 sparsr-vm itself failed
2 Bad command line
3 The kernel faulted, or exited with a non-zero status

So a script can tell a broken kernel from a broken command line.

Serving

sparsr-vm serve runs one or more devices and answers the Sparsr wire protocol over a Unix socket, so a host program in another process can drive it.

sparsr-vm serve --endpoint=/tmp/sparsr.sock --devices=2

You rarely start this by hand. The vmproc backend spawns one for you, with --exit-when-idle, so it stops when the last client disconnects.

An option a verb does not accept is refused rather than ignored, so a misspelled --endpoint cannot quietly run against the wrong device.

Built 2026-10-05 19:25 UTC · c0237a4