diff --git a/visualc/ng_shared_xspice_v/examples/adder_mos.cir b/visualc/ng_shared_xspice_v/examples/adder_mos.cir new file mode 100644 index 000000000..5e1b9b02a --- /dev/null +++ b/visualc/ng_shared_xspice_v/examples/adder_mos.cir @@ -0,0 +1,66 @@ + ADDER - 4 BIT ALL-NAND-GATE BINARY ADDER + +*** SUBCIRCUIT DEFINITIONS +.SUBCKT NAND in1 in2 out VDD +* NODES: INPUT(2), OUTPUT, VCC +M1 out in2 Vdd Vdd p1 W=7.5u L=0.35u pd=13.5u ad=22.5p ps=13.5u as=22.5p +M2 net.1 in2 0 0 n1 W=3u L=0.35u pd=9u ad=9p ps=9u as=9p +M3 out in1 Vdd Vdd p1 W=7.5u L=0.35u pd=13.5u ad=22.5p ps=13.5u as=22.5p +M4 out in1 net.1 0 n1 W=3u L=0.35u pd=9u ad=9p ps=9u as=9p +.ENDS NAND + +.SUBCKT ONEBIT 1 2 3 4 5 6 +* NODES: INPUT(2), CARRY-IN, OUTPUT, CARRY-OUT, VCC +X1 1 2 7 6 NAND +X2 1 7 8 6 NAND +X3 2 7 9 6 NAND +X4 8 9 10 6 NAND +X5 3 10 11 6 NAND +X6 3 11 12 6 NAND +X7 10 11 13 6 NAND +X8 12 13 4 6 NAND +X9 11 7 5 6 NAND +.ENDS ONEBIT + +.SUBCKT TWOBIT 1 2 3 4 5 6 7 8 9 +* NODES: INPUT - BIT0(2) / BIT1(2), OUTPUT - BIT0 / BIT1, +* CARRY-IN, CARRY-OUT, VCC +X1 1 2 7 5 10 9 ONEBIT +X2 3 4 10 6 8 9 ONEBIT +.ENDS TWOBIT + +.SUBCKT FOURBIT 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 +* NODES: INPUT - BIT0(2) / BIT1(2) / BIT2(2) / BIT3(2), +* OUTPUT - BIT0 / BIT1 / BIT2 / BIT3, CARRY-IN, CARRY-OUT, VCC +X1 1 2 3 4 9 10 13 16 15 TWOBIT +X2 5 6 7 8 11 12 16 14 15 TWOBIT +.ENDS FOURBIT + +*** POWER +VCC 99 0 DC 3.3V + +*** ALL INPUTS +VIN1A 1 0 DC 0 PULSE(0 3 0 5NS 5NS 20NS 50NS) +VIN1B 2 0 DC 0 PULSE(0 3 0 5NS 5NS 30NS 100NS) +VIN2A 3 0 DC 0 PULSE(0 3 0 5NS 5NS 50NS 200NS) +VIN2B 4 0 DC 0 PULSE(0 3 0 5NS 5NS 90NS 400NS) +VIN3A 5 0 DC 0 PULSE(0 3 0 5NS 5NS 170NS 800NS) +VIN3B 6 0 DC 0 PULSE(0 3 0 5NS 5NS 330NS 1600NS) +VIN4A 7 0 DC 0 PULSE(0 3 0 5NS 5NS 650NS 3200NS) +VIN4B 8 0 DC 0 PULSE(0 3 0 5NS 5NS 1290NS 6400NS) + +*** DEFINE NOMINAL CIRCUIT +X1 1 2 3 4 5 6 7 8 9 10 11 12 0 13 99 FOURBIT + +.option noinit acct +.TRAN 500p 6400NS +* save inputs +.save V(1) V(2) V(3) V(4) V(5) V(6) V(7) V(8) + +* use BSIM3 model with default parameters +.model n1 nmos level=49 version=3.3.0 +.model p1 pmos level=49 version=3.3.0 +*.include ./Modelcards/modelcard32.nmos +*.include ./Modelcards/modelcard32.pmos + +.END diff --git a/visualc/ng_shared_xspice_v/examples/count-latch-dac.cir b/visualc/ng_shared_xspice_v/examples/count-latch-dac.cir new file mode 100644 index 000000000..7a8c7d90a --- /dev/null +++ b/visualc/ng_shared_xspice_v/examples/count-latch-dac.cir @@ -0,0 +1,81 @@ +* counter, latch DAC + +* 10 bit synchronous digital counter +* inhibit at overflow, no revolving +.subckt count10 din dinb dclk drs dout1 dout2 dout3 dout4 dout5 dout6 dout7 dout8 dout9 dout10 + +* j k clk set reset out nout +ajk1 din dinb diclk ds1 drs dout1 dnout1 jkflop +ajk2 dout1 dout1 diclk ds2 drs dout2 dnout2 jkflop +ajk3 djk3 djk3 diclk ds3 drs dout3 dnout3 jkflop +ajk4 djk4 djk4 diclk ds4 drs dout4 dnout4 jkflop +ajk5 djk5 djk5 diclk ds1 drs dout5 dnout5 jkflop +ajk6 djk6 djk6 diclk ds2 drs dout6 dnout6 jkflop +ajk7 djk7 djk7 diclk ds3 drs dout7 dnout8 jkflop +ajk8 djk8 djk8 diclk ds4 drs dout8 dnout8 jkflop +ajk9 djk9 djk9 diclk ds3 drs dout9 dnout9 jkflop +ajk10 djk10 djk10 diclk ds4 drs dout10 dnout10 jkflop + +aand1 [dout1 dout2] djk3 and1 +aand2 [dout1 dout2 dout3] djk4 and1 +aand3 [dout1 dout2 dout3 dout4] djk5 and1 +aand4 [dout1 dout2 dout3 dout4 dout5] djk6 and1 +aand5 [dout1 dout2 dout3 dout4 dout5 dout6] djk7 and1 +aand6 [dout1 dout2 dout3 dout4 dout5 dout6 dout7] djk8 and1 +aand7 [dout1 dout2 dout3 dout4 dout5 dout6 dout7 dout8] djk9 and1 +aand8 [dout1 dout2 dout3 dout4 dout5 dout6 dout7 dout8 dout9] djk10 and1 + +* inhibit revolving of counter, just let it saturate +* (footnote p. 57) +aand_all [dout1 dout2 dout3 dout4 dout5 dout6 dout7 dout8 dout9 dout10] dinhibit nand1 +aandclk [dclk dinhibit] diclk and1 + + +.model nand1 d_nand(rise_delay = 1e-9 fall_delay = 1e-9 ++ input_load = 0.5e-12) + +.model and1 d_and(rise_delay = 1e-9 fall_delay = 1e-9 ++ input_load = 0.5e-12) + +.model jkflop d_jkff(clk_delay = 1.0e-9 set_delay = 1e-9 ++ reset_delay = 1e-9 ic = 0 rise_delay = 1.0e-9 ++ fall_delay = 1e-9) + +.ends count 10 + +** 10 bit edge triggered latch +.subckt latch10 din1 din2 din3 din4 din5 din6 din7 din8 din9 din10 ++ dout1 dout2 dout3 dout4 dout5 dout6 dout7 dout8 dout9 dout10 dclk + +*data clk set reset out nout +aff1 din1 dclk dzero dzero dout1 dnout1 flop1 +aff2 din2 dclk dzero dzero dout2 dnout2 flop1 +aff3 din3 dclk dzero dzero dout3 dnout3 flop1 +aff4 din4 dclk dzero dzero dout4 dnout4 flop1 +aff5 din5 dclk dzero dzero dout5 dnout5 flop1 +aff6 din6 dclk dzero dzero dout6 dnout6 flop1 +aff7 din7 dclk dzero dzero dout7 dnout7 flop1 +aff8 din8 dclk dzero dzero dout8 dnout8 flop1 +aff9 din9 dclk dzero dzero dout9 dnout9 flop1 +aff10 din10 dclk dzero dzero dout10 dnout10 flop1 + +.model flop1 d_dff(clk_delay = 1e-9 set_delay = 0 ++ reset_delay = 0 ic = 0 rise_delay = 1e-9 ++ fall_delay = 1e-9) + +.ends latch10 + +** emulation of 10 bit DAC +.subckt dac10 din1 din2 din3 din4 din5 din6 din7 din8 din9 din10 aout +.param vref=1 +abridge1 [din1 din2 din3 din4 din5 din6 din7 din8 din9 din10] ++ [ain1 ain2 ain3 ain4 ain5 ain6 ain7 ain8 ain9 ain10] dac1 +BVout aout 0 V = 'vref'*(v(ain10)/2 + v(ain9)/4 + v(ain8)/8 + v(ain7)/16 + v(ain6)/32 + ++ v(ain5)/64 + v(ain4)/128 + v(ain3)/256 + v(ain2)/512 + v(ain1)/1024) + +.model dac1 dac_bridge(out_low = 0 out_high = 1 out_undef = 0.5 ++ input_load = 5.0e-12 t_rise = 1e-9 ++ t_fall = 1e-9) + +.ends dac10 + diff --git a/visualc/ng_shared_xspice_v/examples/counter-test.cir b/visualc/ng_shared_xspice_v/examples/counter-test.cir new file mode 100644 index 000000000..c293c5c79 --- /dev/null +++ b/visualc/ng_shared_xspice_v/examples/counter-test.cir @@ -0,0 +1,45 @@ +* 10 bit synchronous digital counter +* inhibit at overflow, no revolving +* according to Schreier, Temes: Understanding Delta-Sigma Data Converters, 2005 +* Fig. 2.27, p. 58 + +.options noinit noacct + +* clock generation +* PULSE(V1 V2 TD TR TF PW PER) +vclk aclk 0 dc 0 pulse(0 1 1u 2n 2n 1u 2u) + +* reset generation +* single pulse, actual value stored in latch and read by DAC +vres ars 0 dc 0 pulse(0 1 1.1m 2n 2n 1u 2.2m) + +vone aone 0 dc 1 +vzero azero 0 dc 0 + +* digital one +* digital zero +abridge1 [aone azero] [done dzero] adc_buff +.model adc_buff adc_bridge(in_low = 0.5 in_high = 0.5) + +* digital clock +* digital reset +abridge2 [aclk ars] [dclk dreset] adc_buff +.model adc_buff adc_bridge(in_low = 0.5 in_high = 0.5) + +XCounter done done dclk dreset dout1 dout2 dout3 dout4 dout5 dout6 dout7 dout8 dout9 dout10 count10 +Xlatch dout1 dout2 dout3 dout4 dout5 dout6 dout7 dout8 dout9 dout10 ++ dlout1 dlout2 dlout3 dlout4 dlout5 dlout6 dlout7 dlout8 dlout9 dlout10 dreset ++ latch10 +Xdac dlout1 dlout2 dlout3 dlout4 dlout5 dlout6 dlout7 dlout8 dlout9 dlout10 adacout dac10 + +.include count-latch-dac.cir +.tran 1u 2.5m + +* no .control section if to be started with bg_run +*.control +*eprint dout1 dout2 dout3 dout4 dout5 dout6 dout7 dout8 dout9 dout10 > digi4b.txt +*eprint dlout1 dlout2 dlout3 dlout4 dlout5 dlout6 dlout7 dlout8 dlout9 dlout10 >> digi4b.txt +*plot adacout +*.endc + +.end diff --git a/visualc/ng_shared_xspice_v/ng_shared_start.bat b/visualc/ng_shared_xspice_v/ng_shared_start.bat new file mode 100644 index 000000000..8b3af437e --- /dev/null +++ b/visualc/ng_shared_xspice_v/ng_shared_start.bat @@ -0,0 +1,2 @@ +start /B .\Debug\ng_shared_test_v.exe +PAUSE diff --git a/visualc/ng_shared_xspice_v/ng_shared_test_v.sln b/visualc/ng_shared_xspice_v/ng_shared_test_v.sln new file mode 100644 index 000000000..9438370fb --- /dev/null +++ b/visualc/ng_shared_xspice_v/ng_shared_test_v.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25029.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ng_shared_test_v", "ng_shared_test_v\ng_shared_test_v.vcxproj", "{01B94AD4-AF8F-4173-9BF8-120638B8BC6C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {01B94AD4-AF8F-4173-9BF8-120638B8BC6C}.Debug|Win32.ActiveCfg = Debug|Win32 + {01B94AD4-AF8F-4173-9BF8-120638B8BC6C}.Debug|Win32.Build.0 = Debug|Win32 + {01B94AD4-AF8F-4173-9BF8-120638B8BC6C}.Release|Win32.ActiveCfg = Release|Win32 + {01B94AD4-AF8F-4173-9BF8-120638B8BC6C}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/visualc/ng_shared_xspice_v/ng_shared_test_v/ng_shared_test_v.vcxproj b/visualc/ng_shared_xspice_v/ng_shared_test_v/ng_shared_test_v.vcxproj new file mode 100644 index 000000000..abe62a582 --- /dev/null +++ b/visualc/ng_shared_xspice_v/ng_shared_test_v/ng_shared_test_v.vcxproj @@ -0,0 +1,109 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {01B94AD4-AF8F-4173-9BF8-120638B8BC6C} + ng_shared_test_v + Win32Proj + + + + Application + v140 + NotSet + true + + + Application + v140 + NotSet + + + + + + + + + + + + + <_ProjectFileVersion>14.0.25029.0 + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + true + + + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + false + + + + Disabled + WIN32;_DEBUG;_CONSOLE;XSPICE;%(PreprocessorDefinitions) + true + + Default + MultiThreadedDebug + true + + Level4 + EditAndContinue + CompileAsC + + + true + Console + false + + MachineX86 + + + + + Full + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + + MultiThreaded + false + true + + Level3 + + CompileAsC + + + false + Console + true + true + + MachineX86 + + + + + + + + + + + + \ No newline at end of file diff --git a/visualc/ng_shared_xspice_v/src/main_xspice.c b/visualc/ng_shared_xspice_v/src/main_xspice.c new file mode 100644 index 000000000..55e65dfd9 --- /dev/null +++ b/visualc/ng_shared_xspice_v/src/main_xspice.c @@ -0,0 +1,581 @@ +/* +Test file for shared ngspice +Copyright Holger Vogt 2013 + +ngspice library loaded dynamically + +Test 1 +Load and initialize ngspice +Source an input file adder_mos.cir +Run the simulation for 5 seconds in a background thread +Stop the simulation for 3 seconds +Resume the simulation in the background thread +Write rawfile +Unload ngspice + +*/ + + + +#include +#include +#include +#include +#ifndef _MSC_VER +#include +#include +#else +#define bool int +#define true 1 +#define false 0 +#define strdup _strdup +#endif +#include "../../../src/include/ngspice/sharedspice.h" + +#if defined(__MINGW32__) || defined(_MSC_VER) +#undef BOOLEAN +#include +typedef FARPROC funptr_t; +void *dlopen (const char *, int); +funptr_t dlsym (void *, const char *); +int dlclose (void *); +char *dlerror (void); +#define RTLD_LAZY 1 /* lazy function call binding */ +#define RTLD_NOW 2 /* immediate function call binding */ +#define RTLD_GLOBAL 4 /* symbols in this dlopen'ed obj are visible to other dlopen'ed objs */ +static char errstr[128]; +#else +#include /* to load libraries*/ +#include +#include +typedef void * funptr_t; +#endif + +bool no_bg = true; +bool not_yet = true; +bool will_unload = false; +bool error_ngspice = false; + +int cieq(register char *p, register char *s); +int ciprefix(const char *p, const char *s); + +/* callback functions used by ngspice */ +int +ng_getchar(char* outputreturn, int ident, void* userdata); + +int +ng_getstat(char* outputreturn, int ident, void* userdata); + +int +ng_thread_runs(bool noruns, int ident, void* userdata); + +/* callback functions used by XSPICE for event data */ +int +ng_getevtdata(int index, double step, double dvalue, char *svalue, + void *pvalue, int plen, int mode, int ident, void *userdata); + +int +ng_getinitevtdata(int index, int max_index, char * name, char *type, int ident, void *userdata); + +ControlledExit ng_exit; +SendData ng_data; +SendInitData ng_initdata; + +int vecgetnumber = 0; +double v2dat; +static bool has_break = false; +int testnumber = 0; +void alterp(int sig); + +/* functions exported by ngspice */ +funptr_t ngSpice_Init_handle = NULL; +funptr_t ngSpice_Command_handle = NULL; +funptr_t ngSpice_Circ_handle = NULL; +funptr_t ngSpice_CurPlot_handle = NULL; +funptr_t ngSpice_AllVecs_handle = NULL; +funptr_t ngSpice_GVI_handle = NULL; +funptr_t ngSpice_AllNodes_handle = NULL; +funptr_t ngSpice_EVT_handle = NULL; +funptr_t ngSpice_Init_Evt_handle = NULL; + +void * ngdllhandle = NULL; + +#ifndef _MSC_VER +pthread_t mainthread; +#endif // _MSC_VER + +int main() +{ + char *errmsg = NULL, *loadstring, *curplot, *vecname; + int *ret, i; + char **vecarray; + + printf("****************************\n"); + printf("** ngspice shared start **\n"); + printf("****************************\n"); + +#ifndef _MSC_VER + mainthread = pthread_self(); +#endif // _MSC_VER + printf("Load ngspice.dll\n"); +#ifdef __CYGWIN__ + loadstring = "/cygdrive/c/cygwin/usr/local/bin/cygngspice-0.dll"; +#elif _MSC_VER +// loadstring = "ngspice.dll"; +// loadstring = "..\\..\\..\\ngspice\\visualc\\sharedspice\\Debug.Win32\\ngspice.dll"; +// loadstring = "..\\..\\..\\ngspice\\visualc\\sharedspice\\ReleaseOMP.Win32\\ngspice.dll"; + loadstring = "D:\\Spice_general\\ngspice\\visualc\\sharedspice\\Debug.Win32\\ngspice.dll"; +#elif __MINGW32__ + loadstring = "D:\\Spice_general\\ngspice\\visualc-shared\\Debug\\bin\\ngspice.dll"; +#else + loadstring = "libngspice.so"; +#endif + ngdllhandle = dlopen(loadstring, RTLD_NOW); + errmsg = dlerror(); + if (errmsg) + printf("%s\n", errmsg); + if (ngdllhandle) + printf("ngspice.dll loaded\n"); + else { + printf("ngspice.dll not loaded !\n"); +// exit(1); + } + + ngSpice_Init_handle = dlsym(ngdllhandle, "ngSpice_Init"); + errmsg = dlerror(); + if (errmsg) + printf(errmsg); + ngSpice_Command_handle = dlsym(ngdllhandle, "ngSpice_Command"); + errmsg = dlerror(); + if (errmsg) + printf(errmsg); + ngSpice_CurPlot_handle = dlsym(ngdllhandle, "ngSpice_CurPlot"); + errmsg = dlerror(); + if (errmsg) + printf(errmsg); + ngSpice_AllVecs_handle = dlsym(ngdllhandle, "ngSpice_AllVecs"); + errmsg = dlerror(); + if (errmsg) + printf(errmsg); + ngSpice_GVI_handle = dlsym(ngdllhandle, "ngGet_Vec_Info"); + errmsg = dlerror(); + if (errmsg) + printf(errmsg); + ngSpice_AllNodes_handle = dlsym(ngdllhandle, "ngSpice_AllEvtNodes"); + errmsg = dlerror(); + if (errmsg) + printf(errmsg); + ngSpice_EVT_handle = dlsym(ngdllhandle, "ngGet_Evt_NodeInfo"); + errmsg = dlerror(); + if (errmsg) + printf(errmsg); + ngSpice_Init_Evt_handle = dlsym(ngdllhandle, "ngSpice_Init_Evt"); + errmsg = dlerror(); + if (errmsg) + printf(errmsg); + + /* general callback initialization */ + ret = ((int * (*)(SendChar*, SendStat*, ControlledExit*, SendData*, SendInitData*, + BGThreadRunning*, void*)) ngSpice_Init_handle)(ng_getchar, ng_getstat, + ng_exit, NULL, ng_initdata, ng_thread_runs, NULL); + + /* event data initialization */ + ret = ((int * (*)(SendEvtData*, SendInitEvtData*, void*)) ngSpice_Init_Evt_handle)(ng_getevtdata, + ng_getinitevtdata, NULL); + + testnumber = 1; + printf("\n** Test no. %d with sourcing input file **\n\n", testnumber); + error_ngspice = false; + will_unload = false; + +#if defined(__CYGWIN__) + ret = ((int * (*)(char*)) ngSpice_Command_handle)("source /cygdrive/d/Spice_general/ngspice_sh/examples/shared-ngspice/counter-test.cir"); +#elif __MINGW32__ + ret = ((int * (*)(char*)) ngSpice_Command_handle)("source D:\\Spice_general\\ngspice_sh\\examples\\shared-ngspice\\counter-test.cir"); +#elif _MSC_VER + ret = ((int * (*)(char*)) ngSpice_Command_handle)("source ./examples/counter-test.cir"); +#else + ret = ((int * (*)(char*)) ngSpice_Command_handle)("source ../examples/counter-test.cir"); + // ret = ((int * (*)(char*)) ngSpice_Command_handle)("source adder_mos.cir"); +#endif + + ret = ((int * (*)(char*)) ngSpice_Command_handle)("bg_run"); + printf("We are back again\n"); + + /* wait to catch error signal, if available */ +#if defined(__MINGW32__) || defined(_MSC_VER) + Sleep(100); +#else + usleep(100000); +#endif + /* Upon error: unload ngspice and skip rest of test code */ + if (error_ngspice) { + printf("Error detected, let's unload\n"); + ret = ((int * (*)(char*)) ngSpice_Command_handle)("quit"); + dlclose(ngdllhandle); + printf("ngspice.dll unloaded\n\n"); + ngdllhandle = NULL; + return 0; + } + + /* simulate for 500 milli seconds or until simulation has finished */ + for (i = 0; i < 5; i++) { +#if defined(__MINGW32__) || defined(_MSC_VER) + Sleep(100); +#else + usleep(100000); +#endif + /* we are faster than anticipated */ + if (no_bg) + goto endsim; + } + + ret = ((int * (*)(char*)) ngSpice_Command_handle)("bg_halt"); + for (i = 3; i > 0; i--) { + printf("Pause for %d seconds\n", i); +#if defined(__MINGW32__) || defined(_MSC_VER) + Sleep(1000); +#else + usleep(1000000); +#endif + } + ret = ((int * (*)(char*)) ngSpice_Command_handle)("bg_resume"); + + /* wait for 1s while simulation continues */ +#if defined(__MINGW32__) || defined(_MSC_VER) + Sleep(1000); +#else + usleep(1000000); +#endif + /* read current plot while simulation continues */ + curplot = ((char * (*)()) ngSpice_CurPlot_handle)(); + printf("\nCurrent plot is %s\n\n", curplot); + + vecarray = ((char ** (*)(char*)) ngSpice_AllVecs_handle)(curplot); + /* get length of first vector */ + if (vecarray) { + char plotvec[256]; + pvector_info myvec; + int veclength; + vecname = vecarray[0]; + sprintf(plotvec, "%s.%s", curplot, vecname); + myvec = ((pvector_info(*)(char*)) ngSpice_GVI_handle)(plotvec); + veclength = myvec->v_length; + printf("\nActual length of vector %s is %d\n\n", plotvec, veclength); + } + + /* wait until simulation finishes */ + for (;;) { +#if defined(__MINGW32__) || defined(_MSC_VER) + Sleep(100); +#else + usleep(100000); +#endif + if (no_bg) + break; + } +endsim: + /* Print all event nodes to stdout */ + vecarray = ((char ** (*)()) ngSpice_AllNodes_handle)(); + i = 0; + if (vecarray) { + char* node; + printf("\nWe print all event node names:\n"); + for (i = 0; ; i++) { + node = vecarray[i]; + if (!vecarray[i]) + break; + fprintf(stdout, "%s\n", vecarray[i]); + } + } + printf("We have %d event nodes\n\n", i); + + /* just to select some nodes */ + int j = (int)(i / 2); + char * nodename; + if (j > 0) { + nodename = vecarray[j]; + printf("We analyse event node %s\n", nodename); + pevt_shared_data evtnode; + /* Get data from ngspice.dll */ + evtnode = ((pevt_shared_data(*)(char*)) ngSpice_EVT_handle)(nodename); + pevt_data *nodevals = evtnode->evt_dect; + int count = evtnode->num_steps; + for (i = 0; i < count; i++) { + char *nodeval = nodevals[i]->node_value; + double step = nodevals[i]->step; + fprintf(stdout, "%e %s\n", step, nodeval); + } + /* Delete data */ + ((pevt_shared_data(*)(char*)) ngSpice_EVT_handle)(NULL); + /* just watch another node */ + nodename = vecarray[j - 1]; + printf("We analyse event node %s\n", nodename); + evtnode = ((pevt_shared_data(*)(char*)) ngSpice_EVT_handle)(nodename); + nodevals = evtnode->evt_dect; + count = evtnode->num_steps; + for (i = 0; i < count; i++) { + char *nodeval = nodevals[i]->node_value; + double step = nodevals[i]->step; + fprintf(stdout, "%e %s\n", step, nodeval); + } + /* Delete data */ + ((pevt_shared_data(*)(char*)) ngSpice_EVT_handle)(NULL); + } + else + printf("Not enough nodes for selection\n"); + + ret = ((int * (*)(char*)) ngSpice_Command_handle)("quit"); +#if 0 + /* unload now */ + dlclose(ngdllhandle); + ngdllhandle = NULL; + printf("Unloaded\n\n"); +#endif + if (will_unload) { + printf("Unload now\n"); + dlclose(ngdllhandle); + ngdllhandle = NULL; + printf("Unloaded\n\n"); + } + + return 0; +} + + +/* Callback function called from bg thread in ngspice to transfer + any string created by printf or puts. Output to stdout in ngspice is + preceded by token stdout, same with stderr.*/ +int +ng_getchar(char* outputreturn, int ident, void* userdata) +{ + printf("%s\n", outputreturn); + /* setting a flag if an error message occurred */ + if (ciprefix("stderr Error:", outputreturn)) + error_ngspice = true; + return 0; +} + +/* Callback function called from bg thread in ngspice to transfer + simulation status (type and progress in percent. */ +int +ng_getstat(char* outputreturn, int ident, void* userdata) +{ + printf("%s\n", outputreturn); + return 0; +} + +/* Callback function called from ngspice upon starting (returns true) or + leaving (returns false) the bg thread. */ +int +ng_thread_runs(bool noruns, int ident, void* userdata) +{ + no_bg = noruns; + if (noruns) + printf("bg not running\n"); + else + printf("bg running\n"); + + return 0; +} + +/* Callback function called from bg thread in ngspice if fcn controlled_exit() + is hit. Do not exit, but unload ngspice. */ +int +ng_exit(int exitstatus, bool immediate, bool quitexit, int ident, void* userdata) +{ + + if(quitexit) { + printf("DNote: Returned from quit with exit status %d\n", exitstatus); + } + if(immediate) { + printf("DNote: Unload ngspice\n"); + ((int * (*)(char*)) ngSpice_Command_handle)("quit"); + dlclose(ngdllhandle); + } + + else { + printf("DNote: Prepare unloading ngspice\n"); + will_unload = true; + } + + return exitstatus; + +} + +/* Callback function called from bg thread in ngspice once per accepted data point */ +int +ng_data(pvecvaluesall vdata, int numvecs, int ident, void* userdata) +{ + int *ret; + + v2dat = vdata->vecsa[vecgetnumber]->creal; + if (!has_break && (v2dat > 0.5)) { + /* using signal SIGTERM by sending to main thread, alterp() then is run from the main thread, + (not on Windows though!) */ +#ifndef _MSC_VER + if (testnumber == 4) + pthread_kill(mainthread, SIGTERM); +#endif + has_break = true; + /* leave bg thread for a while to allow halting it from main */ +#if defined(__MINGW32__) || defined(_MSC_VER) + Sleep (100); +#else + usleep (100000); +#endif +// ret = ((int * (*)(char*)) ngSpice_Command_handle)("bg_halt"); + } + return 0; +} + + +/* Callback function called from bg thread in ngspice once upon intialization + of the analog simulation vectors)*/ +int +ng_initdata(pvecinfoall intdata, int ident, void* userdata) +{ + int i; + /* suppress second printing (after bg_resume) */ + static bool printonce = TRUE; + int vn = intdata->veccount; + if (printonce) { + for (i = 0; i < vn; i++) { + printf("Vector: %s\n", intdata->vecs[i]->vecname); + /* find the location of a vector */ + char *myvec = "adacout"; + if (cieq(intdata->vecs[i]->vecname, myvec)) { + vecgetnumber = i; + printf("Vector %s has index %d\n", myvec, i); + } + } + printonce = FALSE; + } + return 0; +} + +int mindex = -1; +char* mynode = "dout8"; +/* callback functions used by XSPICE for event data. */ + +/* Function is executed each time EVTdump() in ngspice is called and output + data for the node indexed by index have changed. */ +int +ng_getevtdata(int index, double step, double dvalue, char *svalue, + void *pvalue, int plen, int mode, int ident, void *userdata) +{ + static bool once = TRUE; + if (mindex == -1) { + if (once) { + fprintf(stderr, "Error: Cannot watch node %s, not found\n", mynode); + once = FALSE; + } + return 1; + } + /* Select an action only for a specific node. + The value of mindex for node mynode has been determined in function + ng_getinitevtdata() given below. */ + if (index == mindex) + fprintf(stdout, "Node %s, Index %d, Step %e, Value %s\n", mynode, index, step, svalue); + return 0; +} + +char *evt_nodes[2][1000]; +/* Immediately after initialization, get the list of event nodes as a string array: + evt_nodes[0][x]: node name + evt_nodes[1][x]: node type + index x: node number, may be used to access node value by using + function ng_getevtdata(index, ...) */ +int +ng_getinitevtdata(int index, int max_index, char * name, char *type, int ident, void *userdata) +{ + evt_nodes[0][index] = strdup(name); + evt_nodes[1][index] = strdup(type); + /* for a given node name, find the corresponding index */ + if (cieq(name, mynode)) + mindex = index; + return 0; +} + +/* Funcion called from main thread upon receiving signal SIGTERM */ +void +alterp(int sig) { + ((int * (*)(char*)) ngSpice_Command_handle)("bg_halt"); +} + +/* Unify LINUX and Windows dynamic library handling: + Add functions dlopen, dlsym, dlerror, dlclose to Windows by + tranlating to Windows API functions. +*/ +#if defined(__MINGW32__) || defined(_MSC_VER) + +void *dlopen(const char *name,int type) +{ + return LoadLibrary((LPCSTR)name); +} + +funptr_t dlsym(void *hDll, const char *funcname) +{ + return GetProcAddress(hDll, funcname); +} + +char *dlerror(void) +{ + LPVOID lpMsgBuf; + char * testerr; + DWORD dw = GetLastError(); + + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + dw, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) &lpMsgBuf, + 0, + NULL + ); + testerr = (char*)lpMsgBuf; + strcpy(errstr,lpMsgBuf); + LocalFree(lpMsgBuf); + if (ciprefix("Der Vorgang wurde erfolgreich beendet.", errstr)) + return NULL; + else + return errstr; +} + +int dlclose (void *lhandle) +{ + return (int)FreeLibrary(lhandle); +} +#endif + +/* Case insensitive str eq. + Like strcasecmp( ) XXX */ +int +cieq(register char *p, register char *s) +{ + while (*p) { + if ((isupper(*p) ? tolower(*p) : *p) != + (isupper(*s) ? tolower(*s) : *s)) + return(false); + p++; + s++; + } + return (*s ? false : true); +} + +/* Case insensitive prefix. */ +int +ciprefix(const char *p, const char *s) +{ + while (*p) { + if ((isupper(*p) ? tolower(*p) : *p) != + (isupper(*s) ? tolower(*s) : *s)) + return(false); + p++; + s++; + } + return (true); +}