Hi Carsten,

thanks for reply!

On 2024-10-18 20:34:26 Carsten Schoenert wrote:
> Hello Robert,
> 
> Am Fri, Oct 18, 2024 at 05:41:44PM +0000 schrieb Robert Paciorek:
>  
> > libngspice uses configuration and model files provided by ngspice
> > package (/usr/share/ngspice/scripts/spinit and
> > /usr/lib/x86_64-linux-gnu/ngspice/*.cm).  
> 
> I disagree, the libngsice0 package is only containing the shared
> libray parts and if the libary would use some external things without
> depending on it would be programmed in a bad way.

These files are part of the official library archives from
sourceforge.net
(https://sourceforge.net/projects/ngspice/files/ng-spice-rework/43/ngspice-43_dll_64.7z).

> > * running software used libngspice0 without ngspice installed may
> > results in error "MIF-ERROR - unable to find definition of model
> > and Simulation interrupted due to error!" (with previous warning
> > "Warning: can't find the initialization file spinit")  
> 
> The ngspice binary isn't even depending on any symbol from libngspice
> libary so dpkg-shlibdeps isn't filling in the library as an
> dependency.
> 
> https://packages.debian.org/unstable/ngspice

Yes, ngspice is not depending on symbols from libngspice.

It is libngspice that (in some scenarios) uses files provided only with
ngspice package (perhaps they should be in a separate package, e.g.
ngspice-data, because they are used also by the ngspice executable).

> If there is a symbol from there needed then this needs to get fixed
> upstream. But I'm sure this isn't the case here. Maybe Holger (CCed)
> can give a better explanation.
> 
> > * running software used libngspice0 with installed ngspice in
> > version different than libngspice0 version (for example libngspice0
> > 43+ds-1~bpo12+1 and ngspice 39.3+ds-1) may cause segmentation
> > fault.  
> 
> You do not provide an example where we could prove your assumption.
> Without it's impossible to re-adjust a potential misbehavior.
> 
> > Segmentation fault occurs only while referring to standard models
> > provided by *.cm files, for example while simulating digital
> > systems using:
> > 
> > A1 [in1 in2] out AND
> > .model AND d_and  
> 
> You might provide what you try to do in detail, Holger can then have a
> look at this.

I'm attaching the source code of simple program used libngspice
(gdspice.cpp) and two netlist files:
- digital.netlist - simple digital circuit (used standard ngspice model
  for AND gate via `.model` command)
- analog.netlist - similar (but analog, without `.model` command)
  circuit

`gdspice.cpp` can load libngspice via dlopen (default, build via `g++
gdspice.cpp`) or can be linked with libngspice on build time (unset
USE_DLOPEN macro and build via `g++ gdspice-nogodot.cpp -lngspice`).

This allow test all 3 scenarios:

1. The same version (43+ds-1~bpo12+1) of libngspice0 and ngspice
   packages:
   -> both circuit are simulated.
2. Installed only libngspice0 (still 43+ds-1~bpo12+1, but ngspice is not
   installed):
   -> analog circuit produce warning about spinit, but is simulated,
   -> digital circuit produce error about missed definition of model
   and is not simulated.
3. Different version of libngspice0 (43+ds-1~bpo12+1) and ngspice
   (39.3+ds-1):
   -> analog circuit is simulated (no warning),
   -> digital circuit cause segmentation fault inside libngspice0.

Using strace shows that *.cm files are opened even though they are not
referenced in the program source code (they are used internally by the
library, due to content of the default `spinit` file, also internally
referenced via libngspice).

Regards
Robert

> Holger, I assume you are interested in some samples so you could have
> a look at? Thanks!
> 
> Regards
> Carsten
> 

Attachment: digital.netlist
Description: Binary data

Attachment: analog.netlist
Description: Binary data

// SPDX-FileCopyrightText: Robert Ryszard Paciorek <r...@opcode.eu.org>
// SPDX-License-Identifier: MIT

#include <ngspice/sharedspice.h>
#include <iostream>

#define USE_DLOPEN

#ifdef USE_DLOPEN
#include <dlfcn.h>
extern "C" {
	typedef int (*ngSpice_Init_Type) (SendChar*, SendStat*, ControlledExit*, SendData*, SendInitData*, BGThreadRunning*, void*);
	typedef int (*ngSpice_Init_Sync_Type) (GetVSRCData*, GetISRCData*, GetSyncData*, int*, void*);
	typedef int (*ngSpice_Command_Type) (char*);
}
#endif

struct GdSpice {
	GdSpice(const char* libngspice = "libngspice.so") {
		#ifdef USE_DLOPEN
		ngSpice_dll = dlopen(libngspice, RTLD_NOW);
		if (!ngSpice_dll) {
			throw std::runtime_error("can't load libngspice.so");
		}
		ngSpice_Init = reinterpret_cast<ngSpice_Init_Type>(dlsym(ngSpice_dll, "ngSpice_Init"));
		ngSpice_Init_Sync = reinterpret_cast<ngSpice_Init_Sync_Type>(dlsym(ngSpice_dll, "ngSpice_Init_Sync"));
		ngSpice_Command = reinterpret_cast<ngSpice_Command_Type>(dlsym(ngSpice_dll, "ngSpice_Command"));
		
		if (!ngSpice_Init || !ngSpice_Command) {
			throw std::runtime_error("missed function in libngspice.so");
		}
		#endif
		
		int ret = ngSpice_Init(on_getchar, /*on_getstat*/ nullptr, /*on_exit*/ nullptr, /*on_data*/ nullptr, /*on_initdata*/ nullptr, /*on_thread_runs*/ nullptr, this);
		std::cout << "init thread returned: " << ret << std::endl;
	}
	
	void start(std::string circuit_file) {
		run_command("reset");
		run_command(("source " + circuit_file).c_str());
		std::cerr << "pre run \n";
		run_command("bg_run");
	}
	
	int run_command(const char* command) {
		int ret = ngSpice_Command( const_cast<char*>(command) );
		std::cout << "command \"" << command << "\" returned: " << ret << std::endl;
		return ret;
	}
	
	#ifdef USE_DLOPEN
	void* ngSpice_dll = nullptr;
	ngSpice_Init_Type ngSpice_Init;
	ngSpice_Init_Sync_Type ngSpice_Init_Sync;
	ngSpice_Command_Type ngSpice_Command;
	#endif
	
	static int on_getchar(char* text, int ident, void* userdata) {
		auto gd_spice = static_cast<GdSpice*>(userdata);
		std::cout << "ngspice " << ident << " (" << userdata << "): " << text << std::endl;
		return 0;
	}
};

#include <unistd.h>

int main(int argc, char** argv) {
	if (argc < 2) {
		std::cout << "USAGE: " << argv[0] << " netlist_file" << std::endl;
		return 1;
	}
	auto spice = new GdSpice();
	spice->start(argv[1]);
	sleep(4);
}

Reply via email to