Days
Architectural Design

Simulation Engines

Execution and lifecycle boundaries for the exact and legacy engines.

Scope: Days AGO and Legacy Days. Days does not have one interchangeable runtime API. The exact engine consumes a compiled SimulationImage; the legacy engine builds and runs Nexosim models.

Exact transition engine

The exact image is a closed data structure: model kinds, event kinds, state ownership, initial payloads, and channels are known before execution. An event identifies its target LP and carries a fixed payload rather than a callback. The transition code in executor/src/scalar.rs updates the target's owned state and emits local or remote events with canonical keys.

The same transition contract is used by five entry paths:

  • run_scalar: one global ordered event calendar
  • run_scalar_rounds: single-threaded reference execution with per-LP queues and safe horizons
  • run_cpu: persistent workers that own complete LPs
  • run_metal and run_cuda: planned device arenas and device round execution

Every path returns the same normalized RunResult contract. Device backends omit diagnostic-only observation planes, but not canonical state or measurement results.

Exact safe-horizon lifecycle

For the round paths, executor/src/safe_horizon.rs and the parallel backends repeat:

  1. Find the minimum pending LP frontier.
  2. Set an exclusive horizon to frontier + minimum_channel_lookahead, clamped to the run boundary.
  3. Drain every active LP strictly before that horizon.
  4. Collect cross-LP outboxes.
  5. Sort remote events canonically and merge them at the barrier.
  6. Update the sparse frontier and begin the next round.

The minimum delay on every cross-LP channel makes the drain safe: work emitted in the round cannot arrive below the horizon. Global scalar does not need this rule and can run a zero-delay image; all round and parallel paths reject nonpositive lookahead.

Legacy Nexosim lifecycle

The legacy simulator uses actor-like models with async handlers:

  • Mailbox<M> is a bounded inbound queue.
  • Output<T> connects one model to typed handlers on other models.
  • Context exposes the scheduler and authoritative MonotonicTime clock.
  • SimInit registers models and selects the single-threaded or multithreaded executor.

legacy/src/topos/topo.rs creates and connects switches, per-edge schedulers, endpoints, optional wires and L2/PFC models, and the UI. It then initializes a Nexosim Simulation, injects source start events, advances through the configured integer-nanosecond stop time, collects sink statistics, and flushes enabled logs.

With threading = "single", Topology::new selects one Nexosim worker. With threading = "multiple", it uses num_threads or the detected CPU count. hot_workers and concurrency_level tune the vendored executor; they do not configure exact CPU ownership.

See Nexosim for the legacy runtime API and /docs/internals for exact executor internals.

On this page