# essim — scripting This page covers the two facilities that make essim sessions reproducible: `source` (replay a file) and `set` (declare named variables that subsequent commands expand). For the per-command reference, see [`commands.md`](commands.md). ## File format A script is a plain text file, one command per line. The format is intentionally minimal: - Lines starting with `#` are comments — skipped. - Blank lines are skipped. - Leading / trailing whitespace is trimmed. - A leading `~/` in arguments is expanded to `$HOME` (paths only). - Each line goes through the same `Submit` path as if typed at the prompt, so anything that works interactively works in a script *except* commands that open an interactive screen (see below). By convention essim scripts use the `.essim` extension. ## Variables — `set` and `$expansion` `set ` declares a **session-scoped** variable. Subsequent commands expand `$name` and `${name}` in their arguments: ```text > set netlist_dir /path/to/netlists > set backplane_nets $netlist_dir/backplane.NET > load backplane $backplane_nets altium ``` Names must match `[A-Za-z_][A-Za-z0-9_]*`. Unknown variables are left literal (`$undef` stays `$undef`) so a typo surfaces as a "file not found" or "unknown module" error rather than a silent empty string. The expansion happens at **dispatch time**, between recording the canonical form and calling the action. So: - `history` and `script-save` keep the **unexpanded** form (`$backplane_nets` is preserved as `$backplane_nets`), which makes the recorded script portable across sessions if you set the variables before sourcing it. - The action itself sees the resolved value (the actual filesystem path). `new` resets the variable table to empty. ## Replaying — `source ` `source ` runs the script line by line. Three behavioural details are worth knowing: 1. **Event-paced execution.** The runtime processes one effective line (skipping comments / blanks) every ~30 ms tick, dispatched by a background thread that posts FTXUI events. This lets the screen redraw between lines and surface a centred `Computing…` modal with a `N / M lines` counter. Without this pacing, FTXUI would batch queued events and freeze the modal until the entire script is done. 2. **Interactive screens are rejected.** If a sourced line opens a full-screen mode (`screen_idx != 0` after `Submit`), the script is aborted with `source: line is interactive (would open a screen) — aborting.`. The fix is to use the inline form of that command (e.g. `connect backplane J20 payload1 P0` instead of a bare `connect`). 3. **Pending prompts are filled by subsequent lines.** A multi-step command split across lines is treated as one logical unit. If the first line says `load`, the next non-blank line answers the `module name?` prompt, then `filename?`, then `import type?`. While `in_source = true`: - `Dispatch` / `Finalize` skip writing to memory + on-disk history. - The `recorded` buffer (used by `script-save`) is still populated with each effective line; so sourcing a script and immediately running `script-save` produces a self-contained replay even if the original source path is lost. ## Recording — `script-save ` `script-save ` dumps every command issued since the last `new` into ``, one line per command, in canonical inline form. The following commands are deliberately **not** recorded: ``` clear, help, quit, exit, source, script-save ``` `source` is excluded for a subtle reason: when you source a script, the individual lines inside it go through `Finalize` and *are* recorded, so the saved replay reproduces the same end-state without the indirection. `set` lines and `$var` references are recorded as typed, so the saved script keeps its abstraction. ## Worked example The `test/system.essim` script (committed in the repo) is the canonical anonymised bring-up — one backplane, four payload cards, three peripherals: ```text new # variables set netlist_dir /path/to/netlists set peripheral1_nets $netlist_dir/peripheral1.qcv set backplane_nets $netlist_dir/backplane.NET # ... more set lines ... # modules load payload1 $payload_nets mentor duplicate payload1 payload2 duplicate payload1 payload3 load peripheral1 $peripheral1_nets mentor load backplane $backplane_nets altium # ... more loads ... # connector type tagging set-type backplane J20 vpx-3u-bkp-p0 set-type payload1 P0 vpx-3u-payload-p0 # ... more tags ... # wiring connect backplane J20 payload1 P0 # ... more connects ... ``` Run it with `source test/system.essim` after adjusting `$netlist_dir` to point at your real netlist files.