Anulum Overview Host analysis AMP simulation Validation Python API Rust API C/C++ API

Loop Timing Witness

Sponsor PyPI crates.io DOI CI Docs CodeQL Pre-commit License Typed Python Codecov OpenSSF Scorecard

The coverage badge describes Python host/tool reports. Native and RTL proof scopes are documented in the coverage guide. Download history and missing-data handling are described in repository metrics.

Loop Timing Witness architecture concept

Illustrative architecture concept. Hardware qualification and board measurements remain pending.

An open measurement instrument, in design, that timestamps the events of a real-time control loop in FPGA fabric and reports latency, jitter, deadline misses, fault response and energy per control cycle on a PolarFire SoC board — independently of the processor whose software is being measured.

Evidence maturity: architecture_only. No board instrument has been built or measured. The repository contains measurement contracts, fabric timestamp capture, a dual-clock buffer, plants, references, PID and discrete LQR controllers with bit-exact C/Rust/RTL parity, a deadline monitor and fault injector tested in RTL simulation, and a host analysis command that reports simulation provenance separately from board evidence. The capability and claim inventories remain empty and checked by the manifest validator.

The measurement problem

Real-time control on embedded systems-on-chip is usually characterised by software that times itself on the processor under test: a timer wake-up benchmark, or timestamps logged by the control task. Those numbers share clock, scheduler and interrupts with the system being measured, often describe a proxy task rather than the control loop, and rarely come with energy per cycle or with the effect of latency on control quality. Moving a controller between a Linux task, a bare-metal core and FPGA logic therefore changes the measurement method along with the placement.

What the instrument is designed to do

For one closed control loop on one PolarFire SoC Icicle Kit, the planned instrument:

  1. timestamps every sample-ready, sample-read, actuator-write and deadline event in FPGA fabric on a 64-bit counter clocked at 100 MHz (10 ns resolution);
  2. reports latency and jitter as distributions (median, 95th, 99th and 99.9th percentile, maximum) and counts deadline misses in hardware;
  3. compares three controller placements under identical plant and controller definitions: Linux user space on the U54 application cores, a bare-metal loop on one U54 core in asymmetric multiprocessing, and fixed-point logic in fabric;
  4. relates latency to the tracking error of an emulated plant in the same run;
  5. estimates energy per control cycle from the board's PAC1934 power monitor, with the limits stated in docs/MEASUREMENT_PROTOCOL.md;
  6. injects faults and measures detection and time to a defined safe actuator state;
  7. writes every run as raw event records plus a hashed manifest, so a run can be repeated and audited.

A second event profile, COMPUTE, applies the same event witness to fabric accelerators: input write, compute start, compute done, output read and interrupt entry.

Who it is for

Engineers and researchers who must show measured loop timing instead of estimates: motor, power-electronics and motion control, laboratory hardware-in-the-loop set-ups, and teams that place computation in FPGA fabric and need its end-to-end latency on real hardware.

Evidence boundary and non-claims

Relation to SC-NeuroCore

Loop Timing Witness is developed as hardware-validation tooling for SC-NeuroCore, an open neuromorphic computing library. The COMPUTE profile is designed to measure the memory-mapped write, compute, read and interrupt path that fabric neuron peripherals use. No SC-NeuroCore code, model or adapter is part of this repository: adapters that place such peripherals in the instrument's device-under-test slot belong to the SC-NeuroCore repository and consume this repository's published manifest format and interface. No SC-NeuroCore latency or energy on PolarFire SoC has been measured.

Explicit exclusions

Architecture

The instrument architecture, event record format and verification plan are described in docs/ARCHITECTURE.md. The repository boundary is fixed by docs/adr/0001-repository-boundary.md, the measurement procedure and its stated limits by docs/MEASUREMENT_PROTOCOL.md, and the threat model by docs/THREAT_MODEL.md. The implemented simulation and host file contract is in docs/HOST_ANALYSIS.md. The source-bound vendor input procedure is in hardware/icicle/README.md; no Libero or board result is claimed.

The system block diagram illustrates the planned PolarFire SoC Icicle Kit instrument.

The planned contracts are machine-readable in measurement-domain.json (schema measurement-domain.schema.json): timebase, event record layout, event profiles and the intervals derived from them, event buffer sizing, controller placements and the run plan. Each run manifest binds a snapshot of this file by SHA-256. The validator checks their internal consistency, for example that the event buffer outlasts the slowest permitted drain at the highest sample rate and that the timebase counter cannot wrap during a repeat.

The RTL stream contract is described in docs/FABRIC_WITNESS.md; the integrated plant, monitor and injector are in docs/PLANT_WITNESS.md. Controller arithmetic, design, native interfaces and simulation limits are in docs/CONTROLLERS.md. Dedicated-hart firmware preparation, actual ISA capture and analysis limits are in docs/AMP_SIMULATION.md. The IRQ-free Linux AMP logger, mailbox startup and board qualification requirements are in docs/AMP_LINUX.md.

Repository layout

Path Content
measurement-domain.json, measurement-domain.schema.json identity, boundary and planned measurement contracts
run-manifest.schema.json versioned, provenance-bound run input contract
amp-capture.schema.json actual dedicated-hart ISA logger receipt and artifact custody
amp-plugin-build.schema.json original generation/compilation, native compiler, SDK, source/header and link provenance
capability-inventory.json generated public inventory, empty at architecture_only
development-dependency-licences.json reviewed licence of every pinned development tool
docs/ architecture, measurement protocol, threat model, decision records
papers/ manuscript collection; no manuscript exists yet
rtl/ fixed-point controllers, plants, monitor, injector, timestamp capture and dual-clock stream
controllers/ dependency-free C and Rust kernels, streaming CLIs and API documentation
runtime/rtl/ native process transport through the actual production AXI simulation
runtime/linux/ UIO transport, native controller and AMP logger entries, bracketed PAC1934 IIO journal; hardware qualification pending
benchmarks/ matching native workloads and labelled local regression records
tools/ host analysis, validators, inventory generator, repository guards and preflight runner
tests/ command-line, file and RTL-simulation tests
.github/ workflow definitions, workflow inventory and contribution metadata

Python package and native interfaces

The software package version is 0.1.0. It installs the typed loop_timing_witness API, packaged JSON schemas and the loop-timing-witness-analyze command. The package analyses existing hash-bound run records; native simulation, firmware preparation and hardware access remain separate source tools with the dependencies stated in VALIDATION.md.

Install the published host analysis package in a Python 3.13 environment:

python -m pip install loop-timing-witness==0.1.0
loop-timing-witness-analyze path/to/manifest.json --output-dir report

The standalone no_std Rust controller is published as witness-controller:

[dependencies]
witness-controller = "=0.1.0"

Its versioned API reference covers the PID state, coefficient validation and LQR step. Native execution and board adapters remain source tools; the AMP kernel is not a registry crate.

From a source checkout with Python 3.13.15:

make venv
.venv/bin/loop-timing-witness-analyze path/to/manifest.json --output-dir build/report

The unreleased source analyser reports absolute adjacent-cycle latency jitter in JSON, summary and pair CSV files, and an SVG comparison. Counts expose missing pairs; warm-up and missing cycles are never bridged. This addition is separate from the published 0.1.0 artefact. See the definition and outputs.

The unreleased report writer supports Linux with capability-checked renameat2(RENAME_NOREPLACE) publication. A destination created during staging is preserved and the write fails. Other OS report publication remains unqualified; the pure loading and calculation API below is independent of this native binding. See the host analysis contract.

For programmatic analysis:

from pathlib import Path

from loop_timing_witness.analyze_run import build_report
from loop_timing_witness.run_manifest import load_run

report, cycle_rows = build_report(load_run(Path("path/to/manifest.json")))

Both entry points validate schema identifiers, source/file hashes and run provenance before analysis. A simulation record remains labelled as simulation. The actual package-consumer check, make python-package-tests, builds both wheel and source archive, installs them into independent environments and analyses events produced by the real Icarus RTL path.

The documentation website contains the source guides and Python, Rust and C/C++ API references. Native interfaces are documented in the controller contract, the Rust crate README and the AMP runtime contracts. make documentation-toolchain docs-site builds the source documentation, Python pydoc, both Rustdoc references and the C/C++ Doxygen declaration reference into build/docs-site. Python has NumPy docstring checks. Rustdoc rejects missing public items, warnings and broken intra-doc links. Doxygen rejects undocumented public declarations, structure members and enum values. The site build refuses publication if any maintained language reference is missing.

Validation

Every gate and its exact scope are listed in VALIDATION.md. From a clean checkout with Python 3.13:

make venv        # .venv from the hashed development lock
make preflight   # every local gate, failing closed on a missing tool

Security

Report vulnerabilities privately as described in SECURITY.md.

Licence

AGPL-3.0-or-later, with a commercial licence available; see NOTICE.md and LICENSES/. Licensing metadata follows REUSE 3.x (REUSE.toml).

Citation

Citation metadata is in CITATION.cff. The 0.1.0 source archive is published on Zenodo and binds source commit 1d12e0342d5320f62182fef41709773f3c555b50. The GitHub release includes the same source ZIP and a provenance manifest with verified artifact hashes. Published PyPI/crates.io 0.1.0 artifacts retain their original build provenance and are not replaced by the later source archive. Cite the software version and the commit you inspected. Software version numbers do not establish physical board qualification or measured platform performance.

Native source-bound simulation capture is available through tools/capture_native_simulation.py; see the host analysis contract for configuration, retained source/binary provenance, the bound parent Python producer context and observed tracking coverage. Optional Linux host load profiles retain actual bounded worker activity and scheduling facts; all captures remain simulation-only.

Support development

Support the project through GitHub Sponsors, Buy Me a Coffee, Stripe, PayPal or TWINT. For commercial licensing, contact Anulum.

Anulum Fortis Studio