eulernpu: NPU inference composition and simulation stack
Project description
eulernpu
An inference-first NPU full-stack for edge AI — from a YAML spec, all the way to real silicon on a $50 FPGA.
eulernpu lets you describe a small inference accelerator and a model
as a reviewable YAML spec, then proves it on the host (cpu_ref),
simulates it on a functional NPU with cycle / memory estimates
(npu_sim), analyses PL offload for Zynq boards (zynq_ps /
zynq_pl_stub), and — when you want a physical proof — synthesises
the same graph through HLS → Vivado → xsdb and runs it on a real board.
spec.yaml
│
▼
validate ──► compile ──► .npuart ──► run / sim / profile
│ │
▼ ▼
explain cycle & memory
(PL offload plan) trace (JSON)
│
▼
quantize (INT8 / INT4)
The same YAML that produces a cpu_ref golden also drives the
simulator, the board profiler, and the HLS template library that
generates RTL for real FPGAs. One spec, one graph, four backends,
one board.
Table of contents
- Why eulernpu
- What it is / what it isn't
- Highlights
- Install
- Quickstart — 60 seconds from spec to golden
- Tutorials — read these in order
- Silicon-proven demos
- The CLI
- Architecture in one page
- Testing
- License
Why eulernpu
Every small-NPU project hits the same three cliffs:
- Spec drift. The paper drawing, the RTL, and the simulator disagree; nobody knows which is authoritative.
- Silent mis-estimates. A "quick cycle count" turns out to
include a 2× init pass that nobody accounted for, and silicon is
3× slower than expected. Or a
uint32_tPMU sum overflows and the resulting speed-up is completely fictional. - Board-shape lock-in. A neat kernel that fits XC7Z020 falls off the DSP budget the moment you try it on a bigger graph.
eulernpu is built to make each of those cliffs visible early:
- A single spec is the ground truth. Validator, compiler, cost model, cycle model, HLS template library, and the runtime all consume the same YAML — there is no separate "hardware spec" that can drift.
- Every measurement is deterministic and reproducible.
cpu_refis byte-deterministic;npu_simmatches it within1e-5; the silicon cycle model is anchored to a real measurement (P06 on XC7Z020: predicted 456 cycles vs measured 460, ±1 %). A regression test fails CI if the model ever drifts more than ±10 %. - Board-realistic profiling is one command.
eulernpu profile --all-boardsre-runs the same trace across every board profile in one table, so "will this fit ZU7EV?" is answered in a second, not in a full re-synthesis cycle.
If you have ever chased a fictitious 5× speed-up that turned out to
be a 32-bit counter wrap, that's the class of failure eulernpu is
designed to catch before you ever put a board on a bench.
What it is / what it isn't
-
✅ A full-stack inference accelerator for small models (transformer / MLP / CNN / recurrent / SSM / robotics policy / LLM).
-
✅ Operator-first, spec-first, host-first, board-realistic, measured design. Every claim in this README has a test or a silicon capture behind it.
-
✅ Works on a $50 FPGA (QMTECH XC7Z020 CLG484-1). Scales up through XC7Z045 / XCZU7EV / Kria KV260 / XCZU9EG.
-
❌ Not a general-purpose GPU or OpenCL compatible.
-
❌ Not a graphics product.
-
❌ Not a training framework — the ML training happens in PyTorch (or whatever you like);
eulernputakes the trained model and puts it on hardware. -
❌ Not a promise that every NPU is faster than a CPU. Sometimes the CPU wins, and
eulernpuis designed to measure honestly when it does. See the LLM silicon tutorial for a worked example.
Highlights
- 138 operators in 17 groups (A – Q). Core math, conv / vision, attention (incl. flash / sliding-window / grouped-query), normalisation, MoE, recurrent, graph, multimodal, Mamba / SSM, KV-cache compression, autonomy / perception, vision-encoder, diffusion, speculative decoding.
- 4 backends —
cpu_ref(deterministic NumPy reference),npu_sim(functional sim + per-op cycle / MAC / memory trace),zynq_ps(ARM PS emulation),zynq_pl_stub(PL offload analysis with real-value fallback). - INT8 / INT4 quantization with a calibration workflow
(
eulernpu quantize) and a wrap-safe fake-fixed-point host sim that matches silicon math byte-for-byte. - Board-realistic cycle model anchored to real silicon
measurements.
profile --all-boardscompares the same graph across 5 board profiles in one table. - Two-stage validation — JSON Schema (Draft 7) + 20 semantic rules (S01 – S23) with a 3-line actionable error format.
- Interop — ONNX importer (
pip install eulernpu[onnx]) and a Verilator testbench generator for plugging in your own RTL. - i18n CLI — help / logs / errors localise via
--lang ko|en|zh|ja|es(defaultko); command names, op names, and rule codes stay English (they are API surface).
Install
pip install eulernpu # core
pip install eulernpu[demo] # + rich, for terminal demos
pip install eulernpu[onnx] # + onnx, for the ONNX importer
# development
pip install -e ".[dev]" # tests + rich + typing
Requires Python ≥ 3.10 and NumPy / Click / PyYAML / jsonschema.
Optional extras: demo (rich), onnx (onnx).
Silicon bring-up (KWS / bearing / LLM demos) additionally uses Vitis HLS 2025.1, Vivado 2025.1, and xsdb on a Linux host with a QMTECH XC7Z020 CLG484-1 or equivalent Zynq-7000 / ZynqMP board. None of these are needed to run the Python side (validate, compile, sim, profile, quantize).
Quickstart — 60 seconds from spec to golden
# 1. Show what's supported on this install
eulernpu info # backends + capability matrix
eulernpu info --ops # 138 operators grouped by category
# 2. Validate a spec YAML (schema + 20 semantic rules)
eulernpu validate examples/tiny_mlp/spec.yaml
# 3. Compile it into an artifact (.npuart)
eulernpu compile --spec examples/tiny_mlp/spec.yaml \
--target cpu_ref
# → build/tiny_mlp.npuart
# 4. Run and compare against a golden
eulernpu run --artifact build/tiny_mlp.npuart \
--backend cpu_ref \
--golden examples/tiny_mlp/golden.npz
# 5. Same graph, but now on the NPU simulator with a full trace
eulernpu sim --artifact build/tiny_mlp.npuart \
--backend npu_sim --trace trace.json
# 6. Multi-board comparison of the same graph
eulernpu profile --artifact build/tiny_mlp.npuart --all-boards
# 7. INT8 quantize using a calibration dataset
eulernpu quantize --artifact build/tiny_mlp.npuart \
--calib-data data/calib/ \
--out build/tiny_mlp_int8.npuart
The examples/ directory ships several models you can run this
sequence against (MLP, CNN, single-block Transformer, LSTM anomaly
detector, transformer policy, quantized CNN, MoE, decoder + KV
cache, and several op-level demos). Each ships a spec.yaml,
weights.npz, input.npz, and a golden.npz for the compare step.
Tutorials — read these in order
The tutorials are the intended entry point. They are short (100 – 200 lines each), fully runnable, and available in Korean and English:
| # | Topic | Korean | English |
|---|---|---|---|
| 01 | Overview — identity, spec layers, backends | ko | en |
| 02 | Validate — schema + 20 semantic rules | ko | en |
| 03 | Compile / Run — artifact → result → golden | ko | en |
| 04 | npu_sim — cycle model + trace + profile |
ko | en |
| 05 | Quantize — INT8 / INT4 workflow | ko | en |
| 06 | Model examples — catalog | ko | en |
| 07 | FPGA overview — Zynq + 7-stage silicon flow | ko | en |
| 08 | KWS silicon — canonical, 8.07× speed-up | ko | en |
| 09 | Bearing silicon — deeper graph, 11.13× | ko | en |
| 10 | LLM L2 hybrid silicon — honest slowdown | ko | en |
If you only have ten minutes: read 01_overview and 08_kws_silicon.
Silicon-proven demos
Three demos have been synthesised end-to-end and run on real silicon (QMTECH XC7Z020 CLG484-1). Every number below comes from a UART capture on a board, not a prediction:
| Demo | What | Silicon Result |
|---|---|---|
| KWS (tutorials 08) | DS-CNN + GRU keyword spotter (11 commands), full graph as one PL IP (Apple-ANE style) | 11 / 11 CPU ↔ NPU MATCH · NPU 8.07× faster than ARM Cortex-A9 (3.17 ms vs 25.7 ms per inference) |
| Bearing (tutorial 09) | 4-class CWRU vibration fault classifier (Conv1D × 3 + GAP + FC) | 40 / 40 MATCH · 200-window monitor 150 / 150 fault detect, 0 false alarm · NPU 11.13× faster (4.0 ms vs 44 ms) |
| LLM (tutorial 10) | 10.77 M-parameter nanoGPT, L2 hybrid: FFN block on PL, embed / attention + KV / LayerNorm / sampling on ARM | 5 / 5 byte-equal MATCH · live 50-char Shakespeare generation · NPU 2.20× slower per token (honest wrap-safe benchmark — bottleneck: 6 m_axi pointers share one bundle=gmem and serialise weight bursts) |
These three form a silicon ladder:
- KWS proves the toolchain end-to-end on a graph that fits
in BRAM: single IP, weights baked in as ROM, one
ap_startper inference. Cleanest "the toolchain works" evidence. - Bearing carries the same L3 pattern to a deeper graph (3
Conv1D layers) and hits a resource ceiling — first-pass II=4
spilled to DSP 231 % / LUT 265 %;
ALLOCATION operation instances=fmul/fadd limit=4+ II=64 restored the budget. - LLM is a deliberate departure — a 10.77 M-parameter
model does not fit in 140 KB of BRAM, so only the FFN block goes
to PL and the rest stays on ARM. The measurement is honestly
slower than the CPU on this chip; the wrap-safe benchmark
(
BENCHMARK.md) names the exact bottleneck and the four ways to flip the ratio on a larger board.
The LLM demo is deliberately included even though the NPU is slower — because that is what measuring instead of guessing looks like. The same toolchain that ships an 11× speed-up in one demo tells you the truth when there isn't one in another.
The CLI
Every feature is a subcommand of the single eulernpu entrypoint.
Hyphen-joined variants (eulernpu-info, eulernpu-compile, …) are
not supported.
| Command | What |
|---|---|
eulernpu info [--ops] [--dtypes] |
Backend capabilities, operator groups, dtypes |
eulernpu validate <spec> |
Schema + semantic validation |
eulernpu compile --spec <yaml> --target <backend> |
Spec → .npuart artifact |
eulernpu run --artifact <art> --backend <backend> |
Execute (with optional --golden) |
eulernpu sim --artifact <art> --backend npu_sim |
Functional sim + trace + per-op cycles |
eulernpu profile --artifact <art> [--all-boards] |
Per-op profile (or 5-board comparison) |
eulernpu sweep --artifact <art> [--systolic 8,16,32] |
Board × systolic Pareto sweep |
eulernpu quantize --artifact <art> --calib-data <dir> |
INT8 quantization workflow |
eulernpu explain --artifact <art> |
Graph + memory plan + PL offload analysis |
eulernpu generate --artifact <lm.npuart> |
Autoregressive token generation (decoder LMs) |
eulernpu migrate-spec <spec> --from 0.4 |
Bump spec_version + list new requirements |
eulernpu board smoke --target <zynq_ps|zynq_pl_stub> |
Board smoke test (emulated) |
eulernpu benchmark / replay / calibrate / compress-cache |
Profiling utilities |
Every error message is three lines:
<Category>: <what happened>
Fix: <one-line guidance>
See: <doc path>
Full reference: docs/cli.md.
Architecture in one page
docs/architecture.md— a one-page summary: system layers, data flow, spec structure, compiler pipeline, artifact format, runtime dispatch,npu_simcost model, PL partitioning, and the determinism / reproducibility guarantees the whole stack rests on.
Reading it before the tutorials makes CLI output and error messages easier to place.
Testing
python -m pytest # full suite
python -m pytest tests/hls/ # HLS-kernel equivalence + silicon anchor
python -m pytest tests/integration/ # end-to-end integration
Test strategy, coverage layers, and CI gates:
docs/testing.md.
Highlights the suite enforces:
- Every valid spec fixture is compiled and executed on
cpu_ref. - Every invalid spec fixture is checked to fail with the expected rule code (regression assets — never deleted, never weakened).
npu_simnumerical equivalence withcpu_ref(atol = rtol = 1e-5).- Silicon anchor:
matmul_systoliccycle model must stay within ±10 % of the P06 measured 460 cycles.
License
eulernpu is dual-licensed.
Open Source — AGPL v3
Available as free, open-source software under the GNU Affero General Public License v3.0 (AGPL-3.0).
Under the AGPL, you may freely use, modify, and distribute
eulernpu provided that any modifications and any software that
incorporates or links with eulernpu — including network
services — are also released under the AGPL.
Ideal for:
- Academic and research use
- Open-source projects
- Internal evaluation
Commercial License
A commercial license is available for organisations that:
- Distribute
eulernpuas part of a proprietary product or embedded system - Provide SaaS / API services built on
eulernpuwithout open-sourcing their stack - Require OEM or redistribution rights (defence, industrial, medical devices)
- Need support agreements or IP indemnification
Contact: licensing@eulerwa.com Details: COMMERCIAL_LICENSE.md
Not sure which applies? If your use of
eulernpuis entirely internal and never exposed over a network, standard AGPL terms likely apply without a commercial license. For any commercial deployment or distribution, contact us.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file eulernpu-0.1.0.tar.gz.
File metadata
- Download URL: eulernpu-0.1.0.tar.gz
- Upload date:
- Size: 197.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cd189faa1c70b393acae9e15f8ad8c0014857380bf822e677f769350192dffc3
|
|
| MD5 |
aa75167f97f30db4a5c916eee58e8a13
|
|
| BLAKE2b-256 |
6afe8ddc9368645711b20a4055d47fb2ba6845536810cb0c4fcd250d028565e4
|
File details
Details for the file eulernpu-0.1.0-py3-none-any.whl.
File metadata
- Download URL: eulernpu-0.1.0-py3-none-any.whl
- Upload date:
- Size: 222.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
557daf4e231f94ab60f4692165662ccac06d6dc138fc481cd303eaf26d08070a
|
|
| MD5 |
bf745561a0e539c30f7f6e5833680d81
|
|
| BLAKE2b-256 |
d4cd5d4cbcc6b30834b26d1f685fa464d56c7d01d7bfb2c37e697f6e681f0848
|