net screen, main + per-screen title bars, focus highlight, help split.
- New `net` full-screen layout (`screen_net.cpp`, `screen_idx = 5`): three columns (module menu / signal filter + menu / live BFS result). Bare `net` opens the screen; `net <m> <s>` keeps the inline path. - Main screen grows a title bar: " essim — system digital twin " (bold + dim) on the left, live "N module(s), M connection(s)" on the right. - Every interactive screen now renders the same breadcrumb at the top: " essim → <name> — <short description> ", followed by a separator. - `tui_helpers.hpp` exports `FocusLabel(elem, focused)`. Every interactive screen wraps its field labels with it so the active field's label flips to inverted video. Buttons (Connect, Apply) invert as a whole. - `CommandSpec` gains a `bool interactive`. `help` (no args) splits the listing into "Interactive (open a full-screen mode)" and "Other". `help <name>` tags interactive entries with [interactive] and explains the bare-vs-inline duality. - `DESIGN.md` (renamed from `CLAUDE.md`): refreshed Layout, TUI, and screen-recipe sections to cover the new field, the title idiom, FocusLabel, the `net` screen, and the event-paced `Computing…` modal during `source`. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
essim — system digital twin
Interactive simulator for the interconnections between cards in a system. Built around a domain model of modules → parts → pins / signals → connections, with importers for Mentor Graphics and ODS pinout sheets, and a TUI shell for browsing, search, connection authoring, scripting, and snapshot save/restore.
Status: early work-in-progress.
Build
cmake -S . -B build
cmake --build build -j
./build/essim
Requirements:
- A C++17 compiler.
- CMake 3.14+.
- System packages:
libzipandpugixml(Arch:pacman -S libzip pugixml). - FTXUI (v6.1.9) and doctest (v2.4.11) are fetched at configure time via
FetchContent.
To run the test suite:
./build/essim_tests
# or
ctest --test-dir build
To skip building tests:
cmake -S . -B build -DBUILD_TESTING=OFF
TUI commands
Type help inside the shell for the live list, or help <name> for the per-command synopsis. At a glance:
| Command | Purpose |
|---|---|
new |
create a new (empty) system; resets the script-save buffer |
load <module> <file> <mentor|altium|ods> |
load a module from a netlist / pinout file |
save <file> / restore <file> |
snapshot the current system / replace it from a snapshot |
source <file> |
replay a file of commands (interactive ones rejected) |
script-save <file> |
dump commands run since last new as a replay-ready script |
set-type |
tag a part's connector type (interactive screen if no args) |
set-signal-type <module> <signal> <power|gnd|other> |
override the auto-detected signal type |
connect |
connect a part across two modules (interactive screen if no args) |
search |
live-filter parts/signals (interactive screen if no args) |
explore |
browse modules → parts/signals/connections → details |
verify |
report pins whose connected signal type doesn't match the connector role |
Persistent command history lives at $XDG_DATA_HOME/essim/history (or %LOCALAPPDATA%\essim\history on Windows once ported).
Tests
Layered with doctest:
- Unit tests on pure helpers: tokenizer, natural-order comparator, longest common prefix, signal-type heuristics, VPX transform mapping.
- Round-trip tests on the persist layer: a synthetic system is built in code, saved, restored, and compared field by field (modules, parts, connector types, NC pins, signal-type overrides, connections +
pin_map).
Project layout
src/
main.cpp — launches Tui
system/ — domain model
syselmts.hpp SystemElement + SystemElementContainer<T>
modules.{hpp,cpp} Module, Modules
parts.{hpp,cpp} Part, Parts
pins.{hpp,cpp} Pin, Pins
signals.{hpp,cpp} Signal, Signals (auto-typed at construction)
signal_type.hpp SignalType + helpers
connect.{hpp,cpp} Connection (endpoints + pin_map + transform_name)
transform.{hpp,cpp} Transform / IdentityTransform / TransformRegistry
transform_vpx.{hpp,cpp} 3U-VPX-specific transforms (3 connector pairs)
pin_role.{hpp,cpp} per-(connector_type, pin) expected SignalType
persist.{hpp,cpp} save / restore (tab-delimited)
system.{hpp,cpp} System: owns Modules + Connections
imports/ — adapters that populate the domain
import_base.hpp
import_mentor.{hpp,cpp}
import_ods.{hpp,cpp}
tui/ — FTXUI shell, split by responsibility
tui.{hpp,cpp} class Tui + Run() + screen-mode dispatcher
tui_helpers.{hpp,cpp} free helpers (ToLower, NaturalLess, …)
shell.cpp Print / Submit / Dispatch / Finalize / persistence
completion.cpp command + path Tab completion
commands.cpp registry of all built-in commands
screen_main.cpp visualisation area + bottom input
screen_search.cpp live filter on parts / signals
screen_connect.cpp part-to-part connection authoring
screen_settype.cpp connector type tagging
screen_explore.cpp modules → parts/signals/connections → detail
tests/ — doctest suite (essim_tests target)
CLAUDE.md — implementation notes
LICENSE — EUPL-1.2
Licence
Copyright (c) 2026 François Dausseur
Licensed under the European Union Public Licence (EUPL), Version 1.2 —
the "Licence". You may not use this work except in compliance with the
Licence. You may obtain a copy of the Licence in the LICENSE
file or at https://joinup.ec.europa.eu/software/page/eupl.
Unless required by applicable law or agreed to in writing, software distributed under the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the Licence for the specific language governing permissions and limitations under the Licence.
SPDX-License-Identifier: EUPL-1.2