Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 100 additions & 0 deletions FUNDING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# Funding

Limen is an independent open-source project. This document describes what
funding supports, the licensing commitments for funded work, and how the
project plans to sustain itself long-term.

---

## What Funding Supports

Limen is working toward a production-ready v1.0 release. Funding
accelerates the path from the current alpha to a stable, battle-tested
framework that downstream projects can depend on.

The v1.0 roadmap includes:

- **Contract stabilisation** — freezing the public trait surface (`Node`,
`Edge`, `GraphApi`, `LimenRuntime`, `MemoryManager`) with semver
guarantees.
- **Robotics primitives** — freshness, liveness, criticality, urgency, and
mailbox semantics for real-time control system graphs.
- **Production runtimes** — `NoAllocRuntime` with full policy enforcement
and `ThreadedRuntime` with EDF and throughput scheduling.
- **Inference backends** — TFLite Micro (Cortex-M4) and Tract
(desktop/server) behind the `ComputeBackend` trait.
- **Platform implementations** — Raspberry Pi and Cortex-M4 reference
platforms with clock, GPIO, and I/O support.
- **Conformance and testing** — comprehensive test suite covering tensor
payloads, N-to-M graphs, mailbox semantics, staleness detection, liveness
violations, and telemetry events.
- **Documentation and release hygiene** — full API documentation, feature
flag audit, CI gates, changelog, and cross-platform reference examples.

See the [Roadmap](docs/roadmap.md) for the full phased plan.

---

## Licensing Commitment for Funded Work

All deliverables produced under accepted public grants — including code,
tests, documentation, and example artifacts delivered under funded
milestones — will be released publicly under the Apache License, Version 2.0.

These deliverables will remain available under Apache-2.0. The Apache
License is irrevocable: once a version is released under Apache-2.0, that
version stays under Apache-2.0 permanently. This is a property of the
licence itself, not a policy that can be changed.

The goal is to deliver a production-ready v1.0 under Apache-2.0 as a
public good.

---

## Future Versions and Sustainability

Future major versions of Limen may be distributed under different or
additional licence terms (for example, dual-licensing for commercial
sustainability). This is a standard approach used by many open-source
projects and does not affect the Apache-2.0 availability of earlier
releases.

In concrete terms: if v1.0 is released under Apache-2.0 with grant
funding, v1.0 remains Apache-2.0 forever. Any future versions developed
independently may ship under different terms — but v1.0 and its source
code remain freely available under the original licence.

The long-term aspiration is to keep Limen free and open-source. If the
project achieves significant adoption, moving it to a non-profit
foundation for community stewardship is a possibility the maintainer is
open to.

---

## Contributor Licence Agreement

Contributions to Limen are accepted under a lightweight
[Contributor Licence Agreement](CLA.md) (CLA). The CLA grants the project
maintainer the right to sublicence and relicence contributions. This
flexibility supports long-term sustainability while keeping the open-source
core accessible.

The CLA does not affect the licensing commitments for funded work described
in this document.

---

## How to Support Limen

If you are interested in funding, sponsoring, or collaborating on Limen,
please open an issue or contact the maintainer directly.

- **Public grants and innovation funds** — Limen is actively seeking
support from open-source and public innovation programmes.
- **Corporate sponsorship** — partnerships with companies in robotics,
embedded systems, and edge AI.
- **Community support** — GitHub Sponsors (coming soon).

---

Copyright © 2025–present Arlo Louis Byrne (idky137)
33 changes: 18 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,23 +60,22 @@ Limen closes this gap.

## Quickstart

**Prerequisites:** Rust stable toolchain. No external dependencies.
**Prerequisites:** Rust stable toolchain (1.81+). No external dependencies.

```bash
# Clone and enter the repository
git clone https://github.com/idky137/limen.git
cd limen

# Run the no_std single-threaded pipeline
cargo test -p limen-examples -- codegen_core_pipeline_runs_with_nostd_runtime --nocapture

# Run the std multi-threaded pipeline (concurrent queues, scoped threads)
cargo test -p limen-examples --features std -- codegen_std_pipeline_runs_with_std_runtime --nocapture
# Run the pipeline demo (requires std feature for concurrent execution)
cargo run -p limen-examples --features std --example pipeline_demo
```

Both tests build a three-node **Source → Model → Sink** pipeline from a
codegen-generated graph, wire it to a runtime, and step it through several
iterations. `--nocapture` prints edge occupancies and telemetry to stdout.
The demo builds a **Sensor → Model → Actuator** pipeline, runs it
step-by-step showing backpressure and batching, then runs the same graph
concurrently with one thread per node. See the
[Quickstart Guide](docs/quickstart.md) for a full walkthrough of the output
and what each section demonstrates.

---

Expand Down Expand Up @@ -208,9 +207,11 @@ beyond.
| Document | Description |
|---|---|
| [API Reference](https://idky137.github.io/limen/) | Rustdoc API documentation (GitHub Pages) |
| [Quickstart Guide](docs/quickstart.md) | Pipeline demo walkthrough and expected output |
| [Architecture Guide](docs/architecture/index.md) | System design, memory model, execution flow |
| [Decision Records](docs/ADRs/) | Rationale behind key design decisions |
| [Roadmap](docs/roadmap.md) | Phased plan to v0.1.0 and stretch goals |
| [Funding & Licensing](FUNDING.md) | Funded work commitments and how to support the project |
| [Development Guide](docs/dev_guide.md) | Building, testing, and contributing |

---
Expand All @@ -221,12 +222,14 @@ Limen is released under the Apache License, Version 2.0
([LICENSE-APACHE](LICENSE-APACHE)).

The project is developed and owned by its original author. Contributions
are accepted under a Contributor Licence Agreement (CLA), which ensures
the project can be maintained, evolved, and (if necessary) dual-licensed
for commercial use.

The goal is to keep Limen broadly accessible while retaining the ability
to support long-term sustainability and real-world deployment.
are accepted under a Contributor Licence Agreement ([CLA](CLA.md)), which
ensures the project can be maintained, evolved, and (if necessary)
dual-licensed for commercial use.

All deliverables produced under accepted public grants will be released
under Apache-2.0 and remain available under Apache-2.0. Future major
versions may be distributed under different or additional licence terms.
See [FUNDING.md](FUNDING.md) for details.

---

Expand Down
198 changes: 198 additions & 0 deletions docs/quickstart.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
# Quickstart Guide

This guide walks through the **pipeline demo** — a runnable example that
demonstrates Limen's core capabilities in under a minute.

---

## Prerequisites

- **Rust stable toolchain** (1.81+). Install via [rustup](https://rustup.rs/).
- No external dependencies — everything builds from source.

```bash
git clone https://github.com/idky137/limen.git
cd limen
```

---

## Running the Demo

```bash
cargo run -p limen-examples --features std --example pipeline_demo
```

The `std` feature enables concurrent queues and threaded runtimes. Without
it, only the single-threaded `no_std` path is available.

---

## What the Demo Does

The demo builds a three-node **Sensor → Model → Actuator** inference
pipeline — the canonical pattern for edge AI and robotics systems:

```
[Sensor] --edge 0--> [Model] --edge 1--> [Actuator]
```

| Node | Role | Real-world analogue |
|---|---|---|
| **Sensor** | Produces tensor data from an upstream backlog | IMU, camera, LiDAR |
| **Model** | Identity inference pass-through (batched) | TFLite Micro, Tract |
| **Actuator** | Consumes results | Motor controller, UART, MQTT |

**Configuration:**
- **Edges:** SPSC (single-producer single-consumer) queues, capacity 16
- **Backpressure:** DropOldest — when the queue is full, the oldest item is
evicted. This is the correct policy for real-time systems where stale
sensor data should be discarded in favour of fresh readings.
- **Batching:** Fixed size 4 on sensor and model nodes — items are grouped
into batches of 4 before processing.
- **Memory:** Static (no-alloc) managers with 20 slots per edge — no heap
allocation required.

The same graph definition, node logic, and policies work identically on
bare-metal `no_std` microcontrollers and multi-threaded Linux servers.

---

## Expected Output Walkthrough

### Header

```
====================================================================
Limen Pipeline Demo -- Edge Inference Runtime
====================================================================

Graph topology:

[Sensor] --edge 0--> [Model] --edge 1--> [Actuator]

Edges: SPSC queues, capacity 16, DropOldest backpressure
Batching: fixed size 4 on sensor and model nodes
Memory: static (no-alloc) managers, 20 slots per edge
```

### Part 1: Step-by-step execution

This section runs the pipeline one step at a time using a single-threaded
`no_std`-compatible runtime. The source is pre-loaded with 20 items (more
than the edge capacity of 16), so backpressure will engage.

```
Step | sensor->model | model->actuator
-------+------------------+---------------------
1 | 4 items | 0 items
2 | 0 items | 4 items
3 | 0 items | 3 items
4 | 4 items | 3 items
5 | 0 items | 7 items
...
15 | 0 items | 15 items

Pipeline complete:
Messages consumed by actuator: 5
Backpressure policy: DropOldest (stale data evicted)
```

**What to notice:**

- **Batching in action:** The sensor pushes 4 items per batch (visible in
steps 1, 4, 7, 10, 13 where `sensor→model` jumps by 4).
- **Pipeline flow:** The model consumes from edge 0 and produces to edge 1.
The actuator consumes from edge 1 one item at a time.
- **Round-robin scheduling:** The single-threaded runtime visits each node
in turn. One step = one pass through all three nodes.
- **Accumulation:** Items accumulate in `model→actuator` because the
actuator consumes one item per step while the model produces batches.
- **Backpressure:** The source generates more items than can fit (the
source also adds 1–2 random items to its backlog each step to simulate
continuous sensor input). The DropOldest policy ensures that stale data
is evicted rather than blocking the pipeline.

### Part 2: Concurrent execution

This section rebuilds the graph with thread-safe concurrent edges and runs
it with one worker thread per node for 500ms.

```
Launching 3 worker threads (one per node)...
Running for 500ms with continuous sensor input.

Concurrent pipeline stopped gracefully via RuntimeStopHandle.
Messages processed by actuator: ~400
```

**What to notice:**

- **Thread-per-node:** Each node runs on its own OS thread with a backoff
scheduler (sleeps briefly when idle or backpressured).
- **Graceful shutdown:** A `RuntimeStopHandle` is cloned before `run()` and
passed to a timer thread that requests cooperative stop after 500ms. All
threads drain cleanly.
- **Throughput:** The concurrent pipeline processes hundreds of messages in
500ms despite simulated processing delays in each node.

### Telemetry Summary

The final section prints per-node and per-edge metrics collected during the
concurrent run:

```
graph id: 0
node id: 0 processed=~800 dropped=~360 ingress=0 egress=~800 ...
node id: 1 processed=~400 dropped=0 ingress=~400 egress=~400 ...
node id: 2 processed=~400 dropped=0 ingress=~400 egress=0 ...
edge id: 0 queue_depth=0
edge id: 1 queue_depth=16
edge id: 2 queue_depth=2
```

**What to notice:**

- **Sensor (node 0):** `dropped=~360` — nearly half the produced messages
were dropped by the DropOldest admission policy. This is correct
behaviour: the model processes batches slower than the sensor produces,
so stale readings are evicted.
- **Model (node 1):** `dropped=0` — the model never drops; it processes
everything it receives. `processed` is roughly half of the sensor's
output because it processes in batches of 4.
- **Actuator (node 2):** Consumes everything the model produces.
- **Edge depths:** Edge 1 (`sensor→model`) is drained (0). Edge 2
(`model→actuator`) is at capacity (16) — the actuator is the bottleneck.
- **Latency metrics:** `lat_sum`, `lat_cnt`, `lat_max` track per-node
processing time in nanoseconds.

> Exact numbers vary between runs due to thread scheduling and simulated
> processing delays.

---

## Next Steps

| Topic | Resource |
|---|---|
| Define your own graph | See `limen-examples/examples/pipeline_demo.rs` for the `define_graph!` DSL |
| Architecture deep dive | [Architecture Guide](architecture/index.md) |
| API reference | `cargo doc --workspace --open` or [GitHub Pages](https://idky137.github.io/limen/) |
| Design decisions | [ADRs](ADRs/) |
| Full roadmap | [Roadmap](roadmap.md) |

### Running the Integration Tests

The full test suite exercises all graph generation methods (proc-macro,
build-script codegen, hand-written) across all feature profiles:

```bash
# no_std (default) — single-threaded, static queues
cargo test -p limen-examples

# std — concurrent queues, threaded runtimes
cargo test -p limen-examples --features std

# All features including unsafe lock-free ring buffer
cargo test -p limen-examples --features spsc_raw
```
8 changes: 8 additions & 0 deletions limen-examples/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,18 @@ alloc = ["limen-core/alloc"]
std = ["alloc", "limen-core/std"]
spsc_raw = ["std", "limen-core/spsc_raw"]

[dependencies]
limen-core = { workspace = true, features = ["bench"] }
limen-build = { workspace = true }

[dev-dependencies]
limen-core = { workspace = true, features = ["bench"] }
limen-build = { workspace = true }

[[example]]
name = "pipeline_demo"
required-features = ["std"]

[build-dependencies]
limen-core = { workspace = true, features = ["bench"] }
limen-codegen = { workspace = true }
Expand Down
Loading