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>
163 lines
7.2 KiB
Markdown
163 lines
7.2 KiB
Markdown
# 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 value** — `3V3`, `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.
|