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.Sandldscripts/sparsr.ldfrom the SDK.spasmlooks for them next to its own binary, so an unpacked SDK just works. If you have moved things around, pointSPARSR_SDK_ROOTat the directory holdinginclude/andldscripts/.- RISC-V binutils on your
PATH, from thebinutils-riscv64-unknown-elfpackage.
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.