Files
essim/doc/user/analysis.md
François 7d307dad57 Export command (CSV + ODS), file dialog, error modal, path persistence.
New user-facing features:
- `export connections <file>` writes a tabular dump of every wire pair:
  connection, transform, left/right module/part/pin/signal/type/suspect,
  mixed-types flag. Dispatch on extension: `.csv` (flat file) or `.ods`
  (one sheet per connection). Any other extension shows an error and
  writes nothing.
- Bare `export` (or dashboard `[x]`, or palette `export`) opens an
  interactive file-picker dialog with a CSV/ODS toggle at the top.
  Picking a filter rewrites the filename's extension. Last-used
  directory and filename are remembered per-call-site.
- Two new CLI flags on the binary: `--source FILE` to run a script at
  boot, `--restore FILE` to restore a snapshot at boot. Combinable.

Reusable infrastructure:
- `OdsWriter` (`src/imports/ods_writer.{hpp,cpp}`): minimal .ods writer
  using libzip + pugixml (already in the build for the importer).
  Multi-sheet workbook of string cells. ~180 lines, no new dep.
- Generic file-picker dialog (`screen_filedialog.cpp`): one Modal
  reused for any "pick a path" interaction via
  `OpenFileDialog(title, persist_key, default_filename, filters, cb)`.
  Validates the picked extension against the filter whitelist;
  unknown ones stay in the dialog with a status message. Persists
  (dir, filename) per `persist_key`.
- Generic error modal (`screen_error.cpp`, `ShowError(msg)`): centred
  red-titled popup, dismissable with Esc/Enter. Used by the export
  failures (open-for-write, ODS save, unknown extension/kind);
  ready for adoption elsewhere.
- Per-key path persistence (`SaveLastUsed`/`LoadLastUsed` in
  `shell.cpp`): two-line file per key under the user-data dir.
- `UserDataDir()` extracted from the history path helper so the new
  per-key persistence shares the same XDG/AppData logic.
- New help-screen topic "Export"; user-facing `doc/user/analysis.md`
  gains an "Exporting" section; `DESIGN.md` gains a generics
  section covering the dialog / error modal / persistence / ODS
  writer; `DumpCommandsMd` now respects the `hidden` flag (the
  `connect` alias no longer appears in the auto-gen reference).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-16 12:03:39 +02:00

7.2 KiB

essim — how the analysis classifies things

essim looks at signal names and the way pins are wired to decide whether a net is a power rail, a ground, a diff pair, a bus, etc. This page summarises those rules in plain language so you know what to expect when you run analyze (the [a] shortcut on the dashboard) or when you read the numbers on the home screen.

Nothing here mutates anything you cannot fix manually: every inference can be overridden with set-signal-type, and the rules are re-run on every load so the picture stays consistent with the netlists currently in memory.

Signal type — Power / Gnd / Other

Every signal is classified into one of three buckets.

Gnd if the name matches one of: GND, GROUND, EARTH, SHIELD, CHASSIS (or starts with any of those followed by _). The name alone is enough — false positives here are essentially nil.

Power is a two-stage decision:

  1. The name has to suggest power — it contains PWR, POWER, VCC, VDD, VEE, VSS, VBAT, or starts with VS_, VS3_, +5V-style or -12V-style prefixes.

  2. The wiring has to corroborate it. essim requires at least one of:

    • the signal lands on 4 or more pins (a real rail goes to decouplers + ICs + connectors, so it almost always has many pads), or
    • the name contains a voltage value3V3, 5V, 12V, 0V9, 5V0, etc. (any V next to a digit).

    Hard floor: a signal touching fewer than 3 pins is never Power, even if both 1 and the voltage motif are present. Physically you cannot have a rail on 1 or 2 pads.

Other in every other case.

This rule deliberately rejects things that look like power but aren't: PWR_OK (status), VSEL_0 (voltage select), VDD_SENSE (sense feedback) — they all match step 1 but fail steps 2/3. The analyze screen lists them under Suspect Power with the reason attached (fan-out 1, no voltage etc.). Inspect, then either accept the suspect status or force it back with set-signal-type.

NC (no-connect) pins

A pin is shown as (NC) in the explore detail when it has no signal attached. essim distinguishes three reasons:

  • Imported NC — the netlist explicitly says the pin is unconnected (Mentor format: signal name unconnected or unconnected (by TERM); Altium format: the pin is simply omitted from every signal block).
  • Dropped singleton — after import, essim removes every signal that touches exactly one pin. A net with a single endpoint cannot carry signal anywhere, so the pin is detached and tagged. This catches both intentional sentinels and the per-IC NC_* labels that customers often put on dead pads.
  • Filled at connect — when you connect two parts that don't agree on which pins exist (a Mentor part may have all pads, an Altium part only the wired ones), essim materialises the missing pads on the smaller side. They are unconnected locally on that module but are bridged to a real signal on the other module via the connection — so they do not count as orphans.

The dashboard's "NC" row summarises orphan counts (imported and dropped only; filled-at-connect pins are excluded). The analyze screen's "Types" tab adds a trailing line with the totals.

Signal groups

essim groups signals that share an obvious structural pattern. They are detected per module — a multi-card bus on the system is the BFS union of the per-module groups it touches.

Diff pair — two signals named STEM_P and STEM_N (case-insensitive, _ required before the polarity letter). Both halves must be present. Lone _P halves are flagged as orphans; lone _N halves are not flagged (the _N suffix is overloaded with active-low semantics — RESET_N, BOOTMODE_N — and flagging them would flood the report).

Diff bus — at least two diff pairs whose stems share a common prefix and only differ by a trailing index: MDI0_P/MDI0_N, MDI1_P/MDI1_N, … → MDI[0..3]_P/N. Both STEMN and STEM_N forms work (MDI0, PCIE_TX_0).

Bus — at least two signals with a common stem and a trailing integer index. Two notations: DATA[0], DATA[1], … (bracketed) or ADDR_0, ADDR_1, … (underscore — strict: an underscore is required between the stem and the digits, so a name like GETH_01_VDD12 is not a bus).

Anomalies are emitted alongside groups:

  • Diff pair orphan: a _P with no matching _N.
  • Diff bus gap: e.g. MDI[0..3] has MDI0, MDI1, MDI3 (MDI2 missing).
  • Bus gap: same idea on plain buses.

Internal Mentor net names that start with $ (like $N12345) are skipped from every group/bus detection.

Issues reported by analyze

The Issues tab of the analyze screen aggregates everything that deserves attention:

Tag What it means
[pin-role] A connector pin is typed (via set-connector-type) as Power or Gnd but the actual signal landing on it disagrees.
[net-mix] A net bridged across modules carries both Power and Gnd signals — almost always a topology mistake.
[diff-pair-orphan] STEM_P with no STEM_N in the same module.
[bus-gap] A bus is missing one or more index values inside its range.
[diff-bus-gap] A diff bus is missing one or more lane indices.

Zero issues = the module passes every structural check essim knows how to run today.

Overrides

Every classification is advisory. To force a different type:

  • Signal type: from the explore screen, press Enter on a signal entry → a popup lets you pick power / gnd / other. The same popup also opens when you press Enter on a pin row in the parts detail (changes the pin's signal type) or on a net member row in the signal detail (works across modules). Or type set-signal-type <module> <signal> <type> in the console (or from the palette).
  • Connector type: from explore with type = parts, press Enter on a part to jump to the dedicated set-connector-type screen with that part pre-selected and the cursor on the type input. The set-connector-type command also keeps working from the console / palette.
  • Connector type: set-connector-type <module> <part> <connector-kind> (also via the dashboard [t] shortcut). This drives the pin role expectations, which feed the pin-role check.

Overrides survive save/restore but are recomputed at every load (i.e. the inference re-runs).

Exporting

Dump structured data to an external file:

  • export connections <file> — every wire pair, one row, with the signals and types on both sides plus a suspect flag (name says Power but the structural check disagreed) and a mixed flag (both sides typed but disagreeing).
  • The dashboard's [x] shortcut, the export command without arguments, or the palette entry export: opens an interactive file-picker dialog. A small toggle at the top of the dialog lets you pick the format — CSV (flat, one row per wire) or ODS (one sheet per connection, opens directly in LibreOffice / Excel). The dialog remembers the directory and filename you used last so the next export resumes from there.
  • Inline scriptable form: export connections /path/foo.csv (or .ods). Unknown extensions raise an error popup.