docs: document the PinSpec refactor + add a Dependencies section

DESIGN.md: Pin now carries a PinSpec (function/direction/pad/source);
expected_signal_type() is a derived accessor; pin_role() returns a PinSpec.
README.md: dedicated Dependencies section with libzip/pugixml install
commands for Debian/Ubuntu, Arch and Fedora.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-03 12:31:34 +02:00
parent 1b507f1752
commit 86236d744d
2 changed files with 19 additions and 14 deletions

View File

@@ -24,15 +24,16 @@ src/
syselmts.hpp SystemElement + SystemElementContainer<T> (templated, get/merge/iterate) syselmts.hpp SystemElement + SystemElementContainer<T> (templated, get/merge/iterate)
modules.{hpp,cpp} Module, Modules modules.{hpp,cpp} Module, Modules
parts.{hpp,cpp} Part (carries `kind` + `connector_type`), Parts parts.{hpp,cpp} Part (carries `kind` + `connector_type`), Parts
pins.{hpp,cpp} Pin, Pins pins.{hpp,cpp} Pin (carries PinSpec `spec`), Pins
signals.{hpp,cpp} Signal, Signals signals.{hpp,cpp} Signal, Signals
signal_type.hpp SignalType + helpers signal_type.hpp SignalType + helpers
pin_spec.hpp PinSpec (function/direction/pad/source) + SignalType mapping
component_kind.{hpp,cpp} ComponentKind enum + infer_component_kind(name) component_kind.{hpp,cpp} ComponentKind enum + infer_component_kind(name)
pin_name.{hpp,cpp} canonical_pin_name(s) — zero-pad digit suffix to 3 pin_name.{hpp,cpp} canonical_pin_name(s) — zero-pad digit suffix to 3
connect.{hpp,cpp} Connection, Connections connect.{hpp,cpp} Connection, Connections
transform.{hpp,cpp} Transform / IdentityTransform / TransformRegistry + transform.{hpp,cpp} Transform / IdentityTransform / TransformRegistry +
CheckIdentityCompatible + FillIdentityNCs CheckIdentityCompatible + FillIdentityNCs
pin_role.{hpp,cpp} pin_role(kind, name), pin_layout(kind), pin_role.{hpp,cpp} pin_role(kind, name) → PinSpec, pin_layout(kind),
FillPartFromLayout(part, kind) FillPartFromLayout(part, kind)
nets.{hpp,cpp} find_net / compute_all_nets / net_type_consistent nets.{hpp,cpp} find_net / compute_all_nets / net_type_consistent
analysis.{hpp,cpp} analyze_system → AnalysisReport (diff pairs, buses, anomalies) analysis.{hpp,cpp} analyze_system → AnalysisReport (diff pairs, buses, anomalies)
@@ -94,7 +95,7 @@ Built-in commands: `new`, `set`, `load`, `duplicate`, `save`, `restore`, `source
`set <name> <value>` declares a session-scoped variable. Subsequent commands expand `$name` and `${name}` in their args (substitution happens in `Finalize` between canonical-form recording and `spec.action(args)` — so `history` and `script-save` keep the **unexpanded** form, while the action sees resolved values). Unknown variables are left literal. `vars` is reset by `new`. Validation: `[A-Za-z_][A-Za-z0-9_]*`. `set <name> <value>` declares a session-scoped variable. Subsequent commands expand `$name` and `${name}` in their args (substitution happens in `Finalize` between canonical-form recording and `spec.action(args)` — so `history` and `script-save` keep the **unexpanded** form, while the action sees resolved values). Unknown variables are left literal. `vars` is reset by `new`. Validation: `[A-Za-z_][A-Za-z0-9_]*`.
`duplicate <source> <newname>` deep-copies a module: signals (with type overrides), parts (with `connector_type` and `kind`), pins (with `expected_signal_type`), and rewires each pin to the equivalent same-named signal in the new module. Connections are NOT copied (they're cross-module topology). `duplicate <source> <newname>` deep-copies a module: signals (with type overrides), parts (with `connector_type` and `kind`), pins (with their `PinSpec` `spec`), and rewires each pin to the equivalent same-named signal in the new module. Connections are NOT copied (they're cross-module topology).
`script-save <file>` writes a replay-ready script of every command issued since the last `new` (the `recorded` buffer is cleared inside the `new` action). The buffer is appended to inside `Finalize()` after the action runs, with a denylist of commands that aren't useful in a replay: `clear`, `help`, `quit`, `exit`, `source`, `script-save`. **Additionally, a bare invocation of an `interactive` command is skipped** (`opens_screen = spec.interactive && args.empty()`) — those open a full-screen mode rather than mutating state. Mutating actions taken *inside* a screen record their own canonical line (e.g. the signal-type popup pushes `set-signal-type <m> <s> <t>`). Note the `source` exclusion: when a script is sourced, the *individual lines inside* the script are recorded (because each goes through `Finalize`), so the saved script reproduces the same end state without the indirection. `script-save <file>` writes a replay-ready script of every command issued since the last `new` (the `recorded` buffer is cleared inside the `new` action). The buffer is appended to inside `Finalize()` after the action runs, with a denylist of commands that aren't useful in a replay: `clear`, `help`, `quit`, `exit`, `source`, `script-save`. **Additionally, a bare invocation of an `interactive` command is skipped** (`opens_screen = spec.interactive && args.empty()`) — those open a full-screen mode rather than mutating state. Mutating actions taken *inside* a screen record their own canonical line (e.g. the signal-type popup pushes `set-signal-type <m> <s> <t>`). Note the `source` exclusion: when a script is sourced, the *individual lines inside* the script are recorded (because each goes through `Finalize`), so the saved script reproduces the same end state without the indirection.
@@ -117,11 +118,11 @@ Pending prompts (from incomplete inline commands) are NOT considered interactive
The explore screen shows the type in the signal detail header. The explore screen shows the type in the signal detail header.
**Pin role expectations**: every Pin carries an `expected_signal_type` populated by `set-connector-type` from a per-(connector_type, pin_name) lookup (`src/system/pin_role.{hpp,cpp}`). The framework is wired end-to-end; the actual VPX 3U lookup table is currently a stub returning Other for all positions — fill in `vpx_3u_role(col, row, idx)` with the real VITA 46 layout when needed. **Pin spec (expected attributes)**: every Pin carries a `PinSpec spec` (`src/system/pin_spec.hpp`) — the *expected* half of verification, set from a model: `function` (Power/Ground/Signal/Clock/NoConnect/Jtag*), `direction` (In/Out/Bidir/Passive/Power), `pad` (physical package terminal, e.g. a BSDL ball), and `source` (which model wrote it). `set-connector-type` populates it via `pin_role(connector_type, pin_name) → PinSpec`. `Pin::expected_signal_type()` is now a **derived accessor**`to_signal_type(spec.function)` (Power→Power, Ground→GndShield, else Other) — not a stored field; the *observed* half stays `Pin::signal()` + the net + inference, and `verify` diffs the two. The framework is wired end-to-end; the VPX 3U lookup (`vpx_3u_role`) is still a stub returning Other for every position, so today every pin's `function` resolves to Unknown → `expected_signal_type()` Other (behaviour unchanged from the old field) — fill in the real VITA 46 layout when needed. `direction`/`function`/`pad` are present but not yet model-populated: they are what the BSDL ingest (`libbsdl`) and the planned contention / undriven-net / NC-wired / JTAG-chain checks will consume.
**Connector pin layout (preparation)**: `pin_layout(connector_type)` returns the canonical full pin-name list for a known connector kind, and `FillPartFromLayout(part, kind)` materialises NC pins for any layout position absent from the imported netlist. `set-connector-type` calls it after setting `connector_type` (no-op today since `pin_layout` is a stub returning `{}` for everything — populate alongside `vpx_3u_role`). End-to-end chain in place: `set-connector-type → FillPartFromLayout → pin_role`. **Connector pin layout (preparation)**: `pin_layout(connector_type)` returns the canonical full pin-name list for a known connector kind, and `FillPartFromLayout(part, kind)` materialises NC pins for any layout position absent from the imported netlist. `set-connector-type` calls it after setting `connector_type` (no-op today since `pin_layout` is a stub returning `{}` for everything — populate alongside `vpx_3u_role`). End-to-end chain in place: `set-connector-type → FillPartFromLayout → pin_role`.
**`verify` (three passes)**: (1) walks all typed pins and reports local mismatches between `expected_signal_type` and the actual signal type; (2) walks all bridged nets reporting Power↔GndShield inconsistencies; (3) prints a single-line orphan summary `N orphan pin(s) at import (X imported NC, Y dropped singleton)`. The orphan pass filters out pins that appear in any `Connection::pin_map` — those are bridged to a real signal on the peer module (typically `FillIdentityNCs`-materialised) and not real NCs at system level. The BFS-reached `(module, signal)` set for any signal is shown live in `explore`'s detail pane when a signal entry is selected. **`verify` (three passes)**: (1) walks all typed pins and reports local mismatches between each pin's `expected_signal_type()` (derived from its `PinSpec`) and the actual signal type; (2) walks all bridged nets reporting Power↔GndShield inconsistencies; (3) prints a single-line orphan summary `N orphan pin(s) at import (X imported NC, Y dropped singleton)`. The orphan pass filters out pins that appear in any `Connection::pin_map` — those are bridged to a real signal on the peer module (typically `FillIdentityNCs`-materialised) and not real NCs at system level. The BFS-reached `(module, signal)` set for any signal is shown live in `explore`'s detail pane when a signal entry is selected.
**`analyze` (post-processing pass)**: `analyze_system(System*) → AnalysisReport` (`src/system/analysis.{hpp,cpp}`) is a stateless read-only pass that detects structural signal groups and anomalies. Per-module (signals are module-scoped): **`analyze` (post-processing pass)**: `analyze_system(System*) → AnalysisReport` (`src/system/analysis.{hpp,cpp}`) is a stateless read-only pass that detects structural signal groups and anomalies. Per-module (signals are module-scoped):
@@ -286,7 +287,7 @@ Type is set by `infer_signal_types(System*)` (`src/system/analysis.cpp`), called
The analyze screen additionally surfaces two "verify-class" issues, computed the same way as the textual `verify` command: The analyze screen additionally surfaces two "verify-class" issues, computed the same way as the textual `verify` command:
- **pin-role mismatch** — a pin whose `expected_signal_type` (set by `set-connector-type` via `pin_role(connector_type, pin_name)`) disagrees with the actual signal type. - **pin-role mismatch** — a pin whose `expected_signal_type()` (derived from its `PinSpec`, set by `set-connector-type` via `pin_role(connector_type, pin_name)`) disagrees with the actual signal type.
- **net-mix** — a bridged net (BFS over `Connection::pin_map`, ≥ 2 members) where `net_type_consistent(net, &dominant)` returns false. Specifically, the net contains both `Power` and `GndShield` signals. - **net-mix** — a bridged net (BFS over `Connection::pin_map`, ≥ 2 members) where `net_type_consistent(net, &dominant)` returns false. Specifically, the net contains both `Power` and `GndShield` signals.
### Component kind ### Component kind

View File

@@ -15,19 +15,23 @@ cmake --build build -j
./build/essim ./build/essim
``` ```
Requirements:
- A C++17 compiler.
- CMake 3.14+.
- System packages: `libzip` and `pugixml` (Arch: `pacman -S libzip pugixml`).
- FTXUI (v6.1.9) and doctest (v2.4.11) are fetched at configure time via
`FetchContent`.
Inside the shell, type `help` for the live command list — or read the Inside the shell, type `help` for the live command list — or read the
auto-generated reference at [`doc/user/commands.md`](doc/user/commands.md). auto-generated reference at [`doc/user/commands.md`](doc/user/commands.md).
A worked bring-up script is at [`test/system.essim`](test/system.essim); A worked bring-up script is at [`test/system.essim`](test/system.essim);
load it with `source test/system.essim`. load it with `source test/system.essim`.
## Dependencies
- **C++17 compiler** and **CMake 3.14+**.
- System libraries **libzip** and **pugixml** — install the *development*
packages:
- Debian/Ubuntu — `sudo apt install libzip-dev libpugixml-dev`
- Arch — `sudo pacman -S libzip pugixml`
- Fedora — `sudo dnf install libzip-devel pugixml-devel`
- Fetched automatically at configure time via `FetchContent` (nothing to
install): **FTXUI** v6.1.9 and **doctest** v2.4.11.
- Optional, only for the `doc` target: **doxygen** and **python3**.
## Tests ## Tests
```sh ```sh