diff --git a/DESIGN.md b/DESIGN.md index e45b849..52dc5c6 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -24,15 +24,16 @@ src/ syselmts.hpp SystemElement + SystemElementContainer (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 ` 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 ` 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 ` 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 ` 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 `). 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 diff --git a/README.md b/README.md index 1fb2725..c236c5a 100644 --- a/README.md +++ b/README.md @@ -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