AntOS Library — ee (reference)
The
eelibrary is AntOS's single interface to the EE — the Execution Engine RISC-V soft core. One 64-bit core serves both machines — the same RV64 EE sits inside the Ant64's FireStorm and the eZX Spectrum's eZX. Load code and data, run it, read back results and memory, drive contexts and the debugger. Its defining trick: the same API runs against either the real FPGA soft core or a software model of it, chosen by one OS setting, so the software above never knows which answered.
What it is
There is one EE — a 64-bit RISC-V core with the full extension set — and both FireStorm (Ant64) and eZX (the eZX Spectrum) run it. Code is portable between the machines by construction, and ee needs no per-machine target: the only choice is the backend.
Everything that wants the EE to do something — AntBASIC's inline { } RISC-V blocks, a tool, an app offloading a kernel, the OS itself — goes through ee. It handles getting code and data into the EE, starting execution, and returning results, and it deliberately hides where that execution happens.
The interface
- Load — place a code image (narrow or wide) and its data into EE-visible memory (
ee.load(image),ee.write(addr, bytes)), and resolve an entry point. - Run —
ee.call(entry, args…)runs to completion and returns results;ee.spawn(entry)starts an Xctx context and returns a handle to poll or await;ee.halt/ee.resumefor lower-level control. - Results & state —
ee.result(h),ee.getreg(ctx, r)/ee.setreg, andee.read(addr, len)/ee.writefor EE memory (scratchpad, DDR3, MMIO). The register files (x0–x63), PC, CSRs and all 32 contexts are inspectable. - Debug —
ee.step,ee.breakpoint,ee.watch, plus full register / context / stack inspection — richest on the model backend, which sees everything.
Two backends, one API
The library carries two implementations of that interface, and an OS setting picks which is live:
- FPGA backend (default). Drives the real EE on the GoWin FPGA (the same core on either machine):
ee.loadstages code and data over the DeMon↔FPGA link (PCIe / register window — see FPGA),ee.callkicks a context, results and memory return over the same path, and the hard RISC-V coprocessor reads architectural state at silicon speed. Production: real hardware, full speed. - Simulator backend. A functional golden model of the EE ISA — RV64GC plus all the extensions, the narrow/wide instruction encoding, the architectural memory model — running on DeMon's ARM cores. Same API, same results, no FPGA involved: EE code can be written and verified on any machine and runs identically on either system's core.
The switch is a debug option in OS settings — Run EE on: hardware / simulator. Flip it and every ee call retargets; the software above is byte-for-byte identical and never learns which core answered. Software will not know — the API, not the backend, is the contract, so code proven on the model runs on the FPGA unchanged and vice-versa.
Tandem mode — co-simulation
A third setting runs both at once: every ee call goes to the FPGA and the model, and their architectural state is compared after each step. A divergence names the exact instruction where the real core and the specified behaviour disagree — a hardware bug or a spec ambiguity — caught on the live machine, the coprocessor as probe and the model as oracle. Verification becomes a settings toggle over the very programs the system already runs.
Why it's built this way
- Software is backend-agnostic. One contract; the backend is an implementation detail a game, tool, or
{ }block never sees. - Develop without the FPGA. Bring up EE code, the toolchain, and CI on the model alone; move to hardware by flipping a setting.
- Verify on the real board. Tandem mode makes the golden model a co-simulator against the actual soft core — no external rig.
- Debug with full visibility. The model exposes every register, context and stack, more than the on-chip debugger can, behind the identical API.
Native core — libantos_ee
Owns both backends: the FPGA transport (staging, context kick, and state read-back over the DeMon↔FireStorm links plus the hard coprocessor) and the software model of the ISA. The active backend is a runtime setting; the model is always built in, so a machine can run EE code even while the FPGA is reloading a personality or absent entirely.