Developer Manual¶
This manual is for people who modify or extend Lince — adding peripherals, ISA frontends, or JIT passes; changing the execution model; or working on the RTEMS pass-rate goal. It explains not just what the code does but how it is conceived and why each decision was made. For running or embedding Lince, see the User Manual.
Read this first
The repository's CLAUDE.md is the canonical statement of the project's
identity, frozen technical decisions, coding conventions, and the
Architectural Decision Records (ADR-001..004). Every page here is the prose
expansion of it and must stay consistent with it.
The big picture¶
flowchart TD
app["lince_app (lince-emu CLI)"] --> rt["lince_runtime<br/>(Emulator, scheduler, GDB, ELF loader)"]
rt --> core["lince_core<br/>(SPARC V8 ISA, CpuState, decoder, traps, FPU)"]
rt --> per["lince_peripherals<br/>(IRQMP/IRQAMP, GPTIMER, APBUART, …)"]
rt --> jit["lince_jit (LLVM ORCv2)"]
rt --> arch["lince_arch_sparc (SPARC → IR)"]
per --> bus["lince_bus (SystemBus, RAM)"]
jit --> ir["lince_ir (arch-neutral IR, GuestState)"]
arch --> ir
core --> if["lince_interfaces (types, I* seams)"]
ir --> if
bus --> if
Dependencies flow one way: interfaces ← core, bus ← peripherals ← runtime ←
app, and the translation stack layers as interfaces ← ir ← {arch/sparc, jit}
← runtime. lince_ir works on an opaque GuestState blob — a byte-addressed
snapshot of the guest CPU registers carrying no ISA-specific knowledge — and so
does not depend on lince_core; any ISA frontend can target it. These
boundaries are enforced, not aspirational — see
Layers and modules.
Where to start¶
| Topic | Page |
|---|---|
| How the whole thing is conceived | Architecture overview |
| Module/layer graph and dependency rules | Layers and modules |
| The non-negotiable design rules and why | Design principles |
| The frozen decisions and ADRs | Design decisions |
| Switch interpreter vs LLVM JIT, the run loop | Execution model |
| Arch-neutral IR and the tiered LLVM JIT | IR and LLVM JIT |
| Adding a new ISA frontend (e.g. ARM) | Adding a frontend |
| SPARC traps, register windows, interrupts | Traps and interrupts |
| Round-robin & MultiThread SMP, time, events | Multicore and timing |
| Bus, memory API, endianness | Memory and bus |
The IPeripheral framework |
Peripheral system |
Per-target (lince_*) reference |
Modules |
| Status, roadmap, performance | Development |
| Generated C++ API | C++ API |
How to extend Lince¶
| Goal | Start at |
|---|---|
| Add a peripheral | Peripherals → Custom peripherals |
| Add an ISA frontend | Adding a frontend |
| Add a SoC recipe | Configuration + Memory and bus |
| Add a test | Testing |