NgspiceTclBridge - drive ngspice (shared library) from TclTop, Main, Index
ngspicetclbridge is a Tcl C extension that embeds Ngspice (built as a shared library) and exposes a small, thread-safe command API for loading circuits, running analyses in the ngspice background thread, and receiving data/messages/events back into Tcl.
It targets Tcl 9.0 and works on Linux/macOS/Windows. Dynamic loading is abstracted via a tiny portability layer.
What it gives you (at a glance)Top, Main, Index
- Create one or more ngspice instances inside Tcl.
- Issue ngspice commands (e.g. bg_run, circbyline ...).
- Wait for events (send_stat, send_data, etc.) with optional timeouts.
- Collect messages from ngspice stdout/stderr.
- Fetch vector metadata and values (both asynchronously collected and on-demand).
All Ngspice → Tcl crossings are deferred onto Tcl’s event loop, so you stay in the safe thread.
Building & requirementsTop, Main, Index
Requirements:
- ngspice built as a shared library (e.g. libngspice.so, libngspice.dylib, or libngspice.dll) with the sharedspice interface (sharedspice.h).
- Tcl headers/libs (9.0).
To install, run following commands:
git clone https://github.com/georgtree/NgspiceTclBridge.git./configuresudo make install
During installation manpages are also installed.
For test package in place run make test.
For package uninstall run sudo make uninstall.
DocumentationTop, Main, Index
Documentation could be found here.
NotesTop, Main, Index
The commands that are subcommand to the simulator command, like $s1 command bg_run are considered low level and communicate/interact directly with the simulator. On the other side, commands that accept simulator as a parameter are considered as "helper" commands, built on top of low-level commands.
WarningsTop, Main, Index
This library should be considere semi-stable now. It works well for single loading of shared library per process, without unloading and loading again. It also works with multiple unloadings (destroying) and loadings of the same library, but I've encountered a few possible memory corruption cases. I am trying my best to eliminate them, but I am not in full control of Ngspice shared library behaviour.
One of the instances I've encountered is the running two circuit in sequence, with pattern load circuit->run->load circuit->run, and then try destroying the instance. This could lead to segmentation violation, unless the command remcirc for unloading previous circuit is issued before loading new circuit. It is done automatically now if you previously loaded the circuit with circuit command. But in case you want to load circuit with command circbyline, you need to issue remcirc command yourself.
Quick start (synchronous operation)Top, Main, Index
Package loading and initialization:
package require ngspicetclbridge # Path to your ngspice shared library set ngspiceLibPath /path/to/libngspice.so # Create a new instance bound to a Tcl command set sim [ngspicetclbridge::new $ngspiceLibPath]
Pass resistor divider circuit to Ngspice, and start the run (in background thread), and wait for completion:
$sim circuit [split $resDivCircuit \n] run $sim
Get vector data dictionary saved in internal buffer:
$sim vectors
Destroy instance of simulator (removes instance command, frees internal storages and simulator context)
$sim destroy
If you want to continue work with current simulator instance, you need to clear internal messages storage with next commands:
$s1 messages -clear
Vector storage is resetted after run new simulation, so no need to explicitly frees vectors data.