From da0c63c3b08ebd4eaf84836d131828128090ac02 Mon Sep 17 00:00:00 2001 From: Jim Holmes Date: Sun, 26 Oct 2014 18:56:04 +0200 Subject: [PATCH] new files --- src/spicelib/analysis/cktlxt2.c | 68 ++++++++++++++++ src/spicelib/analysis/lxt2_init.c | 126 ++++++++++++++++++++++++++++++ src/xspice/evt/evtlxt2.c | 97 +++++++++++++++++++++++ 3 files changed, 291 insertions(+) create mode 100644 src/spicelib/analysis/cktlxt2.c create mode 100644 src/spicelib/analysis/lxt2_init.c create mode 100644 src/xspice/evt/evtlxt2.c diff --git a/src/spicelib/analysis/cktlxt2.c b/src/spicelib/analysis/cktlxt2.c new file mode 100644 index 000000000..b2133eab7 --- /dev/null +++ b/src/spicelib/analysis/cktlxt2.c @@ -0,0 +1,68 @@ +#include "ngspice/ngspice.h" +#include "ngspice/fteext.h" + +#include "../frontend/outitf.h" + +#include + +#ifdef XSPICE +#include "ngspice/evtproto.h" +#endif + +#include "ngspice/lxt2_write.h" + +#define CKALLOC(var, size, type) \ + if(size) { \ + if(!(var = (type *) MALLOC((size) * sizeof(type)))) \ + return(E_NOMEM); \ + } + + +void +CKTemitlxt2(runDesc *run) +{ + struct lxt2_wr_symbol **trace_table; + struct lxt2_wr_symbol *trace; + char *name; + double value; + static unsigned int last_set_time, set_time; + static double time_resolution = 1.0e-9; + int i, trace_num; + int *trace_index; + CKTcircuit *ckt; + IFvalue valData; + + ckt = run->circuit; + + trace_table = ckt->lxt2.kvl_table; + trace_num = ckt->lxt2.kvl_num; + trace_index = ckt->lxt2.kvl_indexmap; + + valData.v.numValue = ckt->CKTmaxEqNum - 1; + valData.v.vec.rVec = ckt->CKTrhsOld + 1; + + if (ckt->CKTtime <= 0.0) { + time_resolution = pow(10.0, LXT2_TIME_RESOLUTION_EXPONENT); + last_set_time = 0; + lxt2_wr_set_time(ckt->lxt2.file, last_set_time); + } + + set_time = (unsigned int) (ckt->CKTtime / time_resolution); + + if (set_time > last_set_time) { + lxt2_wr_set_time(ckt->lxt2.file, set_time); + last_set_time = set_time; + } + + for (i = 0; i < trace_num; i++) + if (trace_index[i] > 0) { + trace = trace_table[i]; + if (trace) { + value = valData.v.vec.rVec[run->data[trace_index[i]].outIndex]; + name = run->data[trace_index[i]].name; + lxt2_wr_emit_value_double(ckt->lxt2.file, trace, 0, value); + } + } + + lxt2_wr_flush(ckt->lxt2.file); +} diff --git a/src/spicelib/analysis/lxt2_init.c b/src/spicelib/analysis/lxt2_init.c new file mode 100644 index 000000000..a6bc1ab94 --- /dev/null +++ b/src/spicelib/analysis/lxt2_init.c @@ -0,0 +1,126 @@ +#include "ngspice/ngspice.h" +#include "ngspice/sperror.h" +#include "ngspice/fteext.h" + +#include "../frontend/outitf.h" + +#ifdef XSPICE +#include "ngspice/evtproto.h" +#endif + +#include "ngspice/lxt2_write.h" + + +#define CKALLOC(var, size, type) \ + if(size) { \ + if(!(var = (type *) MALLOC((size) * sizeof(type)))) \ + return(E_NOMEM); \ + } + + +static void EVTtraceinit(CKTcircuit *ckt); +static void KVLtraceinit(runDesc *run); + + +void +lxt2_init(runDesc *run) +{ + if (run && run->circuit) { + run->circuit->lxt2.file = lxt2_wr_init("waveforms.lxt"); + lxt2_wr_set_timescale(run->circuit->lxt2.file, LXT2_TIME_RESOLUTION_EXPONENT); + EVTtraceinit(run->circuit); + KVLtraceinit(run); + } +} + + +void +lxt2_end(runDesc *run) +{ + if (run && run->circuit) { + lxt2_wr_flush(run->circuit->lxt2.file); + lxt2_wr_close(run->circuit->lxt2.file); + free(run->circuit->lxt2.evt_table); + free(run->circuit->lxt2.evt_indexmap); + free(run->circuit->lxt2.kvl_table); + free(run->circuit->lxt2.kvl_indexmap); + } +} + + +static void +EVTtraceinit(CKTcircuit *ckt) /* the circuit structure */ +{ + + struct lxt2_wr_symbol **trace_table = NULL; /* vector of pointer to traces in lxt2 output file */ + Evt_Node_Info_t **node_table; + int i; + int num_nodes; + + int *evt_indexmap = NULL; + + node_table = ckt->evt->info.node_table; + num_nodes = ckt->evt->counts.num_nodes; + + + /* Allocate and initialize table of lxt2 evt trace pointers */ + CKALLOC(trace_table, num_nodes, struct lxt2_wr_symbol *); + CKALLOC(evt_indexmap, num_nodes, int); + + for (i = 0; i < num_nodes; i++) { + + evt_indexmap[i] = i; + + switch (node_table[i]->udn_index) + { + case 0: /* Bit */ + trace_table[i] = lxt2_wr_symbol_add(ckt->lxt2.file, node_table[i]->name, 0, 0, 0, LXT2_WR_SYM_F_BITS); + break; + case 1: /* Integer */ + trace_table[i] = lxt2_wr_symbol_add(ckt->lxt2.file, node_table[i]->name, 0, 0, 0, LXT2_WR_SYM_F_INTEGER); + break; + case 2: /* Double */ + trace_table[i] = lxt2_wr_symbol_add(ckt->lxt2.file, node_table[i]->name, 0, 0, 0, LXT2_WR_SYM_F_DOUBLE); + break; + default: /* Bit */ + trace_table[i] = lxt2_wr_symbol_add(ckt->lxt2.file, node_table[i]->name, 0, 0, 0, LXT2_WR_SYM_F_BITS); + break; + } + } + + ckt->lxt2.evt_indexmap = evt_indexmap; + ckt->lxt2.evt_table = trace_table; + ckt->lxt2.evt_num = num_nodes; +} + + +static void +KVLtraceinit(runDesc *run) /* Call this after OUTpBeginPlot after all electrical run data is loaded */ +{ + struct lxt2_wr_symbol **trace_table = NULL; + int *kvl_indexmap = NULL; + int i; + + if (run->circuit) { + + CKALLOC(trace_table, run->numData, struct lxt2_wr_symbol *); + CKALLOC(kvl_indexmap, run->numData, int); + + for (i = 0; i < run->numData; i++) { + kvl_indexmap[i] = -1; + trace_table[i] = NULL; + if (run->data[i].outIndex != -1) { /* Skip over the time vector. Once we parse the saves list this check won't be necessary. */ + if (run->data[i].regular) { /* Check that the data is not "special" like a parameter, might allow this later */ + if (run->data[i].type == IF_REAL) { /* As opposed to being complex */ + kvl_indexmap[i] = i; + trace_table[i] = lxt2_wr_symbol_add(run->circuit->lxt2.file, run->data[i].name, 0, 0, 0, LXT2_WR_SYM_F_DOUBLE); + } + } + } + } + + run->circuit->lxt2.kvl_indexmap = kvl_indexmap; + run->circuit->lxt2.kvl_table = trace_table; + run->circuit->lxt2.kvl_num = run->numData; + } +} diff --git a/src/xspice/evt/evtlxt2.c b/src/xspice/evt/evtlxt2.c new file mode 100644 index 000000000..c122594cc --- /dev/null +++ b/src/xspice/evt/evtlxt2.c @@ -0,0 +1,97 @@ +#include "ngspice/ngspice.h" +#include "ngspice/evtproto.h" + +#include + +static char *EVTbitmap(int i); + + +/* + * This function emits an evt value into an lxt2 change-on-event file stream. + */ + +void +EVTemitlxt2( + CKTcircuit *ckt, /* The circuit structure */ + int node_index, /* The node to copy */ + Evt_Node_t *from) /* Location to copy from */ +{ + static unsigned int last_set_time; + static double time_resolution = -1.0; + unsigned int set_time; + int type; + char *name; + + Evt_Node_Info_t **node_table; + struct lxt2_wr_symbol **trace_table; + struct lxt2_wr_symbol *trace; + + node_table = ckt->evt->info.node_table; + trace_table = ckt->lxt2.evt_table; + + type = node_table[node_index]->udn_index; + name = node_table[node_index]->name; + + if (time_resolution < 0.0) { + time_resolution = pow(10.0, LXT2_TIME_RESOLUTION_EXPONENT); + last_set_time = 0; + } + + set_time = (unsigned int) (ckt->CKTtime / time_resolution); + + if (set_time > last_set_time) { + lxt2_wr_set_time(ckt->lxt2.file, set_time); + last_set_time = set_time; + } + + trace = trace_table[node_index]; + + switch (type) + { + case 0: /* Bit */ + lxt2_wr_emit_value_bit_string(ckt->lxt2.file, trace, 0, EVTbitmap(*((int *)(from->node_value)))); + break; + case 1: /* Integer */ + lxt2_wr_emit_value_int(ckt->lxt2.file, trace, 0, *((int *)(from->node_value))); + break; + case 2: /* Double */ + lxt2_wr_emit_value_double(ckt->lxt2.file, trace, 0, *((double *)(from->node_value))); + break; + default: /* Bit */ + lxt2_wr_emit_value_bit_string(ckt->lxt2.file, trace, 0, EVTbitmap(*((int *)(from->node_value)))); + break; + } + + lxt2_wr_flush(ckt->lxt2.file); +} + + +static char * +EVTbitmap(int i) +{ + static char s[2]; + char *p = s; + + switch (i) + { + case 0: + *(p++) = '0'; + break; + case 1: + *(p++) = '1'; + break; + case 2: + *(p++) = 'u'; + break; + case 3: + *(p++) = 'z'; + break; + default: + *(p++) = 'u'; + break; + } + + *(p) = '\0'; + + return s; +}