Building a programmable packet processor from chip to programming language. 🐻❄️
Landing page · Playground — the eDSL, IR, and assembly, live in your browser, with a step-scrubber debugger that walks each packet through the IR interpreter and an instruction-set simulator in lockstep.
Nanuk is an educational project: a programmable packet-processing pipeline of two sibling ISAs (inspired by xISA) — a parser engine that classifies packets and a match-action engine whose lookup tables ARE the forwarding policy. Both are specified formally in Sail with generated golden-model emulators, assemblers, a Python eDSL compiling to a protobuf IR (with step-exact interpreters and a Z3 symbolic executor), and Amaranth RTL cores cosimulated against the specs — demonstrated end to end by pushing real traffic through the composed pipeline in a SimBricks network simulation: table-driven forwarding, live policy swaps, and a two-switch tunnel speaking an invented protocol. A Tiny Tapeout chip is deferred to future work. See docs/superpowers/specs/ for the full design.
spec/sail/ Sail ISA models (the source of truth: model/{pp,map}) and the
generated golden-model emulators
spec/proto/ The protobuf IR schema (nanuk.ir.v0) — the language-neutral
interchange contract; each implementation vendors its gencode
sw/python/ The Nanuk package, three descending abstraction levels: nanuk.lang
(eDSL) -> nanuk.ir (protobuf IR, lowerings, interpreters, symex)
-> nanuk.isa (assemblers, encodings, ISS). Plus its test suite
(tests/; the golden-model pcap rig = tests/golden) and
nanuk.testkit, the conformance machinery every suite shares.
hw/amaranth/ The Nanuk core in Amaranth: PP (parser processor) + MAP
(match-action processor), with cosim tests judging them against
the ISS oracle and the Sail golden models.
examples/ Example programs: hand-written asm paired with its eDSL twin
benchmarks/ The graded suite the ISA answers to: expressiveness ladders for
each processor, the coverage audit against four reference corpora,
and e2e/ — the SimBricks scenarios plus the rig that runs them
docs/ Design docs, plans, and lab notes
benchmarks/e2e/build_and_run.sh runs the end-to-end demo: two QEMU Linux
hosts exchange real traffic through the Verilator'd Nanuk PP
inside SimBricks — ping works because the loaded parser program accepts
the frames. Load examples/drop_all/parse.asm instead and the network
goes dark: the parser program is the switch's forwarding policy.
The second application is SIIT (benchmarks/siit/): a
stateless IPv4↔IPv6 translator (RFC 7915/6052/7757) on the same core — the
CLAT half of 464XLAT, the translator quietly running in every phone on a
v6-only network. Try it live in the
playground, or
two guests across address families via benchmarks/e2e/run_siit.sh.
Requires Docker and the devcontainer CLI.
# Build the dev container (Sail toolchain + Python)
devcontainer build --workspace-folder .
devcontainer up --workspace-folder .
# Build the Sail model, emulator, and tests
./dev.sh cmake -S spec/sail -B spec/sail/build
./dev.sh cmake --build spec/sail/build
# Sail model tests + emulator smoke test
./dev.sh ctest --test-dir spec/sail/build --output-on-failure
# The SW suite: ISA, IR, eDSL, golden-model pcap rig, and playground bridge
./dev.sh bash -lc 'cd sw/python && uv sync && NANUK_COSIM=1 uv run pytest tests ../../web/py/tests'
# The HW suite: Amaranth cores (NANUK_COSIM=1 also runs RTL-vs-oracle cosim)
./dev.sh bash -lc 'cd hw/amaranth && uv sync && NANUK_COSIM=1 uv run pytest tests'The first thing Nanuk ever parsed: examples/l2l3l4/parse.asm — Ethernet,
802.1Q (incl. QinQ), IPv4 (incl. options), and UDP parsed by a
12-instruction ISA, verified against a scapy-generated pcap corpus on the
Sail golden model.
docs/development.md has the dev environment, the full test matrix, and repo conventions. Nanuk is a personal educational project and isn't accepting external contributions yet.