Major additions, all wired end-to-end with doctest coverage:
- Altium netlist importer (`imports/import_altium.{hpp,cpp}`): two-pass
parser for `[ ]` parts and `( )` signals; `System::Load` no longer has
the IMPORT_ALTIUM hole.
- `duplicate <src> <dst>` deep-copies a module (signals, parts, pins,
rewired signals); connections excluded by design.
- Nets (`system/nets.{hpp,cpp}`): BFS over `Connection::pin_map` to
return the transitive (Module, Signal) closure. `verify` extended with
a second pass flagging Power↔GndShield inconsistencies in bridged
nets; new `net <module> <signal>` command for inspection.
- Canonical pin names (`system/pin_name.{hpp,cpp}`): zero-padded digit
suffix lets A1 ↔ A001 pair via `IdentityTransform` and
`CheckIdentityCompatible` without losing the imported notation.
- Component classification (`system/component_kind.{hpp,cpp}`):
`Part::kind` inferred at construction from the reference-designator
prefix (longest-match: LED/TP/SW/FB/MK/MP/MH/HS/RA/RN/RP/RV first,
then R/C/L/F/D/Q/U/J/P/Y/X/S).
- Identity wiring tolerance: `CheckIdentityCompatible` accepts the
subset case (typical when one importer drops NC pins, e.g. Altium)
and surfaces orphans as an info string. `FillIdentityNCs`
materialises orphan canonical positions as NC pins on the missing
side at connect time.
- Connector layout preparation: `pin_layout(kind)` and
`FillPartFromLayout(part, kind)` stubs in `pin_role`, called from
`set-type`. Empty today; populate alongside `vpx_3u_role`.
- TUI scrollback: PageUp/PageDown step 10 lines, Home/End jump to
ends; `Print()` snaps back to the tail.
- `set <name> <value>` declares session variables; `$name` / `${name}`
expanded inside `Finalize` between canonical-form recording and the
action call — history and script-save preserve `$var` references.
- Long `source` scripts now show a centred "Computing…" modal with a
N/M progress counter. Driven by a ticker thread that posts one
paced `Event::Special` per processed line, ack'd by the main thread,
so heavy lines don't backlog ticks and freeze the counter.
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