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)
modules.{hpp,cpp} Module, Modules
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
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)
pin_name.{hpp,cpp} canonical_pin_name(s) — zero-pad digit suffix to 3
connect.{hpp,cpp} Connection, Connections
transform.{hpp,cpp} Transform / IdentityTransform / TransformRegistry +
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)
nets.{hpp,cpp} find_net / compute_all_nets / net_type_consistent
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_]*`.
`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.
@@ -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.
**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`.
**`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):
@@ -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:
- **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.
### Component kind

View File

@@ -15,19 +15,23 @@ cmake --build build -j
./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
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);
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
```sh