Browse Source

Add two new functions to the shared library API.

ngSpice_Raw_Evt() requests a callback that returns all the
XSPICE events for a specific node that occurred during the last timestep.
ngSpice_Decode_Evt() provides numeric and string versions of
the event data.  Also fix some warnings in sharedspice.c.
pre-master-46
Giles Atkinson 1 year ago
committed by Holger Vogt
parent
commit
16aadef4c7
  1. 12
      src/include/ngspice/evtproto.h
  2. 38
      src/include/ngspice/sharedspice.h
  3. 63
      src/sharedspice.c
  4. 1
      src/xspice/evt/evtplot.c

12
src/include/ngspice/evtproto.h

@ -148,16 +148,18 @@ void EVTcancel_value_call(const char *node,
Evt_New_Value_Cb_t fn, Evt_New_Value_Cb_t fn,
void *ctx); void *ctx);
/* Internal utility functions. */
void Evt_purge_free_outputs(void);
/* Parse a node name with member and find the node index. */
/* Parse a node name with member and return the node index and type. */
struct node_parse { struct node_parse {
char *node; char *node;
char *member; char *member;
int udn_index;
}; };
int Evt_Parse_Node(const char *node, struct node_parse *result); int Evt_Parse_Node(const char *node, struct node_parse *result);
/* Internal utility functions. */
void Evt_purge_free_outputs(void);
#endif #endif

38
src/include/ngspice/sharedspice.h

@ -357,6 +357,18 @@ typedef int (SendInitEvtData)(int, int, char*, char*, int, void*);
int identification number of calling ngspice shared lib int identification number of calling ngspice shared lib
void* return pointer received from caller void* return pointer received from caller
*/ */
/* Upon time step finished, all events that occurred on a node.
* A non-zero return value cancels further reports for tis node.
*/
typedef int (SendRawEvtData)(double, void *, void *, int);
/*
double event time
void* pointer to the node's value (a Digital_t for digital nodes)
void* return pointer received from caller
int zero if another event report for the same node follows
*/
#endif #endif
/* ngspice initialization, /* ngspice initialization,
@ -415,6 +427,32 @@ userData: pointer to user-defined data, will not be modified, but
handed over back to caller during Callback, e.g. address of calling object */ handed over back to caller during Callback, e.g. address of calling object */
IMPEXP IMPEXP
int ngSpice_Init_Evt(SendEvtData* sevtdata, SendInitEvtData* sinitevtdata, void* userData); int ngSpice_Init_Evt(SendEvtData* sevtdata, SendInitEvtData* sinitevtdata, void* userData);
/* Request callback for every event on a specific XSPICE event node.
* A single callback function pointer is stored, with all calls directed
* to the function specified last.
* The return value identifies the node data type or is -1 on error.
*
* node name of an event node.
* srawevt pointer to callback function.
* userData pointer to user-defined data.
*/
IMPEXP
int ngSpice_Raw_Evt(const char* node, SendRawEvtData* srawevt, void* userData);
/* Decode raw event node data. Return 0 on success.
* evt pointer to event data (a reported node value).
* type node type index, return value from ngSpice_Raw_Evt().
* pplotval pointer to a double, the "plotting value" is returned. NULL OK.
* printval pointer to a char pointer that is updated to point to a
* readonly string describing the value. If evt is NULL, a string
* identifying the node data type is returned. NULL is OK.
*/
IMPEXP
int ngSpice_Decode_Evt(void* evt, int type,
double *pplotval, const char **pprintval);
#endif #endif

63
src/sharedspice.c

@ -182,6 +182,8 @@ typedef void (*sighandler)(int);
#ifdef XSPICE #ifdef XSPICE
#include "ngspice/evtshared.h" #include "ngspice/evtshared.h"
#include "ngspice/evtproto.h"
#include "ngspice/evtudn.h"
extern bool wantevtdata; extern bool wantevtdata;
#endif #endif
@ -222,7 +224,7 @@ extern struct comm spcp_coms[];
struct comm* cp_coms = spcp_coms; struct comm* cp_coms = spcp_coms;
/* Main options */ /* Main options */
static bool ft_servermode = FALSE;
bool ft_batchmode = FALSE; bool ft_batchmode = FALSE;
bool ft_pipemode = FALSE; bool ft_pipemode = FALSE;
bool rflag = FALSE; /* has rawfile */ bool rflag = FALSE; /* has rawfile */
@ -341,6 +343,8 @@ void sh_delete_myvec(void);
#ifdef XSPICE #ifdef XSPICE
void shared_send_event(int, double, double, char *, void *, int, int); void shared_send_event(int, double, double, char *, void *, int, int);
void shared_send_dict(int, int, char*, char*); void shared_send_dict(int, int, char*, char*);
static int evt_shim(double time, Mif_Value_t *vp, void *ctx, int last);
#endif #endif
#if !defined(low_latency) #if !defined(low_latency)
@ -397,6 +401,7 @@ static int intermj = 1;
#ifdef XSPICE #ifdef XSPICE
static SendInitEvtData* sendinitevt; static SendInitEvtData* sendinitevt;
static SendEvtData* sendevt; static SendEvtData* sendevt;
static SendRawEvtData *sendrawevt;
#endif #endif
static void* euserptr; static void* euserptr;
static wordlist *shcontrols; static wordlist *shcontrols;
@ -1387,6 +1392,41 @@ int ngSpice_Init_Evt(SendEvtData* sevtdata, SendInitEvtData* sinitevtdata, void
return(TRUE); return(TRUE);
} }
/* Set callback address for raw XSPICE events.
* The return value identifies the node data type or is -1 on error.
*/
IMPEXP
int ngSpice_Raw_Evt(const char* node, SendRawEvtData* srawevt, void* userData)
{
struct node_parse np;
if (Evt_Parse_Node(node, &np) < 0 || np.member)
return -1; // Invalid node name.
sendrawevt = srawevt;
EVTnew_value_call(node, evt_shim, Evt_Cbt_Raw, userData);
return np.udn_index;
}
IMPEXP
int ngSpice_Decode_Evt(void* evt, int type,
double *pplotval, const char **ppprintval)
{
if (type >= g_evt_num_udn_types)
return 1;
if (!evt) {
if (!ppprintval)
return 2;
*ppprintval = g_evt_udn_info[type]->name;
return 0;
}
if (pplotval)
g_evt_udn_info[type]->plot_val(evt, "", pplotval);
if (ppprintval)
g_evt_udn_info[type]->print_val(evt, "", (char **)ppprintval);
return 0;
}
/* Get info about the event node vector. /* Get info about the event node vector.
If node_name is NULL, just delete previous data */ If node_name is NULL, just delete previous data */
IMPEXP IMPEXP
@ -1467,7 +1507,7 @@ sh_vfprintf(FILE *f, const char *fmt, va_list args)
{ {
char buf[1024]; char buf[1024];
char *p/*, *s*/; char *p/*, *s*/;
int nchars, /*escapes,*/ result;
int nchars;
size_t size; size_t size;
@ -1547,7 +1587,7 @@ sh_vfprintf(FILE *f, const char *fmt, va_list args)
Spice_Init() from caller of ngspice.dll */ Spice_Init() from caller of ngspice.dll */
result = sh_fputs(p, f);
sh_fputs(p, f);
if (p != buf) if (p != buf)
tfree(p); tfree(p);
@ -1929,7 +1969,6 @@ void SetAnalyse(
|| defined (HAVE_FTIME) || defined (HAVE_FTIME)
PerfTime timenow; /* actual time stamp */ PerfTime timenow; /* actual time stamp */
int diffsec, diffmillisec; /* differences actual minus prev. time stamp */ int diffsec, diffmillisec; /* differences actual minus prev. time stamp */
int result; /* return value from callback function */
char* s; /* outputs to callback function */ char* s; /* outputs to callback function */
int OldPercent; /* Previous progress value */ int OldPercent; /* Previous progress value */
char OldAn[128]; /* Previous analysis type */ char OldAn[128]; /* Previous analysis type */
@ -1994,7 +2033,7 @@ void SetAnalyse(
if (!strcmp(Analyse, "tran")) { if (!strcmp(Analyse, "tran")) {
if (ckt && (ckt->CKTtime > ckt->CKTfinalTime - ckt->CKTmaxStep)) { if (ckt && (ckt->CKTtime > ckt->CKTfinalTime - ckt->CKTmaxStep)) {
sprintf(s, "--ready--"); sprintf(s, "--ready--");
result = statfcn(s, ng_ident, userptr);
statfcn(s, ng_ident, userptr);
tfree(s); tfree(s);
return; return;
} }
@ -2007,7 +2046,7 @@ void SetAnalyse(
return; return;
} }
sprintf( s, "--ready--"); sprintf( s, "--ready--");
result = statfcn(s, ng_ident, userptr);
statfcn(s, ng_ident, userptr);
tfree(s); tfree(s);
return; return;
} }
@ -2056,7 +2095,7 @@ void SetAnalyse(
} }
/* ouput only after a change */ /* ouput only after a change */
if (strcmp(olds, s)) if (strcmp(olds, s))
result = statfcn(s, ng_ident, userptr);
statfcn(s, ng_ident, userptr);
if(thread1) if(thread1)
strcpy(olds1, s); strcpy(olds1, s);
else else
@ -2065,11 +2104,10 @@ void SetAnalyse(
tfree(s); tfree(s);
#else #else
char* s; char* s;
int result;
static bool havesent = FALSE; static bool havesent = FALSE;
if (!havesent) { if (!havesent) {
s = copy("No usage info available"); s = copy("No usage info available");
result = statfcn(s, ng_ident, userptr);
statfcn(s, ng_ident, userptr);
tfree(s); tfree(s);
havesent = TRUE; havesent = TRUE;
} }
@ -2460,6 +2498,13 @@ void shared_send_dict(int index, int no_of_nodes, char* name, char*type)
if (sendinitevt) if (sendinitevt)
sendinitevt(index, no_of_nodes, name, type, ng_ident, euserptr); sendinitevt(index, no_of_nodes, name, type, ng_ident, euserptr);
} }
static int evt_shim(double time, Mif_Value_t *vp, void *ctx, int last)
{
if (sendrawevt)
return sendrawevt(time, vp->pvalue, ctx, last); // Strip Mif_value.
return 1;
}
#endif #endif
static int totalreset(void) static int totalreset(void)

1
src/xspice/evt/evtplot.c

@ -114,6 +114,7 @@ int Evt_Parse_Node(const char *node, struct node_parse *result)
tfree(name); tfree(name);
return -1; return -1;
} }
result->udn_index = node_table[i]->udn_index;
return i; return i;
} }

Loading…
Cancel
Save