Repository navigation
targets and interop
Phase 5 turns an exported NIR graph into a deployment story and consumes graphs from other frameworks. It adds a deployment-target registry, a capability matrix, a per-target deployment report, and an external NIR import/export surface with a round-trip fidelity guarantee. Every surface (CLI, WebSocket, dashboard) renders from the same payload shapes.
spikeforge_targets/ declares
what each target can run as a TargetSpec:
its kind, the pip extra that would install its SDK, the primitives it
supports, its substitutions, and its constraints (dtype, timestep, weight
quantization, and activation_quantization, which is none on every
shipped target because the vendors' state widths are not verified here).
The registry ships:
| Target | Kind | Extra | Notes |
|---|---|---|---|
reference |
reference | — | In-process NIR interpreter; always available |
lava_loihi2 |
hardware | lava |
Lava SDK path to Intel Loihi 2 |
spinnaker2 |
hardware | spinnaker2 |
SpiNNaker2 digital hardware |
speck |
hardware |
speck (sinabs) |
SynSense Speck edge chip |
xylo |
hardware |
xylo (rockpool) |
SynSense Xylo LIF fabric |
norse |
simulator | norse |
Norse PyTorch simulator |
SDKs are optional and are reported honestly. Availability is resolved on
demand through isolated probes
(targets/probe.py and
targets/backends/api.py — the
only modules that import a backend SDK; both import nothing at module load
time). A target whose SDK is absent is returned with "available": false and
named in the report notes; it is never hidden or silently treated as ready.
The reference target is always available, and norse/lava_loihi2 gain
executable backends when their extras are installed (see WS-B above).
classify(graph_or_spec, target)
places every node of a graph in exactly one
CapabilityMatrix bucket:
- supported — the target runs the node's primitive natively.
-
substituted — the target lacks the primitive but declares a replacement
(for example Loihi 2 maps
AvgPool2dtoSumPool2d; Norse mapsIFto abeta=0LIF). The record names the node, the primitive, and its substitute. - unsupported — no native support and no declared substitute; the node name is reported explicitly.
The three buckets partition the node set, so a node is never silently dropped.
deployment_report(spec_or_graph, target)
returns JSON carrying the classified nodes (with per-bucket counts), the
target's constraints, an optional validation drift section, and
human-readable notes. deployable is true only when the target is
available and has zero unsupported nodes; a target with a missing SDK or a
gap is reported deployable: false rather than raising. The deploy CLI
command and the WebSocket deployment_report action emit the same payload.
spikeforge/nir_bridge/
grows a cross-library surface:
-
save_graph/load_graphpersist a graph in a version-stamped JSON envelope. Node semantics stay owned bynir's ownto_dict/dict2NIRNode; numpy values are tagged with dtype and shape, so a reload reconstructs the exact array rather than a rounded list. -
load_external/interpret_graph/interpret_fileingest a graph produced elsewhere and run it on the independent interpreter, which never touches snnTorch. -
roundtrippersists, reloads, and compares the reloaded interpretation against the in-memory export. The report isidentical: trueonly when every spike and membrane trace and the readout match with zero maximum absolute error.
Failures are typed and named, never silent:
GraphNotFoundError, MalformedGraphError, UnknownNodeKindError, and
UnsupportedNodeError (errors.py).
The verify CLI gains four subcommands (all print JSON; they exit non-zero
on a negative result so they double as CI gates):
python -m spikeforge.cli.verify targets
python -m spikeforge.cli.verify deploy --topology conv_net --target reference
python -m spikeforge.cli.verify deploy --topology conv_net --target xylo
python -m spikeforge.cli.verify roundtrip --topology conv_net --out build/graph.json
python -m spikeforge.cli.verify ingest --file build/graph.json
python -m spikeforge.cli.verify test-deploy --topology fc_legacytargets lists the registry with live availability; deploy classifies a
topology against a target and exits 0 only when deployable (its
--activation-quantization <scheme> flag makes the quantization drift check
simulate that activation/membrane scheme, see
Implications and boundaries §3); roundtrip
exits 0 only when the persisted graph is identical; ingest runs a saved
external graph and prints its traced nodes, or a typed error with a non-zero
exit. ingest reads the version-stamped JSON envelope written by
roundtrip --out (or nir_bridge.save_graph), not the node/edge summary
that export --out writes.
test_deploy.run_matrix(graph, spikes)
runs one graph across every registered target and returns a
TestDeployMatrix with one
DeployCell per target. Each
cell carries the target's capability classification
(classify) plus its
deployment outcome: status (ok/unavailable/error), the execution
path (e.g. a Lava emulator), a named reason when it did not complete, and
the reference parity comparison.
The matrix is deliberately honest, matching the availability model above:
- the
referencecell always runs in-process and compares to itself; - an SDK-backed simulator whose SDK is absent reports
available: false,status: "unavailable", and the enabling extra in itsreason; - a declared-only simulator with no backend wired reports
unavailablewith a reason naming it, never a failure and never silently skipped; - an available backend that refuses the graph reports
status: "error"with the offending node and kind named.
Every catalog target now has exactly one executable backend. Besides
reference, norse, and lava_loihi2, the vendor simulators are wired
through isolated probes and backends: Speck
(sinabs), Xylo (rockpool), and SpiNNaker2 (spinnaker2). Each
probes its SDK by a lazy import plus a minimal capability check, lowers a
linear chain with the shared lowering, and runs through an isolated SDK
touch-point that names its path (speck_simulator, xylo_simulator,
spinnaker2_simulator). A present SDK yields available: true and
status: "ok"|"error"; an absent or unrecognised SDK yields
available: false with a named reason.
ok is true when the reference ran and no available backend errored, so a
missing optional SDK never fails the matrix. estimate is always true — at
the matrix level and on every cell: a simulator or emulator run is never a
device measurement, and hardware energy and latency stay declared estimates.
python -m spikeforge.cli.verify test-deploy --topology fc_legacy
python -m spikeforge.cli.verify test-deploy --topology fc_legacy --targets reference,norseTwo read-only actions were added, with client types in
client/src/targetTypes.ts:
| Action | Reply | Payload |
|---|---|---|
targets |
target_list |
Availability-annotated target registry |
deployment_report |
deployment_report |
Capability matrix, constraints, optional drift |
An unknown target or topology emits the existing error message. A report is
still produced when no sample is loaded — the drift section is simply omitted,
never fabricated.
The dashboard renders a
TargetsPanel: it lists the
registry (kind, extra, availability), lets you select a target, and shows its
deployment report as supported/substituted/unsupported buckets, a constraint
table, and the optional drift table. A report is only shown when its target
matches the current selection, so a stale reply can never imply support for a
different target.
See also Implications and boundaries for why each boundary below exists and what it implies for a user.
-
Availability, not capability. The in-process
referencetarget is always available.norseandlava_loihi2now have executable backends (WS-B) that compile and run when their extras are installed; without the SDK they reportavailable: falseandrunreturnsstatus: "unavailable".spinnaker2,speck, andxyloremain declarative placeholders. - Substitutions are executed. The declared mapping stays the source of truth; the rewrite executor (WS-B) applies it and reports a post-rewrite drift check.
-
No on-device measurement.
reference,norse, andlava_loihi2compile and run, but no physical device is attached, so hardware timing and energy are not measured. -
Graph exchange uses NIR's node vocabulary. Import/export round-trips a
graph in this project's version-stamped JSON envelope, and
nirtorchextraction of third-party PyTorch modules ships in WS-F.
- Home
- Architecture
- Backend Execution
- Benchmarks
- Dashboard
- Development
- Event Datasets
- Event Runtime And Energy
- Features
- Implications And Boundaries
- Interop Foldins
- Interpreter Spine
- Introspection
- Model Deployment
- Model Hub
- Notes
- Operational Maturity
- Production Workflows
- Project Layout
- Quickstart
- Requirements
- Sequence Primitives
- Streaming Timeseries
- Targets And Interop
- Usage
- Arch 0001 Adr Repo Topology
- Arch 0001 Core Boundary
- Arch 0001 Decision Metrics
- Arch 0001 Migration Plan
- Arch 0001 Packaging Versioning
- Arch 0001 Protocol Contract
- Arch 0001 Risk Register
- Arch 0001 Target Topology
- Backend Execution Plan
- Ecosystem Listings
- Ecosystem Roadmap
- Event Runtime Plan
- Hub Expansion Plan
- Plans
- Interop Foldins Plan
- Interpreter Spine Plan
- Memory System Research
- Model Hub Plan
- Operations Plan
- Production Toolkit Plan
- Production Use Cases
- Professional Roadmap
- Repo Topology Plan
- Sequence Primitives Plan
- Use Case Audio Keyword Spotting
- Use Case Biosignal Medical Monitoring
- Use Case Computational Neuroscience
- Use Case Edge Power Budgets
- Use Case Event Camera Vision
- Use Case Intrusion Anomaly Detection
- Use Case Low Latency Sensor Stream
- Use Case Rl Control Robotics
- Use Case Spiking Transformers
- Use Case Streaming Timeseries