Add two new XSPICE functions: EVTnew_value_call() and
EVTcancel_value_call(). EVTnew_value_call() specifies a function to be called for each confirmed new value produced on an XSPICE event node. To be used to add event node support for iplot.
This commit is contained in:
parent
f4963b1ada
commit
33f206b916
|
|
@ -78,6 +78,14 @@ struct Evt_Inst_Index {
|
||||||
int index; /* the value of the index */
|
int index; /* the value of the index */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Evt_Node_Cb {
|
||||||
|
struct Evt_Node_Cb *next;
|
||||||
|
Evt_New_Value_Cb_t fn; /* Function to be called. */
|
||||||
|
Evt_Node_Cb_Type_t type; /* Data type to pass to fn. */
|
||||||
|
const char *member; /* For event data type's plot fn. */
|
||||||
|
void *ctx;
|
||||||
|
};
|
||||||
|
|
||||||
struct Evt_Node_Info {
|
struct Evt_Node_Info {
|
||||||
Evt_Node_Info_t *next; /* the next in the linked list */
|
Evt_Node_Info_t *next; /* the next in the linked list */
|
||||||
char *name; /* Name of node in deck */
|
char *name; /* Name of node in deck */
|
||||||
|
|
@ -88,6 +96,7 @@ struct Evt_Node_Info {
|
||||||
int num_outputs; /* Number of outputs connected to this node */
|
int num_outputs; /* Number of outputs connected to this node */
|
||||||
int num_insts; /* The number of insts receiving node as input */
|
int num_insts; /* The number of insts receiving node as input */
|
||||||
Evt_Inst_Index_t *inst_list; /* Linked list of indexes of these instances */
|
Evt_Inst_Index_t *inst_list; /* Linked list of indexes of these instances */
|
||||||
|
Evt_Node_Cb_t *cbs; /* New value callbacks. */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Evt_Inst_Info {
|
struct Evt_Inst_Info {
|
||||||
|
|
@ -195,8 +204,6 @@ struct Evt_Queue {
|
||||||
/* ************** */
|
/* ************** */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct Evt_Node {
|
struct Evt_Node {
|
||||||
Evt_Node_t *next; /* pointer to next in linked list */
|
Evt_Node_t *next; /* pointer to next in linked list */
|
||||||
Mif_Boolean_t op; /* true if computed from op analysis */
|
Mif_Boolean_t op; /* true if computed from op analysis */
|
||||||
|
|
@ -204,6 +211,7 @@ struct Evt_Node {
|
||||||
void **output_value; /* Array of outputs posted to this node */
|
void **output_value; /* Array of outputs posted to this node */
|
||||||
void *node_value; /* Resultant computed from output values */
|
void *node_value; /* Resultant computed from output values */
|
||||||
void *inverted_value; /* Inverted copy of node_value */
|
void *inverted_value; /* Inverted copy of node_value */
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Evt_Node_Data {
|
struct Evt_Node_Data {
|
||||||
|
|
@ -362,6 +370,4 @@ struct Evt_Ckt_Data {
|
||||||
Evt_Option_t options; /* Data input on .options cards */
|
Evt_Option_t options; /* Data input on .options cards */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -136,6 +136,28 @@ bool Evtcheck_nodes(
|
||||||
struct INPtables *stab); /* Symbol table. */
|
struct INPtables *stab); /* Symbol table. */
|
||||||
|
|
||||||
struct dvec *EVTfindvec(char *node);
|
struct dvec *EVTfindvec(char *node);
|
||||||
|
|
||||||
|
/* Set and remove call-backs on new node values. */
|
||||||
|
|
||||||
|
Mif_Boolean_t EVTnew_value_call(const char *node,
|
||||||
|
Evt_New_Value_Cb_t fn,
|
||||||
|
Evt_Node_Cb_Type_t type,
|
||||||
|
void *ctx);
|
||||||
|
|
||||||
|
void EVTcancel_value_call(const char *node,
|
||||||
|
Evt_New_Value_Cb_t fn,
|
||||||
|
void *ctx);
|
||||||
|
|
||||||
|
/* Internal utility functions. */
|
||||||
|
|
||||||
void Evt_purge_free_outputs(void);
|
void Evt_purge_free_outputs(void);
|
||||||
|
|
||||||
|
/* Parse a node name with member and find the node index. */
|
||||||
|
|
||||||
|
struct node_parse {
|
||||||
|
char *node;
|
||||||
|
char *member;
|
||||||
|
};
|
||||||
|
|
||||||
|
int Evt_Parse_Node(const char *node, struct node_parse *result);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
#ifndef ngspice_EVTTYPES_H
|
#ifndef ngspice_EVTTYPES_H
|
||||||
#define ngspice_EVTTYPES_H
|
#define ngspice_EVTTYPES_H
|
||||||
|
#include "miftypes.h"
|
||||||
|
|
||||||
typedef struct Evt_Output_Info Evt_Output_Info_t;
|
typedef struct Evt_Output_Info Evt_Output_Info_t;
|
||||||
typedef struct Evt_Port_Info Evt_Port_Info_t;
|
typedef struct Evt_Port_Info Evt_Port_Info_t;
|
||||||
|
|
@ -28,6 +28,11 @@ typedef struct Evt_Limit Evt_Limit_t;
|
||||||
typedef struct Evt_Job Evt_Job_t;
|
typedef struct Evt_Job Evt_Job_t;
|
||||||
typedef struct Evt_Option Evt_Option_t;
|
typedef struct Evt_Option Evt_Option_t;
|
||||||
typedef struct Evt_Ckt_Data Evt_Ckt_Data_t;
|
typedef struct Evt_Ckt_Data Evt_Ckt_Data_t;
|
||||||
|
typedef struct Evt_Node_Cb Evt_Node_Cb_t;
|
||||||
|
|
||||||
|
typedef Mif_Boolean_t (*Evt_New_Value_Cb_t)(double when, Mif_Value_t *val_p,
|
||||||
|
void *ctx, int is_last);
|
||||||
|
|
||||||
|
typedef enum Evt_Node_Cb_Type { Evt_Cbt_Raw, Evt_Cbt_Plot} Evt_Node_Cb_Type_t;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@ NON-STANDARD FEATURES
|
||||||
|
|
||||||
#include "ngspice/mif.h"
|
#include "ngspice/mif.h"
|
||||||
#include "ngspice/evt.h"
|
#include "ngspice/evt.h"
|
||||||
|
#include "ngspice/evtudn.h"
|
||||||
#include "ngspice/evtproto.h"
|
#include "ngspice/evtproto.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -160,18 +161,62 @@ void EVTaccept(
|
||||||
num_modified = node_data->num_modified;
|
num_modified = node_data->num_modified;
|
||||||
/* Loop through list of items modified since last time */
|
/* Loop through list of items modified since last time */
|
||||||
for(i = 0; i < num_modified; i++) {
|
for(i = 0; i < num_modified; i++) {
|
||||||
|
Evt_Node_t *this;
|
||||||
|
Evt_Node_Info_t *node_info;
|
||||||
|
Evt_Node_Cb_t *cb, **cbpp;
|
||||||
|
int udn_index;
|
||||||
|
|
||||||
/* Get the index of the node modified */
|
/* Get the index of the node modified */
|
||||||
index = node_data->modified_index[i];
|
index = node_data->modified_index[i];
|
||||||
/* Reset the modified flag */
|
/* Reset the modified flag */
|
||||||
node_data->modified[index] = MIF_FALSE;
|
node_data->modified[index] = MIF_FALSE;
|
||||||
|
|
||||||
|
/* Call any value-change functions registered for this node. */
|
||||||
|
|
||||||
|
node_info = node_table[index];
|
||||||
|
udn_index = node_info->udn_index;
|
||||||
|
|
||||||
|
cbpp = &node_info->cbs;
|
||||||
|
for (;;) {
|
||||||
|
Mif_Value_t val;
|
||||||
|
|
||||||
|
cb = *cbpp;
|
||||||
|
if (cb == NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
for (this = *node_data->last_step[index];
|
||||||
|
this;
|
||||||
|
this = this->next) {
|
||||||
|
switch (cb->type) {
|
||||||
|
case Evt_Cbt_Raw:
|
||||||
|
val.pvalue = this->node_value;
|
||||||
|
break;
|
||||||
|
case Evt_Cbt_Plot:
|
||||||
|
g_evt_udn_info[udn_index]->plot_val(this->node_value,
|
||||||
|
(char *)cb->member,
|
||||||
|
&val.rvalue);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((*cb->fn)(this->step, &val, cb->ctx, !this->next)) {
|
||||||
|
/* Remove callback from chain. */
|
||||||
|
|
||||||
|
*cbpp = cb->next;
|
||||||
|
txfree(cb);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this == NULL) // Normal loop exit.
|
||||||
|
cbpp = &cb->next;
|
||||||
|
}
|
||||||
|
|
||||||
/* Optionally store node values for later examination.
|
/* Optionally store node values for later examination.
|
||||||
* The test of CKTtime here is copied from dctran.c.
|
* The test of CKTtime here is copied from dctran.c.
|
||||||
* CKTinitTime is from the tstart parameter of the "tran"
|
* CKTinitTime is from the tstart parameter of the "tran"
|
||||||
* command or card.
|
* command or card.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (node_table[index]->save && ckt->CKTtime >= ckt->CKTinitTime &&
|
if (node_info->save && ckt->CKTtime >= ckt->CKTinitTime &&
|
||||||
(ckt->CKTtime > 0 || !(ckt->CKTmode & MODEUIC))) {
|
(ckt->CKTtime > 0 || !(ckt->CKTmode & MODEUIC))) {
|
||||||
/* Update last_step for this index */
|
/* Update last_step for this index */
|
||||||
node_data->last_step[index] = node_data->tail[index];
|
node_data->last_step[index] = node_data->tail[index];
|
||||||
|
|
@ -239,3 +284,77 @@ void EVTaccept(
|
||||||
} /* EVTaccept */
|
} /* EVTaccept */
|
||||||
|
|
||||||
|
|
||||||
|
/* Functions to set-up and cancel value-changed callbacks. */
|
||||||
|
|
||||||
|
Mif_Boolean_t EVTnew_value_call(const char *node,
|
||||||
|
Evt_New_Value_Cb_t fn,
|
||||||
|
Evt_Node_Cb_Type_t type,
|
||||||
|
void *ctx)
|
||||||
|
{
|
||||||
|
struct node_parse result;
|
||||||
|
int index;
|
||||||
|
|
||||||
|
Evt_Ckt_Data_t *evt;
|
||||||
|
CKTcircuit *ckt;
|
||||||
|
Evt_Node_Info_t *node_info;
|
||||||
|
Evt_Node_Cb_t *cb;
|
||||||
|
|
||||||
|
index = Evt_Parse_Node(node, &result);
|
||||||
|
if (index < 0)
|
||||||
|
return MIF_FALSE;
|
||||||
|
ckt = g_mif_info.ckt;
|
||||||
|
evt = ckt->evt;
|
||||||
|
node_info = evt->info.node_table[index];
|
||||||
|
cb = tmalloc(sizeof *cb);
|
||||||
|
cb->next = node_info->cbs;
|
||||||
|
node_info->cbs = cb;
|
||||||
|
cb->fn = fn;
|
||||||
|
cb->type = type;
|
||||||
|
cb->member = copy(result.member);
|
||||||
|
cb->ctx = ctx;
|
||||||
|
txfree(result.node);
|
||||||
|
return MIF_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EVTcancel_value_call(const char *node,
|
||||||
|
Evt_New_Value_Cb_t fn,
|
||||||
|
void *ctx)
|
||||||
|
{
|
||||||
|
Evt_Ckt_Data_t *evt;
|
||||||
|
CKTcircuit *ckt;
|
||||||
|
Evt_Node_Info_t **node_table, *node_info;
|
||||||
|
Evt_Node_Cb_t **cbpp, *cb;
|
||||||
|
int i, num_nodes;
|
||||||
|
|
||||||
|
ckt = g_mif_info.ckt;
|
||||||
|
if (!ckt)
|
||||||
|
return;
|
||||||
|
evt = ckt->evt;
|
||||||
|
if (!evt)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Look for node name in the event-driven node list */
|
||||||
|
|
||||||
|
node_table = evt->info.node_table;
|
||||||
|
num_nodes = evt->counts.num_nodes;
|
||||||
|
|
||||||
|
for (i = 0; i < num_nodes; i++) {
|
||||||
|
if (cieq(node, node_table[i]->name))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i >= num_nodes)
|
||||||
|
return;
|
||||||
|
|
||||||
|
node_info = node_table[i];
|
||||||
|
cbpp = &node_info->cbs;
|
||||||
|
cb = node_info->cbs;
|
||||||
|
while (cb) {
|
||||||
|
if (cb->fn == fn && cb->ctx == ctx) {
|
||||||
|
*cbpp = cb->next;
|
||||||
|
tfree(cb);
|
||||||
|
} else {
|
||||||
|
cbpp = &cb->next;
|
||||||
|
}
|
||||||
|
cb = *cbpp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -168,9 +168,11 @@ Evt_Node_Data_destroy(Evt_Ckt_Data_t *evt, Evt_Node_Data_t *node_data)
|
||||||
for (i = 0; i < evt->counts.num_nodes; i++) {
|
for (i = 0; i < evt->counts.num_nodes; i++) {
|
||||||
Evt_Node_Info_t *info = evt->info.node_table[i];
|
Evt_Node_Info_t *info = evt->info.node_table[i];
|
||||||
Evt_Node_t *node;
|
Evt_Node_t *node;
|
||||||
|
|
||||||
node = node_data->head[i];
|
node = node_data->head[i];
|
||||||
while (node) {
|
while (node) {
|
||||||
Evt_Node_t *next = node->next;
|
Evt_Node_t *next = node->next;
|
||||||
|
|
||||||
Evt_Node_destroy(info, node);
|
Evt_Node_destroy(info, node);
|
||||||
tfree(node);
|
tfree(node);
|
||||||
node = next;
|
node = next;
|
||||||
|
|
@ -178,6 +180,7 @@ Evt_Node_Data_destroy(Evt_Ckt_Data_t *evt, Evt_Node_Data_t *node_data)
|
||||||
node = node_data->free[i];
|
node = node_data->free[i];
|
||||||
while (node) {
|
while (node) {
|
||||||
Evt_Node_t *next = node->next;
|
Evt_Node_t *next = node->next;
|
||||||
|
|
||||||
Evt_Node_destroy(info, node);
|
Evt_Node_destroy(info, node);
|
||||||
tfree(node);
|
tfree(node);
|
||||||
node = next;
|
node = next;
|
||||||
|
|
@ -193,6 +196,7 @@ Evt_Node_Data_destroy(Evt_Ckt_Data_t *evt, Evt_Node_Data_t *node_data)
|
||||||
|
|
||||||
for (i = 0; i < evt->counts.num_nodes; i++) {
|
for (i = 0; i < evt->counts.num_nodes; i++) {
|
||||||
Evt_Node_Info_t *info = evt->info.node_table[i];
|
Evt_Node_Info_t *info = evt->info.node_table[i];
|
||||||
|
|
||||||
Evt_Node_destroy(info, &(node_data->rhs[i]));
|
Evt_Node_destroy(info, &(node_data->rhs[i]));
|
||||||
Evt_Node_destroy(info, &(node_data->rhsold[i]));
|
Evt_Node_destroy(info, &(node_data->rhsold[i]));
|
||||||
}
|
}
|
||||||
|
|
@ -287,6 +291,7 @@ static void
|
||||||
Evt_Info_destroy(Evt_Info_t *info)
|
Evt_Info_destroy(Evt_Info_t *info)
|
||||||
{
|
{
|
||||||
Evt_Inst_Info_t *inst = info->inst_list;
|
Evt_Inst_Info_t *inst = info->inst_list;
|
||||||
|
|
||||||
while (inst) {
|
while (inst) {
|
||||||
Evt_Inst_Info_t *next_inst = inst->next;
|
Evt_Inst_Info_t *next_inst = inst->next;
|
||||||
tfree(inst);
|
tfree(inst);
|
||||||
|
|
@ -295,14 +300,24 @@ Evt_Info_destroy(Evt_Info_t *info)
|
||||||
tfree(info->inst_table);
|
tfree(info->inst_table);
|
||||||
|
|
||||||
Evt_Node_Info_t *nodei = info->node_list;
|
Evt_Node_Info_t *nodei = info->node_list;
|
||||||
|
|
||||||
while (nodei) {
|
while (nodei) {
|
||||||
Evt_Node_Info_t *next_nodei = nodei->next;
|
Evt_Node_Info_t *next_nodei = nodei->next;
|
||||||
|
Evt_Node_Cb_t *cb, *cb_next;
|
||||||
|
|
||||||
tfree(nodei->name);
|
tfree(nodei->name);
|
||||||
|
for (cb = nodei->cbs; cb; cb = cb_next) {
|
||||||
|
cb_next = cb->next;
|
||||||
|
if (cb->member)
|
||||||
|
txfree(cb->member);
|
||||||
|
tfree(cb);
|
||||||
|
}
|
||||||
|
|
||||||
Evt_Inst_Index_t *p = nodei->inst_list;
|
Evt_Inst_Index_t *p = nodei->inst_list;
|
||||||
|
|
||||||
while (p) {
|
while (p) {
|
||||||
Evt_Inst_Index_t *next_p = p->next;
|
Evt_Inst_Index_t *next_p = p->next;
|
||||||
tfree(p);
|
txfree(p);
|
||||||
p = next_p;
|
p = next_p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -45,15 +45,78 @@ NON-STANDARD FEATURES
|
||||||
#include "ngspice/mif.h"
|
#include "ngspice/mif.h"
|
||||||
#include "ngspice/mifproto.h"
|
#include "ngspice/mifproto.h"
|
||||||
|
|
||||||
/*saj for output */
|
|
||||||
#include "ngspice/sim.h"
|
#include "ngspice/sim.h"
|
||||||
#include "ngspice/dvec.h"
|
#include "ngspice/dvec.h"
|
||||||
//#include "ftedata.h"
|
|
||||||
//#include "fteconstant.h"
|
|
||||||
//#include "util.h"
|
|
||||||
#include "ngspice/cpstd.h"
|
#include "ngspice/cpstd.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* Parse member qualifier from node name and find node index.
|
||||||
|
* The node name may be qualified by a member name for nodes with
|
||||||
|
* composite values such as Digital_t, as in "node_name(state)".
|
||||||
|
*/
|
||||||
|
|
||||||
|
int Evt_Parse_Node(const char *node, struct node_parse *result)
|
||||||
|
{
|
||||||
|
Evt_Ckt_Data_t *evt;
|
||||||
|
CKTcircuit *ckt;
|
||||||
|
Evt_Node_Info_t **node_table;
|
||||||
|
char *name, *ptr;
|
||||||
|
int i, num_nodes;
|
||||||
|
|
||||||
|
ckt = g_mif_info.ckt;
|
||||||
|
if (!ckt)
|
||||||
|
return -1;
|
||||||
|
evt = ckt->evt;
|
||||||
|
if (!evt)
|
||||||
|
return -1;
|
||||||
|
if (!evt->info.node_table)
|
||||||
|
return -1;
|
||||||
|
if (evt->counts.num_nodes == 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* Make a copy of the node name. Do not free this string. */
|
||||||
|
|
||||||
|
name = MIFcopy((char *)node);
|
||||||
|
|
||||||
|
/* Convert to all lower case */
|
||||||
|
|
||||||
|
strtolower(name);
|
||||||
|
|
||||||
|
/* Divide into the node name and member name */
|
||||||
|
|
||||||
|
result->node = name;
|
||||||
|
for (ptr = name; *ptr != '\0'; ptr++)
|
||||||
|
if (*ptr == '(')
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (*ptr == '(') {
|
||||||
|
*ptr = '\0';
|
||||||
|
ptr++;
|
||||||
|
result->member = ptr;
|
||||||
|
for( ; *ptr != '\0'; ptr++)
|
||||||
|
if (*ptr == ')')
|
||||||
|
break;
|
||||||
|
*ptr = '\0';
|
||||||
|
} else {
|
||||||
|
result->member = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Look for node name in the event-driven node list */
|
||||||
|
|
||||||
|
node_table = evt->info.node_table;
|
||||||
|
num_nodes = evt->counts.num_nodes;
|
||||||
|
|
||||||
|
for (i = 0; i < num_nodes; i++) {
|
||||||
|
if (cieq(name, node_table[i]->name))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i >= num_nodes) {
|
||||||
|
tfree(name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
EVTfindvec()
|
EVTfindvec()
|
||||||
|
|
@ -80,18 +143,14 @@ struct dvec *EVTfindvec(
|
||||||
char *node) /* The node name (and optional member name) */
|
char *node) /* The node name (and optional member name) */
|
||||||
{
|
{
|
||||||
char *name;
|
char *name;
|
||||||
char *member = "all";
|
struct node_parse result;
|
||||||
char *ptr;
|
int index, i;
|
||||||
|
|
||||||
int i;
|
|
||||||
int num_nodes;
|
|
||||||
int udn_index;
|
int udn_index;
|
||||||
int num_events;
|
int num_events;
|
||||||
|
|
||||||
Mif_Boolean_t found;
|
|
||||||
Evt_Ckt_Data_t *evt;
|
Evt_Ckt_Data_t *evt;
|
||||||
CKTcircuit *ckt;
|
CKTcircuit *ckt;
|
||||||
Evt_Node_Info_t **node_table;
|
Evt_Node_Info_t *node_info;
|
||||||
Evt_Node_t *head;
|
Evt_Node_t *head;
|
||||||
Evt_Node_t *event;
|
Evt_Node_t *event;
|
||||||
|
|
||||||
|
|
@ -105,67 +164,26 @@ struct dvec *EVTfindvec(
|
||||||
/* Exit immediately if event-driven stuff not allocated yet, */
|
/* Exit immediately if event-driven stuff not allocated yet, */
|
||||||
/* or if number of event nodes is zero. */
|
/* or if number of event nodes is zero. */
|
||||||
|
|
||||||
|
index = Evt_Parse_Node(node, &result);
|
||||||
|
if (index < 0)
|
||||||
|
return NULL;
|
||||||
|
name = result.node;
|
||||||
ckt = g_mif_info.ckt;
|
ckt = g_mif_info.ckt;
|
||||||
if(! ckt)
|
|
||||||
return(NULL);
|
|
||||||
evt = ckt->evt;
|
evt = ckt->evt;
|
||||||
if(! evt)
|
|
||||||
return(NULL);
|
|
||||||
if(! evt->info.node_table)
|
|
||||||
return(NULL);
|
|
||||||
if(evt->counts.num_nodes == 0)
|
|
||||||
return(NULL);
|
|
||||||
|
|
||||||
/* Make a copy of the node name. */
|
if (!evt->data.node) {
|
||||||
/* Do not free this string. It is assigned into the dvec structure below. */
|
|
||||||
name = MIFcopy(node);
|
|
||||||
|
|
||||||
/* Convert to all lower case */
|
|
||||||
strtolower(name);
|
|
||||||
|
|
||||||
/* Divide into the node name and member name */
|
|
||||||
for(ptr = name; *ptr != '\0'; ptr++)
|
|
||||||
if(*ptr == '(')
|
|
||||||
break;
|
|
||||||
|
|
||||||
if(*ptr == '(') {
|
|
||||||
*ptr = '\0';
|
|
||||||
ptr++;
|
|
||||||
member = ptr;
|
|
||||||
for( ; *ptr != '\0'; ptr++)
|
|
||||||
if(*ptr == ')')
|
|
||||||
break;
|
|
||||||
*ptr = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Look for node name in the event-driven node list */
|
|
||||||
num_nodes = evt->counts.num_nodes;
|
|
||||||
node_table = evt->info.node_table;
|
|
||||||
|
|
||||||
for(i = 0, found = MIF_FALSE; i < num_nodes; i++) {
|
|
||||||
if(cieq(name, node_table[i]->name)) {
|
|
||||||
found = MIF_TRUE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(! found) {
|
|
||||||
tfree(name);
|
tfree(name);
|
||||||
return(NULL);
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the UDN type index */
|
/* Get the UDN type index */
|
||||||
udn_index = node_table[i]->udn_index;
|
|
||||||
|
|
||||||
if (!evt->data.node) {
|
node_info = evt->info.node_table[index];
|
||||||
// fprintf(stderr, "Warning: No event data available! \n Simulation not yet run?\n");
|
udn_index = node_info->udn_index;
|
||||||
tfree(name);
|
|
||||||
return(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Count the number of events */
|
/* Count the number of events */
|
||||||
head = evt->data.node->head[i];
|
|
||||||
|
|
||||||
|
head = evt->data.node->head[index];
|
||||||
for(event = head, num_events = 0; event; event = event->next)
|
for(event = head, num_events = 0; event; event = event->next)
|
||||||
num_events++;
|
num_events++;
|
||||||
|
|
||||||
|
|
@ -188,7 +206,7 @@ struct dvec *EVTfindvec(
|
||||||
/* Get the next value by calling the appropriate UDN plot_val function */
|
/* Get the next value by calling the appropriate UDN plot_val function */
|
||||||
value = 0.0;
|
value = 0.0;
|
||||||
g_evt_udn_info[udn_index]->plot_val(event->node_value,
|
g_evt_udn_info[udn_index]->plot_val(event->node_value,
|
||||||
member,
|
result.member ? result.member : "all",
|
||||||
&value);
|
&value);
|
||||||
|
|
||||||
/* Put the first value of the horizontal line in the vector */
|
/* Put the first value of the horizontal line in the vector */
|
||||||
|
|
@ -206,8 +224,7 @@ struct dvec *EVTfindvec(
|
||||||
/* Allocate dvec structures and assign the vectors into them. */
|
/* Allocate dvec structures and assign the vectors into them. */
|
||||||
/* See FTE/OUTinterface.c:plotInit() for initialization example. */
|
/* See FTE/OUTinterface.c:plotInit() for initialization example. */
|
||||||
|
|
||||||
ptr = tprintf("%s_steps", name);
|
scale = dvec_alloc(tprintf("%s_steps", name),
|
||||||
scale = dvec_alloc(ptr,
|
|
||||||
SV_TIME,
|
SV_TIME,
|
||||||
(VF_REAL | VF_EVENT_NODE) & ~VF_PERMANENT,
|
(VF_REAL | VF_EVENT_NODE) & ~VF_PERMANENT,
|
||||||
i, anal_point_vec);
|
i, anal_point_vec);
|
||||||
|
|
|
||||||
|
|
@ -330,6 +330,7 @@ static void EVTnode_insert(
|
||||||
node->name = MIFcopy(node_name);
|
node->name = MIFcopy(node_name);
|
||||||
node->udn_index = udn_index;
|
node->udn_index = udn_index;
|
||||||
node->save = MIF_TRUE; /* Backward compatible behaviour: save all. */
|
node->save = MIF_TRUE; /* Backward compatible behaviour: save all. */
|
||||||
|
node->cbs = NULL;
|
||||||
index = ckt->evt->counts.num_nodes;
|
index = ckt->evt->counts.num_nodes;
|
||||||
(ckt->evt->counts.num_nodes)++;
|
(ckt->evt->counts.num_nodes)++;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue