Lince¶
A C++20 functional emulator for the LEON3 / LEON4 SPARC V8 processors, designed to boot the RTEMS testsuite and to be wrapped as an SMP2 simulation model for the European space industry.
Lince emulates the GR712RC (dual-core LEON3FT) and GR740 (quad-core LEON4FT) System-on-Chips at the functional level: the CPU, memory, bus, interrupt controller, timers and UART are modelled with bit-accurate register semantics, while caches, MMU and FPU are deliberately scoped out of the MVP and tracked in the Phase 7 roadmap.
Why Lince exists¶
Most existing LEON3/LEON4 simulators fall into two camps:
| Strength | Weakness for our use case | |
|---|---|---|
| QEMU SPARC | Fast | Generic SPARC32, not LEON3-faithful in peripherals or trap timing |
Lince picks a third path: functional but bit-accurate at the register level, open, embeddable as a C++ library, and architected from day one to be wrapped as an SMP2 simulation model.
It is fast enough to run RTEMS to completion, faithful enough that the RTEMS BSP-level testsuite passes 10/10, and small enough that adding a custom peripheral takes a single file.
What you get¶
-
Full SPARC V8 integer ISA
Register windows, traps, privileged instructions, delayed PSR pipeline, branch annul, RETT — everything an OS needs.
-
GR712RC peripherals
IRQMP (multi-core), GPTimer (4 sub-timers + watchdog), APBUART (FIFO + IRQ), MemCtrl (FTMCTRL stub).
-
Trivial extensibility
Implement
IPeripheral, register withadd_peripheral(). DMA, IRQs and timed events all work out of the box. -
GDB remote stub
Bind a TCP port, attach
sparc-rtems-gdb, set breakpoints, step, inspect registers. Designed for early-boot debugging. -
263 tests, 0 warnings
Catch2 unit + integration suite. Real RTEMS sptests run in CTest.
-Werrorwith a strict warning set. -
SMP2-ready boundaries
Every external dependency is an injected interface (
ILogger,ITimeSource,ICharacterDevice, …) ready to be mapped to SMP2 services.
Quick taste¶
#include "lince/runtime/emulator.hpp"
#include "lince/runtime/emulator_config.hpp"
int main() {
auto cfg = lince::runtime::gr712rc_config();
cfg.num_cores = 2;
cfg.ram_size = 16 * 1024 * 1024;
auto emu = lince::runtime::Emulator::create(cfg).value();
emu->initialize();
emu->load_elf("rtems_hello.elf");
auto result = emu->run_for(lince::SimTimeNs{5'000'000'000ULL});
// UART output already written via the injected ICharacterDevice.
}
Or from the shell:
Get started in 5 minutes Read the architecture
Project status¶
The MVP (Phases 0–6) is complete. 263 tests pass, RTEMS hello-world
boots cleanly through the APBUART, and 10 RTEMS sptests reach
*** END OF TEST. Phase 7 — Berkeley SoftFloat FPU, SRMMU, GDB stub,
real cache control and full SMP — is in progress.
| Phase | Title | Status |
|---|---|---|
| 0 | Scaffolding | Done |
| 1 | Memory and Bus | Done |
| 2 | Integer ISA without traps | Done |
| 3 | Traps, window overflow, privileged | Done |
| 4 | Minimal peripherals | Done |
| 5 | RTEMS 5 boot | Done |
| 6 | Testsuite + demo peripheral | Done |
| 7 | FPU, MMU, GDB stub, SMP, cache | In progress |
SMP2 readiness¶
The architecture follows the ECSS-E-ST-40-07 lifecycle:
…even though the SMP2 wrapper itself is not part of the MVP. Every external service the core needs is injected through an interface, so the wrapper is a pure adapter layer rather than a refactor.
| Lince interface | Default impl | SMP2 mapping |
|---|---|---|
ILogger |
StdoutLogger |
Smp::Services::ILogger |
ITimeSource |
Internal SimTimeNs |
Smp::Services::ITimeKeeper |
IPublisher |
DebugPublisher (JSON) |
Smp::IPublication |
IFaultInjector |
NullFaultInjector |
Custom SMP2 ops |
ICharacterDevice |
StdoutCharDevice |
SMP2 output field |
IEntryPoint |
Direct calls | Smp::IEntryPoint |
IExternalPort |
Loopback | Smp::LinkRegistry |
License¶
Lince source code is released under the Apache License 2.0.
Vendored third-party components retain their upstream licenses
(see THIRD_PARTY_LICENSES.txt).