Skip to main content
Use xsim to run an XMOS .xe application without an xTAG or physical board. Results describe the simulated target. They do not establish real-board electrical behavior or hardware timing.

Set up a simulated target

  1. Install XMOS XTC Tools with xrun, xsim, xgdbserver, and xgdb, and build the .xe application.
  2. For a custom installation, set EMBEDDER_XTC_PATH to the XTC root or bin directory in the environment launching Embedder.
  3. Select the simulator explicitly in .embedder/xmos.json:
Replace the artifact path with your project-relative .xe path. Ask Embedder to check simulator readiness before starting. The installed Embedder build must include simulator support for your host; finding XTC Tools alone does not establish that the complete integration is ready.

Run and inspect output

Replace BOOT_OK with a message your firmware emits. For a repeatable check, save this as .embedder/hardware/sim_boot.py:
Run it through Embedder’s hardware-script runner. A missing message raises a timeout; inspect the output and simulator state before assuming a firmware defect. Cleanup stops a simulation started by that script. A simulation it reused is not automatically stopped by cleanup. The xSCOPE Monitor can show simulated application output. Use XMOS debugging with simulator=True when you need breakpoints, stepping, tiles, registers, or stack frames. Starting a debugger is a separate workflow and can replace a standalone simulation.

Record an instruction trace

Start the trace before launching an ordinary simulator run:
The trace records retired instructions with tile, logical core, PC, symbol, and tile-clock cycle. It uses symbols from the .xe; no separate ELF is required. Ask Embedder to stop recording when the interval is complete, then inspect the Trace tab or request a summary. The default retained window is one million instructions across tiles and cores. The instruction limit is a rolling window: older rows are removed as newer ones arrive, rather than stopping execution at that count. A recording has a ten-minute wall-clock limit. Boot-ROM tracing is off by default; request it explicitly when needed. Cycle values describe the simulator’s tile clock. Convert cycles to time only with the correct simulated clock frequency. They are not host elapsed time or a measurement of a physical board. If an existing simulation was started without instruction tracing, trace startup fails instead of silently replacing it. Stop that simulation and start the trace first. Stopping a trace also stops a simulation launched by that trace; a compatible simulation that was already running remains available.

Analyze the capture from Python

xsim.trace_start() returns a session_id you can query from hardware scripts, live during recording or after xsim.trace_stop():
trace_summary, trace_instructions, and trace_hotspots accept tile, core, start_cycle, and end_cycle. Cycle ranges are half-open (start_cycle <= cycle < end_cycle) and require a tile because tiles have separate clocks. Hotspots group by function, line, or address and count actual retained rows; unresolved rows appear as a separate counter rather than silently changing the total. Instruction pages use absolute indices, so pass the returned next_after_index to page forward and check cursor_evicted and window_truncated when the rolling window advances. New captures freeze the .xe and extract one application ELF per tile for source-line lookup; legacy or attached captures without a frozen image report their source provenance as unavailable.

Sim IO and pin driving

Configure the sampled pins with sim.pins in .embedder/xmos.json. The plugin samples them each tick and streams edges to the Sim IO tab. sim.sampleMhz controls the sampling rate and sim.vcd also writes ports.vcd for tile[0]. From a hardware script you can subscribe to pins, force them, release them, and sample memory through xsim.* helpers. From the Monitor’s Sim IO tab you can watch pins animate and force values live. Never put user paths with spaces in sim.args; those arguments travel through --sim-args and cannot be shell-quoted. Do not put --max-cycles in a debugger-owned simulator; xgdbserver never stops on it.

Troubleshoot

  • No .xe found: build the project and correct xe in .embedder/xmos.json.
  • Simulator support unavailable: check that the installed Embedder build supports your host and that XTC Tools is complete.
  • Output wait times out: inspect the console, paused/running state, and expected message; increase the bounded wait only when the firmware needs it.
  • Instruction tracing was not enabled: stop the ordinary simulation and start the trace before the next run.
  • The beginning of the trace is missing: use a shorter capture or a larger retained instruction window.
  • A simulation exits at its cycle limit: check additional simulator arguments. A debugger-controlled simulation does not honor the standalone --max-cycles limit in the same way.
Last modified on September 12, 2026