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 8.6–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 (8.6–9.0).
To install, run following commands:
git clone https://github.com/georgtree/NgspiceTclBridge.git
./configure
sudo 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.
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] # Initialize callbacks and internal structures $sim init
To feed a circuit one line at a time via ngspice’s circbyline:
proc cirPass {sim circuitText} { foreach line [split $circuitText "\n"] { if {[string trim $line] ne ""} { $sim command [concat circbyline $line] } } } set resDivCircuit { Resistor divider v1 in 0 1 r1 in out 1e3 r2 out 0 2e3 .dc v1 0 5 0.1 .save all .end }
Pass resistor divider circuit to Ngspice, and start the run background thread:
cirPass $sim $resDivCircuit $sim command bg_run
Wait for an event (e.g., status becoming ready):
set res [$sim waitevent send_stat 1000]
Explicitly process pending events handlers (without processing the events the messages, vector data and status will not be written into internal data storages)
update
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 vector/messages storage with next commands (otherwise data will be appended to data from previous simulation):
$s1 vectors -clear $s1 messages -clear