> ## Documentation Index
> Fetch the complete documentation index at: https://docs.embedder.com/llms.txt
> Use this file to discover all available pages before exploring further.

# XMOS xsim

> Run an XMOS application in simulation, inspect its output, and record instruction traces.

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`:

```json theme={"system"}
{
  "xe": "bin/app.xe",
  "target": "simulator"
}
```

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

```text theme={"system"}
Run bin/app.xe in xsim, using the simulator selection in .embedder/xmos.json.
Wait up to 10 seconds for BOOT_OK, show the console output, and stop the
simulation. Do not use the connected physical board.
```

Replace `BOOT_OK` with a message your firmware emits. For a repeatable check, save this as `.embedder/hardware/sim_boot.py`:

```python theme={"system"}
xsim.start(xe="bin/app.xe")
xsim.wait_for_output(text="BOOT_OK", timeout_seconds=10)
print(xsim.console_log(max_chars=4000))
xsim.stop()
```

Run it through Embedder's [hardware-script runner](/debug-mode/hardware-scripts). 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](/debug-mode/xscope) can show simulated application output. Use [XMOS debugging](/debug-mode/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:

```text theme={"system"}
Record an xsim instruction trace for bin/app.xe. Retain the latest 100000
instructions, stop after a short boot run, and summarize the active tiles,
logical cores, and functions. Show the result in the Trace tab.
```

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](/debug-mode/hardware-scripts), live during recording or after `xsim.trace_stop()`:

```python theme={"system"}
session = xsim.trace_start(max_instructions=200_000)
xsim.wait_for_output("BENCH_DONE", timeout_seconds=30)
xsim.trace_stop()

print(xsim.trace_summary(session))
page = xsim.trace_instructions(session, tile=0, after_index=-1, limit=1000)
print(xsim.trace_hotspots(session, group_by="line", tile=0, limit=50))
```

`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.
