Host App Development

Host Application Development

Concept: Target Selection

The Sparsr architecture is designed to provide a seamless transition from local development to production-scale FPGA acceleration. By utilizing the SPARSR_TARGET environment variable, developers can hot-swap the execution backend without modifying a single line of application code.

  • SPARSR_TARGET=EMULATOR: Routes all kernel executions through the Sparsr Emulator Library. This local C/C++ simulator runs your 4096-bit Sparsr assembly instructions directly on your local host CPU. While execution is significantly slower than hardware processing, this mode incurs zero AWS instance costs and is ideal for rapid prototyping, CI/CD automated deployment tests, and algorithmic validation.
  • SPARSR_TARGET=AWS_F2: Targets the Sparsr Host Library bound to an AWS EC2 F2 instance via PCIe. In this mode, the library handles proprietary license-key validation, provisions the FPGA, and dispatches compiled bitcode to the live hardware for maximum throughput on binary sparse matrix compression and ultra-wide bitwise operations.

C / C++ Integration

For native C or C++ applications requiring the lowest possible latency, the Sparsr hardware is exposed through a lightweight shared library.

  1. Include & Link: Include the standard header #include <sparsr.h> in your source files and link against libsparsr_host.so (using -lsparsr_host in GCC/Clang).
  2. Memory Management: Data transfer between Host RAM and the FPGA's Co-processor Memory (CMEM) relies on direct memory-mapped arrays, allowing high-speed bursts over the PCIe bus.
  3. API Usage: Core data movement is achieved via write_cmem(cmem_offset, host_ptr, size) to push data to the hardware, and read_cmem(cmem_offset, host_ptr, size) to pull the computed matrices back.

Python Integration

Data scientists and machine learning engineers can interface with Sparsr directly from Python using our native wrapper, completely abstracting the hardware layer.

  • Installation: Integration is as simple as running pip install sparsr in your environment.
  • NumPy Compatibility: The Python SDK is deeply integrated with NumPy arrays. You can pass standard numpy.ndarray buffers directly into sparsr.write_cmem(). Because the underlying C-extension implements the buffer protocol, memory is transferred directly to the FPGA without unnecessary Python object serialization or data copying.

C# / .NET Integration

Enterprise applications and robust backend services can leverage Sparsr using our official .NET NuGet package.

  • Installation: Add the package to your project via the .NET CLI (dotnet add package Sparsr).
  • Memory Safety: To maximize performance and bypass the C# Garbage Collector (GC), the SDK supports unsafe memory blocks. You can pin managed arrays utilizing fixed statements and pass raw pointers directly to the native library.
  • Execution: The C# Host App leverages wrapper functions to orchestrate the hardware natively. You instantiate a Sparsr context and call methods like Context.ExecuteKernel("my_kernel") to handle the assembly-to-FPGA pipeline automatically.

Sample Applications Walkthrough

Below is a line-by-line breakdown of the standard SDK C example (examples/01_hello_world_c), which demonstrates the lifecycle of a Sparsr application: loading a kernel, pushing data, executing, and retrieving the output.


// 1. Initialize the Sparsr environment and compile the assembly kernel.
//    This automatically checks SPARSR_TARGET to route to the EMULATOR or AWS_F2 backend.
sparsr_handle_t handle = load_kernel("kernels/sparse_compress.sasm");

// 2. Prepare local CPU data (e.g., an uncompressed matrix).
uint32_t host_input[1024];
fill_matrix_data(host_input); 

// 3. Transfer data from Host RAM to FPGA CMEM at offset 0x0000.
//    This maps the local buffer over PCIe to the FPGA.
write_cmem(handle, 0x0000, host_input, sizeof(host_input));

// 4. Trigger the custom 4096-bit wide instructions on the hardware (or emulator).
run_kernel(handle);

// 5. Retrieve the compressed matrix results from CMEM offset 0x1000 back to Host RAM.
uint32_t host_output[1024];
read_cmem(handle, 0x1000, host_output, sizeof(host_output));

// 6. Cleanup hardware resources and release the PCIe/Emulator locks.
free_kernel(handle);