François c3bb00cb4d Altium import, nets, canonical pins, component kinds, set/$var, scrollback, source modal.
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>
2026-05-09 20:28:21 +02:00
2025-03-21 18:47:49 +01:00
2025-04-21 18:19:37 +02:00
2025-03-21 18:51:19 +01:00
2026-05-08 20:38:30 +02:00
2026-05-08 20:38:30 +02:00

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: libzip and pugixml (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

Description
Embedded System Simulation
Readme EUPL-1.2 3.8 MiB
Languages
C++ 98.2%
CMake 1.8%