Sparsr Docs

API Reference

Every function libsparsr_host.so exports, as declared in include/sparsr.h. This is the interface your host application uses. For the intrinsics a kernel uses, see Writing a Kernel in C.

Include the header and link the library:

#include "sparsr.h"     /* -lsparsr_host */

The header is guarded for C++, so a C++ program includes it unchanged.

Constants

Name Value Meaning
SPARSR_BACKEND_ENV_VAR "SPARSR_BACKEND" The environment variable that picks the backend
SPARSR_WMEM_COMPRESSED_SIZE 240 Bytes one vector takes on the wire when it is compressed
SPARSR_WMEM_UNCOMPRESSED_SIZE 512 Bytes in one whole wide vector, 4,096 bits
SPARSR_WMEM_SLOT_COUNT 64 WMEM rows the machine has

Use the constants rather than the numbers. SPARSR_WMEM_SLOT_COUNT keeps an older name. A row once stored a compressed slot. Today it stores one whole wide vector.

Setup

void sparsr_kernel_init(void)

Selects and configures the backend, reading SPARSR_BACKEND from the environment. Call it before anything else on this page. Values are vm, vmproc, fpgasim and fpgaf2. Unset, empty or auto uses an F2 card when one answers and the VM otherwise, and prints one line to standard error when the F2 backend is installed but no card answers. See Choosing a backend.

If the backend you named cannot answer, the library reports "no device" and does not switch to another backend. This happens when its library is missing, when it lacks a call, or when the name is not a backend. Every call then answers "no device": the kernel does not run, reads return NULL, sparsr_wide_bytes() returns 0, and sparsr_read_status() returns done with the fault SPARSR_STATUS_FAULT_NO_DEVICE. Standard error gets one line per function, the first time it is called. The library never exits your process.

Loading a kernel

void sparsr_load_batch_from_bin(char inst_bin_file[30], uint32_t start_address)

Reads a .spex kernel image from disk and writes it into instruction memory at start_address. The path is at most 30 characters.

An image may contain initialised data as well as instructions. That happens when a kernel declares a lookup table or a global with a starting value. This call then also places that data in data memory. A kernel cannot do it for itself: its own image is in instruction memory, and a data load from there is a fatal trap.

void sparsr_load_batch(uint32_t *instructions, uint32_t start_address, uint32_t numb_of_inst)

The same thing without the file: you supply the instruction words, in the target's own byte order. Useful for a library with its own built-in kernels, or a program that generates one.

This loads instructions and nothing else. A kernel with initialised data also needs that data written, with sparsr_write_data_dmem. sparsr_load_batch_from_bin is the call that does both.

Running a kernel

void sparsr_execute_batch(uint32_t start_address)

Starts execution at start_address in instruction memory. Returns immediately.

uint32_t sparsr_read_status(void)

Returns the status word. Bit 0 is 0 while the batch is still running and 1 when it has finished. Bits 8-15 hold a fault code, where one is reported.

sparsr_execute_batch(0);
while (sparsr_read_status() == 0) { }
Name Value Meaning
SPARSR_STATUS_DONE 0x1 Bit 0: the device is idle, so the last batch has finished
SPARSR_STATUS_FAULT_SHIFT 8 Where the fault field starts in the status word
SPARSR_STATUS_FAULT_MASK 0xFF The fault field, once shifted down
SPARSR_STATUS_FAULT_OF(status) macro The fault code in a status word. 0 means no fault.
SPARSR_STATUS_FAULT_NO_DEVICE 0xFF The fault when there is no device at all

A batch that faulted still sets the done bit, so a loop that polls for it always stops. The vm backend returns the done bit alone.

Wide vectors (WMEM), compressed on the wire

The ordinary path. You hand over and receive whole vectors, and the compression and decompression happen on the way to and from the device.

void sparsr_write_data_wmem(uint8_t *data, uint32_t address)

Writes 512 bytes from host memory into WMEM row address.

At most 48 of the vector's 128 32-bit lanes may contain any bits, because the vector crosses to the device compressed. A denser vector is an error rather than a truncation, and the row keeps what it had.

uint8_t *sparsr_read_data_wmem(uint32_t address)

Reads WMEM row address and returns a pointer to 512 bytes in host memory, or NULL if the read failed.

Wide vectors (WMEM), sent raw

For a vector too dense for the call above. This pair takes any density.

void sparsr_write_data_wmem_raw(uint8_t *data, uint32_t row)

Writes a full 512-byte vector into WMEM row row, with no compression on the wire.

uint8_t *sparsr_read_data_wmem_raw(uint32_t row)

Reads the 512 bytes of WMEM row row. It returns what sparsr_read_data_wmem() returns, and it is kept for callers that already use the name. Returns NULL if the read failed or the active backend has no raw path.

These calls address the same rows as the pair above. A WMEM row stores one whole wide vector either way, so a vector written with one call reads back correctly with the other. The only difference is whether the library compresses it for the transfer.

Scalars (DMEM)

void sparsr_write_data_dmem(uint32_t *data, uint32_t start_address, uint32_t numb_of_data)

Writes numb_of_data 32-bit words into data memory at start_address. This is how a host passes arguments into a kernel that was compiled once and has to work on whatever the host picked, such as the WMEM base address for a register-indirect wide load.

uint32_t *sparsr_read_data_dmem(uint32_t start_address, uint32_t numb_of_data)

Reads numb_of_data words from data memory at start_address and returns a pointer to them in host memory.

Compression helpers

Available if you want to see or produce the compressed form yourself. Ordinary host programs never need them, because the WMEM calls above do the conversion.

uint8_t *sparsr_lil_comp_32b(uint8_t *uncomp_data, uint8_t show_compression)

Compresses 512 bytes into the 240-byte LIL form. Pass 1 for show_compression to print the encoded values, 0 to skip the printing.

uint8_t *sparsr_lil_decomp_32b(uint8_t *comp_data, uint8_t show_compression)

Decompresses 240 bytes back into 512.

Buffer ownership

The calls that return a pointer return a buffer the library owns. Read it or copy it before the next call of the same kind, and do not free it.

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