Rename set-type to set-connector-type; help-panel & types-glossary polish.
- Command renamed from `set-type` to `set-connector-type` for clarity (the previous name was ambiguous — "type" of what?). No legacy alias kept; old scripts that still used `set-type` must be migrated. `test/system.essim` and all user/design docs updated. - Help panel (RenderHelpPanel) now wraps in borderRounded with a centred bold title, so it is visually distinct from the main content on every screen. Width bumped from 30 to 32 to include the border. - Analyze screen's Types tab gains a sibling "type glossary" panel (also borderRounded, only visible when the Types tab is focused) that explains Power / Suspect Power / Hard floor / Gnd in plain language using `paragraph()` for clean word-wrap. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
20
DESIGN.md
20
DESIGN.md
@@ -87,7 +87,7 @@ doc/classes.puml -- PlantUML class diagram
|
||||
- Multi-step prompts work via a `std::deque<Prompt>` queue. `Submit()` pops them one by one before falling back to dispatch. Adding a new command = one entry in `RegisterCommands()`; the prompt-flow and inline-flow are both handled automatically.
|
||||
- Tab completion: at the top-level prompt (no `pending`), completes built-in command names. Inside a prompt with `path_completion = true` (e.g. the `filename` step of `load`), completes file paths via `std::filesystem::directory_iterator` (handles `~/`, dirs get a trailing `/`). Logic: 1 match → replace; multiple with progress on the longest common prefix → extend; multiple stuck at LCP → list candidates in the visualisation area.
|
||||
|
||||
Built-in commands: `new`, `set`, `load`, `duplicate`, `save`, `restore`, `source`, `script-save`, `connect`, `set-type`, `set-signal-type`, `search`, `explore`, `verify`, `net`, `clear`, `help`, `quit`/`exit`. `Esc` cancels an in-progress multi-step prompt.
|
||||
Built-in commands: `new`, `set`, `load`, `duplicate`, `save`, `restore`, `source`, `script-save`, `connect`, `set-connector-type`, `set-signal-type`, `search`, `explore`, `verify`, `net`, `clear`, `help`, `quit`/`exit`. `Esc` cancels an in-progress multi-step prompt.
|
||||
|
||||
`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_]*`.
|
||||
|
||||
@@ -97,7 +97,7 @@ Built-in commands: `new`, `set`, `load`, `duplicate`, `save`, `restore`, `source
|
||||
|
||||
`source <file>` reads a script line by line and feeds each line through `Submit()`. While the script is running, `in_source = true` is set on the `Tui` and:
|
||||
- `Dispatch` / `Finalize` skip writing to memory + on-disk history.
|
||||
- After each `Submit`, if `screen_idx != 0` (a screen was opened by an "interactive" command like bare `connect`/`search`/`set-type`), the script is aborted with an error message and `screen_idx` is reset to 0 — interactive screen-opening commands are explicitly disallowed in scripts.
|
||||
- After each `Submit`, if `screen_idx != 0` (a screen was opened by an "interactive" command like bare `connect`/`search`/`set-connector-type`), the script is aborted with an error message and `screen_idx` is reset to 0 — interactive screen-opening commands are explicitly disallowed in scripts.
|
||||
|
||||
Pending prompts (from incomplete inline commands) are NOT considered interactive and are filled by subsequent script lines, the way you'd expect. Lines starting with `#` and blank lines are skipped; leading/trailing whitespace is trimmed; `~/` is expanded.
|
||||
|
||||
@@ -114,9 +114,9 @@ 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-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 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.
|
||||
|
||||
**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-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-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. `net <module> <signal>` prints the BFS-reached `(module, signal)` set with types and an `[INCONSISTENT]` flag.
|
||||
|
||||
@@ -130,7 +130,7 @@ The explore screen shows the type in the signal detail header.
|
||||
|
||||
Exposed as the `analyze` shell command which prints groups (sorted by module + label) followed by anomalies. Designed to be consumed by the upcoming dashboard so the summary is visible at a glance. Tests: `tests/test_analysis.cpp`.
|
||||
|
||||
**Component classification**: every `Part` carries a `ComponentKind kind` (`Passive | Semiconductor | IntegratedCircuit | Connector | TestPoint | Switch | Crystal | Mechanical | Other`) inferred at construction by `infer_component_kind(name)` from the leading reference-designator letter(s) (longest-match: `LED/TP/SW/FB/MK/MP/MH/HS/RA/RN/RP/RV` first, then single-letter R/C/L/F/D/Q/U/J/P/Y/X/S). Recomputed on `restore` (no persistence tag). Not yet exposed in TUI commands — branchpoints will be `search` filter, `set-type` guard, and `explore` header.
|
||||
**Component classification**: every `Part` carries a `ComponentKind kind` (`Passive | Semiconductor | IntegratedCircuit | Connector | TestPoint | Switch | Crystal | Mechanical | Other`) inferred at construction by `infer_component_kind(name)` from the leading reference-designator letter(s) (longest-match: `LED/TP/SW/FB/MK/MP/MH/HS/RA/RN/RP/RV` first, then single-letter R/C/L/F/D/Q/U/J/P/Y/X/S). Recomputed on `restore` (no persistence tag). Not yet exposed in TUI commands — branchpoints will be `search` filter, `set-connector-type` guard, and `explore` header.
|
||||
|
||||
`SignalType` lives in its own header `src/system/signal_type.hpp` (extracted from signals to avoid a pins↔signals include cycle).
|
||||
|
||||
@@ -138,13 +138,13 @@ Exposed as the `analyze` shell command which prints groups (sorted by module + l
|
||||
|
||||
**NC origin tag**: each `Pin` carries `NcOrigin nc_origin` (`None | ImportedUnconnected | DroppedSingleton`, default `None`). Set in three places: (a) Mentor importer when the signal field starts with `unconnected` → `ImportedUnconnected`; (b) `drop_singleton_signals(Signals*)` called at the end of `load` → `DroppedSingleton` on each detached pin (signals with exactly one pin are NC by definition — see commits motivating this); (c) `duplicate` propagates the tag. Pins materialised by `FillIdentityNCs` keep `None` — they have no local signal but are bridged via `pin_map` and shouldn't be counted as orphans. The tag is persisted (see `N` record), reported as a total in `verify`, and tested in `tests/test_nc_origin.cpp`.
|
||||
|
||||
**Connector types & transforms**: every `Part` carries a `connector_type` string (default `""`, set via the `set-type` command — inline `set-type m p kind` or bare which opens a TUI screen with module menu, part filter+menu, type input, list of types already in use, and an Apply button). When `connect` validates a pair, it consults `TransformRegistry::lookup(p1->connector_type, p2->connector_type)` (defined in `src/system/transform.{hpp,cpp}`) — both directions of the pair are tried. If neither is registered, an `IdentityTransform` fallback wires each pin of A to the canonical-equivalent pin of B (when present). The resulting `(Pin*, Pin*)` list and the transform's name are stored on the `Connection` (`pin_map`, `transform_name`). To register a real transform: define a `Transform` subclass in `transform.cpp` and call `TransformRegistry::get().add("kindA", "kindB", new MyTransform())` at init — there's no startup hook for this yet, so a small `RegisterBuiltinTransforms()` helper is the natural place to add when more types appear.
|
||||
**Connector types & transforms**: every `Part` carries a `connector_type` string (default `""`, set via the `set-connector-type` command — inline `set-connector-type m p kind` or bare which opens a TUI screen with module menu, part filter+menu, type input, list of types already in use, and an Apply button). When `connect` validates a pair, it consults `TransformRegistry::lookup(p1->connector_type, p2->connector_type)` (defined in `src/system/transform.{hpp,cpp}`) — both directions of the pair are tried. If neither is registered, an `IdentityTransform` fallback wires each pin of A to the canonical-equivalent pin of B (when present). The resulting `(Pin*, Pin*)` list and the transform's name are stored on the `Connection` (`pin_map`, `transform_name`). To register a real transform: define a `Transform` subclass in `transform.cpp` and call `TransformRegistry::get().add("kindA", "kindB", new MyTransform())` at init — there's no startup hook for this yet, so a small `RegisterBuiltinTransforms()` helper is the natural place to add when more types appear.
|
||||
|
||||
**Identity wiring uses canonical names**: `IdentityTransform::apply` builds `unordered_map<canonical, Pin*>` for side B and looks up each side-A pin by its canonical form. So `A1` (one card) auto-pairs with `A001` (the other) thanks to `canonical_pin_name` (`pre + zero-padded(3) digit suffix`; mixed/non-numeric returns the original). Same canonicalisation in `CheckIdentityCompatible`. **`pin_role` doesn't need canonicalisation** because `parse_pin` extracts `(col, row)` via `stoi` which already strips leading zeros.
|
||||
|
||||
**Subset wiring + NC backfill**: `CheckIdentityCompatible(a, b, info=&s)` accepts the case where one side's canonical pin set is a subset of the other's — typical when one importer drops NC pins (Altium) and the other doesn't (Mentor). It populates `info` with a non-fatal "N pin(s) only on '<part>'" message. Bidirectional mismatch (both sides have orphans) is still refused. After acceptance, `connect` calls `FillIdentityNCs(p1, p2)` which materialises the orphan canonical positions on the missing side as NC pins (`new Pin(other_side_name)`) — so `Connection::pin_map.size()` matches the larger side's count. Idempotent.
|
||||
|
||||
`screen_idx` mapping: **6 = dashboard (home, set in the constructor)**, 0 = console (textual shell + log view), 1 = search, 2 = connect, 3 = set-type, 4 = explore, 5 = net, 7 = analyze. The dashboard is the boot screen; the console is the secondary screen reachable via the `[c]` shortcut and used to display textual output from `verify`/`analyze`/etc. plus collect arguments for multi-step commands. The label was renamed from "log" to "console" because the screen is also where commands are typed — "log" only described half of what it does.
|
||||
`screen_idx` mapping: **6 = dashboard (home, set in the constructor)**, 0 = console (textual shell + log view), 1 = search, 2 = connect, 3 = set-connector-type, 4 = explore, 5 = net, 7 = analyze. The dashboard is the boot screen; the console is the secondary screen reachable via the `[c]` shortcut and used to display textual output from `verify`/`analyze`/etc. plus collect arguments for multi-step commands. The label was renamed from "log" to "console" because the screen is also where commands are typed — "log" only described half of what it does.
|
||||
|
||||
**Dashboard letter conflicts**: with the screen renames, `[c]` now opens the **console** rather than `connect`. The connect command is surfaced as **`[p]lug`** on the dashboard (a UI rename only — the canonical command stays `connect` for script + save/restore stability, with `plug` registered as an alias so the palette finds it under either name).
|
||||
|
||||
@@ -260,7 +260,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-type` via `pin_role(connector_type, pin_name)`) disagrees with the actual signal type.
|
||||
- **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.
|
||||
- **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
|
||||
@@ -271,7 +271,7 @@ The analyze screen additionally surfaces two "verify-class" issues, computed the
|
||||
- Single-letter fallback: `R / C / L / F → Passive`, `D / Q → Semiconductor`, `U → IntegratedCircuit`, `J / P → Connector`, `Y / X → Crystal`, `S → Switch`.
|
||||
- No match → `Other`.
|
||||
|
||||
Recomputed on `restore` (no persistence tag). Currently not used by any decision flow — branch points are search filter / `set-type` guard / explore header.
|
||||
Recomputed on `restore` (no persistence tag). Currently not used by any decision flow — branch points are search filter / `set-connector-type` guard / explore header.
|
||||
|
||||
### Connector wiring (transforms)
|
||||
|
||||
@@ -286,7 +286,7 @@ Pins materialised this way are bridged via `Connection::pin_map` to a real signa
|
||||
## Gotchas
|
||||
|
||||
- All three importers (`IMPORT_MENTOR`, `IMPORT_ALTIUM`, `IMPORT_ODS`) are wired in `System::Load`. Wrap calls in `try/catch` (the TUI does).
|
||||
- **Altium importer drops NC pins entirely**: the source format only enumerates pins inside `(signal …)` blocks, so positions not connected to any signal on this card never become `Pin`s. Mentor (via `Explicit Pin:`) and ODS (one row per pin) materialise NC. This is the asymmetry that motivates `FillIdentityNCs` at `connect` time and (eventually) `FillPartFromLayout` at `set-type` time.
|
||||
- **Altium importer drops NC pins entirely**: the source format only enumerates pins inside `(signal …)` blocks, so positions not connected to any signal on this card never become `Pin`s. Mentor (via `Explicit Pin:`) and ODS (one row per pin) materialise NC. This is the asymmetry that motivates `FillIdentityNCs` at `connect` time and (eventually) `FillPartFromLayout` at `set-connector-type` time.
|
||||
- **Mentor importer + NC**: the Mentor `.qcv` format names every pin's signal explicitly. Sentinel values like `'unconnected'` or `'unconnected (by TERM)'` mean NC — the parser detects them via `is_nc_signal_name` (lowercase prefix match) and keeps the pin on the part with no signal, tagged `ImportedUnconnected`. Additionally, after each `load` the system runs `drop_singleton_signals(mod->signals)`: any signal whose pin set has size 1 is unconnected by definition (electrically nowhere to go), so it is detached and the lone pin is tagged `DroppedSingleton`. The count is shown inline in the `load` output. The semantics covers both Mentor patterns and the few `NC_*`-prefixed signals that turn out to be singletons in real-world boards — the name `NC_*` alone is *not* enough (most of them connect two or more parts and are real bridges, even if cosmetically called NC).
|
||||
- ODS importer: each spreadsheet sheet becomes a `Part` (sheet name = part name). Rows are pin/signal pairs; the **first non-empty row of each sheet is dropped as a header** (no validation of header content). Empty cells skip the row; `"NC"` keeps the pin in the part but doesn't connect it to a signal. Pins or parts whose name collides (rare in well-formed sheets) are silently dropped.
|
||||
- `System::Load` throws `std::runtime_error("Unknown import type")` for any value outside the three enum cases.
|
||||
|
||||
@@ -111,7 +111,7 @@ deserves attention:
|
||||
|
||||
| Tag | What it means |
|
||||
|---|---|
|
||||
| `[pin-role]` | A connector pin is typed (via `set-type`) as Power or Gnd but the actual signal landing on it disagrees. |
|
||||
| `[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. |
|
||||
@@ -128,7 +128,7 @@ Every classification is advisory. To force a different type:
|
||||
on a signal entry → a popup lets you pick `power` / `gnd` /
|
||||
`other`. Or type `set-signal-type <module> <signal> <type>` in the
|
||||
console (or from the palette).
|
||||
- **Connector type**: `set-type <module> <part> <connector-kind>`
|
||||
- **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.
|
||||
|
||||
|
||||
@@ -31,8 +31,8 @@ commands. The most common bring-up looks like this:
|
||||
> new
|
||||
> load backplane /path/to/netlists/backplane.NET altium
|
||||
> load payload1 /path/to/netlists/payload.qcv mentor
|
||||
> set-type backplane J20 vpx-3u-bkp-p0
|
||||
> set-type payload1 P0 vpx-3u-payload-p0
|
||||
> set-connector-type backplane J20 vpx-3u-bkp-p0
|
||||
> set-connector-type payload1 P0 vpx-3u-payload-p0
|
||||
> connect backplane J20 payload1 P0
|
||||
> verify
|
||||
> save my-system.essim
|
||||
@@ -46,7 +46,7 @@ Things to try at any time:
|
||||
| Help on one command | `help <name>` |
|
||||
| Scroll back through output | `PageUp` / `PageDown`, `Home`, `End` |
|
||||
| Re-run a previous command | ↑ / ↓ (also `history` is on disk) |
|
||||
| Tab-complete a command name | `set‹Tab›` → `set-type` etc. |
|
||||
| Tab-complete a command name | `set‹Tab›` → `set-connector-type` etc. |
|
||||
| Cancel a multi-step prompt | `Esc` |
|
||||
| Leave essim | `quit` (or `exit`) |
|
||||
|
||||
@@ -65,7 +65,7 @@ share the same conventions:
|
||||
a sourced script. A sourced script must use the inline form of these
|
||||
commands instead.
|
||||
|
||||
Today's interactive screens: `connect`, `search`, `set-type`,
|
||||
Today's interactive screens: `connect`, `search`, `set-connector-type`,
|
||||
`explore`, `net`. See [`commands.md`](commands.md) for each.
|
||||
|
||||
## Saving, restoring, replaying
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
// NOTE: real VITA 46 pin roles are connector-/profile-specific (data lanes,
|
||||
// power planes, GND chassis, etc.). The placeholders below are intentionally
|
||||
// minimal — fill in the actual per-(col,row) roles for your design when the
|
||||
// reference is available; the rest of the chain (set-type → verify) is
|
||||
// reference is available; the rest of the chain (set-connector-type → verify) is
|
||||
// already wired through this single function.
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
class Part;
|
||||
|
||||
// For a given connector type and pin position, return the expected SignalType
|
||||
// (Power / GndShield / Other). Used at `set-type` to populate each pin's
|
||||
// (Power / GndShield / Other). Used at `set-connector-type` to populate each pin's
|
||||
// `expected_signal_type`, then later by `verify` to flag mismatches between
|
||||
// the connector's expectation and the actual signal's inferred/declared type.
|
||||
//
|
||||
@@ -23,7 +23,7 @@ SignalType pin_role(const std::string &connector_type,
|
||||
// vector for connector types that don't have a registered layout — callers
|
||||
// must treat that as "unknown, do not auto-fill".
|
||||
//
|
||||
// Used at `set-type` to materialise NC pins for positions absent from the
|
||||
// Used at `set-connector-type` to materialise NC pins for positions absent from the
|
||||
// imported netlist (Altium drops NC, Mentor doesn't). Stub today: every
|
||||
// known kind returns {} — populate alongside `vpx_3u_role`.
|
||||
std::vector<std::string> pin_layout(const std::string &connector_type);
|
||||
|
||||
@@ -29,7 +29,7 @@ class Pin : public SystemElement
|
||||
public:
|
||||
Pin(std::string name);
|
||||
Part *prnt; ///< Pointer to the parent part.
|
||||
SignalType expected_signal_type; ///< Set from connector_type at set-type.
|
||||
SignalType expected_signal_type; ///< Set from connector_type at set-connector-type.
|
||||
NcOrigin nc_origin = NcOrigin::None;
|
||||
bool connected();
|
||||
Signal *signal() const { return sig; }
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
// instances are registered at startup, under the type pairs
|
||||
// (vpx-3u-bkp-N, vpx-3u-payload-N)
|
||||
// for N in {0, 1, 2}. Tag each Part with the correct connector_type via
|
||||
// `set-type`, then `connect` will pick the right transform automatically.
|
||||
// `set-connector-type`, then `connect` will pick the right transform automatically.
|
||||
class VpxTransform : public Transform
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -431,7 +431,7 @@ void Tui::RegisterCommands() {
|
||||
"override the auto-detected signal type (power | gnd | other)",
|
||||
};
|
||||
|
||||
commands["set-type"] = {
|
||||
commands["set-connector-type"] = {
|
||||
{{"module", Completion::None},
|
||||
{"part (name or pattern)", Completion::None},
|
||||
{"connector type (free string, e.g. vpx-bp, vpx-payload)", Completion::None}},
|
||||
@@ -454,7 +454,7 @@ void Tui::RegisterCommands() {
|
||||
}
|
||||
|
||||
if (args.size() != 3) {
|
||||
Print("usage: set-type <module> <part> <kind> (or no args for interactive)");
|
||||
Print("usage: set-connector-type <module> <part> <kind> (or no args for interactive)");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -480,7 +480,7 @@ void Tui::RegisterCommands() {
|
||||
}
|
||||
std::string err = ValidatePartForKind(prt, args[2]);
|
||||
if (!err.empty()) {
|
||||
Print("set-type refused: " + err);
|
||||
Print("set-connector-type refused: " + err);
|
||||
return;
|
||||
}
|
||||
prt->connector_type = args[2];
|
||||
@@ -490,7 +490,7 @@ void Tui::RegisterCommands() {
|
||||
Print(mod->name + "/" + prt->name + ": connector_type = "
|
||||
+ (args[2].empty() ? "(none)" : args[2]));
|
||||
if (filled > 0)
|
||||
Print("set-type: materialised " + std::to_string(filled)
|
||||
Print("set-connector-type: materialised " + std::to_string(filled)
|
||||
+ " NC pin(s) from connector layout");
|
||||
},
|
||||
/*prompt_for_missing=*/ false,
|
||||
@@ -498,7 +498,6 @@ void Tui::RegisterCommands() {
|
||||
/*scriptable=*/ true,
|
||||
/*interactive=*/ true,
|
||||
};
|
||||
|
||||
commands["connect"] = {
|
||||
{{"module1", Completion::None},
|
||||
{"part1 (name or pattern)", Completion::None},
|
||||
@@ -596,7 +595,7 @@ void Tui::RegisterCommands() {
|
||||
+ (p1->connector_type.empty() ? "(none)" : p1->connector_type)
|
||||
+ "' ↔ '"
|
||||
+ (p2->connector_type.empty() ? "(none)" : p2->connector_type)
|
||||
+ "'. Set matching types via 'set-type' first.");
|
||||
+ "'. Set matching types via 'set-connector-type' first.");
|
||||
return;
|
||||
}
|
||||
std::string info;
|
||||
|
||||
@@ -244,34 +244,35 @@ Component Tui::BuildAnalyzeScreen() {
|
||||
{"Esc", "dashboard"},
|
||||
});
|
||||
|
||||
// Glossary: only relevant on the Types tab. Same width as the help
|
||||
// panel for visual coherence.
|
||||
// Glossary: shown only when the Types tab is focused. Same border
|
||||
// styling as the help panel (borderRounded) for visual coherence;
|
||||
// text uses `paragraph` so lines wrap cleanly to the panel width.
|
||||
auto term = [](const std::string &name, const std::string &desc) {
|
||||
return vbox({
|
||||
text(name) | bold,
|
||||
paragraph(desc) | dim,
|
||||
text(""),
|
||||
});
|
||||
};
|
||||
Element types_glossary = vbox({
|
||||
text(" types ") | bold,
|
||||
text(" type glossary ") | bold | center,
|
||||
separator(),
|
||||
hbox({text(" Power ") | bold | size(WIDTH, EQUAL, 12),
|
||||
text("name + structure") | flex}),
|
||||
hbox({text(" ") | dim | size(WIDTH, EQUAL, 12),
|
||||
text("(fan-out ≥ 4 or") | dim | flex}),
|
||||
hbox({text(" ") | dim | size(WIDTH, EQUAL, 12),
|
||||
text(" voltage in name)") | dim | flex}),
|
||||
text(""),
|
||||
hbox({text(" Suspect ") | bold | size(WIDTH, EQUAL, 12),
|
||||
text("name only,") | flex}),
|
||||
hbox({text(" ") | dim | size(WIDTH, EQUAL, 12),
|
||||
text("weak evidence") | dim | flex}),
|
||||
text(""),
|
||||
hbox({text(" hard ") | bold | size(WIDTH, EQUAL, 12),
|
||||
text("fan-out < 3 →") | flex}),
|
||||
hbox({text(" floor ") | bold | size(WIDTH, EQUAL, 12),
|
||||
text("never Power") | flex}),
|
||||
text(""),
|
||||
hbox({text(" Gnd ") | bold | size(WIDTH, EQUAL, 12),
|
||||
text("name only") | flex}),
|
||||
}) | size(WIDTH, EQUAL, 30);
|
||||
term("Power",
|
||||
"Name suggests Power AND structure agrees: fan-out ≥ 4 pins, "
|
||||
"or a voltage pattern in the name (e.g. 3V3, 5V, 12V)."),
|
||||
term("Suspect Power",
|
||||
"Name suggests Power but the structural check failed — "
|
||||
"fan-out too low and no voltage in the name."),
|
||||
term("Hard floor",
|
||||
"Fan-out below 3 pins forces Other regardless of the name. "
|
||||
"A real rail physically cannot live on 1-2 pads."),
|
||||
term("Gnd",
|
||||
"Name matches GND, SHIELD, CHASSIS or EARTH. Name alone is "
|
||||
"enough — false positives are essentially nil."),
|
||||
}) | borderRounded | size(WIDTH, EQUAL, 32);
|
||||
|
||||
Element side = (analyze_focus_idx == 2)
|
||||
? vbox({help, text(""), types_glossary}) | size(WIDTH, EQUAL, 30)
|
||||
? vbox({help, text(""), types_glossary}) | size(WIDTH, EQUAL, 32)
|
||||
: help;
|
||||
|
||||
return vbox({
|
||||
|
||||
@@ -76,7 +76,7 @@ Component Tui::BuildConnectScreen() {
|
||||
+ (p1->connector_type.empty() ? "(none)" : p1->connector_type)
|
||||
+ "' ↔ '"
|
||||
+ (p2->connector_type.empty() ? "(none)" : p2->connector_type)
|
||||
+ "'. Set matching types via 'set-type' first.");
|
||||
+ "'. Set matching types via 'set-connector-type' first.");
|
||||
screen_idx = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -296,7 +296,7 @@ Component Tui::BuildDashboardScreen() {
|
||||
{"c", "console"},
|
||||
{"s", "search"},
|
||||
{"p", "plug"},
|
||||
{"t", "set-type"},
|
||||
{"t", "set-connector-type"},
|
||||
{"e", "explore"},
|
||||
{"n", "net"},
|
||||
{"a", "analyze (verify + groups)"},
|
||||
|
||||
@@ -58,7 +58,7 @@ Component Tui::BuildSettypeScreen() {
|
||||
std::string msg = mod->name + "/" + prt->name + " = "
|
||||
+ (settype_type.empty() ? "(none)" : settype_type);
|
||||
settype_status = "applied: " + msg;
|
||||
Print("set-type " + msg);
|
||||
Print("set-connector-type " + msg);
|
||||
} catch (const std::exception &e) {
|
||||
settype_status = std::string("failed: ") + e.what();
|
||||
}
|
||||
@@ -129,11 +129,11 @@ Component Tui::BuildSettypeScreen() {
|
||||
auto title = hbox({
|
||||
text(" essim ") | bold,
|
||||
text("→ ") | dim,
|
||||
text("set-type") | bold,
|
||||
text("set-connector-type") | bold,
|
||||
text(" — tag a part with its connector kind (drives transforms + pin roles)") | dim,
|
||||
});
|
||||
|
||||
Element help = RenderHelpPanel("set-type", {
|
||||
Element help = RenderHelpPanel("set-connector-type", {
|
||||
{"Tab", "cycle focus"},
|
||||
{"↑/↓", "navigate menu"},
|
||||
{"Enter", "on [Apply] → tag"},
|
||||
|
||||
@@ -100,7 +100,7 @@ void Tui::Run() {
|
||||
if (e == Event::Character("c")) { screen_idx = 0; return true; }
|
||||
if (e == Event::Character("p")) { Dispatch("connect"); return true; }
|
||||
if (e == Event::Character("s")) { Dispatch("search"); return true; }
|
||||
if (e == Event::Character("t")) { Dispatch("set-type"); return true; }
|
||||
if (e == Event::Character("t")) { Dispatch("set-connector-type"); return true; }
|
||||
if (e == Event::Character("e")) { Dispatch("explore"); return true; }
|
||||
if (e == Event::Character("n")) { Dispatch("net"); return true; }
|
||||
// [a]nalyze is the unified verify + analyze screen (issues +
|
||||
@@ -121,7 +121,7 @@ void Tui::Run() {
|
||||
if (e == Event::TabReverse) { explore_focus_idx = (explore_focus_idx + 5) % 6; return true; }
|
||||
return false;
|
||||
|
||||
case 3: // set-type
|
||||
case 3: // set-connector-type
|
||||
if (e == Event::Escape) { screen_idx = 6; return true; }
|
||||
if (e == Event::Tab) { settype_focus_idx = (settype_focus_idx + 1) % 5; return true; }
|
||||
if (e == Event::TabReverse) { settype_focus_idx = (settype_focus_idx + 4) % 5; return true; }
|
||||
|
||||
@@ -188,7 +188,7 @@ private:
|
||||
// and close the popup.
|
||||
void ApplySignalTypeChoice();
|
||||
|
||||
// Filtered part list rebuild (used by connect & set-type screens)
|
||||
// Filtered part list rebuild (used by connect & set-connector-type screens)
|
||||
void RefreshFilteredPartList(const std::vector<std::string> &modules,
|
||||
int m_idx,
|
||||
const std::string &filter,
|
||||
|
||||
@@ -14,15 +14,18 @@ Element RenderHelpPanel(const std::string &title,
|
||||
Elements rows;
|
||||
for (const auto &e : entries) {
|
||||
rows.push_back(hbox({
|
||||
text(" " + e.key) | bold | size(WIDTH, EQUAL, KEY_W),
|
||||
text(e.key) | bold | size(WIDTH, EQUAL, KEY_W),
|
||||
text(e.desc) | flex,
|
||||
}));
|
||||
}
|
||||
// borderRounded gives the panel a distinct visual boundary, so the
|
||||
// user can find it without ambiguity even when the main content is
|
||||
// dense (e.g. the analyze screen).
|
||||
return vbox({
|
||||
text(" " + title + " ") | bold,
|
||||
text(" " + title + " ") | bold | center,
|
||||
separator(),
|
||||
vbox(std::move(rows)),
|
||||
}) | size(WIDTH, EQUAL, 30);
|
||||
}) | borderRounded | size(WIDTH, EQUAL, 32);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -27,32 +27,32 @@ load peripheral3 $peripheral3_nets mentor
|
||||
# ---------------------------------------------------------------- VPX tags
|
||||
# Backplane payload-side connectors, one slot per (Jx0,Jx1,Jx2):
|
||||
# J2x → payload1, J3x → payload2, J4x → payload3, J5x → payload4.
|
||||
set-type backplane J20 vpx-3u-bkp-p0
|
||||
set-type backplane J21 vpx-3u-bkp-p1
|
||||
set-type backplane J22 vpx-3u-bkp-p2
|
||||
set-type backplane J30 vpx-3u-bkp-p0
|
||||
set-type backplane J31 vpx-3u-bkp-p1
|
||||
set-type backplane J32 vpx-3u-bkp-p2
|
||||
set-type backplane J40 vpx-3u-bkp-p0
|
||||
set-type backplane J41 vpx-3u-bkp-p1
|
||||
set-type backplane J42 vpx-3u-bkp-p2
|
||||
set-type backplane J50 vpx-3u-bkp-p0
|
||||
set-type backplane J51 vpx-3u-bkp-p1
|
||||
set-type backplane J52 vpx-3u-bkp-p2
|
||||
set-connector-type backplane J20 vpx-3u-bkp-p0
|
||||
set-connector-type backplane J21 vpx-3u-bkp-p1
|
||||
set-connector-type backplane J22 vpx-3u-bkp-p2
|
||||
set-connector-type backplane J30 vpx-3u-bkp-p0
|
||||
set-connector-type backplane J31 vpx-3u-bkp-p1
|
||||
set-connector-type backplane J32 vpx-3u-bkp-p2
|
||||
set-connector-type backplane J40 vpx-3u-bkp-p0
|
||||
set-connector-type backplane J41 vpx-3u-bkp-p1
|
||||
set-connector-type backplane J42 vpx-3u-bkp-p2
|
||||
set-connector-type backplane J50 vpx-3u-bkp-p0
|
||||
set-connector-type backplane J51 vpx-3u-bkp-p1
|
||||
set-connector-type backplane J52 vpx-3u-bkp-p2
|
||||
|
||||
# Payload connectors on each plug-in card.
|
||||
set-type payload1 P0 vpx-3u-payload-p0
|
||||
set-type payload1 P1 vpx-3u-payload-p1
|
||||
set-type payload1 P2 vpx-3u-payload-p2
|
||||
set-type payload2 P0 vpx-3u-payload-p0
|
||||
set-type payload2 P1 vpx-3u-payload-p1
|
||||
set-type payload2 P2 vpx-3u-payload-p2
|
||||
set-type payload3 P0 vpx-3u-payload-p0
|
||||
set-type payload3 P1 vpx-3u-payload-p1
|
||||
set-type payload3 P2 vpx-3u-payload-p2
|
||||
set-type payload4 P0 vpx-3u-payload-p0
|
||||
set-type payload4 P1 vpx-3u-payload-p1
|
||||
set-type payload4 P2 vpx-3u-payload-p2
|
||||
set-connector-type payload1 P0 vpx-3u-payload-p0
|
||||
set-connector-type payload1 P1 vpx-3u-payload-p1
|
||||
set-connector-type payload1 P2 vpx-3u-payload-p2
|
||||
set-connector-type payload2 P0 vpx-3u-payload-p0
|
||||
set-connector-type payload2 P1 vpx-3u-payload-p1
|
||||
set-connector-type payload2 P2 vpx-3u-payload-p2
|
||||
set-connector-type payload3 P0 vpx-3u-payload-p0
|
||||
set-connector-type payload3 P1 vpx-3u-payload-p1
|
||||
set-connector-type payload3 P2 vpx-3u-payload-p2
|
||||
set-connector-type payload4 P0 vpx-3u-payload-p0
|
||||
set-connector-type payload4 P1 vpx-3u-payload-p1
|
||||
set-connector-type payload4 P2 vpx-3u-payload-p2
|
||||
|
||||
# ---------------------------------------------------------------- VPX wiring
|
||||
# Each connect dispatches via the registered vpx-3u transform.
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
namespace {
|
||||
|
||||
// Build a Part with `pin_names` pins, attached to a fresh module so prnt
|
||||
// chains exist (set-type's validation depends on pins; transforms don't).
|
||||
// chains exist (set-connector-type's validation depends on pins; transforms don't).
|
||||
Part *make_part(Module *mod, const std::string &part_name,
|
||||
const std::vector<std::string> &pin_names) {
|
||||
Part *p = new Part(part_name);
|
||||
|
||||
Reference in New Issue
Block a user