diff --git a/src/frontend/com_dl.c b/src/frontend/com_dl.c new file mode 100755 index 000000000..b219393d5 --- /dev/null +++ b/src/frontend/com_dl.c @@ -0,0 +1,24 @@ +#include /* for wl */ +#include "ftedefs.h" +#include /* solve deps in dev.h*/ +#include <../spicelib/devices/dev.h> /*for load library commands*/ + +#ifdef XSPICE +void com_codemodel(wordlist *wl){ + wordlist *ww; + for(ww = wl;ww;ww = ww->wl_next) + if(load_opus(wl->wl_word)) + fprintf(cp_err,"Error: Library %s couldn't be loaded!\n",ww->wl_word); + return; +} +#endif +#ifdef DEVLIB +void com_use(wordlist *wl){ + wordlist *ww; + for(ww = wl;ww;ww = ww->wl_next) + if(load_dev(wl->wl_word)) + fprintf(cp_err,"Error: Library %s couldn't be loaded!\n",ww->wl_word); + return; +} +#endif + diff --git a/src/frontend/com_dl.h b/src/frontend/com_dl.h new file mode 100755 index 000000000..e8210cefd --- /dev/null +++ b/src/frontend/com_dl.h @@ -0,0 +1,12 @@ +#ifndef _COM_DL_H +#define _COM_DL_H 1 + +#ifdef XSPICE +void com_codemodel(wordlist *wl); +#endif + +#ifdef DEVLIB +void com_use(wordlist *wl); +#endif + +#endif diff --git a/src/frontend/hpgl.c b/src/frontend/hpgl.c new file mode 100644 index 000000000..e248b2073 --- /dev/null +++ b/src/frontend/hpgl.c @@ -0,0 +1,315 @@ +/********** +Author: Jim Groves +**********/ + +/* + HPGL driver +*/ + +/* + 1000 plotter units / inch - 1pu = 0.025mm 1pu = 1mil + + SP - select pen + PU - pen up (PU x,y) + PD - pen down (PD x,y) + LT - line type + 0 dots only at plotted points + 1 . . . . . + 2 ___ ___ ___ ___ + 3 ---- ---- ---- ---- + 4 ----- . ----- . ----- . -----. + 5 ---- - ---- - ---- - + 6 --- - - --- - - --- - - --- - - + null - solid line + IN - initialize + DF - default values (PA, solid line, set 0) + PA - plot absolute + SI - absolute character size (SI width, height) in cm + +*/ + + + +#include "spice.h" +#include "cpdefs.h" +#include "graph.h" +#include "ftedbgra.h" +#include "ftedev.h" +#include "fteinput.h" + +#include "variable.h" + +#define RAD_TO_DEG (180.0 / M_PI) +#define DEVDEP(g) (*((GLdevdep *) (g)->devdep)) +#define MAX_GL_LINES 9999 +#define SOLID 0 +#define DOTTED 1 + +#define gtype graph->grid.gridtype +#define xoff dispdev->minx +#define yoff dispdev->miny +#define XOFF 25 /* printer left margin */ +#define YOFF 28 /* printer bottom margin */ +#define XTADJ 0 /* printer text adjustment x */ +#define YTADJ 0 /* printer text adjustment y */ + +#define DELXMAX 360 /* printer gridsize divisible by 10, [7-2] */ +#define DELYMAX 360 /* printer gridsize divisible by [10-8], [6-2] */ + +#define FONTWIDTH 6 /* printer default fontwidth */ +#define FONTHEIGHT 8 /* printer default fontheight */ + +typedef struct { + int lastlinestyle; /* initial invalid value */ + int lastx, lasty, linecount; +} GLdevdep; + +static char *linestyle[] = { + "", /* solid */ + "1", /* was 1 - dotted */ + "", /* longdashed */ + "3", /* shortdashed */ + "4", /* longdotdashed */ + "5", /* shortdotdashed */ + "1" + }; + +static FILE *plotfile; +char psfont[128], psfontsize[32], psscale[32]; +static int fontwidth = FONTWIDTH; +static int fontheight = FONTHEIGHT; +static int jgmult = 10; +static int screenflag = 0; +static double tocm = 0.0025; +static double scale; /* Used for fine tuning */ +static int hcopygraphid; + +extern int DestroyGraph (int id); +extern void internalerror (char *message); + +int GL_Init() +{ + if (!cp_getvar("hcopyscale", VT_STRING, psscale)) { + scale = 1.0; + } else { + sscanf(psscale, "%lf", &scale); + if ((scale <= 0) || (scale > 10)) + scale = 1.0; + } + + dispdev->numlinestyles = NUMELEMS(linestyle); + dispdev->numcolors = 6; + + dispdev->width = DELXMAX * scale; + dispdev->height = DELYMAX * scale; + + + screenflag = 0; + dispdev->minx = XOFF * 1.0; + dispdev->miny = YOFF * 1.0; + + return(0); + +} + +/* devdep initially contains name of output file */ +int GL_NewViewport(graph) +GRAPH *graph; +{ +/* double scaleps, scalex, scaley; */ + + hcopygraphid = graph->graphid; + + if (!(plotfile = fopen(graph->devdep, "w"))) { + perror(graph->devdep); + graph->devdep = (char *) NULL; + return(1); + } + + if (graph->absolute.width) { + /* hardcopying from the screen */ + + screenflag = 1; + + /* scale to fit on 8 1/2 square */ + + } + + /* reasonable values, used in gr_ for placement */ + graph->fontwidth = fontwidth * scale; /* was 12, p.w.h. */ + graph->fontheight = fontheight * scale; /* was 24, p.w.h. */ + + graph->absolute.width = dispdev->width; + graph->absolute.height = dispdev->height; + /* Also done in gr_init, if called . . . */ + graph->viewportxoff = 16 * fontwidth; + graph->viewportyoff = 8 * fontheight; + + xoff = XOFF; + yoff = YOFF; + + /* start file off with a % */ + fprintf(plotfile, "IN;DF;PA;"); + fprintf(plotfile, "SI %f,%f;", tocm*jgmult*fontwidth*scale,tocm*jgmult*fontheight*scale); + +#ifdef notdef + if (!screenflag) +#endif + + graph->devdep = tmalloc(sizeof(GLdevdep)); + DEVDEP(graph).lastlinestyle = -1; + DEVDEP(graph).lastx = -1; + DEVDEP(graph).lasty = -1; + DEVDEP(graph).linecount = 0; + graph->linestyle = -1; + + return 0; +} + +int GL_Close() +{ + + /* in case GL_Close is called as part of an abort, + w/o having reached GL_NewViewport */ + if (plotfile) { + if (DEVDEP(currentgraph).lastlinestyle != -1) { + DEVDEP(currentgraph).linecount = 0; + } + fclose(plotfile); + plotfile = NULL; + } + /* In case of hardcopy command destroy the hardcopy graph + * and reset currentgraph to graphid 1, if possible + */ + if (!screenflag) { + DestroyGraph(hcopygraphid); + currentgraph = FindGraph(1); + } + + return 0; +} + +int GL_Clear() +{ + + /* do nothing */ + + + return 0; +} + +int GL_DrawLine(x1, y1, x2, y2) +int x1, y1, x2, y2; +{ + + /* note: this is not extendible to more than one graph + => will have to give NewViewport a writeable graph XXX */ + + + if (DEVDEP(currentgraph).linecount == 0 + || x1 != DEVDEP(currentgraph).lastx + || y1 != DEVDEP(currentgraph).lasty) + { + fprintf(plotfile, "PU;PA %d , %d ;", jgmult*(x1 + xoff), jgmult*(y1 + yoff)); + } + if (x1 != x2 || y1 != y2) { + fprintf(plotfile, "PD;PA %d , %d ;", jgmult*(x2 + xoff), jgmult*(y2 + yoff)); + DEVDEP(currentgraph).linecount += 1; + } + + DEVDEP(currentgraph).lastx = x2; + DEVDEP(currentgraph).lasty = y2; + DEVDEP(currentgraph).lastlinestyle = currentgraph->linestyle; + + return 0; +} + +/* ARGSUSED */ +int GL_Arc(x0, y0, r, theta1, theta2) +int x0, y0, r; +double theta1, theta2; +{ + double x1, y1; + double angle1, angle2; + + while (theta1 >= theta2) + theta2 += 2 * M_PI; + + angle1 = (double) (RAD_TO_DEG * theta1); + angle2 = (double) (RAD_TO_DEG * theta2); + x1 = (double) x0 + r * cos(theta1); + y1 = (double) y0 + r * sin(theta1); +/* + fprintf(plotfile, "%lf %lf moveto ", x1+(double)xoff, y1+(double)yoff); + fprintf(plotfile, "%d %d %d %lf %lf arc\n", x0+xoff, y0+yoff, r, + angle1, angle2); + fprintf(plotfile, "stroke\n"); + */ + DEVDEP(currentgraph).linecount = 0; + + return 0; +} + +int GL_Text(text, x, y) +char *text; +int x, y; +{ + +/* int savedlstyle; */ + + + /* move to (x, y) */ + + fprintf(plotfile, "PU;PA %d , %d;", jgmult*(x+xoff+XTADJ), jgmult*(y+yoff+YTADJ)); + fprintf(plotfile, "LB %s \x03", text); + + DEVDEP(currentgraph).lastx = -1; + DEVDEP(currentgraph).lasty = -1; + + + return 0; +} + +int +GL_SetLinestyle(linestyleid) +int linestyleid; +{ + + /* special case + get it when GL_Text restores a -1 linestyle */ + if (linestyleid == -1) { + currentgraph->linestyle = -1; + return 0; + } + + if (linestyleid < 0 || linestyleid > dispdev->numlinestyles) { + internalerror("bad linestyleid"); + return 0; + } + + if (currentgraph->linestyle != linestyleid) { + fprintf(plotfile, "LT %s ;", linestyle[linestyleid]); + currentgraph->linestyle = linestyleid; + } + return 0; + +} + +/* ARGSUSED */ +int GL_SetColor(colorid) +int colorid; +{ +/*va: unused: static int flag = 0;*/ /* A hack */ + + fprintf(plotfile, "SP %d;", colorid); + + return 0; +} + +int GL_Update() +{ + + fflush(plotfile); + + return 0; +} diff --git a/src/include/cluster.h b/src/include/cluster.h new file mode 100755 index 000000000..6e4dde2d6 --- /dev/null +++ b/src/include/cluster.h @@ -0,0 +1,24 @@ +#ifndef _CLUSTER_H_ +#define _CLUSTER_H_ +#include + +/* Cluster definitions */ +#define PORT 1234 +#define TIME_PORT 1235 +#define DOMAIN_NAME "cluster.multigig" +#define CLUSTER_WIDTH 4 +#define TIME_HOST "time.cluster.multigig" +/* does all the setups */ +extern int CLUsetup(CKTcircuit *ckt); + +/* reads input pipes and sets voltages*/ +/* call each time the present time is changed, ie just before NIinter*/ +extern int CLUinput(CKTcircuit *ckt); + +/* call after each accepted timestep, ie CKTdump */ +extern int CLUoutput(CKTcircuit *ckt); + + +/* the time step control */ +extern int CLUsync(double time,double *delta, int error); +#endif diff --git a/src/include/cm.h b/src/include/cm.h new file mode 100755 index 000000000..8590f50b9 --- /dev/null +++ b/src/include/cm.h @@ -0,0 +1,49 @@ +#ifndef CM_DEFINED +#define CM_DEFINED + +/* =========================================================================== +FILE CM.h + +MEMBER OF process XSPICE + +Copyright 1991 +Georgia Tech Research Corporation +Atlanta, Georgia 30332 +All Rights Reserved + +PROJECT A-8503 + +AUTHORS + + 9/12/91 Bill Kuhn + +MODIFICATIONS + + + +SUMMARY + + This file is includes all include data in the CM package. + +INTERFACES + + None. + +REFERENCED FILES + + None. + +NON-STANDARD FEATURES + + None. + +=========================================================================== */ + +#include "cmtypes.h" +#include "cmconstants.h" // K.A. wrong name +//#include "Cmconsta.h" +#include "cmproto.h" +#include "mifcmdat.h" + + +#endif /* CM_DEFINED */ diff --git a/src/include/cmconstants.h b/src/include/cmconstants.h new file mode 100755 index 000000000..13d9146be --- /dev/null +++ b/src/include/cmconstants.h @@ -0,0 +1,57 @@ +#ifndef CMCONSTANTS_DEFINED +#define CMCONSTANTS_DEFINED + +/* =========================================================================== +FILE CMconstants.h + +MEMBER OF process XSPICE + +Copyright 1991 +Georgia Tech Research Corporation +Atlanta, Georgia 30332 +All Rights Reserved + +PROJECT A-8503 + +AUTHORS + + 9/12/91 Bill Kuhn + +MODIFICATIONS + + + +SUMMARY + + This file contains constants used by code models. + +INTERFACES + + None. + +REFERENCED FILES + + None. + +NON-STANDARD FEATURES + + None. + +=========================================================================== */ + +#include "miftypes.h" + +/***** Define Constants *******************************************/ + +#define FALSE 0 +#define TRUE 1 + +#define DC MIF_DC +#define AC MIF_AC +#define TRANSIENT MIF_TRAN + +#define ANALOG MIF_ANALOG +#define EVENT MIF_EVENT_DRIVEN + + +#endif /* CMCONSTANTS_DEFINED */ diff --git a/src/include/cmproto.h b/src/include/cmproto.h new file mode 100755 index 000000000..9f8baf5ed --- /dev/null +++ b/src/include/cmproto.h @@ -0,0 +1,95 @@ +#ifndef CMPROTO_DEFINED +#define CMPROTO_DEFINED + +/* =========================================================================== +FILE CMproto.h + +MEMBER OF process XSPICE + +Copyright 1991 +Georgia Tech Research Corporation +Atlanta, Georgia 30332 +All Rights Reserved + +PROJECT A-8503 + +AUTHORS + + 9/12/91 Jeff Murray, Bill Kuhn + +MODIFICATIONS + + + +SUMMARY + + This file contains ANSI C function prototypes for cm_xxx functions + called by code models. + +INTERFACES + + None. + +REFERENCED FILES + + None. + +NON-STANDARD FEATURES + + None. + +=========================================================================== */ + +/* Prototypes for functions used by internal code models */ +/* The actual functions reside in ../ICM/CMutil.c */ +/* 12/17/90 */ + + +#include "cmtypes.h" + + +void cm_climit_fcn(double in, double in_offset, double cntl_upper, + double cntl_lower, double lower_delta, + double upper_delta, double limit_range, + double gain, int percent, double *out_final, + double *pout_pin_final, double *pout_pcntl_lower_final, + double *pout_pcntl_upper_final); + + + +void cm_smooth_corner(double x_input, double x_center, double y_center, + double domain, double lower_slope, double upper_slope, + double *y_output, double *dy_dx); +void cm_smooth_discontinuity(double x_input, double x_lower, double y_lower, + double x_upper, double y_upper, + double *y_output, double *dy_dx); +double cm_smooth_pwl(double x_input, double *x, double *y, int size, + double input_domain, double *dout_din); + +double cm_analog_ramp_factor(void); +void *cm_analog_alloc(int tag, int bytes); +void *cm_analog_get_ptr(int tag, int timepoint); +int cm_analog_integrate(double integrand, double *integral, double *partial); +int cm_analog_converge(double *state); +int cm_analog_set_temp_bkpt(double time); +int cm_analog_set_perm_bkpt(double time); +void cm_analog_not_converged(void); +void cm_analog_auto_partial(void); + +void *cm_event_alloc(int tag, int bytes); +void *cm_event_get_ptr(int tag, int timepoint); +int cm_event_queue(double time); + +char *cm_message_get_errmsg(void); +int cm_message_send(char *msg); + +double cm_netlist_get_c(void); +double cm_netlist_get_l(void); + +Complex_t cm_complex_set(double real, double imag); +Complex_t cm_complex_add(Complex_t x, Complex_t y); +Complex_t cm_complex_subtract(Complex_t x, Complex_t y); +Complex_t cm_complex_multiply(Complex_t x, Complex_t y); +Complex_t cm_complex_divide(Complex_t x, Complex_t y); + +#endif /* CMPROTO_DEFINED */ diff --git a/src/include/cmtypes.h b/src/include/cmtypes.h new file mode 100755 index 000000000..372e0aa04 --- /dev/null +++ b/src/include/cmtypes.h @@ -0,0 +1,71 @@ +#ifndef CMTYPES_DEFINED +#define CMTYPES_DEFINED + +/* =========================================================================== +FILE CMtypes.h + +MEMBER OF process XSPICE + +Copyright 1991 +Georgia Tech Research Corporation +Atlanta, Georgia 30332 +All Rights Reserved + +PROJECT A-8503 + +AUTHORS + + 9/12/91 Jeff Murray, Bill Kuhn + +MODIFICATIONS + + + +SUMMARY + + This file contains type definitions used by code models. + +INTERFACES + + None. + +REFERENCED FILES + + None. + +NON-STANDARD FEATURES + + None. + +=========================================================================== */ + +#include "miftypes.h" + +/***** Define Typedefs ********************************************/ + +typedef int Boolean_t; + +typedef Mif_Complex_t Complex_t; + + +typedef enum { + ZERO, /* Normally referenced as 0 */ + ONE, /* Normally referenced as 1 */ + UNKNOWN, /* Unknown */ +} Digital_State_t; + +typedef enum { + STRONG, /* strong */ + RESISTIVE, /* resistive */ + HI_IMPEDANCE, /* high impedance */ + UNDETERMINED, /* unknown strength */ +} Digital_Strength_t; + +typedef struct { + Digital_State_t state; + Digital_Strength_t strength; +} Digital_t; + + + +#endif /* CMTYPES_DEFINED */ diff --git a/src/include/dllitf.h b/src/include/dllitf.h new file mode 100755 index 000000000..716b13da6 --- /dev/null +++ b/src/include/dllitf.h @@ -0,0 +1,79 @@ +/* + DLL load interface + (c)2000 Arpad Buermen +*/ + +#ifndef __DLLITF_H +#define __DLLITF_H + +#include "mifproto.h" +#include "cmproto.h" + + +// This structure contains pointers to core SPICE OPUS functions used in CMs and UDNs. +// A pointer to this structure is passed to the dll when the dll is loaded. + +struct coreInfo_t { + // MIF stuff + void ((*dllitf_MIF_INP2A)(void *, INPtables *, card *)); + char * ((*dllitf_MIFgetMod)(void *, char *, INPmodel **, INPtables *)); + IFvalue * ((*dllitf_MIFgetValue)(void *, char **, int, INPtables *, char **)); + int ((*dllitf_MIFsetup)(SMPmatrix *, GENmodel *, CKTcircuit *, int *)); + int ((*dllitf_MIFunsetup)(GENmodel *, CKTcircuit *)); + int ((*dllitf_MIFload)(GENmodel *, CKTcircuit *)); + int ((*dllitf_MIFmParam)(int, IFvalue *, GENmodel *)); + int ((*dllitf_MIFask)(CKTcircuit *, GENinstance *, int, IFvalue *, IFvalue *)); + int ((*dllitf_MIFmAsk)(CKTcircuit *, GENmodel *, int, IFvalue *)); + int ((*dllitf_MIFtrunc)(GENmodel *, CKTcircuit *, double *)); + int ((*dllitf_MIFconvTest)(GENmodel *, CKTcircuit *)); + int ((*dllitf_MIFdelete)(GENmodel *, IFuid, GENinstance **)); + int ((*dllitf_MIFmDelete)(GENmodel **, IFuid, GENmodel *)); + void ((*dllitf_MIFdestroy)(GENmodel **)); + char * ((*dllitf_MIFgettok)(char **)); + char * ((*dllitf_MIFget_token)(char **, Mif_Token_Type_t *)); + Mif_Cntl_Src_Type_t ((*dllitf_MIFget_cntl_src_type)(Mif_Port_Type_t, Mif_Port_Type_t)); + char * ((*dllitf_MIFcopy)(char *)); + // CM stuff + void ((*dllitf_cm_climit_fcn)(double, double, double, double, double, double, + double, double, int, double *, double *, double *, + double *)); + void ((*dllitf_cm_smooth_corner)(double, double, double, double, double, double, + double *, double *)); + void ((*dllitf_cm_smooth_discontinuity)(double, double, double, double, double, + double *, double *)); + double ((*dllitf_cm_smooth_pwl)(double, double *, double *, int, double, double *)); + double ((*dllitf_cm_analog_ramp_factor)(void)); + void * ((*dllitf_cm_analog_alloc)(int, int)); + void * ((*dllitf_cm_analog_get_ptr)(int, int)); + int ((*dllitf_cm_analog_integrate)(double, double *, double *)); + int ((*dllitf_cm_analog_converge)(double *)); + int ((*dllitf_cm_analog_set_temp_bkpt)(double)); + int ((*dllitf_cm_analog_set_perm_bkpt)(double)); + void ((*dllitf_cm_analog_not_converged)(void)); + void ((*dllitf_cm_analog_auto_partial)(void)); + void * ((*dllitf_cm_event_alloc)(int, int)); + void * ((*dllitf_cm_event_get_ptr)(int, int)); + int ((*dllitf_cm_event_queue)(double)); + char * ((*dllitf_cm_message_get_errmsg)(void)); + int ((*dllitf_cm_message_send)(char *)); + double ((*dllitf_cm_netlist_get_c)(void)); + double ((*dllitf_cm_netlist_get_l)(void)); + Complex_t ((*dllitf_cm_complex_set)(double, double)); + Complex_t ((*dllitf_cm_complex_add)(Complex_t, Complex_t)); + Complex_t ((*dllitf_cm_complex_subtract)(Complex_t, Complex_t)); + Complex_t ((*dllitf_cm_complex_multiply)(Complex_t, Complex_t)); + Complex_t ((*dllitf_cm_complex_divide)(Complex_t, Complex_t)); + FILE * ((*dllitf_cm_stream_out)(void)); + FILE * ((*dllitf_cm_stream_in)(void)); + FILE * ((*dllitf_cm_stream_err)(void)); + /*Other stuff*/ + void * ((*dllitf_malloc_pj)(size_t)); + void * ((*dllitf_calloc_pj)(size_t, size_t)); + void * ((*dllitf_realloc_pj)(void *, size_t)); + void ((*dllitf_free_pj)(void *)); + char * ((*dllitf_tmalloc)(int)); + char * ((*dllitf_trealloc)(char *, int)); + void ((*dllitf_txfree)(char *)); +}; + +#endif diff --git a/src/include/enh.h b/src/include/enh.h new file mode 100755 index 000000000..18108d4be --- /dev/null +++ b/src/include/enh.h @@ -0,0 +1,109 @@ +#ifndef ENH_HEADER +#define ENH_HEADER x + +/* =========================================================================== +FILE ENH.h + +MEMBER OF process XSPICE + +Copyright 1991 +Georgia Tech Research Corporation +Atlanta, Georgia 30332 +All Rights Reserved + +PROJECT A-8503 + +AUTHORS + + 9/12/91 Bill Kuhn + +MODIFICATIONS + + + +SUMMARY + + This file contains typedefs used by the event-driven algorithm. + +INTERFACES + + None. + +REFERENCED FILES + + None. + +NON-STANDARD FEATURES + + None. + +=========================================================================== */ + + +#include "miftypes.h" +#include "fteinp.h" + +/* +The following data is used in implementing various enhancements made to the +simulator. The main struct is dynamically allocated in ckt so that incremental additions +can be made more easily without the need to recompile multiple modules. +Allocation and initialization is done in CKTinit.c which should be the only +module needed to recompile after additions are made here. +*/ + + +typedef enum { + ENH_ANALOG_NODE, /* An analog node */ + ENH_EVENT_NODE, /* An event-driven node */ + ENH_ANALOG_BRANCH, /* A branch current */ + ENH_ANALOG_INSTANCE, /* An analog instance */ + ENH_EVENT_INSTANCE, /* An event-driven instance */ + ENH_HYBRID_INSTANCE, /* A hybrid (analog/event-driven) instance */ +} Enh_Conv_Source_t; + + +typedef struct { + double current; /* The current dynamic breakpoint time */ + double last; /* The last used dynamic breakpoint time */ +} Enh_Bkpt_t; + +typedef struct { + double ramptime; /* supply ramping time specified on .options */ +} Enh_Ramp_t; + +typedef struct { + Mif_Boolean_t last_NIiter_call; /* True if this is the last call to NIiter() */ + Mif_Boolean_t report_conv_probs; /* True if conv test functions should send debug info */ +} Enh_Conv_Debug_t; + + +typedef struct { + Mif_Boolean_t enabled; /* True if convergence limiting enabled on code models */ + double abs_step; /* Minimum limiting step size */ + double step; /* Fractional step amount */ +} Enh_Conv_Limit_t; + + +typedef struct { + Mif_Boolean_t enabled; /* True if rshunt option used */ + double gshunt; /* 1.0 / rshunt */ + int num_nodes; /* Number of nodes in matrix */ + double **diag; /* Pointers to matrix diagonals */ +} Enh_Rshunt_t; + + +typedef struct { + Enh_Bkpt_t breakpoint; /* Data used by dynamic breakpoints */ + Enh_Ramp_t ramp; /* New options added to simulator */ + Enh_Conv_Debug_t conv_debug; /* Convergence debug info dumping data */ + Enh_Conv_Limit_t conv_limit; /* Convergence limiting info */ + Enh_Rshunt_t rshunt_data; /* Shunt conductance from nodes to ground */ +} Enh_Ckt_Data_t; + + + +void ENHreport_conv_prob(Enh_Conv_Source_t type, char *name, char *msg); +struct line *ENHtranslate_poly(struct line *deck); + + +#endif /* ENH_HEADER */ diff --git a/src/include/evt.h b/src/include/evt.h new file mode 100755 index 000000000..1a5da1008 --- /dev/null +++ b/src/include/evt.h @@ -0,0 +1,371 @@ +#ifndef EVT_HEADER +#define EVT_HEADER x + +/* =========================================================================== +FILE EVT.h + +MEMBER OF process XSPICE + +Copyright 1991 +Georgia Tech Research Corporation +Atlanta, Georgia 30332 +All Rights Reserved + +PROJECT A-8503 + +AUTHORS + + 9/12/91 Bill Kuhn + +MODIFICATIONS + + + +SUMMARY + + This file contains the definition of the evt data structure and all + its substructures. The single evt structure is housed inside of + the main 3C1 circuit structure 'ckt' and contains virtually all + information about the event-driven simulation. + +INTERFACES + + None. + +REFERENCED FILES + + None. + +NON-STANDARD FEATURES + + None. + +=========================================================================== */ + + +#include "mifdefs.h" +#include "mifcmdat.h" +#include "miftypes.h" + + + +/* ************** */ +/* Info structure */ +/* ************** */ + + +typedef struct Evt_Output_Info_s { + struct Evt_Output_Info_s *next; /* the next in the linked list */ + int node_index; /* index into node info struct for this output */ + int output_subindex; /* index into output data in node data struct */ + int inst_index; /* Index of instance the port is on */ + int port_index; /* Index of port the output corresponds to */ +} Evt_Output_Info_t; + +typedef struct Evt_Port_Info_s { + struct Evt_Port_Info_s *next; /* the next in the linked list of node info */ + int inst_index; /* Index of instance the port is on */ + int node_index; /* index of node the port is connected to */ + char *node_name; /* name of node port is connected to */ + char *inst_name; /* instance name */ + char *conn_name; /* connection name on instance */ + int port_num; /* port number of instance connector */ +} Evt_Port_Info_t; + +typedef struct Evt_Inst_Index_s { + struct Evt_Inst_Index_s *next; /* the next in the linked list */ + int index; /* the value of the index */ +} Evt_Inst_Index_t; + +typedef struct Evt_Node_Info_s { + struct Evt_Node_Info_s *next; /* the next in the linked list */ + char *name; /* Name of node in deck */ + int udn_index; /* Index of the node type */ + Mif_Boolean_t invert; /* True if need to make inverted copy */ + int num_ports; /* Number of ports 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 */ + Evt_Inst_Index_t *inst_list; /* Linked list of indexes of these instances */ +} Evt_Node_Info_t; + +typedef struct Evt_Inst_Info_s { + struct Evt_Inst_Info_s *next; /* the next in the linked list of node info */ + MIFinstance *inst_ptr; /* Pointer to MIFinstance struct for this instance */ +} Evt_Inst_Info_t; + +typedef struct { + Evt_Inst_Info_t *inst_list; /* static info about event/hybrid instances */ + Evt_Node_Info_t *node_list; /* static info about event nodes */ + Evt_Port_Info_t *port_list; /* static info about event ports */ + Evt_Output_Info_t *output_list; /* static info about event outputs */ + int *hybrid_index; /* vector of inst indexs for hybrids */ + Evt_Inst_Info_t **inst_table; /* vector of pointers to elements in inst_list */ + Evt_Node_Info_t **node_table; /* vector of pointers to elements in node_list */ + Evt_Port_Info_t **port_table; /* vector of pointers to elements in port_list */ + Evt_Output_Info_t **output_table; /* vector of pointers to elements in output_list */ +} Evt_Info_t; + + + + + + + + +/* *************** */ +/* Queue structure */ +/* *************** */ + + + +typedef struct Evt_Inst_Event_s { + struct Evt_Inst_Event_s *next; /* the next in the linked list */ + double event_time; /* Time for this event to happen */ + double posted_time; /* Time at which event was entered in queue */ +} Evt_Inst_Event_t; + +typedef struct { + Evt_Inst_Event_t **head; /* Beginning of linked lists */ + Evt_Inst_Event_t ***current; /* Beginning of pending events */ + Evt_Inst_Event_t ***last_step; /* Values of 'current' at last accepted timepoint */ + Evt_Inst_Event_t **free; /* Linked lists of items freed by backups */ + double last_time; /* Time at which last_step was set */ + double next_time; /* Earliest next event time in queue */ + int num_modified; /* Number modified since last accepted timepoint */ + int *modified_index; /* Indexes of modified instances */ + Mif_Boolean_t *modified; /* Flags used to prevent multiple entries */ + int num_pending; /* Count of number of pending events in lists */ + int *pending_index; /* Indexes of pending events */ + Mif_Boolean_t *pending; /* Flags used to prevent multiple entries */ + int num_to_call; /* Count of number of instances that need to be called */ + int *to_call_index; /* Indexes of instances to be called */ + Mif_Boolean_t *to_call; /* Flags used to prevent multiple entries */ +} Evt_Inst_Queue_t; + + + + +typedef struct { + int num_to_eval; /* Count of number of nodes that need to be evaluated */ + int *to_eval_index; /* Indexes of nodes to be evaluated */ + Mif_Boolean_t *to_eval; /* Flags used to prevent multiple entries */ + int num_changed; /* Count of number of nodes that changed */ + int *changed_index; /* Indexes of nodes that changed */ + Mif_Boolean_t *changed; /* Flags used to prevent multiple entries */ +} Evt_Node_Queue_t; + + + + +typedef struct Evt_Output_Event_s { + struct Evt_Output_Event_s *next; /* the next in the linked list */ + double event_time; /* Time for this event to happen */ + double posted_time; /* Time at which event was entered in queue */ + Mif_Boolean_t removed; /* True if event has been deactivated */ + double removed_time; /* Time at which event was deactivated */ + void *value; /* The delayed value sent to this output */ +} Evt_Output_Event_t; + +typedef struct { + Evt_Output_Event_t **head; /* Beginning of linked lists */ + Evt_Output_Event_t ***current; /* Beginning of pending events */ + Evt_Output_Event_t ***last_step; /* Values of 'current' at last accepted timepoint */ + Evt_Output_Event_t **free; /* Linked lists of items freed by backups */ + double last_time; /* Time at which last_step was set */ + double next_time; /* Earliest next event time in queue */ + int num_modified; /* Number modified since last accepted timepoint */ + int *modified_index; /* Indexes of modified outputs */ + Mif_Boolean_t *modified; /* Flags used to prevent multiple entries */ + int num_pending; /* Count of number of pending events in lists */ + int *pending_index; /* Indexes of pending events */ + Mif_Boolean_t *pending; /* Flags used to prevent multiple entries */ + int num_changed; /* Count of number of outputs that changed */ + int *changed_index; /* Indexes of outputs that changed */ + Mif_Boolean_t *changed; /* Flags used to prevent multiple entries */ +} Evt_Output_Queue_t; + + + + +typedef struct { + Evt_Inst_Queue_t inst; /* dynamic queue for instances */ + Evt_Node_Queue_t node; /* dynamic queue of changing nodes */ + Evt_Output_Queue_t output; /* dynamic queue of delayed outputs */ +} Evt_Queue_t; + + + + +/* ************** */ +/* Data structure */ +/* ************** */ + + + + +typedef struct Evt_Node_s { + struct Evt_Node_s *next; /* pointer to next in linked list */ + Mif_Boolean_t op; /* true if computed from op analysis */ + double step; /* DC step or time at which data was computed */ + void **output_value; /* Array of outputs posted to this node */ + void *node_value; /* Resultant computed from output values */ + void *inverted_value; /* Inverted copy of node_value */ +} Evt_Node_t; + +typedef struct { + Evt_Node_t **head; /* Beginning of linked lists */ + Evt_Node_t ***tail; /* Location of last item added to list */ + Evt_Node_t ***last_step; /* 'tail' at last accepted timepoint */ + Evt_Node_t **free; /* Linked lists of items freed by backups */ + int num_modified; /* Number modified since last accepted timepoint */ + int *modified_index; /* Indexes of modified nodes */ + Mif_Boolean_t *modified; /* Flags used to prevent multiple entries */ + Evt_Node_t *rhs; /* Location where model outputs are placed */ + Evt_Node_t *rhsold; /* Location where model inputs are retrieved */ + double *total_load; /* Location where total load inputs are retrieved */ +} Evt_Node_Data_t; + + + + +typedef struct Evt_State_s { + struct Evt_State_s *next; /* Pointer to next state */ + struct Evt_State_s *prev; /* Pointer to previous state */ + double step; /* Time at which state was assigned (0 for DC) */ + void *block; /* Block of memory holding all states on inst */ +} Evt_State_t; + + +typedef struct Evt_State_Desc_s { + struct Evt_State_Desc_s *next; /* Pointer to next description */ + int tag; /* Tag for this state */ + int size; /* Size of this state */ + int offset; /* Offset of this state into the state block */ +} Evt_State_Desc_t; + + +typedef struct { + Evt_State_t **head; /* Beginning of linked lists */ + Evt_State_t ***tail; /* Location of last item added to list */ + Evt_State_t ***last_step; /* 'tail' at last accepted timepoint */ + Evt_State_t **free; /* Linked lists of items freed by backups */ + int num_modified; /* Number modified since last accepted timepoint */ + int *modified_index; /* List of indexes modified */ + Mif_Boolean_t *modified; /* Flags used to prevent multiple entries */ + int *total_size; /* Total bytes for all states allocated */ + Evt_State_Desc_t **desc; /* Lists of description structures */ +} Evt_State_Data_t; + + + + +typedef struct Evt_Msg_s { + struct Evt_Msg_s *next; /* Pointer to next state */ + Mif_Boolean_t op; /* true if output from op analysis */ + double step; /* DC step or time at which message was output */ + char *text; /* The value of the message text */ + int port_index; /* The index of the port from which the message came */ +} Evt_Msg_t; + + +typedef struct { + Evt_Msg_t **head; /* Beginning of linked lists */ + Evt_Msg_t ***tail; /* Location of last item added to list */ + Evt_Msg_t ***last_step; /* 'tail' at last accepted timepoint */ + Evt_Msg_t **free; /* Linked lists of items freed by backups */ + int num_modified; /* Number modified since last accepted timepoint */ + int *modified_index; /* List of indexes modified */ + Mif_Boolean_t *modified; /* Flags used to prevent multiple entries */ +} Evt_Msg_Data_t; + + +typedef struct { + int op_alternations; /* Total alternations between event and analog */ + int op_load_calls; /* Total load calls in DCOP analysis */ + int op_event_passes; /* Total passes through event iteration loop */ + int tran_load_calls; /* Total inst calls in transient analysis */ + int tran_time_backups; /* Number of transient timestep cuts */ +} Evt_Statistic_t; + + + + +typedef struct { + Evt_Node_Data_t *node; /* dynamic event solution vector */ + Evt_State_Data_t *state; /* dynamic event instance state data */ + Evt_Msg_Data_t *msg; /* dynamic event message data */ + Evt_Statistic_t *statistics; /* Statistics for events, etc. */ +} Evt_Data_t; + + + +/* **************** */ +/* Counts structure */ +/* **************** */ + + +typedef struct { + int num_insts; /* number of event/hybrid instances parsed */ + int num_hybrids; /* number of hybrids parsed */ + int num_hybrid_outputs; /* number of outputs on all hybrids parsed */ + int num_nodes; /* number of event nodes parsed */ + int num_ports; /* number of event ports parsed */ + int num_outputs; /* number of event outputs parsed */ +} Evt_Count_t; + + + +/* **************** */ +/* Limits structure */ +/* **************** */ + + +typedef struct { + int max_event_passes; /* maximum loops in attempting convergence of event nodes */ + int max_op_alternations; /* maximum loops through event/analog alternation */ +} Evt_Limit_t; + + +/* ************** */ +/* Jobs structure */ +/* ************** */ + + +typedef struct { + int num_jobs; /* Number of jobs run */ + char **job_name; /* Names of different jobs */ + Evt_Node_Data_t **node_data; /* node_data for different jobs */ + Evt_State_Data_t **state_data; /* state_data for different jobs */ + Evt_Msg_Data_t **msg_data; /* messages for different jobs */ + Evt_Statistic_t **statistics; /* Statistics for different jobs */ +} Evt_Job_t; + + + +/* ***************** */ +/* Options structure */ +/* ***************** */ + + +typedef struct { + Mif_Boolean_t op_alternate; /* Alternate analog/event solutions in OP analysis */ +} Evt_Option_t; + + +/* ****************** */ +/* Main evt structure */ +/* ****************** */ + +typedef struct { + Evt_Count_t counts; /* Number of insts, nodes, etc. */ + Evt_Info_t info; /* Static info about insts, etc. */ + Evt_Queue_t queue; /* Dynamic queued events */ + Evt_Data_t data; /* Results and state data */ + Evt_Limit_t limits; /* Iteration limits, etc. */ + Evt_Job_t jobs; /* Data held from multiple job runs */ + Evt_Option_t options; /* Data input on .options cards */ +} Evt_Ckt_Data_t; + + + +#endif /* EVT_HEADER */ diff --git a/src/include/evtproto.h b/src/include/evtproto.h new file mode 100755 index 000000000..104814472 --- /dev/null +++ b/src/include/evtproto.h @@ -0,0 +1,124 @@ +#ifndef EVTPROTO_HEADER +#define EVTPROTO_HEADER x + +/* =========================================================================== +FILE EVTproto.h + +MEMBER OF process XSPICE + +Copyright 1991 +Georgia Tech Research Corporation +Atlanta, Georgia 30332 +All Rights Reserved + +PROJECT A-8503 + +AUTHORS + + 9/12/91 Bill Kuhn + +MODIFICATIONS + + + +SUMMARY + + This file contains ANSI C function prototypes for functions + in the event-driven simulation algorithm package. + +INTERFACES + + None. + +REFERENCED FILES + + None. + +NON-STANDARD FEATURES + + None. + +=========================================================================== */ + +#include "cktdefs.h" +#include "cpstd.h" +#include "mifdefs.h" +#include "ipc.h" + + +/* ******************* */ +/* Function Prototypes */ +/* ******************* */ + + +int EVTinit(CKTcircuit *ckt); +/*int EVTinit2(CKTcircuit *ckt);*/ + +void EVTtermInsert( + CKTcircuit *ckt, + MIFinstance *fast, + char *node_name, + char *type_name, + int conn_num, + int port_num, + char **err_msg); + +int EVTsetup(CKTcircuit *ckt); + +int EVTiter(CKTcircuit *ckt); + +void EVTbackup(CKTcircuit *ckt, double new_time); + +double EVTnext_time(CKTcircuit *ckt); + +void EVTqueue_output( + CKTcircuit *ckt, + int output_index, + int udn_index, + Evt_Output_Event_t *new_event, + double posted_time, + double event_time); + + +void EVTqueue_inst( + CKTcircuit *ckt, + int inst_index, + double posted_time, + double event_time); + +void EVTdequeue(CKTcircuit *ckt, double time); + +int EVTload(CKTcircuit *ckt, int inst_index); + +void EVTprint(wordlist *wl); + +int EVTop( + CKTcircuit *ckt, + long firstmode, + long continuemode, + int max_iter, + Mif_Boolean_t first_call); + +void EVTop_save( + CKTcircuit *ckt, + Mif_Boolean_t op, + double step); + +void EVTnode_copy( + CKTcircuit *ckt, + int node_index, + Evt_Node_t *from, + Evt_Node_t **to); + +void EVTcall_hybrids(CKTcircuit *ckt); + +void EVTdump( + CKTcircuit *ckt, + Ipc_Anal_t mode, + double step); + +void EVTaccept( + CKTcircuit *ckt, /* main circuit struct */ + double time); /* time at which analog soln was accepted */ + +#endif /* EVTPROTO_HEADER */ diff --git a/src/include/evtudn.h b/src/include/evtudn.h new file mode 100755 index 000000000..20f9b7d94 --- /dev/null +++ b/src/include/evtudn.h @@ -0,0 +1,123 @@ +#ifndef EVTUDN_HEADER +#define EVTUDN_HEADER x + +/* =========================================================================== +FILE EVTudn.h + +MEMBER OF process XSPICE + +Copyright 1991 +Georgia Tech Research Corporation +Atlanta, Georgia 30332 +All Rights Reserved + +PROJECT A-8503 + +AUTHORS + + 9/12/91 Bill Kuhn + +MODIFICATIONS + + + +SUMMARY + + This file contains the definition of "User-Defined Nodes". + These nodes are integrated into the simulator similar to the + way models are tied into SPICE 3C1, so that new node types + can be relatively easily added. The functions (required and + optional) are listed below. For optional functions, the + function can be left undefined and the pointer placed into the + Evt_Udn_Info_t structure can be specified as NULL. + + Required functions: + create - allocate data structure used as inputs and outputs to code models + initialize - set structure to appropriate initial value for first use as model input + copy - make a copy of the contents into created but possibly uninitialized structure + compare - determine if two structures are equal in value + + Optional functions: + dismantle - free allocations _inside_ structure (but not structure itself) + invert - invert logical value of structure + resolve - determine the resultant when multiple outputs are connected to a node + plot_val - output a real value for specified structure component for plotting purposes + print_val - output a string value for specified structure component for printing + ipc_val - output a binary data structure and size of the structure for IPC + +INTERFACES + + None. + +REFERENCED FILES + + None. + +NON-STANDARD FEATURES + + None. + +=========================================================================== */ + + +#include "miftypes.h" /* for Mif_Boolean_t used in udn_..._compare */ + +#define MALLOCED_PTR (*evt_struct_ptr) +#define STRUCT_PTR evt_struct_ptr +#define STRUCT_PTR_1 evt_struct_ptr_1 +#define STRUCT_PTR_2 evt_struct_ptr_2 +#define EQUAL (*evt_equal) +#define INPUT_STRUCT_PTR evt_input_struct_ptr +#define OUTPUT_STRUCT_PTR evt_output_struct_ptr +#define INPUT_STRUCT_PTR_ARRAY evt_input_struct_ptr_array +#define INPUT_STRUCT_PTR_ARRAY_SIZE evt_input_struct_ptr_array_size +#define STRUCT_MEMBER_ID evt_struct_member_id +#define PLOT_VAL (*evt_plot_val) +#define PRINT_VAL (*evt_print_val) +#define IPC_VAL (*evt_ipc_val) +#define IPC_VAL_SIZE (*evt_ipc_val_size) + +#define CREATE_ARGS void **evt_struct_ptr +#define INITIALIZE_ARGS void *evt_struct_ptr +#define COMPARE_ARGS void *evt_struct_ptr_1, \ + void *evt_struct_ptr_2, \ + Mif_Boolean_t *evt_equal +#define COPY_ARGS void *evt_input_struct_ptr, \ + void *evt_output_struct_ptr +#define DISMANTLE_ARGS void *evt_struct_ptr +#define INVERT_ARGS void *evt_struct_ptr +#define RESOLVE_ARGS int evt_input_struct_ptr_array_size, \ + void **evt_input_struct_ptr_array, \ + void *evt_output_struct_ptr +#define PLOT_VAL_ARGS void *evt_struct_ptr, \ + char *evt_struct_member_id, \ + double *evt_plot_val +#define PRINT_VAL_ARGS void *evt_struct_ptr, \ + char *evt_struct_member_id, \ + char **evt_print_val +#define IPC_VAL_ARGS void *evt_struct_ptr, \ + void **evt_ipc_val, \ + int *evt_ipc_val_size + + +typedef struct { + char *name; + char *description; + void ((*create)(CREATE_ARGS)); + void ((*dismantle)(DISMANTLE_ARGS)); + void ((*initialize)(INITIALIZE_ARGS)); + void ((*invert)(INVERT_ARGS)); + void ((*copy)(COPY_ARGS)); + void ((*resolve)(RESOLVE_ARGS)); + void ((*compare)(COMPARE_ARGS)); + void ((*plot_val)(PLOT_VAL_ARGS)); + void ((*print_val)(PRINT_VAL_ARGS)); + void ((*ipc_val)(IPC_VAL_ARGS)); +} Evt_Udn_Info_t; + + +extern int g_evt_num_udn_types; +extern Evt_Udn_Info_t **g_evt_udn_info; + + +#endif /* EVTUDN_HEADER */ diff --git a/src/include/ipc.h b/src/include/ipc.h new file mode 100755 index 000000000..a75c5d078 --- /dev/null +++ b/src/include/ipc.h @@ -0,0 +1,122 @@ +/* $Id$ + * + */ +/*============================================================================ +FILE IPC.h + +MEMBER OF process XSPICE + +Copyright 1991 +Georgia Tech Research Corporation +Atlanta, Georgia 30332 +All Rights Reserved + +PROJECT A-8503 + +AUTHORS + + 9/12/91 Steve Tynor + +MODIFICATIONS + + + +SUMMARY + + Provides compatibility for the new SPICE simulator to both the MSPICE user + interface and BCP (via ATESSE v.1 style AEGIS mailboxes) and the new ATESSE + v.2 Simulator Interface and BCP (via Bsd Sockets). + +INTERFACES + + +REFERENCED FILES + + None. + +NON-STANDARD FEATURES + + None. + +============================================================================*/ + +#ifndef IPC_DEFINED +#define IPC_DEFINED + + +#define IPC_MAX_LINE_LEN 80 +#define IPC_MAX_PATH_LEN 2048 + +/* Known socket port for server and client to communicate: */ +#define SOCKET_PORT 1064 + +/* Recognition character for Beginning Of Line of message: */ +#define BOL_CHAR '\\' + +/* Length (in bytes) of a socket message header: */ +#define SOCK_MSG_HDR_LEN 5 + + +typedef int Ipc_Boolean_t; + +#define IPC_FALSE 0 +#define IPC_TRUE 1 + +typedef struct { /* Don't change this type! It is cast elsewhere */ + double real; + double imag; +} Ipc_Complex_t; + +/*---------------------------------------------------------------------------*/ +typedef enum { + IPC_STATUS_OK, + IPC_STATUS_NO_DATA, + IPC_STATUS_END_OF_DECK, + IPC_STATUS_EOF, + IPC_STATUS_ERROR, +} Ipc_Status_t; + +#if 0 +/*---------------------------------------------------------------------------*/ +typedef void* Ipc_Connection_t; +/* + * A connection is an `opaque' type - the user has no access to the details of + * the implementation. Indeed the details are different depending on whether + * underlying transport mechanism is AEGIS Mailboxes or Bsd Sockets (or + * something else...) + */ +#endif + +/*---------------------------------------------------------------------------*/ +typedef enum { + IPC_WAIT, + IPC_NO_WAIT, +} Ipc_Wait_t; + +/*---------------------------------------------------------------------------*/ +typedef enum { + IPC_PROTOCOL_V1, /* >DATAB records in ATESSE v.1 format + * Handles v.1 style logfile name passing protocol + */ + IPC_PROTOCOL_V2, /* >DATAB records in ATESSE v.2 format + */ +} Ipc_Protocol_t; + +/*---------------------------------------------------------------------------*/ +typedef enum { + IPC_MODE_BATCH, + IPC_MODE_INTERACTIVE, +} Ipc_Mode_t; + + +/*---------------------------------------------------------------------------*/ +typedef enum { + IPC_ANAL_DCOP, + IPC_ANAL_DCTRCURVE, + IPC_ANAL_AC, + IPC_ANAL_TRAN, +} Ipc_Anal_t; + + + +#endif /* IPC_DEFINED */ diff --git a/src/include/ipcproto.h b/src/include/ipcproto.h new file mode 100755 index 000000000..b211baf6b --- /dev/null +++ b/src/include/ipcproto.h @@ -0,0 +1,52 @@ + +/* IPC.c */ +Ipc_Boolean_t kw_match (char *keyword , char *str ); +Ipc_Status_t ipc_initialize_server (char *server_name , Ipc_Mode_t m , Ipc_Protocol_t p ); +Ipc_Status_t ipc_terminate_server (void ); +Ipc_Status_t ipc_get_line (char *str , int *len , Ipc_Wait_t wait ); +Ipc_Status_t ipc_flush (void ); +Ipc_Status_t ipc_send_line_binary (char *str , int len ); +Ipc_Status_t ipc_send_line (char *str ); +Ipc_Status_t ipc_send_data_prefix (double time ); +Ipc_Status_t ipc_send_dcop_prefix (void ); +Ipc_Status_t ipc_send_data_suffix (void ); +Ipc_Status_t ipc_send_dcop_suffix (void ); +Ipc_Status_t ipc_send_errchk (void ); +Ipc_Status_t ipc_send_end (void ); +int stuff_binary_v1 (double d1 , double d2 , int n , char *buf , int pos ); +Ipc_Status_t ipc_send_double (char *tag , double value ); +Ipc_Status_t ipc_send_complex (char *tag , Ipc_Complex_t value ); +Ipc_Status_t ipc_send_int (char *tag , int value ); +Ipc_Status_t ipc_send_boolean (char *tag , Ipc_Boolean_t value ); +Ipc_Status_t ipc_send_string (char *tag , char *value ); +Ipc_Status_t ipc_send_int_array (char *tag , int array_len , int *value ); +Ipc_Status_t ipc_send_double_array (char *tag , int array_len , double *value ); +Ipc_Status_t ipc_send_complex_array (char *tag , int array_len , Ipc_Complex_t *value ); +Ipc_Status_t ipc_send_boolean_array (char *tag , int array_len , Ipc_Boolean_t *value ); +Ipc_Status_t ipc_send_string_array (char *tag , int array_len , char **value ); +Ipc_Status_t ipc_send_evtdict_prefix (); +Ipc_Status_t ipc_send_evtdict_suffix (); +Ipc_Status_t ipc_send_evtdata_prefix (); +Ipc_Status_t ipc_send_evtdata_suffix (); +Ipc_Status_t ipc_send_event(int, double, double, char *, void *, int); + +/* IPCtiein.c */ +void ipc_handle_stop (void ); +void ipc_handle_returni (void ); +void ipc_handle_mintime (double time ); +void ipc_handle_vtrans (char *vsrc , char *dev ); +void ipc_send_stdout (void ); +void ipc_send_stderr (void ); +Ipc_Status_t ipc_send_std_files (void ); +Ipc_Boolean_t ipc_screen_name (char *name , char *mapped_name ); +int ipc_get_devices (void *circuit , char *device , char ***names , double **modtypes ); +void ipc_free_devices (int num_items , char **names , double *modtypes ); +void ipc_check_pause_stop (void ); + +/* IPCaegis.c */ +Ipc_Status_t ipc_transport_initialize_server (char *server_name , Ipc_Mode_t m , Ipc_Protocol_t p , char *batch_filename ); +Ipc_Status_t extract_msg (char *str , int *len ); +Ipc_Status_t ipc_transport_get_line (char *str , int *len , Ipc_Wait_t wait ); +Ipc_Status_t ipc_transport_terminate_server (void ); +Ipc_Status_t ipc_transport_send_line (char *str , int len ); + diff --git a/src/include/ipctiein.h b/src/include/ipctiein.h new file mode 100755 index 000000000..4a3670bf0 --- /dev/null +++ b/src/include/ipctiein.h @@ -0,0 +1,96 @@ +/*============================================================================ +FILE IPCtiein.h + +MEMBER OF process XSPICE + +Copyright 1991 +Georgia Tech Research Corporation +Atlanta, Georgia 30332 +All Rights Reserved + +PROJECT A-8503 + +AUTHORS + + 9/12/91 Bill Kuhn + +MODIFICATIONS + + + +SUMMARY + + Provides a protocol independent interface between the simulator + and the IPC method used to interface to CAE packages. + +INTERFACES + + +REFERENCED FILES + + None. + +NON-STANDARD FEATURES + + None. + +============================================================================*/ + + +#ifndef IPC_TIEIN_DEFINED +#define IPC_TIEIN_DEFINED + + +#include "ipc.h" +#include "ipcproto.h" + + +#define IPC_STDOUT_FILE_NAME "/usr/tmp/atesse_xspice.out" +#define IPC_STDERR_FILE_NAME "/usr/tmp/atesse_xspice.err" + + +/* +Ipc_Vtrans_t is used by functions that return results to translate +voltage source names to the names of the devices they monitor. +This table is built from #VTRANS cards in the incoming deck and +is provided for ATESSE 1.0 compatibility. +*/ + +typedef struct { + int size; /* Size of arrays */ + char **vsrc_name; /* Array of voltage source name prefixes */ + char **device_name; /* Array of device names the vsources map to */ +} Ipc_Vtrans_t; + + +/* +Ipc_Tiein_t is used by the SPICE mods that take care of interprocess communications +activities. +*/ + +typedef struct { + + Ipc_Boolean_t enabled; /* True if we are using IPC */ + Ipc_Mode_t mode; /* INTERACTIVE or BATCH mode */ + Ipc_Anal_t anal_type; /* DCOP, AC, ... mode */ + Ipc_Boolean_t syntax_error; /* True if error occurred during parsing */ + Ipc_Boolean_t run_error; /* True if error occurred during simulation */ + Ipc_Boolean_t errchk_sent; /* True if #ERRCHK has been sent */ + Ipc_Boolean_t returni; /* True if simulator should return currents */ + double mintime; /* Minimum time between timepoints returned */ + double last_time; /* Last timepoint returned */ + double cpu_time; /* CPU time used during simulation */ + Ipc_Boolean_t *send; /* Used by OUTinterface to determine what to send */ + char *log_file; /* Path to write log file */ + Ipc_Vtrans_t vtrans; /* Used by OUTinterface to translate v sources */ + Ipc_Boolean_t stop_analysis; /* True if analysis should be terminated */ + +} Ipc_Tiein_t; + + + +extern Ipc_Tiein_t g_ipc; + + +#endif /* IPC_TIEIN_DEFINED */ + diff --git a/src/include/mif.h b/src/include/mif.h new file mode 100755 index 000000000..a08941d46 --- /dev/null +++ b/src/include/mif.h @@ -0,0 +1,87 @@ +#ifndef MIF +#define MIF + +/* =========================================================================== +FILE MIF.h + +MEMBER OF process XSPICE + +Copyright 1991 +Georgia Tech Research Corporation +Atlanta, Georgia 30332 +All Rights Reserved + +PROJECT A-8503 + +AUTHORS + + 9/12/91 Bill Kuhn + +MODIFICATIONS + + + +SUMMARY + + This file structure definitions global data used with the MIF package. + The global data structure is used to circumvent the need to modify + argument lists in existing SPICE 3C1 functions. + +INTERFACES + + None. + +REFERENCED FILES + + None. + +NON-STANDARD FEATURES + + None. + +=========================================================================== */ + +#include "miftypes.h" +#include "mifdefs.h" +#include "cktdefs.h" + + +typedef struct { + Mif_Boolean_t init; /* TRUE if first call to model */ + Mif_Boolean_t anal_init; /* TRUE if first call for this analysis type */ + Mif_Analysis_t anal_type; /* The type of analysis being performed */ + Mif_Call_Type_t call_type; /* Type of call to code model - analog or event-driven */ + double evt_step; /* The current DC step or time in event analysis */ +} Mif_Circuit_Info_t; + + +typedef struct { + double current; /* The current dynamic breakpoint time */ + double last; /* The last used dynamic breakpoint time */ +} Mif_Bkpt_Info_t; + + +typedef struct { + Mif_Boolean_t global; /* Set by .option to force all models to use auto */ + Mif_Boolean_t local; /* Set by individual model to request auto partials */ +} Mif_Auto_Partial_t; + + +typedef struct { + Mif_Circuit_Info_t circuit; /* Circuit data that will be needed by MIFload */ + MIFinstance *instance; /* Current instance struct */ + CKTcircuit *ckt; /* The ckt struct for the circuit */ + char *errmsg; /* An error msg from a cm_... function */ + Mif_Bkpt_Info_t breakpoint; /* Data used by dynamic breakpoints */ + Mif_Auto_Partial_t auto_partial; /* Flags to enable auto partial computations */ +} Mif_Info_t; + + +/* These are defined in mif.c */ +extern int MIFiSize; +extern int MIFmSize; + + +extern Mif_Info_t g_mif_info; + +#endif /* MIF */ diff --git a/src/include/mifcmdat.h b/src/include/mifcmdat.h new file mode 100755 index 000000000..ea877455d --- /dev/null +++ b/src/include/mifcmdat.h @@ -0,0 +1,373 @@ +#ifndef MIFCMDAT +#define MIFCMDAT + +/* =========================================================================== +FILE MIFcmdat.h + +MEMBER OF process XSPICE + +Copyright 1991 +Georgia Tech Research Corporation +Atlanta, Georgia 30332 +All Rights Reserved + +PROJECT A-8503 + +AUTHORS + + 9/12/91 Bill Kuhn + +MODIFICATIONS + + + +SUMMARY + + This file contains the data structure definitions used by + code model and the associated MIF package. + + A special preprocessor (cmpp) is used on models written by a + user to turn items like INPUT() into the appropriate structure + reference. + +INTERFACES + + None. + +REFERENCED FILES + + None. + +NON-STANDARD FEATURES + + None. + +=========================================================================== */ + + +#include "miftypes.h" + + +/* ************************************************************************** */ + + +/* + * Pointers into matrix for a voltage input, voltage output partial + */ + +typedef struct Mif_E_Ptr_s { + + double *branch_poscntl; /* Branch row, positive controlling column */ + double *branch_negcntl; /* Branch row, negative controlling column */ + +} Mif_E_Ptr_t; + + + +/* + * Pointers into matrix for a current input, current output partial + */ + +typedef struct Mif_F_Ptr_s { + + double *pos_ibranchcntl; /* Positive row, controlling branch column */ + double *neg_ibranchcntl; /* Negative row, controlling branch column */ + +} Mif_F_Ptr_t; + + + +/* + * Pointers into matrix for a voltage input, current output partial + */ + +typedef struct Mif_G_Ptr_s { + + double *pos_poscntl; /* Positive row, positive controlling column */ + double *pos_negcntl; /* Positive row, negative controlling column */ + double *neg_poscntl; /* Negative row, positive controlling column */ + double *neg_negcntl; /* Negative row, negative controlling column */ + +} Mif_G_Ptr_t; + + +/* + * Pointers into matrix for a current input, voltage output partial + */ + +typedef struct Mif_H_Ptr_s { + + double *branch_ibranchcntl; /* Branch row, controlling branch column */ + +} Mif_H_Ptr_t; + + + + +/* + * Matrix pointers associated with a particular port (of a particular type) + */ + + +typedef union Mif_Port_Ptr_u { + + Mif_E_Ptr_t e; /* Pointers for voltage input, voltage output */ + Mif_F_Ptr_t f; /* Pointers for current input, current output */ + Mif_G_Ptr_t g; /* Pointers for voltage input, current output */ + Mif_H_Ptr_t h; /* Pointers for current input, voltage output */ + +} Mif_Port_Ptr_t; + + + +/* + * Array of matrix data pointers for particular ports in a connection + */ + +typedef struct Mif_Conn_Ptr_s { + + Mif_Port_Ptr_t *port; /* Data for a particular port */ + +} Mif_Conn_Ptr_t; + + + +/* + * Row numbers and matrix entry pointers for loading the matrix and RHS with + * data appropriate for the particular output port and input ports. + */ + +typedef struct Mif_Smp_Ptr_s { + + /* Data at this level is for this connection. The Mif_Conn_Ptr_t */ + /* subtree is used only if this connection is an output. It supplies */ + /* the matrix pointers required for loading the partials from each */ + /* input. */ + + /* node connection equation numbers */ + int pos_node; /* Row associated with positive node */ + int neg_node; /* Row associated with negative node */ + + /* V source branch equation numbers */ + int branch; /* Row associated with V output branch */ + int ibranch; /* Row associated with I input branch */ + + /* matrix pointers for V source output */ + double *pos_branch; /* Positive node row, branch column */ + double *neg_branch; /* Negative node row, branch column */ + double *branch_pos; /* Branch row, positive node column */ + double *branch_neg; /* Branch row, negative node column */ + + /* matrix pointers for the zero-valued V source associated with an I input */ + double *pos_ibranch; /* Positive node row, branch column */ + double *neg_ibranch; /* Negative node row, branch column */ + double *ibranch_pos; /* Branch row, positive node column */ + double *ibranch_neg; /* Branch row, negative node column */ + + /* array of pointer info required for putting partials into the matrix */ + Mif_Conn_Ptr_t *input; /* Matrix pointers associated with inputs */ + +} Mif_Smp_Ptr_t; + + + + +/* ******************************************************************** */ + + + +/* + * Partial derivatives wrt ports of a particular input connection + */ + +typedef struct Mif_Partial_s { + + double *port; /* Partial wrt this port */ + +} Mif_Partial_t; + + +/* + * AC gains wrt ports of a particular input connection + */ + +typedef struct Mif_AC_Gain_s { + + Mif_Complex_t *port; /* AC gain wrt this port */ + +} Mif_AC_Gain_t; + + +/* + * Data used to access information in event struct in CKTcircuit struct ckt + */ + +typedef struct { + int node_index; /* Index of node in event-driven structures */ + int output_subindex; /* Subindex of output on node */ + int port_index; /* Index of port in event-driven structures */ + int output_index; /* Index of output in event-driven structures */ +} Mif_Evt_Data_t; + + +/* + * Information about individual port(s) of a connection. + */ + +typedef struct Mif_Port_Data_s { + + Mif_Port_Type_t type; /* Port type - e.g. MIF_VOLTAGE, ... */ + char *type_str; /* Port type in string form */ + char *pos_node_str; /* Positive node identifier */ + char *neg_node_str; /* Negative node identifier */ + char *vsource_str; /* Voltage source identifier */ + + Mif_Boolean_t is_null; /* Set to true if null in SPICE deck */ + Mif_Value_t input; /* The input value */ + Mif_Value_t output; /* The output value */ + Mif_Partial_t *partial; /* Partials for this port wrt inputs */ + Mif_AC_Gain_t *ac_gain; /* AC gains for this port wrt inputs */ + int old_input; /* Index into CKTstate for old input */ + + Mif_Boolean_t invert; /* True if state should be inverted */ + Mif_Boolean_t changed; /* A new output has been assigned */ + double load; /* Load factor output to this port */ + double total_load; /* Total load for this port */ + double delay; /* Digital delay for this output port */ + char *msg; /* Message string output to port */ + + Mif_Smp_Ptr_t smp_data; /* Pointers used to load matrix/rhs */ + Mif_Evt_Data_t evt_data; /* Data used to access evt struct */ + + double nominal_output; /* Saved output when doing auto partial */ + +} Mif_Port_Data_t; + + +/* ******************************************************************** */ + +/* + * Information in MIFinstance struct used by cm_.. support functions. + */ + + +typedef struct Mif_State_s { /* for cm_analog_alloc() */ + + int tag; /* Tag identifying this particular state */ + int index; /* Index into ckt->CKTstate[i] vector */ + int doubles; /* Number of doubles allocated for this state */ + int bytes; /* Actual number of bytes requested by cm_analog_alloc() */ + +} Mif_State_t; + + +typedef struct Mif_Intgr_s { /* for cm_analog_integrate() */ + + int byte_index; /* Byte offset into state array */ + +} Mif_Intgr_t; + + +typedef struct Mif_Conv_s { /* for cm_analog_converge() */ + + int byte_index; /* Byte offset into state array */ + double last_value; /* Value at last iteration */ + +} Mif_Conv_t; + + + +/* ******************************************************************** */ + + + +/* + * Information about the circuit in which this model is simulating. + */ + +typedef struct Mif_Circ_Data_s { + + Mif_Boolean_t init; /* True if first call to model - a setup pass */ + Mif_Analysis_t anal_type; /* Current analysis type */ + Mif_Boolean_t anal_init; /* True if first call in this analysis type */ + Mif_Call_Type_t call_type; /* Analog or event type call */ + double time; /* Current analysis time */ + double frequency; /* Current analysis frequency */ + double temperature; /* Current analysis temperature */ + double t[8]; /* History of last 8 analysis times t[0]=time */ + +} Mif_Circ_Data_t; + + + +/* + * The structure associated with a named "connection" on the model. + */ + +typedef struct Mif_Conn_Data_s { + + char *name; /* Name of this connection - currently unused */ + char *description; /* Description of this connection - unused */ + Mif_Boolean_t is_null; /* Set to true if null in SPICE deck */ + Mif_Boolean_t is_input; /* Set to true if connection is an input */ + Mif_Boolean_t is_output; /* Set to true if connection is an output */ + int size; /* The size of an array (1 if scalar) */ + Mif_Port_Data_t **port; /* Pointer(s) to port(s) for this connection */ + +} Mif_Conn_Data_t; + + + +/* + * Values for model parameters + */ + +typedef struct Mif_Param_Data_s { + + Mif_Boolean_t is_null; /* True if no value given on .model card */ + int size; /* Size of array (1 if scalar) */ + Mif_Value_t *element; /* Value of parameter(s) */ + +} Mif_Param_Data_t; + + + + +/* + * Values for instance variables + */ + +typedef struct Mif_Inst_Var_Data_s { + + int size; /* Size of array (1 if scalar) */ + Mif_Value_t *element; /* Value of instance variables(s) */ + +} Mif_Inst_Var_Data_t; + + + + +/* ************************************************************************* */ + + + +/* + * HERE IT IS!!! + * The top level data structure passed to code models. + */ + +typedef struct Mif_Private_s { + + Mif_Circ_Data_t circuit; /* Information about the circuit */ + int num_conn; /* Number of connections on this model */ + Mif_Conn_Data_t **conn; /* Information about each connection */ + int num_param; /* Number of parameters on this model */ + Mif_Param_Data_t **param; /* Information about each parameter */ + int num_inst_var; /* Number of instance variables */ + Mif_Inst_Var_Data_t **inst_var; /* Information about each inst variable */ + +} Mif_Private_t; + + + +#endif /* MIFCMDAT */ diff --git a/src/include/mifdefs.h b/src/include/mifdefs.h new file mode 100755 index 000000000..51daf991e --- /dev/null +++ b/src/include/mifdefs.h @@ -0,0 +1,111 @@ +#ifndef MIFDEFS +#define MIFDEFS + +/* =========================================================================== +FILE MIFdefs.h + +MEMBER OF process XSPICE + +Copyright 1991 +Georgia Tech Research Corporation +Atlanta, Georgia 30332 +All Rights Reserved + +PROJECT A-8503 + +AUTHORS + + 9/12/91 Bill Kuhn + +MODIFICATIONS + + + +SUMMARY + + This file contains (augmented) SPICE 3C1 compatible typedefs for use + with code models. These typedefs define the data structures that are + used internally to describe instances and models in the circuit + description linked lists. + +INTERFACES + + None. + +REFERENCED FILES + + None. + +NON-STANDARD FEATURES + + None. + +=========================================================================== */ + + +#include "mifcmdat.h" +#include "ifsim.h" + + +/* The per-instance data structure */ + +typedef struct sMIFinstance { + + struct sMIFmodel *MIFmodPtr; /* backpointer to model */ + struct sMIFinstance *MIFnextInstance; /* pointer to next instance of current model */ + IFuid MIFname; /* pointer to character string naming this instance */ + + int num_conn; /* number of connections on the code model */ + Mif_Conn_Data_t **conn; /* array of data structures for each connection */ + + int num_inst_var; /* number of instance variables on the code model */ + Mif_Inst_Var_Data_t **inst_var; /* array of structs for each instance var */ + + int num_param; /* number of parameters on the code model */ + Mif_Param_Data_t **param; /* array of structs for each parameter */ + + int num_state; /* Number of state tags used for this inst */ + Mif_State_t *state; /* Info about states */ + + int num_intgr; /* Number of integrals */ + Mif_Intgr_t *intgr; /* Info for integrals */ + + int num_conv; /* Number of things to be converged */ + Mif_Conv_t *conv; /* Info for convergence things */ + + Mif_Boolean_t initialized; /* True if model called once already */ + + Mif_Boolean_t analog; /* true if this inst is analog or hybrid type */ + Mif_Boolean_t event_driven; /* true if this inst is event-driven or hybrid type */ + + int inst_index; /* Index into inst_table in evt struct in ckt */ + +} MIFinstance ; + + + +/* The per model data structure */ + +typedef struct sMIFmodel { + + int MIFmodType; /* type index of this device type */ + struct sMIFmodel *MIFnextModel; /* pointer to next possible model in linked list */ + MIFinstance *MIFinstances; /* pointer to list of instances that have this model */ + IFuid MIFmodName; /* pointer to character string naming this model */ + + int num_param; /* number of parameters on the code model */ + Mif_Param_Data_t **param; /* array of structs for each parameter */ + + Mif_Boolean_t analog; /* true if this model is analog or hybrid type */ + Mif_Boolean_t event_driven; /* true if this model is event-driven or hybrid type */ + +} MIFmodel; + + + +/* NOTE: There are no device parameter tags, since the ask, mAsk, ... */ +/* functions for code models work out of the generic code model structure */ + + + +#endif /* MIFDEFS */ diff --git a/src/include/mifparse.h b/src/include/mifparse.h new file mode 100755 index 000000000..fbfc19944 --- /dev/null +++ b/src/include/mifparse.h @@ -0,0 +1,120 @@ +#ifndef MIFPARSE +#define MIFPARSE + +/* =========================================================================== +FILE MIFparse.h + +MEMBER OF process XSPICE + +Copyright 1991 +Georgia Tech Research Corporation +Atlanta, Georgia 30332 +All Rights Reserved + +PROJECT A-8503 + +AUTHORS + + 9/12/91 Bill Kuhn + +MODIFICATIONS + + + +SUMMARY + + This file contains the information structure definitions used by the + code model parser to check for valid connections and parameters. + + Structures of these types are created by the code model preprocessor + (cmpp) from the user created ifspec.ifs file. + +INTERFACES + + None. + +REFERENCED FILES + + None. + +NON-STANDARD FEATURES + + None. + +=========================================================================== */ + + +#include "miftypes.h" + + +/* + * Information about a connection used by the parser to error check input + */ + + +typedef struct Mif_Conn_Info_s { + + char *name; /* Name of this connection */ + char *description; /* Description of this connection */ + Mif_Dir_t direction; /* Is this connection an input, output, or both? */ + Mif_Port_Type_t default_port_type; /* The default port type */ + char *default_type; /* The default type in string form */ + int num_allowed_types; /* The size of the allowed type arrays */ + Mif_Port_Type_t *allowed_type; /* The allowed types */ + char **allowed_type_str; /* The allowed types in string form */ + Mif_Boolean_t is_array; /* True if connection is an array */ + Mif_Boolean_t has_lower_bound; /* True if there is an array size lower bound */ + int lower_bound; /* Array size lower bound */ + Mif_Boolean_t has_upper_bound; /* True if there is an array size upper bound */ + int upper_bound; /* Array size upper bound */ + Mif_Boolean_t null_allowed; /* True if null is allowed for this connection */ + +} Mif_Conn_Info_t; + + + + +/* + * Information about a parameter used by the parser to error check input + */ + +typedef struct Mif_Param_Info_s { + + char *name; /* Name of this parameter */ + char *description; /* Description of this parameter */ + Mif_Data_Type_t type; /* Is this a real, boolean, string, ... */ + Mif_Boolean_t has_default; /* True if there is a default value */ + Mif_Parse_Value_t default_value; /* The default value */ + Mif_Boolean_t has_lower_limit; /* True if there is a lower limit */ + Mif_Parse_Value_t lower_limit; /* The lower limit for this parameter */ + Mif_Boolean_t has_upper_limit; /* True if there is a upper limit */ + Mif_Parse_Value_t upper_limit; /* The upper limit for this parameter */ + Mif_Boolean_t is_array; /* True if parameter is an array */ + Mif_Boolean_t has_conn_ref; /* True if parameter is associated with a connector */ + int conn_ref; /* The subscript of the associated connector */ + Mif_Boolean_t has_lower_bound; /* True if there is an array size lower bound */ + int lower_bound; /* Array size lower bound */ + Mif_Boolean_t has_upper_bound; /* True if there is an array size upper bound */ + int upper_bound; /* Array size upper bound */ + Mif_Boolean_t null_allowed; /* True if null is allowed for this parameter */ + +} Mif_Param_Info_t; + + + + +/* + * Information about an instance parameter used by the parser to error check input + */ + +typedef struct Mif_Inst_Var_Info_s { + + char *name; /* Name of this instance var */ + char *description; /* Description of this instance var */ + Mif_Data_Type_t type; /* Is this a real, boolean, string, ... */ + Mif_Boolean_t is_array; /* True if instance var is an array */ + +} Mif_Inst_Var_Info_t; + + +#endif /* MIFPARSE */ diff --git a/src/include/mifproto.h b/src/include/mifproto.h new file mode 100755 index 000000000..924cbed5f --- /dev/null +++ b/src/include/mifproto.h @@ -0,0 +1,157 @@ +#ifndef MIFPROTO +#define MIFPROTO + +/* =========================================================================== +FILE MIFproto.h + +MEMBER OF process XSPICE + +Copyright 1991 +Georgia Tech Research Corporation +Atlanta, Georgia 30332 +All Rights Reserved + +PROJECT A-8503 + +AUTHORS + + 9/12/91 Bill Kuhn + +MODIFICATIONS + + + +SUMMARY + + This file contains ANSI C function prototypes for functions in the + MIF package. + +INTERFACES + + None. + +REFERENCED FILES + + None. + +NON-STANDARD FEATURES + + None. + +=========================================================================== */ + + + +#include "ifsim.h" +#include "inpdefs.h" +#include "smpdefs.h" +#include "cktdefs.h" +#include "miftypes.h" + + + +extern void MIF_INP2A( + void *ckt, /* circuit structure to put mod/inst structs in */ + INPtables *tab, /* symbol table for node names, etc. */ + card *current /* the card we are to parse */ +); + + +extern char * MIFgetMod( + void *ckt, + char *name, + INPmodel **model, + INPtables *tab +); + + +extern IFvalue * MIFgetValue( + void *ckt, + char **line, + int type, + INPtables *tab, + char **err +); + + +extern int MIFsetup( + SMPmatrix *matrix, + GENmodel *inModel, + CKTcircuit *ckt, + int *state +); + +extern int MIFload( + GENmodel *inModel, + CKTcircuit *ckt +); + + +extern int MIFmParam( + int param_index, + IFvalue *value, + GENmodel *inModel +); + +extern int MIFask( + CKTcircuit *ckt, + GENinstance *inst, + int param_index, + IFvalue *value, + IFvalue *select +); + +extern int MIFmAsk( + CKTcircuit *ckt, + GENmodel *inModel, + int param_index, + IFvalue *value +); + +extern int MIFtrunc( + GENmodel *inModel, + CKTcircuit *ckt, + double *timeStep +); + +extern int MIFconvTest( + GENmodel *inModel, + CKTcircuit *ckt +); + +extern int MIFdelete( + GENmodel *inModel, + IFuid name, + GENinstance **inst +); + +extern int MIFmDelete( + GENmodel **inModel, + IFuid modname, + GENmodel *model +); + +extern void MIFdestroy( + GENmodel **inModel +); + +extern char *MIFgettok( + char **s +); + + +extern char *MIFget_token( + char **s, + Mif_Token_Type_t *type +); + + +extern Mif_Cntl_Src_Type_t MIFget_cntl_src_type( + Mif_Port_Type_t in_port_type, + Mif_Port_Type_t out_port_type +); + +extern char *MIFcopy(char *); + + +#endif /* MIFPROTO */ diff --git a/src/include/miftypes.h b/src/include/miftypes.h new file mode 100755 index 000000000..95c5ab5a6 --- /dev/null +++ b/src/include/miftypes.h @@ -0,0 +1,226 @@ +#ifndef MIFTYPES +#define MIFTYPES + +/* =========================================================================== +FILE MIFtypes.h + +MEMBER OF process XSPICE + +Copyright 1991 +Georgia Tech Research Corporation +Atlanta, Georgia 30332 +All Rights Reserved + +PROJECT A-8503 + +AUTHORS + + 9/12/91 Bill Kuhn + +MODIFICATIONS + + + +SUMMARY + + This file contains typedefs shared by several header files in + the MIF package. + +INTERFACES + + None. + +REFERENCED FILES + + None. + +NON-STANDARD FEATURES + + None. + +=========================================================================== */ + + + + +/* ***************************************************************************** */ + + +typedef int Mif_Boolean_t; + +#define MIF_FALSE 0 +#define MIF_TRUE 1 + + +typedef int Mif_Status_t; + +#define MIF_OK 0 +#define MIF_ERROR 1 + +/* +typedef enum { + MIF_OK, + MIF_ERROR, +} Mif_Status_t; +*/ + + +/* ***************************************************************************** */ + + +/* + * The type of call to a code model - analog or event-driven + */ + +typedef enum { + MIF_ANALOG, /* Analog call */ + MIF_EVENT_DRIVEN, /* Event-driven call */ +} Mif_Call_Type_t; + + + +/* + * Analysis type enumerations + */ + +typedef enum { + MIF_DC, /* A DC or DCOP analysis */ + MIF_AC, /* A swept AC analysis */ + MIF_TRAN, /* A transient analysis */ +} Mif_Analysis_t; + + + +/* + * Port type enumerations + */ + +typedef enum { + MIF_VOLTAGE, /* v - Single-ended voltage */ + MIF_DIFF_VOLTAGE, /* vd - Differential voltage */ + MIF_CURRENT, /* i - Single-ended current */ + MIF_DIFF_CURRENT, /* id - Differential current */ + MIF_VSOURCE_CURRENT, /* vnam - Voltage source current */ + MIF_CONDUCTANCE, /* g - Single-ended VCIS */ + MIF_DIFF_CONDUCTANCE, /* gd - Differential VCIS */ + MIF_RESISTANCE, /* h - Single-ended ICVS */ + MIF_DIFF_RESISTANCE, /* hd - Differential ICVS */ + MIF_DIGITAL, /* d - Digital */ + MIF_USER_DEFINED, /* - Any user defined type */ +} Mif_Port_Type_t; + + + +/* + * The direction of a connector + */ + +typedef enum { + MIF_IN, /* Input only */ + MIF_OUT, /* Output only */ + MIF_INOUT, /* Input and output (e.g. g or h type) */ +} Mif_Dir_t; + + + +/* + * The type of a parameter + */ + +typedef enum { + + MIF_BOOLEAN, + MIF_INTEGER, + MIF_REAL, + MIF_COMPLEX, + MIF_STRING, + +} Mif_Data_Type_t; + + + +/* + * The type of a token + */ + +typedef enum { + + MIF_LARRAY_TOK, + MIF_RARRAY_TOK, + MIF_LCOMPLEX_TOK, + MIF_RCOMPLEX_TOK, + MIF_PERCENT_TOK, + MIF_TILDE_TOK, + MIF_STRING_TOK, + MIF_NULL_TOK, + MIF_NO_TOK, + +} Mif_Token_Type_t; + + + +/* + * Type of controlled source + */ + +typedef enum { + MIF_VCVS, + MIF_VCIS, + MIF_ICVS, + MIF_ICIS, +} Mif_Cntl_Src_Type_t; + + +/* ***************************************************************************** */ + + +/* + * Complex numbers + */ + +typedef struct { + + double real; + double imag; + +} Mif_Complex_t; + + + +/* + * Values of different types used by the load, ... routines + */ + +typedef union { + + Mif_Boolean_t bvalue; /* For digital node value */ + int ivalue; /* For integer parameters */ + double rvalue; /* For spice node values and real parameters */ + Mif_Complex_t cvalue; /* For complex parameters */ + char *svalue; /* For string parameters */ + void *pvalue; /* For user defined nodes */ + +} Mif_Value_t; + + + + +/* + * Values of different types used by the parser. Note that this is a structure + * instead of a union because we need to do initializations in the ifspec.c files for + * the models and unions cannot be initialized in any useful way in C + * + */ + +typedef struct { + + Mif_Boolean_t bvalue; /* For boolean values */ + int ivalue; /* For integer values */ + double rvalue; /* For real values */ + Mif_Complex_t cvalue; /* For complex values */ + char *svalue; /* For string values */ + +} Mif_Parse_Value_t; + + +#endif /* MIFTYPES */ diff --git a/src/include/multi_line.h b/src/include/multi_line.h new file mode 100644 index 000000000..7edf9dbab --- /dev/null +++ b/src/include/multi_line.h @@ -0,0 +1,66 @@ +/* + * project.h + * + * Diagonalization by Successive Rotations Method + * (The Jacobi Method) + * + * Date: October 4, 1991 + * + * Author: Shen Lin + * + * Copyright (C) University of California, Berkeley + * + */ + +/************************************************************ + * + * Macros + * + ************************************************************/ + +#ifndef MAX +#define MAX(x, y) ((x) > (y) ? (x) : (y)) +#endif +#ifndef MIN +#define MIN(x, y) ((x) < (y) ? (x) : (y)) +#endif +#ifndef ABS +#define ABS(x) ((x) >= 0 ? (x) : (-(x))) +#endif +#ifndef SGN +#define SGN(x) ((x) >= 0 ? (1.0) : (-1.0)) +#endif + +/************************************************************ + * + * Defines + * + ************************************************************/ + +#define MAX_DIM 16 +#define Title "Diagonalization of a Symmetric matrix A (A = S^-1 D S)\n" +#define Left_deg 7 /* should be greater than or equal to 6 */ +#define Right_deg 2 + + +/************************************************************ + * + * Data Structure Definitions + * + ************************************************************/ + +typedef struct linked_list_of_max_entry{ + struct linked_list_of_max_entry *next; + int row, col; + float value; +} MAXE, *MAXE_PTR; + +typedef struct { + double *Poly[MAX_DIM]; + double C_0[MAX_DIM]; +} Mult_Out; + +typedef struct { + double *Poly; + double C_0; +} Single_Out; diff --git a/src/include/swec.h b/src/include/swec.h new file mode 100644 index 000000000..532741dfb --- /dev/null +++ b/src/include/swec.h @@ -0,0 +1,396 @@ +/* + * project.h + * + * Timing Simulator (ESWEC) + * + * Date: October 5, 1990 + * + * Author: Shen Lin + * + * Copyright (C) University of California, Berkeley + * + */ +#ifndef _SWEC_H_ +#define _SWEC_H_ + +/************************************************************ + * + * Defines + * + ************************************************************/ + +#define MainTitle " Timing Simulator\n" +#define MAXDEVICE 4 +#define MAXMOS 31500 /* suggested value */ +#define MAXDD 256 /* suggested value */ +#define MAXVCCS 128 /* suggested value */ +#define MAXTIME 1000000 +#define MAXNODE 136 + +#define TAB_SIZE 8192 /* originally 2048 */ +#define NUM_STEPS_PER_MICRON 10 /* 0.1 micron is the smallest step */ +#define MAX_FET_SIZE 80 /* largest fet in microns */ +#define Vol_Step 1.0e-3 /* voltage resolution */ +#define SCL 1000.0 /* voltage scaler (1V/3mv) */ +#define MAX_CP_TX_LINES 4 /* max number of coupled lines in + a multiconductor line system */ + +/************************************************************ + * + * Macro + * + ************************************************************/ +#ifndef MAX +#define MAX(x, y) ((x) > (y) ? (x) : (y)) +#endif +#ifndef MIN +#define MIN(x, y) ((x) < (y) ? (x) : (y)) +#endif +#ifndef ABS +#define ABS(x) ((x) >= 0 ? (x) : (-(x))) +#endif + +/************************************************************ + * + * Data Structure Definitions + * + ************************************************************/ + +typedef struct reglist REGLIST; +typedef struct node NODE; +typedef struct mosfet MOSFET; +typedef struct emosfet EMOSFET; +typedef struct diode DIODE; +typedef struct ediode EDIODE; +typedef struct vccs VCCS; +typedef struct evccs EVCCS; +typedef struct i_cap I_CAP; +typedef struct ei_cap EI_CAP; +typedef struct resistor RESISTOR; +typedef struct eresistor ERESISTOR; +typedef struct rline RLINE; +typedef struct erline ERLINE; +typedef struct txline TXLine; +typedef struct etxline ETXLine; +typedef struct cpline CPLine; +typedef struct ecpline ECPLine; +typedef struct bqueue BQUEUE; +typedef struct pqueue PQUEUE; +typedef struct ms_device MS_DEVICE; +typedef struct bp_device BP_DEVICE; +typedef struct dd_device DD_DEVICE; + +struct mosfet{ + int type; /* 1 : NMOS, 2 : PMOS */ + MS_DEVICE *device; /* NULL if the nominal device model */ + NODE *out_node; + NODE *in_node; + float Cs, Cd; + MOSFET *nx; + int time; /* instantaneous information */ + float voltage, dvg; /* instantaneous information */ + float vgN_1; /* gate voltage at previous event point */ + float G; /* effective conductance at t(n) */ + float effective; /* W over effective L */ + int tabW; /* width in ns/um */ + REGLIST *region; /* region associated with this mos */ + /* NULL if driven by the node of the same region */ +}; + +struct diode{ + float Is; /* saturation current */ + float Vj; /* junction potential */ + double G; + NODE *in_node; + NODE *out_node; + DIODE *nx; +}; + +struct vccs{ + float Is; /* saturation current */ + NODE *in_node; + NODE *out_node; + NODE *pcv_node; + NODE *ncv_node; + DIODE *nx; +}; + +typedef struct { + char name[10]; /* device name */ + int type; /* 1 : NMOS, 2 : PMOS */ + int device_id; /* device id */ +} DEVICENAME; + +struct ms_device{ + char name[10]; + int used; /* device used in circuit flag */ + float rho; /* device vsat denom param */ + float alpha; /* device vsat denom vgg param */ + float vt; /* device zero bias threshold voltage in mv*/ + float gamma; /* device backgate bias vt param */ + float fermi; /* device fermi potential in mv */ + float theta; /* device backgate bias vt width param */ + float mu; /* device vt width param */ + float eta; /* device saturation slope */ + float eta5; /* eta - 0.5 */ + int pzld; /* positive lambda */ + float lambda; /* channel-length modulation */ + float kp; /* device conductance parameter */ + float cgs0; /* gate-source overlap capacitance + per meter channel width */ + float cgd0; /* gate-drain overlap capacitance + per meter channel width */ + float cox; /* oxide-field capacitance + per square meter of gate area */ + float cjsw; /* zero-biased junction sidewall capacitace + per meter of junction perimeter */ + float cj0; /* zero-biased junction bottom capacitace + per square meter of junction area */ + float keq; /* abrupt junction parameter */ + + float ld; /* lateral diffusion */ + float *thresh; + float *sat; + float *dsat; + float *body; + float *gammod; +}; + +struct bp_device{ + char name[10]; + int type; /* 1 : NPN; 2 : PNP */ + float rc; /* collector resistance */ + float re; /* emitter resistance */ + float rb; /* zero bias base resistance */ + float Is; /* transport saturation current */ + float Af; /* ideal maximum forward alpha */ + float Ar; /* ideal maximum reverse alpha */ + float Vje; /* B-E built-in potential */ + float Vjc; /* B-C built-in potential */ +}; + +struct dd_device{ + char name[10]; + float Is; /* saturation current */ + float rs; /* ohmic resistance */ + float Vj; /* junction potential */ +}; + +typedef struct linked_lists_of_Bpoint{ + struct linked_lists_of_Bpoint *next; + int time; + float voltage; + float slope; +} BPOINT, *BPOINTPTR; + +typedef struct linked_lists_of_nodeName{ + char id[24]; + struct linked_lists_of_nodeName *left, *right; + NODE *nd; +} NDname, *NDnamePt; + +struct node { + NDnamePt name; + EMOSFET *mptr; /* pointer to head of src/drn MOSFET list */ + EMOSFET *gptr; /* pointer to head of gate MOSFET list */ + EI_CAP *cptr; /* pointer to head of internodal cap list */ + ERESISTOR *rptr; /* pointer to head of internodal resistor list */ + ERLINE *rlptr; /* pointer to head of internodal TX line list */ + ETXLine *tptr; /* pointer to head of transmission line list */ + ECPLine *cplptr; /* pointer to head of coupled lines list */ + EDIODE *ddptr; /* pointer to head of diode list */ + EVCCS *vccsptr; /* pointer to head of VCCS list */ + EVCCS *cvccsptr;/* pointer to head of controlled VCCS list */ + NODE *next; /* pointer to next node */ + REGLIST *region; /* region associated with this node */ + NODE *base_ptr; /* group src/drn nodes into region */ + /* charles 2,2 1/18/93 + float V; + float dv; voltage at t(n-1) and slope at t(n) + */ + double V; + double dv; + float CL; /* grounded capacitance in F */ + double gsum; /*^ sum of the equivalent conductance */ + double cgsum; /*^ sum of the constant conductance */ + double is; /*^ equivalent Is */ + int tag; /* -2 : Vdd, -3 : Vss, -1 : initial value */ + int flag; /*^ flag to show some features of the node */ + PQUEUE *qptr; /*^ pointer to the entry in the queue or waiting list */ + FILE *ofile; /* output file for the signal at this node */ + /* NULL if not for print */ + int dvtag; +}; + +struct reglist{ + REGLIST *rnxt; /* pointer to next region */ + NODE *nlist; /* node list */ + MOSFET *mos; + I_CAP *cap; + RESISTOR *res; + TXLine *txl; + CPLine *cpl; + struct linked_lists_of_Bpoint *Bpoint; /* break points at primary inputs */ + struct linked_lists_of_Bpoint *head; /* header of the break points at primary inputs */ + int eTime; /* time when this region previously evaluated */ + int DCvalue; + /* 1, 0, 2 : unknown, 3 : unchangeable 1, 4 : unchangeable 0 */ + BQUEUE *prediction; +}; + + +struct bqueue{ + int key; /* time for the event to be fired, or DC weight */ + BQUEUE *left; + BQUEUE *right; + BQUEUE *pred; + BQUEUE *pool; + REGLIST *region; /* region id */ +}; + +struct pqueue { + NODE *node; + PQUEUE *next; + PQUEUE *prev; +}; + +struct i_cap { + NODE *in_node; + NODE *out_node; + float cap; + I_CAP *nx; +}; + +struct resistor { + NODE *in_node; + NODE *out_node; + float g; /* conductance */ + int ifF; /* whether floating */ + float g1; /* conductance for floating resistor */ + RESISTOR *nx; +}; + +struct rline { + NODE *in_node; + NODE *out_node; + float g; /* conductance */ + RLINE *nx; +}; + +typedef struct linked_lists_of_vi_txl{ + struct linked_lists_of_vi_txl *next; + struct linked_lists_of_vi_txl *pool; + int time; + /* charles 2,2 + float v_i, v_o; + float i_i, i_o; + */ + double v_i, v_o; + double i_i, i_o; +} VI_list_txl; + +typedef struct linked_lists_of_vi{ + struct linked_lists_of_vi *next; + struct linked_lists_of_vi *pool; + int time; + float v_i[MAX_CP_TX_LINES], v_o[MAX_CP_TX_LINES]; + float i_i[MAX_CP_TX_LINES], i_o[MAX_CP_TX_LINES]; +} VI_list; + +typedef struct { + double c, x; + double cnv_i, cnv_o; +} TERM; + +typedef struct { + int ifImg; + double aten; + TERM tm[3]; +} TMS; + +struct cpline { + int noL; + int ext; + float ratio[MAX_CP_TX_LINES]; + float taul[MAX_CP_TX_LINES]; + TMS *h1t[MAX_CP_TX_LINES][MAX_CP_TX_LINES]; + TMS *h2t[MAX_CP_TX_LINES][MAX_CP_TX_LINES][MAX_CP_TX_LINES]; + TMS *h3t[MAX_CP_TX_LINES][MAX_CP_TX_LINES][MAX_CP_TX_LINES]; + double h1C[MAX_CP_TX_LINES][MAX_CP_TX_LINES]; + double h2C[MAX_CP_TX_LINES][MAX_CP_TX_LINES][MAX_CP_TX_LINES]; + double h3C[MAX_CP_TX_LINES][MAX_CP_TX_LINES][MAX_CP_TX_LINES]; + double h1e[MAX_CP_TX_LINES][MAX_CP_TX_LINES][3]; + NODE *in_node[MAX_CP_TX_LINES]; + NODE *out_node[MAX_CP_TX_LINES]; + int tag_i[MAX_CP_TX_LINES], tag_o[MAX_CP_TX_LINES]; + CPLine *nx; + struct linked_lists_of_vi *vi_head; + struct linked_lists_of_vi *vi_tail; + float dc1[MAX_CP_TX_LINES], dc2[MAX_CP_TX_LINES]; +}; + +struct txline { + int lsl; /* 1 if the line is lossless, otherwise 0 */ + int ext; /* a flag, set if time step is greater than tau */ + float ratio; + float taul; + double sqtCdL; + double h2_aten; + double h3_aten; + double h1C; + double h1e[3]; + int ifImg; + NODE *in_node; + NODE *out_node; + int tag_i, tag_o; + TERM h1_term[3]; + TERM h2_term[3]; + TERM h3_term[6]; + TXLine *nx; + struct linked_lists_of_vi_txl *vi_head; + struct linked_lists_of_vi_txl *vi_tail; + float dc1, dc2; + int newtp; /* flag indicating new time point */ +}; + +struct evccs { + VCCS *vccs; + EVCCS *link; +}; + +struct ediode { + DIODE *dd; + EDIODE *link; +}; + +struct emosfet { + MOSFET *mos; + EMOSFET *link; +}; + +struct ei_cap { + I_CAP *cap; + EI_CAP *link; +}; + +struct eresistor { + RESISTOR *res; + ERESISTOR *link; +}; + +struct erline { + RLINE *rl; + ERLINE *link; +}; + +struct etxline { + TXLine *line; + ETXLine *link; +}; + +struct ecpline { + CPLine *line; + ECPLine *link; +}; + +#endif diff --git a/src/spicelib/devices/cpl/Makefile.am b/src/spicelib/devices/cpl/Makefile.am new file mode 100755 index 000000000..eeba14549 --- /dev/null +++ b/src/spicelib/devices/cpl/Makefile.am @@ -0,0 +1,18 @@ +## Process this file with automake to produce Makefile.in + +noinst_LIBRARIES = libcpl.a + +libcpl_a_SOURCES = \ + cpl.c \ + cpldest.c \ + cplmdel.c \ + cplparam.c \ + cpldel.c \ + cplload.c \ + cplmpar.c \ + cplsetup.c \ + cplinit.c + +INCLUDES = -I$(top_srcdir)/src/include + +MAINTAINERCLEANFILES = Makefile.in diff --git a/src/spicelib/devices/cpl/cpl.c b/src/spicelib/devices/cpl/cpl.c new file mode 100644 index 000000000..4bb1aaf46 --- /dev/null +++ b/src/spicelib/devices/cpl/cpl.c @@ -0,0 +1,39 @@ +/********** +Copyright 1992 Regents of the University of California. All rights +reserved. +Author: 1992 Charles Hough +**********/ + +#include "ngspice.h" +#include +#include "cpldefs.h" +#include "devdefs.h" +#include "ifsim.h" +#include "suffix.h" + +IFparm CPLpTable[] = { + IOP("pos_nodes", CPL_POS_NODE, IF_VECTOR|IF_STRING, "in nodes"), + IOP("neg_nodes", CPL_NEG_NODE, IF_VECTOR|IF_STRING, "out nodes"), + IOP("dimension", CPL_DIM, IF_INTEGER, "number of coupled lines"), + IOP("length", CPL_LENGTH, IF_REAL, "length of lines"), +}; + +IFparm CPLmPTable[] = { /* model parameters */ + IOP( "r", CPL_R, IF_REALVEC,"resistance per length"), + IOP( "l", CPL_L, IF_REALVEC,"inductance per length"), + IOP( "c", CPL_C, IF_REALVEC,"capacitance per length"), + IOP( "g", CPL_G, IF_REALVEC,"conductance per length"), + IOP( "length", CPL_length, IF_REAL,"length"), + IP( "cpl", CPL_MOD_R, IF_FLAG,"Device is a cpl model"), +}; + +char *CPLnames[] = { + "P+", + "P-" +}; + +int CPLnSize = NUMELEMS(CPLnames); +int CPLiSize = sizeof(CPLinstance); +int CPLmSize = sizeof(CPLmodel); +int CPLmPTSize = NUMELEMS(CPLmPTable); +int CPLpTSize = NUMELEMS(CPLpTable); diff --git a/src/spicelib/devices/cpl/cpldefs.h b/src/spicelib/devices/cpl/cpldefs.h new file mode 100644 index 000000000..81aa5a0b3 --- /dev/null +++ b/src/spicelib/devices/cpl/cpldefs.h @@ -0,0 +1,97 @@ +#ifndef CPL +#define CPL + +#include "ifsim.h" +#include "cktdefs.h" +#include "gendefs.h" +#include "complex.h" +#include "noisedef.h" +#include "swec.h" + +/* information used to describe a single instance */ + +typedef struct sCPLinstance { + struct sCPLmodel *CPLmodPtr; /* backpointer to model */ + struct sCPLinstance *CPLnextInstance; /* pointer to next instance of + * current model*/ + + IFuid CPLname; /* pointer to character string naming this instance */ + + int dimension; + int *CPLposNodes; + int *CPLnegNodes; + double CPLlength; + int *CPLibr1; + int *CPLibr2; + CPLine *cplines; /* pointer to SWEC cplines type */ + CPLine *cplines2; /* temporary pointer to SWEC cplines type */ + + char **in_node_names; + char **out_node_names; + + double **CPLibr1Ibr1; + double **CPLibr2Ibr2; + double **CPLposIbr1; + double **CPLnegIbr2; + /* trial */ + double **CPLposPos; + double **CPLnegNeg; + double **CPLposNeg; + double **CPLnegPos; + + double ***CPLibr1Pos; + double ***CPLibr2Neg; + double ***CPLibr1Neg; + double ***CPLibr2Pos; + double ***CPLibr1Ibr2; + double ***CPLibr2Ibr1; + + unsigned CPLibr1Given : 1; + unsigned CPLibr2Given : 1; + unsigned CPLdcGiven : 1; + unsigned CPLlengthgiven : 1; + +} CPLinstance ; + + +/* per model data */ + +typedef struct sCPLmodel { /* model structure for a cpl */ + int CPLmodType; /* type index of this device type */ + struct sCPLmodel *CPLnextModel; /* pointer to next possible model in + * linked list */ + CPLinstance * CPLinstances; /* pointer to list of instances that have this + * model */ + IFuid CPLmodName; /* pointer to character string naming this model */ + + double *Rm; + double *Gm; + double *Lm; + double *Cm; + double length; + unsigned Rmgiven : 1; + unsigned Lmgiven : 1; + unsigned Gmgiven : 1; + unsigned Cmgiven : 1; + unsigned lengthgiven : 1; + +} CPLmodel; + +/* instance parameters */ +#define CPL_POS_NODE 1 +#define CPL_NEG_NODE 2 +#define CPL_DIM 3 +#define CPL_LENGTH 4 + +/* model parameters */ +#define CPL_R 101 +#define CPL_C 102 +#define CPL_G 103 +#define CPL_L 104 +#define CPL_length 105 +#define CPL_MOD_R 106 + +#include "cplext.h" +extern VI_list *pool_vi; + +#endif /*CPL*/ diff --git a/src/spicelib/devices/cpl/cpldel.c b/src/spicelib/devices/cpl/cpldel.c new file mode 100644 index 000000000..746811eaf --- /dev/null +++ b/src/spicelib/devices/cpl/cpldel.c @@ -0,0 +1,38 @@ +/********** +Copyright 1992 Regents of the University of California. All rights +reserved. +Author: 1992 Charles Hough +**********/ + + +#include "ngspice.h" +#include +#include "cpldefs.h" +#include "sperror.h" +#include "suffix.h" + + +int +CPLdelete(inModel,name,inst) + GENmodel *inModel; + IFuid name; + GENinstance **inst; +{ + CPLmodel *model = (CPLmodel *)inModel; + CPLinstance **fast = (CPLinstance **)inst; + CPLinstance **prev = NULL; + CPLinstance *here; + + for( ; model ; model = model->CPLnextModel) { + prev = &(model->CPLinstances); + for(here = *prev; here ; here = *prev) { + if(here->CPLname == name || (fast && here==*fast) ) { + *prev= here->CPLnextInstance; + FREE(here); + return(OK); + } + prev = &(here->CPLnextInstance); + } + } + return(E_NODEV); +} diff --git a/src/spicelib/devices/cpl/cpldest.c b/src/spicelib/devices/cpl/cpldest.c new file mode 100644 index 000000000..e0c6b46f6 --- /dev/null +++ b/src/spicelib/devices/cpl/cpldest.c @@ -0,0 +1,34 @@ +/********** +Copyright 1992 Regents of the University of California. All rights +reserved. +Author: 1992 Charles Hough +**********/ + +#include "ngspice.h" +#include +#include "cpldefs.h" +#include "suffix.h" + +void +CPLdestroy(inModel) + GENmodel **inModel; +{ + CPLmodel **model = (CPLmodel **)inModel; + CPLinstance *here; + CPLinstance *prev = NULL; + CPLmodel *mod = *model; + CPLmodel *oldmod = NULL; + + for( ; mod ; mod = mod->CPLnextModel) { + if(oldmod) FREE(oldmod); + oldmod = mod; + prev = (CPLinstance *)NULL; + for(here = mod->CPLinstances ; here ; here = here->CPLnextInstance) { + if(prev) FREE(prev); + prev = here; + } + if(prev) FREE(prev); + } + if(oldmod) FREE(oldmod); + *model = NULL; +} diff --git a/src/spicelib/devices/cpl/cplext.h b/src/spicelib/devices/cpl/cplext.h new file mode 100644 index 000000000..bc96eb61b --- /dev/null +++ b/src/spicelib/devices/cpl/cplext.h @@ -0,0 +1,19 @@ +#ifdef __STDC__ +/* extern int CPLaccept(CKTcircuit*,GENmodel*); */ +extern int CPLdelete(GENmodel*,IFuid,GENinstance**); +extern void CPLdestroy(GENmodel**); +extern int CPLload(GENmodel*,CKTcircuit*); +extern int CPLmDelete(GENmodel**,IFuid,GENmodel*); +extern int CPLmParam(int,IFvalue*,GENmodel*); +extern int CPLparam(int,IFvalue*,GENinstance*,IFvalue*); +extern int CPLsetup(SMPmatrix*,GENmodel*,CKTcircuit*,int*); +#else /* stdc */ +/* extern int CPLaccept(); */ +extern int CPLdelete(); +extern void CPLdestroy(); +extern int CPLload(); +extern int CPLmDelete(); +extern int CPLmParam(); +extern int CPLparam(); +extern int CPLsetup(); +#endif /* stdc */ diff --git a/src/spicelib/devices/cpl/cplinit.c b/src/spicelib/devices/cpl/cplinit.c new file mode 100644 index 000000000..d9891f9a4 --- /dev/null +++ b/src/spicelib/devices/cpl/cplinit.c @@ -0,0 +1,84 @@ +#include + +#include + +#include "cplitf.h" +#include "cplext.h" +#include "cplinit.h" + +SPICEdev CPLinfo = { + { + "CplLines", + "Simple Coupled Multiconductor Lines", + + &CPLnSize, + &CPLnSize, + CPLnames, + + &CPLpTSize, + CPLpTable, + + &CPLmPTSize, + CPLmPTable, + +#ifdef XSPICE +/*---- Fixed by SDB 5.2.2003 to enable XSPICE/tclspice integration -----*/ + NULL, /* This is a SPICE device, it has no MIF info data */ + + 0, /* This is a SPICE device, it has no MIF info data */ + NULL, /* This is a SPICE device, it has no MIF info data */ + + 0, /* This is a SPICE device, it has no MIF info data */ + NULL, /* This is a SPICE device, it has no MIF info data */ + + 0, /* This is a SPICE device, it has no MIF info data */ + NULL, /* This is a SPICE device, it has no MIF info data */ +/*--------------------------- End of SDB fix -------------------------*/ +#endif + + 0 + }, + + CPLparam, + CPLmParam, + CPLload, + CPLsetup, + NULL, + NULL, + NULL, + NULL, + NULL, /* CPLfindBranch, */ + NULL, + NULL, + CPLdestroy, +#ifdef DELETES + CPLmDelete, + CPLdelete, +#else /* DELETES */ + NULL, + NULL, +#endif /* DELETES */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + &CPLiSize, + &CPLmSize + +}; + +SPICEdev * +get_cpl_info(void) +{ + return &CPLinfo; +} diff --git a/src/spicelib/devices/cpl/cplinit.h b/src/spicelib/devices/cpl/cplinit.h new file mode 100644 index 000000000..17f4a5b24 --- /dev/null +++ b/src/spicelib/devices/cpl/cplinit.h @@ -0,0 +1,13 @@ +#ifndef _CPLINIT_H +#define _CPLINIT_H + +extern IFparm CPLpTable[ ]; +extern IFparm CPLmPTable[ ]; +extern int CPLmPTSize; +extern int CPLpTSize; +extern char *CPLnames[ ]; +extern int CPLiSize; +extern int CPLmSize; +extern int CPLnSize; + +#endif diff --git a/src/spicelib/devices/cpl/cplitf.h b/src/spicelib/devices/cpl/cplitf.h new file mode 100644 index 000000000..4a690f024 --- /dev/null +++ b/src/spicelib/devices/cpl/cplitf.h @@ -0,0 +1,6 @@ +#ifndef DEV_CPL +#define DEV_CPL + +SPICEdev *get_cpl_info(void); + +#endif diff --git a/src/spicelib/devices/cpl/cplload.c b/src/spicelib/devices/cpl/cplload.c new file mode 100644 index 000000000..5b502fe5e --- /dev/null +++ b/src/spicelib/devices/cpl/cplload.c @@ -0,0 +1,890 @@ +/********** +Copyright 1992 Regents of the University of California. All rights +reserved. +Author: 1992 Charles Hough +**********/ + + +#include "ngspice.h" +#include +#include "cpldefs.h" +#include "sperror.h" +#include "suffix.h" + +VI_list *pool_vi; +static double ratio[MAX_CP_TX_LINES]; +static VI_list *new_vi(); +static void free_vi(); +static int get_pvs_vi(); +static int update_cnv(); +static int add_new_vi(); +static int right_consts(); +static int update_delayed_cnv(); +static int multC(); +static int expC(); +static int divC(); +static void update_cnv_a(); +static void copy_cp(); + + +/*ARGSUSED*/ +int +CPLload(inModel,ckt) + GENmodel *inModel; + CKTcircuit *ckt; +{ + register CPLmodel *model = (CPLmodel *)inModel; + register CPLinstance *here; + CPLine *cp, *cp2; + int *k, *l; + int time, time2; + double h, h1, f; + int hint; + float hf; + NODE *nd; + double v, v1, g; + int cond1, i; + int noL, m, p, q; + CKTnode *node; + VI_list *vi, *vi_before; + int before, delta; + int resindex; + + + h = ckt->CKTdelta; + h1 = 0.5 * h; + time2 = (int) (ckt->CKTtime * 1e12); + hint = (int)(h * 1e12); + hf = (float)(h * 1e12); + time = (int) ((ckt->CKTtime - ckt->CKTdelta) * 1e12); + + cond1= ckt->CKTmode & MODEDC; + + for( ; model != NULL; model = model->CPLnextModel ) { + for (here = model->CPLinstances; here != NULL ; + here=here->CPLnextInstance) { + + cp = here->cplines; + if (cond1 || cp->vi_head == NULL) continue; + + noL = cp->noL = here->dimension; + if (cp->vi_tail->time > time) { + time = cp->vi_tail->time; + hint = time2 - time; + } + + before = cp->vi_tail->time; + vi_before = cp->vi_tail; + + if (time > cp->vi_tail->time) { + + copy_cp(cp, here->cplines2); + add_new_vi(here, ckt, time); + delta = time - before; + + for (m = 0; m < noL; m++) { + nd = cp->in_node[m]; + v = vi_before->v_i[m]; + v1 = nd->V = cp->vi_tail->v_i[m]; + nd->dv = (v1 - v) / delta; + } + for (m = 0; m < noL; m++) { + nd = cp->out_node[m]; + v = vi_before->v_o[m]; + v1 = nd->V = cp->vi_tail->v_o[m]; + nd->dv = (v1 - v) / delta; + } + + update_cnv(cp, (float)delta); + if (cp->ext) update_delayed_cnv(cp, (float)delta); + } + } + } + + model = (CPLmodel *)inModel; + /* loop through all the models */ + for( ; model != NULL; model = model->CPLnextModel ) { + + /* loop through all the instances of the model */ + for (here = model->CPLinstances; here != NULL ; + here=here->CPLnextInstance) { + + double mintaul = 123456789.0; + + cp = here->cplines; + cp2 = here->cplines2; + + for (i = 0; i < cp->noL; i++) { + if (mintaul > cp->taul[i]) mintaul = cp->taul[i]; + } + if (mintaul < hf) { + + fprintf(stderr, "your time step is too large for tau.\n"); + fprintf(stderr, "please decrease max time step in .tran card.\n"); + fprintf(stderr, ".tran tstep tstop tstart tmax.\n"); + fprintf(stderr, "make tmax smaller than %e and try again.\n", + mintaul * 1e-12); + + return (1111); + + } + + noL = cp->noL = here->dimension; + if (cond1) { + resindex = 0; + for (m = 0; m < noL; m++) { + if (here->CPLlengthgiven) + g = model->Rm[resindex] * here->CPLlength; + else g = model->Rm[resindex] * here->CPLmodPtr->length; + *(here->CPLposIbr1[m]) += 1.0; + *(here->CPLnegIbr2[m]) += 1.0; + *(here->CPLibr1Ibr1[m]) += 1.0; + *(here->CPLibr1Ibr2[m][m]) += 1.0; + *(here->CPLibr2Pos[m][m]) += 1.0; + *(here->CPLibr2Neg[m][m]) -= 1.0; + *(here->CPLibr2Ibr1[m][m]) -= g; + resindex = resindex + noL - m; + } + continue; + } + + /* dc setup */ + if (here->CPLdcGiven == 0 && !cond1) { + for (i = 0; i < cp->noL; i++) { + nd = cp->in_node[i]; + for(node = ckt->CKTnodes;node; node = node->next) { + if (strcmp(nd->name->id, node->name) == 0) { + cp->dc1[i] = ckt->CKTrhsOld[node->number]; + cp2->dc1[i] = nd->V = cp->dc1[i]; + break; + } + } + nd = cp->out_node[i]; + for(node = ckt->CKTnodes;node; node = node->next) { + if (strcmp(nd->name->id, node->name) == 0) { + cp->dc2[i] = ckt->CKTrhsOld[node->number]; + cp2->dc2[i] = nd->V = cp->dc2[i]; + break; + } + } + } + here->CPLdcGiven = 1; + + vi = new_vi(); + vi->time = 0; + { + int i, j, k, l; + for (i = 0; i < cp->noL; i++) { + for (j = 0; j < cp->noL; j++) { + TMS *tms; + double a, b; + + tms = cp->h1t[i][j]; + if (tms->ifImg) { + tms->tm[0].cnv_i = - cp->dc1[j] * + tms->tm[0].c / tms->tm[0].x; + tms->tm[0].cnv_o = - cp->dc2[j] * + tms->tm[0].c / tms->tm[0].x; + divC(tms->tm[1].c, tms->tm[2].c, + tms->tm[1].x, tms->tm[2].x, &a, &b); + tms->tm[1].cnv_i = - cp->dc1[j] * a; + tms->tm[1].cnv_o = - cp->dc2[j] * a; + tms->tm[2].cnv_i = - cp->dc1[j] * b; + tms->tm[2].cnv_o = - cp->dc2[j] * b; + } else + for (k = 0; k < 3; k++) { + tms->tm[k].cnv_i = - cp->dc1[j] * + tms->tm[k].c / tms->tm[k].x; + tms->tm[k].cnv_o = - cp->dc2[j] * + tms->tm[k].c / tms->tm[k].x; + } + + for (l = 0; l < cp->noL; l++) { + tms = cp->h2t[i][j][l]; + for (k = 0; k < 3; k++) { + tms->tm[k].cnv_i = 0.0; + tms->tm[k].cnv_o = 0.0; + } + } + for (l = 0; l < cp->noL; l++) { + tms = cp->h3t[i][j][l]; + if (tms->ifImg) { + tms->tm[0].cnv_i = - cp->dc1[j] * + tms->tm[0].c / tms->tm[0].x; + tms->tm[0].cnv_o = - cp->dc2[j] * + tms->tm[0].c / tms->tm[0].x; + divC(tms->tm[1].c, tms->tm[2].c, + tms->tm[1].x, tms->tm[2].x, &a, &b); + tms->tm[1].cnv_i = - cp->dc1[j] * a; + tms->tm[1].cnv_o = - cp->dc2[j] * a; + tms->tm[2].cnv_i = - cp->dc1[j] * b; + tms->tm[2].cnv_o = - cp->dc2[j] * b; + } else + for (k = 0; k < 3; k++) { + tms->tm[k].cnv_i = - cp->dc1[j] * + tms->tm[k].c / tms->tm[k].x; + tms->tm[k].cnv_o = - cp->dc2[j] * + tms->tm[k].c / tms->tm[k].x; + } + } + } + + for (i = 0; i < cp->noL; i++) { + vi->i_i[i] = vi->i_o[i] = 0.0; + vi->v_i[i] = cp->dc1[i]; + vi->v_o[i] = cp->dc2[i]; + } + } + + vi->next = NULL; + cp->vi_tail = vi; + cp->vi_head = vi; + cp2->vi_tail = vi; + cp2->vi_head = vi; + + } + } + + for (m = 0; m < noL; m++) { + *(here->CPLibr1Ibr1[m]) = -1.0; + *(here->CPLibr2Ibr2[m]) = -1.0; + } + + for (m = 0; m < noL; m++) { + *(here->CPLposIbr1[m]) = 1.0; + *(here->CPLnegIbr2[m]) = 1.0; + } + + for (m = 0; m < noL; m++) { + for (p = 0; p < noL; p++) { + *(here->CPLibr1Pos[m][p]) = + cp->h1t[m][p]->aten + h1 * cp->h1C[m][p]; + *(here->CPLibr2Neg[m][p]) = + cp->h1t[m][p]->aten + h1 * cp->h1C[m][p]; + } + } + + k = here->CPLibr1; + l = here->CPLibr2; + + copy_cp(cp2, cp); + + if (right_consts(here,cp2, time,time2,h,h1,k,l,ckt)) { + cp2->ext = 1; + for (q = 0; q < noL; q++) { + cp->ratio[q] = ratio[q]; + if (ratio[q] > 0.0) { + for (m = 0; m < noL; m++) { + for (p = 0; p < noL; p++) { + + + if (cp->h3t[m][p][q]) { + f = ratio[q] * (h1 * cp->h3C[m][p][q] + + cp->h3t[m][p][q]->aten); + *(here->CPLibr1Neg[m][p]) = -f; + *(here->CPLibr2Pos[m][p]) = -f; + } + if (cp->h2t[m][p][q]) { + f = ratio[q] * (h1 * cp->h2C[m][p][q] + + cp->h2t[m][p][q]->aten); + *(here->CPLibr1Ibr2[m][p]) = -f; + *(here->CPLibr2Ibr1[m][p]) = -f; + } + + } + } + } + } + } + else cp->ext = 0; + } + } + + return(OK); +} + +static void +copy_cp(new, old) +CPLine *new, *old; +{ + int i, j, k, l, m; + VI_list *temp; + + new->noL = m = old->noL; + new->ext = old->ext; + for (i = 0; i < m; i++) { + new->ratio[i] = old->ratio[i]; + new->taul[i] = old->taul[i]; + + for (j = 0; j < m; j++) { + if (new->h1t[i][j] == NULL) + new->h1t[i][j] = (TMS *) malloc(sizeof (TMS)); + new->h1t[i][j]->ifImg = old->h1t[i][j]->ifImg; + new->h1t[i][j]->aten = old->h1t[i][j]->aten; + new->h1C[i][j] = old->h1C[i][j]; + + for (k = 0; k < 3; k++) { + new->h1t[i][j]->tm[k].c = old->h1t[i][j]->tm[k].c; + new->h1t[i][j]->tm[k].x = old->h1t[i][j]->tm[k].x; + new->h1t[i][j]->tm[k].cnv_i = old->h1t[i][j]->tm[k].cnv_i; + new->h1t[i][j]->tm[k].cnv_o = old->h1t[i][j]->tm[k].cnv_o; + new->h1e[i][j][k] = old->h1e[i][j][k]; + } + for (l = 0; l < m; l++) { + if (new->h2t[i][j][l] == NULL) + new->h2t[i][j][l] = (TMS *) malloc(sizeof (TMS)); + new->h2t[i][j][l]->ifImg = old->h2t[i][j][l]->ifImg; + new->h2t[i][j][l]->aten = old->h2t[i][j][l]->aten; + new->h2C[i][j][l] = old->h2C[i][j][l]; + new->h3C[i][j][l] = old->h3C[i][j][l]; + for (k = 0; k < 3; k++) { + new->h2t[i][j][l]->tm[k].c = old->h2t[i][j][l]->tm[k].c; + new->h2t[i][j][l]->tm[k].x = old->h2t[i][j][l]->tm[k].x; + new->h2t[i][j][l]->tm[k].cnv_i + = old->h2t[i][j][l]->tm[k].cnv_i; + new->h2t[i][j][l]->tm[k].cnv_o + = old->h2t[i][j][l]->tm[k].cnv_o; + } + + if (new->h3t[i][j][l] == NULL) + new->h3t[i][j][l] = (TMS *) malloc(sizeof (TMS)); + new->h3t[i][j][l]->ifImg = old->h3t[i][j][l]->ifImg; + new->h3t[i][j][l]->aten = old->h3t[i][j][l]->aten; + for (k = 0; k < 3; k++) { + new->h3t[i][j][l]->tm[k].c = old->h3t[i][j][l]->tm[k].c; + new->h3t[i][j][l]->tm[k].x = old->h3t[i][j][l]->tm[k].x; + new->h3t[i][j][l]->tm[k].cnv_i + = old->h3t[i][j][l]->tm[k].cnv_i; + new->h3t[i][j][l]->tm[k].cnv_o + = old->h3t[i][j][l]->tm[k].cnv_o; + } + } + } + } + + while (new->vi_head->time < old->vi_head->time) { + temp = new->vi_head; + new->vi_head = new->vi_head->next; + free_vi(temp); + } +} + + +static int +right_consts(here, cp, t, time, h, h1, l1, l2, ckt) +CPLinstance *here; +CPLine *cp; +int t, time; +double h, h1; +int *l1, *l2; +CKTcircuit *ckt; +{ + int i, j, k, l; + double e; + double ff[MAX_CP_TX_LINES], gg[MAX_CP_TX_LINES]; + double v1_i[MAX_CP_TX_LINES][MAX_CP_TX_LINES]; + double v2_i[MAX_CP_TX_LINES][MAX_CP_TX_LINES]; + double i1_i[MAX_CP_TX_LINES][MAX_CP_TX_LINES]; + double i2_i[MAX_CP_TX_LINES][MAX_CP_TX_LINES]; + double v1_o[MAX_CP_TX_LINES][MAX_CP_TX_LINES]; + double v2_o[MAX_CP_TX_LINES][MAX_CP_TX_LINES]; + double i1_o[MAX_CP_TX_LINES][MAX_CP_TX_LINES]; + double i2_o[MAX_CP_TX_LINES][MAX_CP_TX_LINES]; + int ext; + register int noL; + + noL = cp->noL; + + for (j = 0; j < noL; j++) { + register double ff1; + + ff[j] = 0.0; + gg[j] = 0.0; + for (k = 0; k < noL; k++) + if (cp->h1t[j][k]) { + if (cp->h1t[j][k]->ifImg) { + double er, ei, a, b, a1, b1; + TMS *tms; + tms = cp->h1t[j][k]; + cp->h1e[j][k][0] = e = exp((double) tms->tm[0].x * h); + expC(tms->tm[1].x, tms->tm[2].x, h, &er, &ei); + cp->h1e[j][k][1] = er; + cp->h1e[j][k][2] = ei; + + ff1 = tms->tm[0].c * e * h1; + ff[j] -= tms->tm[0].cnv_i * e; + gg[j] -= tms->tm[0].cnv_o * e; + ff[j] -= ff1 * cp->in_node[k]->V; + gg[j] -= ff1 * cp->out_node[k]->V; + + multC(tms->tm[1].c, tms->tm[2].c, er, ei, &a1, &b1); + multC(tms->tm[1].cnv_i, tms->tm[2].cnv_i, er, ei, &a, &b); + ff[j] -= 2.0 * (a1 * h1 * cp->in_node[k]->V + a); + multC(tms->tm[1].cnv_o, tms->tm[2].cnv_o, er, ei, &a, &b); + gg[j] -= 2.0 * (a1 * h1 * cp->out_node[k]->V + a); + } else { + ff1 = 0.0; + for (i = 0; i < 3; i++) { + cp->h1e[j][k][i] = e = exp((double) cp->h1t[j][k]->tm[i].x * h); + ff1 -= cp->h1t[j][k]->tm[i].c * e; + ff[j] -= cp->h1t[j][k]->tm[i].cnv_i * e; + gg[j] -= cp->h1t[j][k]->tm[i].cnv_o * e; + } + ff[j] += ff1 * h1 * cp->in_node[k]->V; + gg[j] += ff1 * h1 * cp->out_node[k]->V; + } + } + } + + ext = get_pvs_vi(t, time, cp, v1_i, v2_i, i1_i, i2_i, + v1_o, v2_o, i1_o, i2_o); + + for (j = 0; j < noL; j++) { /** current eqn **/ + register TERM *tm; + + for (k = 0; k < noL; k++) /** node voltage **/ + for (l = 0; l < noL; l++) /** different mode **/ + if (cp->h3t[j][k][l]) { + if (cp->h3t[j][k][l]->ifImg) { + double er, ei, a, b, a1, b1, a2, b2; + register TMS *tms; + tms = cp->h3t[j][k][l]; + expC(tms->tm[1].x, tms->tm[2].x, h, &er, &ei); + a2 = h1 * tms->tm[1].c; + b2 = h1 * tms->tm[2].c; + a = tms->tm[1].cnv_i; + b = tms->tm[2].cnv_i; + multC(a, b, er, ei, &a, &b); + multC(a2, b2, (double) v1_i[l][k] * er + v2_i[l][k], (double) v1_i[l][k] * ei, &a1, &b1); + tms->tm[1].cnv_i = a + a1; + tms->tm[2].cnv_i = b + b1; + a = tms->tm[1].cnv_o; + b = tms->tm[2].cnv_o; + multC(a, b, er, ei, &a, &b); + multC(a2, b2, (double) v1_o[l][k] * er + v2_o[l][k], (double) v1_o[l][k] * ei, &a1, &b1); + tms->tm[1].cnv_o = a + a1; + tms->tm[2].cnv_o = b + b1; + tm = &(tms->tm[0]); + e = exp((double) tm->x * h); + tm->cnv_i = tm->cnv_i * e + h1 * tm->c * + (v1_i[l][k] * e + v2_i[l][k]); + tm->cnv_o = tm->cnv_o * e + h1 * tm->c * + (v1_o[l][k] * e + v2_o[l][k]); + ff[j] += tms->aten * v2_o[l][k] + tm->cnv_o + + 2.0 * tms->tm[1].cnv_o; + gg[j] += tms->aten * v2_i[l][k] + tm->cnv_i + + 2.0 * tms->tm[1].cnv_i; + } else { + for (i = 0; i < 3; i++) { /** 3 poles **/ + tm = &(cp->h3t[j][k][l]->tm[i]); + e = exp((double) tm->x * h); + tm->cnv_i = tm->cnv_i * e + h1 * tm->c * (v1_i[l][k] * e + v2_i[l][k]); + tm->cnv_o = tm->cnv_o * e + h1 * tm->c * (v1_o[l][k] * e + v2_o[l][k]); + ff[j] += tm->cnv_o; + gg[j] += tm->cnv_i; + } + + ff[j] += cp->h3t[j][k][l]->aten * v2_o[l][k]; + gg[j] += cp->h3t[j][k][l]->aten * v2_i[l][k]; + } + } + for (k = 0; k < noL; k++) /** line current **/ + for (l = 0; l < noL; l++) /** different mode **/ + if (cp->h2t[j][k][l]) { + if (cp->h2t[j][k][l]->ifImg) { + double er, ei, a, b, a1, b1, a2, b2; + register TMS *tms; + tms = cp->h2t[j][k][l]; + expC(tms->tm[1].x, tms->tm[2].x, h, &er, &ei); + a2 = h1 * tms->tm[1].c; + b2 = h1 * tms->tm[2].c; + a = tms->tm[1].cnv_i; + b = tms->tm[2].cnv_i; + multC(a, b, er, ei, &a, &b); + multC(a2, b2, (double) i1_i[l][k] * er + i2_i[l][k], (double) i1_i[l][k] * ei, &a1, &b1); + tms->tm[1].cnv_i = a + a1; + tms->tm[2].cnv_i = b + b1; + a = tms->tm[1].cnv_o; + b = tms->tm[2].cnv_o; + multC(a, b, er, ei, &a, &b); + multC(a2, b2, (double) i1_o[l][k] * er + i2_o[l][k], (double) i1_o[l][k] * ei, &a1, &b1); + tms->tm[1].cnv_o = a + a1; + tms->tm[2].cnv_o = b + b1; + tm = &(tms->tm[0]); + e = exp((double) tm->x * h); + tm->cnv_i = tm->cnv_i * e + h1 * tm->c * + (i1_i[l][k] * e + i2_i[l][k]); + tm->cnv_o = tm->cnv_o * e + h1 * tm->c * + (i1_o[l][k] * e + i2_o[l][k]); + ff[j] += tms->aten * i2_o[l][k] + tm->cnv_o + + 2.0 * tms->tm[1].cnv_o; + gg[j] += tms->aten * i2_i[l][k] + tm->cnv_i + + 2.0 * tms->tm[1].cnv_i; + } else { + for (i = 0; i < 3; i++) { /** 3 poles **/ + tm = &(cp->h2t[j][k][l]->tm[i]); + e = exp((double) tm->x * h); + tm->cnv_i = tm->cnv_i * e + h1 * tm->c * (i1_i[l][k] * e + i2_i[l][k]); + tm->cnv_o = tm->cnv_o * e + h1 * tm->c * (i1_o[l][k] * e + i2_o[l][k]); + ff[j] += tm->cnv_o; + gg[j] += tm->cnv_i; + } + + ff[j] += cp->h2t[j][k][l]->aten * i2_o[l][k]; + gg[j] += cp->h2t[j][k][l]->aten * i2_i[l][k]; + } + } + } + + for (i = 0; i < noL; i++) { + *(ckt->CKTrhs + l1[i]) = ff[i]; + *(ckt->CKTrhs + l2[i]) = gg[i]; + } + + return(ext); +} + +static int +update_cnv(cp, h) +CPLine *cp; +float h; +{ + int i, j, k; + register int noL; + double ai, bi, ao, bo; + double e, t; + register TMS *tms; + register TERM *tm; + + noL = cp->noL; + for (j = 0; j < noL; j++) + for (k = 0; k < noL; k++) { + ai = cp->in_node[k]->V; + ao = cp->out_node[k]->V; + bi = cp->in_node[k]->dv; + bo = cp->out_node[k]->dv; + + if (cp->h1t[j][k]) { + if (cp->h1t[j][k]->ifImg) { + tms = cp->h1t[j][k]; + if (tms == NULL) + continue; + tm = &(tms->tm[0]); + e = cp->h1e[j][k][0]; + t = tm->c / tm->x; + update_cnv_a(tms, h, ai, ao, ai - bi * h, ao - bo * h, + cp->h1e[j][k][1], cp->h1e[j][k][2]); + bi *= t; + bo *= t; + tm->cnv_i = (tm->cnv_i - bi*h) * e + (e - 1.0)*(ai*t + + 1.0e+12*bi/tm->x); + tm->cnv_o = (tm->cnv_o - bo*h) * e + (e - 1.0)*(ao*t + + 1.0e+12*bo/tm->x); + } else + for (i = 0; i < 3; i++) { + tm = &(cp->h1t[j][k]->tm[i]); + + e = cp->h1e[j][k][i]; + + t = tm->c / tm->x; + bi *= t; + bo *= t; + + tm->cnv_i = (tm->cnv_i - bi*h) * e + (e - 1.0)*(ai*t + 1.0e+12*bi/tm->x); + tm->cnv_o = (tm->cnv_o - bo*h) * e + (e - 1.0)*(ao*t + 1.0e+12*bo/tm->x); + } + } + } + return 0; +} + +static VI_list +*new_vi() +{ + VI_list *q; + + if (pool_vi) { + q = pool_vi; + pool_vi = pool_vi->pool; + return(q); + } else return((VI_list *) malloc (sizeof (VI_list))); +} + +static void +free_vi(q) +VI_list *q; +{ + q->pool = pool_vi; + pool_vi = q; +} + + +static int +add_new_vi(here, ckt, time) + CPLinstance *here; + CKTcircuit *ckt; + int time; +{ + VI_list *vi; + register int i, noL; + CPLine *cp, *cp2; + + cp = here->cplines; + cp2 = here->cplines2; + + vi = new_vi(); + vi->time = time; + noL = cp->noL; + for (i = 0; i < noL; i++) { + /* + vi->v_i[i] = cp->in_node[i]->V; + vi->v_o[i] = cp->out_node[i]->V; + */ + vi->v_i[i] = *(ckt->CKTrhsOld + here->CPLposNodes[i]); + vi->v_o[i] = *(ckt->CKTrhsOld + here->CPLnegNodes[i]); + vi->i_i[i] = *(ckt->CKTrhsOld + here->CPLibr1[i]); + vi->i_o[i] = *(ckt->CKTrhsOld + here->CPLibr2[i]); + } + cp->vi_tail->next = vi; + cp2->vi_tail->next = vi; + vi->next = NULL; + cp->vi_tail = vi; + cp2->vi_tail = vi; + + return(1); +} + + +static int +get_pvs_vi(t1, t2, cp, v1_i, v2_i, i1_i, i2_i, v1_o, v2_o, i1_o, i2_o) + CPLine *cp; + int t1, t2; + double v1_i[MAX_CP_TX_LINES][MAX_CP_TX_LINES]; + double v2_i[MAX_CP_TX_LINES][MAX_CP_TX_LINES]; + double i1_i[MAX_CP_TX_LINES][MAX_CP_TX_LINES]; + double i2_i[MAX_CP_TX_LINES][MAX_CP_TX_LINES]; + double v1_o[MAX_CP_TX_LINES][MAX_CP_TX_LINES]; + double v2_o[MAX_CP_TX_LINES][MAX_CP_TX_LINES]; + double i1_o[MAX_CP_TX_LINES][MAX_CP_TX_LINES]; + double i2_o[MAX_CP_TX_LINES][MAX_CP_TX_LINES]; +{ + double ta[MAX_CP_TX_LINES], tb[MAX_CP_TX_LINES]; + register VI_list *vi, *vi1; + register double f; + register int i, j; + int mini = -1; + double minta = 123456789.0; + int ext = 0; + register int noL; + + noL = cp->noL; + + for (i = 0; i < noL; i++) { + ta[i] = t1 - cp->taul[i]; + tb[i] = t2 - cp->taul[i]; + if (ta[i] < minta) { + minta = ta[i]; + mini = i; + } + } + + for (i = 0; i < noL; i++) { + + ratio[i] = 0.0; + + if (tb[i] <= 0) { + for (j = 0; j < noL; j++) { + i1_i[i][j] = i2_i[i][j] = i1_o[i][j] = i2_o[i][j] = 0.0; + v1_i[i][j] = v2_i[i][j] = cp->dc1[j]; + v1_o[i][j] = v2_o[i][j] = cp->dc2[j]; + } + } else { + if (ta[i] <= 0) { + for (j = 0; j < noL; j++) { + i1_i[i][j] = i1_o[i][j] = 0.0; + v1_i[i][j] = cp->dc1[j]; + v1_o[i][j] = cp->dc2[j]; + } + vi1 = cp->vi_head; + vi = vi1->next; + } else { + vi1 = cp->vi_head; + for (vi = vi1->next; vi->time < ta[i]; ) { + /* if (i == mini) + free_vi(vi1); */ + vi1 = vi; + + /* new */ + vi = vi->next; + if (vi == NULL) goto errordetect; + } + f = (ta[i] - vi1->time) / (vi->time - vi1->time); + for (j = 0; j < noL; j++) { + v1_i[i][j] = vi1->v_i[j] + f * (vi->v_i[j] - vi1->v_i[j]); + v1_o[i][j] = vi1->v_o[j] + f * (vi->v_o[j] - vi1->v_o[j]); + i1_i[i][j] = vi1->i_i[j] + f * (vi->i_i[j] - vi1->i_i[j]); + i1_o[i][j] = vi1->i_o[j] + f * (vi->i_o[j] - vi1->i_o[j]); + } + if (i == mini) + cp->vi_head = vi1; + } + + if (tb[i] > t1) { + /* + fprintf(stderr, "pvs: time = %d\n", t2); + */ + ext = 1; + + ratio[i] = f = (tb[i] - t1) / (t2 - t1); + + if (vi) + for (; vi->next; vi = vi->next); + else + vi = vi1; + f = 1 - f; + for (j = 0; j < noL; j++) { + v2_i[i][j] = vi->v_i[j] * f; + v2_o[i][j] = vi->v_o[j] * f; + i2_i[i][j] = vi->i_i[j] * f; + i2_o[i][j] = vi->i_o[j] * f; + } + } else { + for (; vi->time < tb[i];) { + vi1 = vi; + + /* new */ + vi = vi->next; + if (vi == NULL) goto errordetect; + } + + f = (tb[i] - vi1->time) / (vi->time - vi1->time); + for (j = 0; j < noL; j++) { + v2_i[i][j] = vi1->v_i[j] + f * (vi->v_i[j] - vi1->v_i[j]); + v2_o[i][j] = vi1->v_o[j] + f * (vi->v_o[j] - vi1->v_o[j]); + i2_i[i][j] = vi1->i_i[j] + f * (vi->i_i[j] - vi1->i_i[j]); + i2_o[i][j] = vi1->i_o[j] + f * (vi->i_o[j] - vi1->i_o[j]); + } + } + } + } + + return(ext); + +errordetect: + fprintf(stderr, "your maximum time step is too large for tau.\n"); + fprintf(stderr, "decrease max time step in .tran card and try again\n"); + exit(0); +} + + +static int +update_delayed_cnv(cp, h) + CPLine *cp; + float h; +{ + int i, j, k; + float *ratio; + register double f; + register VI_list *vi; + register TMS *tms; + register int noL; + + h *= 0.5e-12; + ratio = cp->ratio; + vi = cp->vi_tail; + noL = cp->noL; + + for (k = 0; k < noL; k++) /* mode */ + if (ratio[k] > 0.0) + for (i = 0; i < noL; i++) /* current eqn */ + for (j = 0; j < noL; j++) { + tms = cp->h3t[i][j][k]; + if (tms == NULL) + continue; + f = h * ratio[k] * vi->v_i[j]; + tms->tm[0].cnv_i += f * tms->tm[0].c; + tms->tm[1].cnv_i += f * tms->tm[1].c; + tms->tm[2].cnv_i += f * tms->tm[2].c; + + f = h * ratio[k] * vi->v_o[j]; + tms->tm[0].cnv_o += f * tms->tm[0].c; + tms->tm[1].cnv_o += f * tms->tm[1].c; + tms->tm[2].cnv_o += f * tms->tm[2].c; + + tms = cp->h2t[i][j][k]; + f = h * ratio[k] * vi->i_i[j]; + tms->tm[0].cnv_i += f * tms->tm[0].c; + tms->tm[1].cnv_i += f * tms->tm[1].c; + tms->tm[2].cnv_i += f * tms->tm[2].c; + + f = h * ratio[k] * vi->i_o[j]; + tms->tm[0].cnv_o += f * tms->tm[0].c; + tms->tm[1].cnv_o += f * tms->tm[1].c; + tms->tm[2].cnv_o += f * tms->tm[2].c; + } + return(1); +} + + +static int expC(ar, ai, h, cr, ci) +double ar, ai, *cr, *ci; +double h; +{ + double e, cs, si; + + e = exp((double) ar * h); + cs = cos((double) ai * h); + si = sin((double) ai * h); + *cr = e * cs; + *ci = e * si; + + return(1); +} + +static int multC(ar, ai, br, bi, cr, ci) +double ar, ai, br, bi; +double *cr, *ci; +{ + register double tp; + + tp = ar*br - ai*bi; + *ci = ar*bi+ai*br; + *cr = tp; + + return (1); + +} + +static void +update_cnv_a(tms, h, ai, ao, bi, bo, er, ei) + TMS *tms; + float h; + double ai, bi, ao, bo; + double er, ei; +{ + double a, b, a1, b1; + + h *= 0.5e-12; + multC(tms->tm[1].c, tms->tm[2].c, er, ei, &a1, &b1); + multC(tms->tm[1].cnv_i, tms->tm[2].cnv_i, er, ei, &a, &b); + tms->tm[1].cnv_i = a + h * (a1 * bi + ai * tms->tm[1].c); + tms->tm[2].cnv_i = b + h * (b1 * bi + ai * tms->tm[2].c); + + multC(tms->tm[1].cnv_o, tms->tm[2].cnv_o, er, ei, &a, &b); + tms->tm[1].cnv_o = a + h * (a1 * bo + ao * tms->tm[1].c); + tms->tm[2].cnv_o = b + h * (b1 * bo + ao * tms->tm[2].c); +} + +static int divC(ar, ai, br, bi, cr, ci) +double ar, ai, br, bi; +double *cr, *ci; +{ + double t; + + t = br*br + bi*bi; + *cr = (ar*br + ai*bi) / t; + *ci = (ai*br - ar*bi) / t; + + return(1); +} + diff --git a/src/spicelib/devices/cpl/cplmdel.c b/src/spicelib/devices/cpl/cplmdel.c new file mode 100644 index 000000000..0697dc890 --- /dev/null +++ b/src/spicelib/devices/cpl/cplmdel.c @@ -0,0 +1,45 @@ +/********** +Copyright 1992 Regents of the University of California. All rights +reserved. +Author: 1992 Charles Hough +**********/ + + +#include "ngspice.h" +#include +#include "cpldefs.h" +#include "sperror.h" +#include "suffix.h" + + +int +CPLmDelete(inModel,modname,kill) + GENmodel **inModel; + IFuid modname; + GENmodel *kill; +{ + CPLmodel **model = (CPLmodel **)inModel; + CPLmodel *modfast = (CPLmodel *)kill; + CPLinstance *here; + CPLinstance *prev = NULL; + CPLmodel **oldmod; + oldmod = model; + + for( ; *model ; model = &((*model)->CPLnextModel)) { + if( (*model)->CPLmodName == modname || + (modfast && *model == modfast) ) goto delgot; + oldmod = model; + } + return(E_NOMOD); + +delgot: + *oldmod = (*model)->CPLnextModel; /* cut deleted device out of list */ + for(here = (*model)->CPLinstances ; here ; here = here->CPLnextInstance) { + if(prev) FREE(prev); + prev = here; + } + if(prev) FREE(prev); + FREE(*model); + return(OK); + +} diff --git a/src/spicelib/devices/cpl/cplmpar.c b/src/spicelib/devices/cpl/cplmpar.c new file mode 100644 index 000000000..03cef866f --- /dev/null +++ b/src/spicelib/devices/cpl/cplmpar.c @@ -0,0 +1,51 @@ +/********** +Copyright 1992 Regents of the University of California. All rights +reserved. +Author: 1992 Charles Hough +**********/ + + +#include "ngspice.h" +#include +#include "const.h" +#include "ifsim.h" +#include "cpldefs.h" +#include "sperror.h" +#include "suffix.h" + + +int +CPLmParam(param,value,inModel) + int param; + IFvalue *value; + GENmodel *inModel; +{ + register CPLmodel *model = (CPLmodel *)inModel; + switch(param) { + case CPL_R: + model->Rm = value->v.vec.rVec; + model->Rmgiven = TRUE; + break; + case CPL_L: + model->Lm = value->v.vec.rVec; + model->Lmgiven = TRUE; + break; + case CPL_G: + model->Gm = value->v.vec.rVec; + model->Gmgiven = TRUE; + break; + case CPL_C: + model->Cm = value->v.vec.rVec; + model->Cmgiven = TRUE; + break; + case CPL_length: + model->length = value->rValue; + model->lengthgiven = TRUE; + break; + case CPL_MOD_R: + break; + default: + return(E_BADPARM); + } + return(OK); +} diff --git a/src/spicelib/devices/cpl/cplparam.c b/src/spicelib/devices/cpl/cplparam.c new file mode 100644 index 000000000..98dd7eaec --- /dev/null +++ b/src/spicelib/devices/cpl/cplparam.c @@ -0,0 +1,45 @@ +/********** +Copyright 1992 Regents of the University of California. All rights +reserved. +Author: 1992 Charles Hough +**********/ + + +#include "ngspice.h" +#include +#include "const.h" +#include "ifsim.h" +#include "cpldefs.h" +#include "sperror.h" +#include "suffix.h" + + +/* ARGSUSED */ +int +CPLparam(param,value,inst,select) + int param; + IFvalue *value; + GENinstance *inst; + IFvalue *select; +{ + CPLinstance *here = (CPLinstance *)inst; + switch(param) { + case CPL_POS_NODE: + here->in_node_names = value->v.vec.sVec; + break; + case CPL_NEG_NODE: + here->out_node_names = value->v.vec.sVec; + break; + case CPL_DIM: + here->dimension = value->iValue; + break; + case CPL_LENGTH: + here->CPLlength = value->rValue; + here->CPLlengthgiven = TRUE; + break; + + default: + return(E_BADPARM); + } + return(OK); +} diff --git a/src/spicelib/devices/cpl/cplsetup.c b/src/spicelib/devices/cpl/cplsetup.c new file mode 100644 index 000000000..f5bb8337c --- /dev/null +++ b/src/spicelib/devices/cpl/cplsetup.c @@ -0,0 +1,2101 @@ +/********** +Copyright 1992 Regents of the University of California. All rights +reserved. +Author: 1992 Charles Hough +**********/ + + +#include "ngspice.h" +#include +#include "smpdefs.h" +#include "cpldefs.h" +#include "sperror.h" +#include "suffix.h" + +#include "../cap/capdefs.h" +#include "multi_line.h" + +#define VECTOR_ALLOC(vec, n) { \ + int i; \ + vec = (double **) malloc(n * sizeof(double *)); \ + for (i = 0; i < n; i++) { \ + vec[i] = (double *) malloc(sizeof(double)); \ + } \ +} +#define MATRIX_ALLOC(mat, m, j) { \ + int k; \ + mat = (double ***) malloc(m * sizeof(double **)); \ + for (k = 0; k < m; k++) { \ + VECTOR_ALLOC(mat[k], j); \ + } \ +} + +#define MAX_DEG 8 +#define epsilon 1.0e-88 +#define ABS(x) ((x) >= 0 ? (x) : (-(x))) +#define MAX_STRING 128 + +static double ZY[MAX_DIM][MAX_DIM]; +static double Sv[MAX_DIM][MAX_DIM]; +static double D[MAX_DIM]; +static double Y5[MAX_DIM][MAX_DIM]; +static double Y5_1[MAX_DIM][MAX_DIM]; +static double Sv_1[MAX_DIM][MAX_DIM]; + +static double R_m[MAX_DIM][MAX_DIM]; +static double G_m[MAX_DIM][MAX_DIM]; +static double L_m[MAX_DIM][MAX_DIM]; +static double C_m[MAX_DIM][MAX_DIM]; +static double length; +static double TAU[MAX_DIM]; + +static double A[MAX_DIM][2*MAX_DIM]; + +static double frequency[MAX_DEG]; + +static double Si[MAX_DIM][MAX_DIM]; +static double Si_1[MAX_DIM][MAX_DIM]; + +/* MacLaurin Series */ +static double *SiSv_1[MAX_DIM][MAX_DIM]; +static double *Sip[MAX_DIM][MAX_DIM]; +static double *Si_1p[MAX_DIM][MAX_DIM]; +static double *Sv_1p[MAX_DIM][MAX_DIM]; +static double *W[MAX_DIM]; + +static Mult_Out IWI[MAX_DIM][MAX_DIM]; +static Mult_Out IWV[MAX_DIM][MAX_DIM]; +static Single_Out SIV[MAX_DIM][MAX_DIM]; +static double At[4][4]; +static double Scaling_F; +static double Scaling_F2; + +/* misc.c match */ +static void new_memory(); +static double *vector(); +static void free_vector(); +static void polint(); +/*static int match_x();*/ +static int match(); +static int Gaussian_Elimination2(); +static void eval_Si_Si_1(); +static void loop_ZY(); +static void poly_matrix(); +/*static int checkW();*/ +static void poly_W(); +static void eval_frequency(); +static void store(); +static void store_SiSv_1(); +/*static int check();*/ +static int coupled(); +static int generate_out(); +static int ReadCpL(); +/*static int divC();*/ + +/* mult */ +static void mult_p(); +static void matrix_p_mult(); +static double approx_mode(); +static double eval2(); +static int get_c(); +static int Pade_apx(); +static int Gaussian_Elimination(); +static double root3(); +static int div3(); +static int find_roots(); + +static NODE* insert_node(); +static NDnamePt insert_ND(); +static NODE* NEW_node(); +static NDnamePt ndn; +static NODE *node_tab; +#define epsi_mult 1e-28 + +/* diag */ +static MAXE_PTR sort(); +static void ordering(); +static MAXE_PTR delete_1(); +static void reordering(); +static void diag(); +static int rotate(); + +#define epsi 1.0e-16 +static char *message = "tau of coupled lines is larger than max time step"; + +/* ARGSUSED */ +int +CPLsetup(matrix,inModel,ckt,state) + register SMPmatrix *matrix; + GENmodel *inModel; + CKTcircuit*ckt; + int *state; +{ + register CPLmodel *model = (CPLmodel *)inModel; + register CPLinstance *here; + CKTnode *tmp, *node; + int error, m, p; + char **branchname; + int noL; + + /* loop through all the models */ + for( ; model != NULL; model = model->CPLnextModel ) { + + /* loop through all the instances of the model */ + for (here = model->CPLinstances; here != NULL ; + here=here->CPLnextInstance) { + +/* macro to make elements with built in test for out of memory */ +#define TSTALLOC(ptr,first,second) \ +if((here->ptr = SMPmakeElt(matrix,here->first,here->second))==(double *)NULL){\ + return(E_NOMEM);\ +} + noL = here->dimension; + + here->CPLposNodes = (int *) malloc(noL * sizeof(int)); + here->CPLnegNodes = (int *) malloc(noL * sizeof(int)); + here->CPLibr1 = (int *) malloc(noL * sizeof(int)); + here->CPLibr2 = (int *) malloc(noL * sizeof(int)); + + VECTOR_ALLOC(here->CPLibr1Ibr1, noL); + VECTOR_ALLOC(here->CPLibr2Ibr2, noL); + VECTOR_ALLOC(here->CPLposIbr1, noL); + VECTOR_ALLOC(here->CPLnegIbr2, noL); + VECTOR_ALLOC(here->CPLposPos, noL); + VECTOR_ALLOC(here->CPLnegNeg, noL); + VECTOR_ALLOC(here->CPLnegPos, noL); + VECTOR_ALLOC(here->CPLposNeg, noL); + + MATRIX_ALLOC(here->CPLibr1Pos, noL, noL); + MATRIX_ALLOC(here->CPLibr2Neg, noL, noL); + MATRIX_ALLOC(here->CPLibr1Neg, noL, noL); + MATRIX_ALLOC(here->CPLibr2Pos, noL, noL); + MATRIX_ALLOC(here->CPLibr1Ibr2, noL, noL); + MATRIX_ALLOC(here->CPLibr2Ibr1, noL, noL); + + branchname = (char **) malloc(sizeof(char *) * here->dimension); + if (! here->CPLibr1Given) { + for (m = 0; m < here->dimension; m++) { + branchname[m] = malloc(MAX_STRING); + sprintf(branchname[m], "branch1_%d", m); + error = + CKTmkCur(ckt, &tmp, here->CPLname, branchname[m]); + if (error) return (error); + here->CPLibr1[m] = tmp->number; + } + here->CPLibr1Given = 1; + } + free(branchname); + branchname = (char **) malloc(sizeof(char *) * here->dimension); + if (! here->CPLibr2Given) { + for (m = 0; m < here->dimension; m++) { + branchname[m] = malloc(MAX_STRING); + sprintf(branchname[m], "branch2_%d", m); + error = + CKTmkCur(ckt, &tmp, here->CPLname, branchname[m]); + if (error) return (error); + here->CPLibr2[m] = tmp->number; + } + here->CPLibr2Given = 1; + } + free(branchname); + + for (m = 0; m < here->dimension; m++) { + for (node = ckt->CKTnodes; node; node = node->next) { + if (strcmp(here->in_node_names[m], + node->name) == 0){ + here->CPLposNodes[m] = node->number; + } + } + } + for (m = 0; m < here->dimension; m++) { + for (node = ckt->CKTnodes; node; node = node->next) { + if (strcmp(here->out_node_names[m], + node->name) == 0){ + here->CPLnegNodes[m] = node->number; + } + } + } + + for (m = 0; m < here->dimension; m++) { + TSTALLOC(CPLibr1Ibr1[m],CPLibr1[m],CPLibr1[m]); + TSTALLOC(CPLibr2Ibr2[m],CPLibr2[m],CPLibr2[m]); + TSTALLOC(CPLposIbr1[m],CPLposNodes[m],CPLibr1[m]); + TSTALLOC(CPLnegIbr2[m],CPLnegNodes[m],CPLibr2[m]); + TSTALLOC(CPLposPos[m],CPLposNodes[m],CPLposNodes[m]); + TSTALLOC(CPLnegNeg[m],CPLnegNodes[m],CPLnegNodes[m]); + TSTALLOC(CPLnegPos[m],CPLnegNodes[m],CPLposNodes[m]); + TSTALLOC(CPLposNeg[m],CPLposNodes[m],CPLnegNodes[m]); + + for (p = 0; p < here->dimension; p++) { + + TSTALLOC(CPLibr1Pos[m][p],CPLibr1[m],CPLposNodes[p]); + TSTALLOC(CPLibr2Neg[m][p],CPLibr2[m],CPLnegNodes[p]); + TSTALLOC(CPLibr1Neg[m][p],CPLibr1[m],CPLnegNodes[p]); + TSTALLOC(CPLibr2Pos[m][p],CPLibr2[m],CPLposNodes[p]); + TSTALLOC(CPLibr1Ibr2[m][p],CPLibr1[m],CPLibr2[p]); + TSTALLOC(CPLibr2Ibr1[m][p],CPLibr2[m],CPLibr1[p]); + + } + } + + ReadCpL(here, ckt); + + } + } + + return(OK); +} + + +static int +ReadCpL(here, ckt) +CPLinstance *here; +CKTcircuit *ckt; +{ + int i, j, noL, counter; + float f; + char *name; + CPLine *c, *c2; + ECPLine *ec; + NODE *nd; + RLINE *lines[MAX_CP_TX_LINES]; + ERLINE *er; + + c = (CPLine *) malloc(sizeof (CPLine)); + c2 = (CPLine *) malloc(sizeof (CPLine)); + c->vi_head = c->vi_tail = NULL; + noL = c->noL = here->dimension; + here->cplines = c; + here->cplines2 = c2; + + for (i = 0; i < noL; i++) { + ec = (ECPLine *) malloc(sizeof (ECPLine)); + name = here->in_node_names[i]; + nd = insert_node(name); + ec->link = nd->cplptr; + nd->cplptr = ec; + ec->line = c; + c->in_node[i] = nd; + c2->in_node[i] = nd; + + er = (ERLINE *) malloc(sizeof (ERLINE)); + er->link = nd->rlptr; + nd->rlptr = er; + er->rl = lines[i] = (RLINE *) malloc(sizeof (RLINE)); + er->rl->in_node = nd; + + c->dc1[i] = c->dc2[i] = 0.0; + } + + for (i = 0; i < noL; i++) { + ec = (ECPLine *) malloc(sizeof (ECPLine)); + name = here->out_node_names[i]; + nd = insert_node(name); + ec->link = nd->cplptr; + nd->cplptr = ec; + ec->line = c; + c->out_node[i] = nd; + c2->out_node[i] = nd; + + er = (ERLINE *) malloc(sizeof (ERLINE)); + er->link = nd->rlptr; + nd->rlptr = er; + er->rl = lines[i]; + er->rl->out_node = nd; + } + + + counter = 0; + for (i = 0; i < noL; i++) { + for (j = 0; j < noL; j++) { + if (i > j) { + R_m[i][j] = R_m[j][i]; + G_m[i][j] = G_m[j][i]; + C_m[i][j] = C_m[j][i]; + L_m[i][j] = L_m[j][i]; + } + else { + f = here->CPLmodPtr->Rm[counter]; + R_m[i][j] =here->CPLmodPtr->Rm[counter]= MAX(f, 1.0e-4); + G_m[i][j] = here->CPLmodPtr->Gm[counter]; + L_m[i][j] = here->CPLmodPtr->Lm[counter]; + C_m[i][j] = here->CPLmodPtr->Cm[counter]; + counter++; + } + } + } + if (here->CPLlengthgiven) + length = here->CPLlength; + else length = here->CPLmodPtr->length; + + for (i = 0; i < noL; i++) + lines[i]->g = 1.0 / (R_m[i][i] * length); + + coupled(noL); + + for (i = 0; i < noL; i++) { + double d, t; + int k; + + c->taul[i] = TAU[i] * 1.0e+12; + for (j = 0; j < noL; j++) { + if (SIV[i][j].C_0 == 0.0) + c->h1t[i][j] = NULL; + else { + c->h1t[i][j] = (TMS *) malloc(sizeof (TMS)); + d = c->h1t[i][j]->aten = SIV[i][j].C_0; + c->h1t[i][j]->ifImg = (int) SIV[i][j].Poly[6] - 1.0; + /* since originally 2 for img 1 for noimg */ + c->h1t[i][j]->tm[0].c = SIV[i][j].Poly[0] * d; + c->h1t[i][j]->tm[1].c = SIV[i][j].Poly[1] * d; + c->h1t[i][j]->tm[2].c = SIV[i][j].Poly[2] * d; + c->h1t[i][j]->tm[0].x = SIV[i][j].Poly[3]; + c->h1t[i][j]->tm[1].x = SIV[i][j].Poly[4]; + c->h1t[i][j]->tm[2].x = SIV[i][j].Poly[5]; + if (c->h1t[i][j]->ifImg) + c->h1C[i][j] = c->h1t[i][j]->tm[0].c + 2.0 * c->h1t[i][j]->tm[1].c; + else { + t = 0.0; + for (k = 0; k < 3; k++) + t += c->h1t[i][j]->tm[k].c; + c->h1C[i][j] = t; + } + } + + for (k = 0; k < noL; k++) { + if (IWI[i][j].C_0[k] == 0.0) + c->h2t[i][j][k] = NULL; + else { + c->h2t[i][j][k] = (TMS *) malloc(sizeof (TMS)); + d = c->h2t[i][j][k]->aten = IWI[i][j].C_0[k]; + c->h2t[i][j][k]->ifImg = (int) IWI[i][j].Poly[k][6] - 1.0; + /* since originally 2 for img 1 for noimg */ + c->h2t[i][j][k]->tm[0].c = IWI[i][j].Poly[k][0] * d; + c->h2t[i][j][k]->tm[1].c = IWI[i][j].Poly[k][1] * d; + c->h2t[i][j][k]->tm[2].c = IWI[i][j].Poly[k][2] * d; + c->h2t[i][j][k]->tm[0].x = IWI[i][j].Poly[k][3]; + c->h2t[i][j][k]->tm[1].x = IWI[i][j].Poly[k][4]; + c->h2t[i][j][k]->tm[2].x = IWI[i][j].Poly[k][5]; + if (c->h2t[i][j][k]->ifImg) + c->h2C[i][j][k] = c->h2t[i][j][k]->tm[0].c + 2.0 * + c->h2t[i][j][k]->tm[1].c; + else + c->h2C[i][j][k] = c->h2t[i][j][k]->tm[0].c + + c->h2t[i][j][k]->tm[1].c + + c->h2t[i][j][k]->tm[2].c; + } + if (IWV[i][j].C_0[k] == 0.0) + c->h3t[i][j][k] = NULL; + else { + c->h3t[i][j][k] = (TMS *) malloc(sizeof (TMS)); + d = c->h3t[i][j][k]->aten = IWV[i][j].C_0[k]; + c->h3t[i][j][k]->ifImg = (int) IWV[i][j].Poly[k][6] - 1.0; + /* since originally 2 for img 1 for noimg */ + c->h3t[i][j][k]->tm[0].c = IWV[i][j].Poly[k][0] * d; + c->h3t[i][j][k]->tm[1].c = IWV[i][j].Poly[k][1] * d; + c->h3t[i][j][k]->tm[2].c = IWV[i][j].Poly[k][2] * d; + c->h3t[i][j][k]->tm[0].x = IWV[i][j].Poly[k][3]; + c->h3t[i][j][k]->tm[1].x = IWV[i][j].Poly[k][4]; + c->h3t[i][j][k]->tm[2].x = IWV[i][j].Poly[k][5]; + if (c->h3t[i][j][k]->ifImg) + c->h3C[i][j][k] = c->h3t[i][j][k]->tm[0].c + 2.0 * + c->h3t[i][j][k]->tm[1].c; + else + c->h3C[i][j][k] = c->h3t[i][j][k]->tm[0].c + + c->h3t[i][j][k]->tm[1].c + + c->h3t[i][j][k]->tm[2].c; + } + } + } + } + + for (i = 0; i < noL; i++) { + if (c->taul[i] < ckt->CKTmaxStep) { + errMsg = MALLOC(strlen(message)+1); + strcpy(errMsg,message); + return(-1); + } + } + + return(1); +} + + +/**************************************************************** + misc.c Miscellaneous procedures for simulation of + coupled transmission lines. + ****************************************************************/ + + +static void +new_memory(dim, deg, deg_o) + int dim, deg, deg_o; +{ + int i, j; + + for (i = 0; i < dim; i++) + for (j = 0; j < dim; j++) + SiSv_1[i][j] = (double *) calloc(deg_o+1, sizeof(double)); + + for (i = 0; i < dim; i++) + for (j = 0; j < dim; j++) + Sip[i][j] = (double *) calloc(deg_o+1, sizeof(double)); + + for (i = 0; i < dim; i++) + for (j = 0; j < dim; j++) + Si_1p[i][j] = (double *) calloc(deg_o+1, sizeof(double)); + + for (i = 0; i < dim; i++) + for (j = 0; j < dim; j++) + Sv_1p[i][j] = (double *) calloc(deg_o+1, sizeof(double)); + + for (i = 0; i < dim; i++) + W[i] = (double *) calloc(MAX_DEG, sizeof(double)); +} + +/*** + ***/ + +/**************************************************************** + match Create a polynomial matching given data points + ****************************************************************/ + + +static double +*vector(nl, nh) + int nl, nh; +{ + double *v; + + v = (double *) malloc((unsigned) (nh - nl +1) * sizeof(double)); + if (!v) { + fprintf(stderr, "Memory Allocation Error by malloc in vector().\n"); + fprintf(stderr, "...now exiting to system ...\n"); + exit(0); + } + return v-nl; +} + +static void +free_vector(v, nl, nh) + double *v; + int nl, nh; +{ + free((char*) (v +nl)); +} + +static void +polint(xa, ya, n, x, y, dy) +/* + Given arrays xa[1..n] and ya[1..n], and given a value x, this routine + returns a value y, and an error estimate dy. If P(x) is the + polynomial of degree n-1 such that P(xa) = ya, then the returned + value y = P(x) + */ + double xa[], ya[], x, *y, *dy; + int n; +{ + int i, m, ns = 1; + double den, dif, dift, ho, hp, w; + double *c, *d, *vector(); + void free_vector(); + + dif = ABS(x - xa[1]); + c = vector(1, n); + d = vector(1, n); + for (i = 1; i <= n; i++) { + if ((dift = ABS(x - xa[i])) < dif) { + ns = i; + dif = dift; + } + c[i] = ya[i]; + d[i] = ya[i]; + } + *y = ya[ns--]; + for (m = 1; m < n; m++) { + for (i = 1; i <= n-m; i++) { + ho = xa[i]-x; + hp = xa[i+m]-x; + w = c[i+1]-d[i]; + if ((den=ho-hp) == 0.0) { + fprintf(stderr, "(Error) in routine POLINT\n"); + fprintf(stderr, "...now exiting to system ...\n"); + exit(0); + } + den = w/den; + d[i] = hp * den; + c[i] = ho * den; + } + *y += (*dy = (2*ns < (n-m) ? c[ns+1] : d[ns--])); + } + free_vector(d, 1, n); + free_vector(c, 1, n); +} + +static int +match(n, cof, xa, ya) + double xa[], ya[], cof[]; + int n; +/* + Given arrays xa[0..n] and ya[0..n] containing a tabulated function + ya = f(xa), this routine returns an array of coefficients cof[0..n], + such that ya[i] = sum_j {cof[j]*xa[i]**j}. + */ +{ + int k, j, i; + double xmin, dy, *x, *y, *xx, *vector(); + void polint(), free_vector(); + + x = vector(0, n); + y = vector(0, n); + xx = vector(0, n); + for (j = 0; j <= n; j++) { + x[j] = xa[j]; + xx[j] = y[j] = ya[j]; + } + for (j = 0; j <= n; j++) { + polint(x-1, y-1, n+1-j, (double) 0.0, &cof[j], &dy); + xmin = 1.0e38; + k = -1; + for (i = 0; i <= n-j; i++) { + if (ABS(x[i]) < xmin) { + xmin = ABS(x[i]); + k = i; + } + if (x[i]) y[i] = (y[i] - cof[j]) / x[i]; + } + for (i = k+1; i <= n-j; i++) { + y[i-1] = y[i]; + x[i-1] = x[i]; + } + } + free_vector(y, 0, n); + free_vector(x, 0, n); + + /**** check ****/ + /* + for (i = 0; i <= n; i++) { + xmin = xa[i]; + dy = cof[0]; + for (j = 1; j <= n; j++) { + dy += xmin * cof[j]; + xmin *= xa[i]; + } + printf("*** real x = %e y = %e\n", xa[i], xx[i]); + printf("*** calculated y = %e\n", dy); + printf("*** error = %e \% \n", (dy-xx[i])/xx[i]); + } + */ + return 0; +} + +/*** + ***/ +/*** +static int +match_x(dim, Alfa, X, Y) + int dim; + double X[]; + double Y[]; + double Alfa[]; +{ + int i, j; + double f; + double scale; + + **** check **** + double xx[16]; + for (i = 0; i <= dim; i++) + xx[i] = Y[i]; + + if (Y[1] == Y[0]) + scale = 1.0; + else + scale = X[1] / (Y[1] - Y[0]); + for (i = 0; i < dim; i++) { + f = X[i+1]; + for (j = dim-1; j >= 0; j--) { + A[i][j] = f; + f *= X[i+1]; + } + A[i][dim] = (Y[i+1] - Y[0])*scale; + } + Gaussian_Elimination2(dim, 1); + Alfa[0] = Y[0]; + for (i = 1; i <= dim; i++) + Alfa[i] = A[dim-i][dim] / scale; + + **** check **** + * + for (i = 0; i <= dim; i++) { + f = X[i]; + scale = Alfa[0]; + for (j = 1; j <= dim; j++) { + scale += f * Alfa[j]; + f *= X[i]; + } + printf("*** real x = %e y = %e\n", X[i], xx[i]); + printf("*** calculated y = %e\n", scale); + printf("*** error = %e \% \n", (scale-xx[i])/xx[i]); + } + * + + return(1); +} +***/ +/*** + ***/ + +static int +Gaussian_Elimination2(dims, type) + /* type = 1 : to solve a linear system + -1 : to inverse a matrix */ + int dims; + int type; +{ + register int i, j, k, dim; + register double f; + double max; + int imax; + + if (type == -1) + dim = 2 * dims; + else + dim = dims; + + for (i = 0; i < dims; i++) { + imax = i; + max = ABS(A[i][i]); + for (j = i+1; j < dim; j++) + if (ABS(A[j][i]) > max) { + imax = j; + max = ABS(A[j][i]); + } + if (max < epsilon) { + fprintf(stderr, " can not choose a pivot (misc)\n"); + exit(0); + } + if (imax != i) + for (k = i; k <= dim; k++) { + f = A[i][k]; + A[i][k] = A[imax][k]; + A[imax][k] = f; + } + + f = 1.0 / A[i][i]; + A[i][i] = 1.0; + + for (j = i+1; j <= dim; j++) + A[i][j] *= f; + + for (j = 0; j < dims ; j++) { + if (i == j) + continue; + f = A[j][i]; + A[j][i] = 0.0; + for (k = i+1; k <= dim; k++) + A[j][k] -= f * A[i][k]; + } + } + + return(1); +} + +/*** + +static void +eval_Si_Si_1(dim, y) + int dim; + double y; +{ + int i, j, k; + + for (i = 0; i < dim; i++) + for (j = 0; j < dim; j++) { + Si_1[i][j] = 0.0; + for (k = 0; k < dim; k++) + if (k == j) + Si_1[i][j] += Sv_1[i][k] * + (y * R_m[k][j] + Scaling_F * L_m[k][j]); + else + Si_1[i][j] += Sv_1[i][k] * L_m[k][j] * Scaling_F; + / + Si_1[i][j] *= Scaling_F; + / + } + + for (i = 0; i < dim; i++) + for (j = 0; j < dim; j++) + Si_1[i][j] /= sqrt((double) D[i]); + + for (i = 0; i < dim; i++) { + for (j = 0; j < dim; j++) + A[i][j] = Si_1[i][j]; + for (j = dim; j < 2* dim; j++) + A[i][j] = 0.0; + A[i][i+dim] = 1.0; + } + Gaussian_Elimination2(dim, -1); + + for (i = 0; i < dim; i++) + for (j = 0; j < dim; j++) + Si[i][j] = A[i][j+dim]; +} + +***/ + +static void +eval_Si_Si_1(dim, y) + int dim; + double y; +{ + int i, j, k; + + for (i = 0; i < dim; i++) + for (j = 0; j < dim; j++) { + Si_1[i][j] = 0.0; + for (k = 0; k < dim; k++) + Si_1[i][j] += Sv_1[i][k] * (y * R_m[k][j] + Scaling_F * L_m[k][j]); + /* + else + Si_1[i][j] += Sv_1[i][k] * L_m[k][j] * Scaling_F; + Si_1[i][j] *= Scaling_F; + */ + } + + for (i = 0; i < dim; i++) + for (j = 0; j < dim; j++) + Si_1[i][j] /= sqrt((double) D[i]); + + for (i = 0; i < dim; i++) { + for (j = 0; j < dim; j++) + A[i][j] = Si_1[i][j]; + for (j = dim; j < 2* dim; j++) + A[i][j] = 0.0; + A[i][i+dim] = 1.0; + } + Gaussian_Elimination2(dim, -1); + + for (i = 0; i < dim; i++) + for (j = 0; j < dim; j++) + Si[i][j] = A[i][j+dim]; +} + +/*** + +static void +loop_ZY(dim, y) + int dim; + double y; +{ + int i, j, k; + double fmin, fmin1; + + for (i = 0; i < dim; i++) + for (j = 0; j < dim; j++) + if (i == j) + ZY[i][j] = Scaling_F * C_m[i][i] + G_m[i] * y; + else + ZY[i][j] = Scaling_F * C_m[i][j]; + diag(dim); + fmin = D[0]; + for (i = 1; i < dim; i++) + if (D[i] < fmin) + fmin = D[i]; + if (fmin < 0) { + fprintf(stderr, "(Error) The capacitance matrix of the multiconductor system is not positive definite.\n"); + exit(0); + } else { + fmin = sqrt(fmin); + fmin1 = 1 / fmin; + } + for (i = 0; i < dim; i++) + D[i] = sqrt((double) D[i]); + for (i = 0; i < dim; i++) + for (j = 0; j < dim; j++) { + Y5[i][j] = D[i] * Sv[j][i]; + Y5_1[i][j] = Sv[j][i] / D[i]; + } + for (i = 0; i < dim; i++) + for (j = 0; j < dim; j++) { + Sv_1[i][j] = 0.0; + for (k = 0; k < dim; k++) + Sv_1[i][j] += Sv[i][k] * Y5[k][j]; + } + for (i = 0; i < dim; i++) + for (j = 0; j < dim; j++) + Y5[i][j] = Sv_1[i][j]; + for (i = 0; i < dim; i++) + for (j = 0; j < dim; j++) { + Sv_1[i][j] = 0.0; + for (k = 0; k < dim; k++) + Sv_1[i][j] += Sv[i][k] * Y5_1[k][j]; + } + for (i = 0; i < dim; i++) + for (j = 0; j < dim; j++) + Y5_1[i][j] = Sv_1[i][j]; + + for (i = 0; i < dim; i++) + for (j = 0; j < dim; j++) { + ZY[i][j] = 0.0; + for (k = 0; k < dim; k++) + if (k == i) + ZY[i][j] += (Scaling_F * L_m[i][i] + R_m[i] * y) * + Y5[k][j]; + else + ZY[i][j] += L_m[i][k] * Y5[k][j] * Scaling_F; + } + for (i = 0; i < dim; i++) + for (j = 0; j < dim; j++) { + Sv_1[i][j] = 0.0; + for (k = 0; k < dim; k++) + Sv_1[i][j] += Y5[i][k] * ZY[k][j]; + } + for (i = 0; i < dim; i++) + for (j = 0; j < dim; j++) + ZY[i][j] = Sv_1[i][j]; + + diag(dim); + + for (i = 0; i < dim; i++) + for (j = 0; j < dim; j++) { + Sv_1[i][j] = 0.0; + for (k = 0; k < dim; k++) + Sv_1[i][j] += Sv[k][i] * Y5[k][j]; + Sv_1[i][j] *= fmin1; + } + for (i = 0; i < dim; i++) + for (j = 0; j < dim; j++) { + ZY[i][j] = 0.0; + for (k = 0; k < dim; k++) + ZY[i][j] += Y5_1[i][k] * Sv[k][j]; + ZY[i][j] *= fmin; + } + for (i = 0; i < dim; i++) + for (j = 0; j < dim; j++) + Sv[i][j] = ZY[i][j]; + +} +***/ + +static void +loop_ZY(dim, y) + int dim; + double y; +{ + int i, j, k; + double fmin, fmin1; + + for (i = 0; i < dim; i++) + for (j = 0; j < dim; j++) + ZY[i][j] = Scaling_F * C_m[i][j] + G_m[i][j] * y; + /* + else + ZY[i][j] = Scaling_F * C_m[i][j]; + */ + diag(dim); + fmin = D[0]; + for (i = 1; i < dim; i++) + if (D[i] < fmin) + fmin = D[i]; + if (fmin < 0) { + fprintf(stderr, "(Error) The capacitance matrix of the multiconductor system is not positive definite.\n"); + exit(0); + } else { + fmin = sqrt(fmin); + fmin1 = 1 / fmin; + } + for (i = 0; i < dim; i++) + D[i] = sqrt((double) D[i]); + for (i = 0; i < dim; i++) + for (j = 0; j < dim; j++) { + Y5[i][j] = D[i] * Sv[j][i]; + Y5_1[i][j] = Sv[j][i] / D[i]; + } + for (i = 0; i < dim; i++) + for (j = 0; j < dim; j++) { + Sv_1[i][j] = 0.0; + for (k = 0; k < dim; k++) + Sv_1[i][j] += Sv[i][k] * Y5[k][j]; + } + for (i = 0; i < dim; i++) + for (j = 0; j < dim; j++) + Y5[i][j] = Sv_1[i][j]; + for (i = 0; i < dim; i++) + for (j = 0; j < dim; j++) { + Sv_1[i][j] = 0.0; + for (k = 0; k < dim; k++) + Sv_1[i][j] += Sv[i][k] * Y5_1[k][j]; + } + for (i = 0; i < dim; i++) + for (j = 0; j < dim; j++) + Y5_1[i][j] = Sv_1[i][j]; + + for (i = 0; i < dim; i++) + for (j = 0; j < dim; j++) { + ZY[i][j] = 0.0; + for (k = 0; k < dim; k++) + ZY[i][j] += (Scaling_F * L_m[i][k] + R_m[i][k] * y) * Y5[k][j]; + /* + else + ZY[i][j] += L_m[i][k] * Y5[k][j] * Scaling_F; + */ + } + for (i = 0; i < dim; i++) + for (j = 0; j < dim; j++) { + Sv_1[i][j] = 0.0; + for (k = 0; k < dim; k++) + Sv_1[i][j] += Y5[i][k] * ZY[k][j]; + } + for (i = 0; i < dim; i++) + for (j = 0; j < dim; j++) + ZY[i][j] = Sv_1[i][j]; + + diag(dim); + + for (i = 0; i < dim; i++) + for (j = 0; j < dim; j++) { + Sv_1[i][j] = 0.0; + for (k = 0; k < dim; k++) + Sv_1[i][j] += Sv[k][i] * Y5[k][j]; + Sv_1[i][j] *= fmin1; + } + for (i = 0; i < dim; i++) + for (j = 0; j < dim; j++) { + ZY[i][j] = 0.0; + for (k = 0; k < dim; k++) + ZY[i][j] += Y5_1[i][k] * Sv[k][j]; + ZY[i][j] *= fmin; + } + for (i = 0; i < dim; i++) + for (j = 0; j < dim; j++) + Sv[i][j] = ZY[i][j]; + +} + + +/*** + ***/ + +static void +poly_matrix(A, dim, deg) + double *A[MAX_DIM][MAX_DIM]; + int dim, deg; +{ + int i, j; + + for (i = 0; i < dim; i++) + for (j = 0; j < dim; j++) + match(deg, A[i][j], frequency, A[i][j]); +} + +/*** + ***/ +/*** +static int +checkW(W, d) + double W[], d; +{ + double f, y; + float y1; + int k; + + printf("(W)y ="); + scanf("%f", &y1); + + f = W[0]; + y = y1; + f += y * W[1]; + for (k = 2; k < 6; k++) { + y *= y1; + f += y * W[k]; + } + printf("W[i]= %e\n ", f*exp((double)-d/y1)); + + return(1); +} +***/ +/*** + ***/ + +static void +poly_W(dim, deg) + int dim, deg; +{ + int i; + extern double approx_mode(); + + for (i = 0; i < dim; i++) { + match(deg, W[i], frequency, W[i]); + TAU[i] = approx_mode(W[i], W[i], length); + /* + checkW(W[i], TAU[i]); + */ + } +} + +/*** + ***/ + +static void +eval_frequency(dim, deg_o) + int deg_o; +{ + int i, im; + double min; + + min = D[0]; + im = 0; + + for (i = 1; i < dim; i++) + if (D[i] < min) { + min = D[i]; + im = i; + } + + if (min <= 0) { + fprintf(stderr, "A mode frequency is not positive. Abort!\n"); + exit(0); + } + + Scaling_F2 = 1.0 / min; + Scaling_F = sqrt(Scaling_F2); + min = length * 8.0; + /* + min *= 1.0e18; + min = sqrt(min)*1.0e-9*length/8.0; + */ + + frequency[0] = 0.0; + + for (i = 1; i <= deg_o; i++) + frequency[i] = frequency[i-1] + min; + + for (i = 0; i < dim; i++) + D[i] *= Scaling_F2; +} + +/*** + ***/ + +static void +store(dim, ind) + int ind; +{ + int i, j; + + for (i = 0; i < dim; i++) { + for (j = 0; j < dim; j++) { + /* store_Sip */ + Sip[i][j][ind] = Si[i][j]; + /* store_Si_1p */ + Si_1p[i][j][ind] = Si_1[i][j]; + /* store_Sv_1p */ + Sv_1p[i][j][ind] = Sv_1[i][j]; + } + /* store_W */ + W[i][ind] = D[i]; + } +} + +/*** + ***/ + +static void +store_SiSv_1(dim, ind) +{ + int i, j, k; + double temp; + + for (i = 0; i < dim; i++) + for (j = 0; j < dim; j++) { + temp = 0.0; + for (k = 0; k < dim; k++) + temp += Si[i][k] * Sv_1[k][j]; + SiSv_1[i][j][ind] = temp; + } +} + +/*** + ***/ +/*** +static int +check(Sip, Si_1p, Sv_1p, SiSv_1p) + double *Sip[MAX_DIM][MAX_DIM]; + double *Si_1p[MAX_DIM][MAX_DIM]; + double *Sv_1p[MAX_DIM][MAX_DIM]; + double *SiSv_1p[MAX_DIM][MAX_DIM]; +{ + double f, y; + float y1; + int i, j, k; + + printf("y ="); + scanf("%f", &y1); + + printf("\n"); + printf("Si =\n"); + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + f = Sip[i][j][0]; + y = y1; + f += y * Sip[i][j][1]; + for (k = 2; k < 8; k++) { + y *= y1; + f += y * Sip[i][j][k]; + } + printf("%e ", f); + } + printf("\n"); + } + printf("\n"); + printf("Si_1 =\n"); + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + f = Si_1p[i][j][0]; + y = y1; + f += y * Si_1p[i][j][1]; + for (k = 2; k < 8; k++) { + y *= y1; + f += y * Si_1p[i][j][k]; + } + printf("%e ", f); + } + printf("\n"); + } + printf("\n"); + printf("Sv_1 =\n"); + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + f = Sv_1p[i][j][0]; + y = y1; + f += y * Sv_1p[i][j][1]; + for (k = 2; k < 8; k++) { + y *= y1; + f += y * Sv_1p[i][j][k]; + } + printf("%e ", f); + } + printf("\n"); + } + printf("\n"); + printf("SiSv_1 =\n"); + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + f = SiSv_1p[i][j][0]; + y = y1; + f += y * SiSv_1p[i][j][1]; + for (k = 2; k < 8; k++) { + y *= y1; + f += y * SiSv_1p[i][j][k]; + } + printf("%e ", f); + } + printf("\n"); + } + return(1); +} +***/ +/*** + ***/ + +static int +coupled(dim) + int dim; +{ + int deg, deg_o; + int i; + + deg = Right_deg; + deg_o = Left_deg; + new_memory(dim, deg, deg_o); + + Scaling_F = Scaling_F2 = 1.0; + + /*** y = 0 : ZY = LC ***/ + loop_ZY(dim, (double) 0.0); + eval_frequency(dim, deg_o); + eval_Si_Si_1(dim, (double) 0.0); + store_SiSv_1(dim, (int) 0); + store(dim, (int) 0); + + /*** Step 1 ***/ + /*** Step 2 ***/ + for (i = 1; i <= deg_o; i++) { + loop_ZY(dim, frequency[i]); + eval_Si_Si_1(dim, frequency[i]); + store_SiSv_1(dim, i); + store(dim, i); + } + poly_matrix(Sip, dim, deg_o); + poly_matrix(Si_1p, dim, deg_o); + poly_matrix(Sv_1p, dim, deg_o); + poly_W(dim, deg_o); + matrix_p_mult(Sip, W, Si_1p, dim, deg_o, deg_o, IWI); + matrix_p_mult(Sip, W, Sv_1p, dim, deg_o, deg_o, IWV); + + poly_matrix(SiSv_1, dim, deg_o); + + /*** + check(Sip, Si_1p, Sv_1p, SiSv_1); + ***/ + + generate_out(dim, deg_o); + + return(1); +} + +/*** + ***/ + +static int +generate_out(dim, deg_o) + int dim, deg_o; +{ + int i, j, k, rtv; + double C; + double *p; + double c1, c2, c3, x1, x2, x3; + + for (i = 0; i < dim; i++) + for (j = 0; j < dim; j++) { + p = SiSv_1[i][j]; + SIV[i][j].C_0 = C = p[0]; + if (C == 0.0) + continue; + for (k = 0; k <= deg_o; k++) + p[k] /= C; + if (i == j) { + rtv = Pade_apx((double) sqrt((double) G_m[i][i] / R_m[i][i]) / C, + p, &c1, &c2, &c3, &x1, &x2, &x3); + if (rtv == 0) { + SIV[i][j].C_0 = 0.0; + printf("SIV\n"); + continue; + } + } else { + rtv = Pade_apx((double) 0.0, + p, &c1, &c2, &c3, &x1, &x2, &x3); + if (rtv == 0) { + SIV[i][j].C_0 = 0.0; + printf("SIV\n"); + continue; + } + } + p = SIV[i][j].Poly = (double *) calloc(7, sizeof(double)); + p[0] = c1; + p[1] = c2; + p[2] = c3; + p[3] = x1; + p[4] = x2; + p[5] = x3; + p[6] = (double) rtv; + } + for (i = 0; i < dim; i++) + for (j = 0; j < dim; j++) + for (k = 0; k < dim; k++) { + p = IWI[i][j].Poly[k]; + C = IWI[i][j].C_0[k]; + if (C == 0.0) + continue; + if (i == j && k == i) { + rtv = Pade_apx((double) + exp(- sqrt((double) G_m[i][i] * R_m[i][i]) * length) / C, + p, &c1, &c2, &c3, &x1, &x2, &x3); + if (rtv == 0) { + IWI[i][j].C_0[k] = 0.0; + printf("IWI %d %d %d\n", i, j, k); + continue; + } + } else { + rtv = Pade_apx((double) 0.0, + p, &c1, &c2, &c3, &x1, &x2, &x3); + if (rtv == 0) { + IWI[i][j].C_0[k] = 0.0; + printf("IWI %d %d %d\n", i, j, k); + continue; + } + } + p[0] = c1; + p[1] = c2; + p[2] = c3; + p[3] = x1; + p[4] = x2; + p[5] = x3; + p[6] = (double) rtv; + } + + for (i = 0; i < dim; i++) + for (j = 0; j < dim; j++) + for (k = 0; k < dim; k++) { + p = IWV[i][j].Poly[k]; + C = IWV[i][j].C_0[k]; + if (C == 0.0) + continue; + if (i == j && k == i) { + rtv = Pade_apx((double) sqrt((double) G_m[i][i] / R_m[i][i]) * + exp(- sqrt((double) G_m[i][i] * R_m[i][i]) * length) / C, + p, &c1, &c2, &c3, &x1, &x2, &x3); + if (rtv == 0) { + IWV[i][j].C_0[k] = 0.0; + printf("IWV %d %d %d\n", i, j, k); + continue; + } + } else { + rtv = Pade_apx((double) 0.0, + p, &c1, &c2, &c3, &x1, &x2, &x3); + if (rtv == 0) { + IWV[i][j].C_0[k] = 0.0; + printf("IWV %d %d %d\n", i, j, k); + continue; + } + } + p[0] = c1; + p[1] = c2; + p[2] = c3; + p[3] = x1; + p[4] = x2; + p[5] = x3; + p[6] = (double) rtv; + } + return(1); +} + +/**************************************************************** + mult.c Multiplication for Matrix of Polynomial + X(y) = A(y) D(y) B(y), + where D(y) is a diagonal matrix with each + diagonal entry of the form + e^{-a_i s}d(y), for which s = 1/y + and i = 1..N. + Each entry of X(y) will be of the form + \sum_{i=1}^N c_i e^{-a_i s} b_i(y), where + b_i(0) = 1; therefore, those + b_i(y)'s will be each entry's output. + ****************************************************************/ + +static void +mult_p(p1, p2, p3, d1, d2, d3) +/* p3 = p1 * p2 */ + double *p1, *p2, *p3; + int d1, d2, d3; +{ + int i, j, k; + + for (i = 0; i <= d3; i++) + p3[i] = 0.0; + for (i = 0; i <= d1; i++) + for (j = i, k = 0; k <= d2; j++, k++) { + if (j > d3) + break; + p3[j] += p1[i] * p2[k]; + } +} + + +static void +matrix_p_mult(A, D, B, dim, deg, deg_o, X) + double *A[MAX_DIM][MAX_DIM]; + double *D[MAX_DIM]; + double *B[MAX_DIM][MAX_DIM]; + int dim, deg, deg_o; + Mult_Out X[MAX_DIM][MAX_DIM]; +{ + int i, j, k, l; + double *p; + double *T[MAX_DIM][MAX_DIM]; + double t1; + + for (i = 0; i < dim; i++) + for (j = 0; j < dim; j++) { + p = T[i][j] = (double *) calloc(deg_o+1, sizeof(double)); + mult_p(B[i][j], D[i], p, deg, deg_o, deg_o); + } + for (i = 0; i < dim; i++) + for (j = 0; j < dim; j++) + for (k = 0; k < dim; k++) { + p = X[i][j].Poly[k] = + (double *) calloc(deg_o+1, sizeof(double)); + mult_p(A[i][k], T[k][j], p, deg, deg_o, deg_o); + t1 = X[i][j].C_0[k] = p[0]; + if (t1 != 0.0) { + p[0] = 1.0; + for (l = 1; l <= deg_o; l++) + p[l] /= t1; + } + } + + /********** + for (i = 0; i < dim; i++) + for (j = 0; j < dim; j++) { + for (k = 0; k < dim; k++) { + fprintf(outFile, "(%5.3f)", X[i][j].C_0[k]); + p = X[i][j].Poly[k]; + for (l = 0; l <= deg_o; l++) + fprintf(outFile, "%5.3f ", p[l]); + fprintf(outFile, "\n"); + } + fprintf(outFile, "\n"); + } + ***********/ +} + +/**************************************************************** + mode approximation + + ****************************************************************/ + +/*** + ***/ + +static double +approx_mode(X, b, length) + double X[], b[], length; +{ + double w0, w1, w2, w3, w4, w5; + double a[8]; + double delay, atten; + double y1, y2, y3, y4, y5, y6; + int i, j; + + w0 = X[0]; + w1 = X[1] / w0; /* a */ + w2 = X[2] / w0; /* b */ + w3 = X[3] / w0; /* c */ + w4 = X[4] / w0; /* d */ + w5 = X[5] / w0; /* e */ + + y1 = 0.5 * w1; + y2 = w2 - y1 * y1; + y3 = 3 * w3 - 3.0 * y1 * y2; + y4 = 12.0 * w4 - 3.0 * y2 * y2 - 4.0 * y1 * y3; + y5 = 60.0 * w5 - 5.0 * y1 * y4 -10.0 * y2 * y3; + y6 = -10.0 * y3 * y3 - 15.0 * y2 * y4 - 6.0 * y1 * y5; + + delay = sqrt(w0) * length / Scaling_F; + atten = exp((double) - delay * y1); + + a[1] = y2 / 2.0; + a[2] = y3 / 6.0; + a[3] = y4 / 24.0; + a[4] = y5 / 120.0; + a[5] = y6 / 720.0; + + a[1] *= -delay; + a[2] *= -delay; + a[3] *= -delay; + a[4] *= -delay; + a[5] *= -delay; + + b[0] = 1.0; + b[1] = a[1]; + for (i = 2; i <= 5; i++) { + b[i] = 0.0; + for (j = 1; j <= i; j++) + b[i] += j * a[j] * b[i-j]; + b[i] = b[i] / (double) i; + } + + for (i = 0; i <= 5; i++) + b[i] *= atten; + + return(delay); +} + +/*** + ***/ + +static double +eval2(a, b, c, x) + double a, b, c, x; +{ + return(a*x*x + b*x + c); +} + +/*** + ***/ + +static int +get_c(q1, q2, q3, p1, p2, a, b, cr, ci) + double q1, q2, q3, p1, p2, a, b; + double *cr, *ci; +{ + double d, n; + + d = (3.0*(a*a-b*b)+2.0*p1*a+p2)*(3.0*(a*a-b*b)+2.0*p1*a+p2); + d += (6.0*a*b+2.0*p1*b)*(6.0*a*b+2.0*p1*b); + n = -(q1*(a*a-b*b)+q2*a+q3)*(6.0*a*b+2.0*p1*b); + n += (2.0*q1*a*b+q2*b)*(3.0*(a*a-b*b)+2.0*p1*a+p2); + *ci = n/d; + n = (3.0*(a*a-b*b)+2.0*p1*a+p2)*(q1*(a*a-b*b)+q2*a+q3); + n += (6.0*a*b+2.0*p1*b)*(2.0*q1*a*b+q2*b); + *cr = n/d; + + return(1); +} + + +static int +Pade_apx(a_b, b, c1, c2, c3, x1, x2, x3) +/* + b[0] + b[1]*y + b[2]*y^2 + ... + b[5]*y^5 + ... + = (q3*y^3 + q2*y^2 + q1*y + 1) / (p3*y^3 + p2*y^2 + p1*y + 1) + + where b[0] is always equal to 1.0 and neglected, + and y = 1/s. + + (q3*y^3 + q2*y^2 + q1*y + 1) / (p3*y^3 + p2*y^2 + p1*y + 1) + = (s^3 + q1*s^2 + q2*s + q3) / (s^3 + p1*s^2 + p2*s + p3) + = c1 / (s - x1) + c2 / (s - x2) + c3 / (s - x3) + 1.0 + */ + double a_b; + double b[]; + double *c1, *c2, *c3; + double *x1, *x2, *x3; +{ + double p1, p2, p3, q1, q2, q3; + + At[0][0] = 1.0 - a_b; + At[0][1] = b[1]; + At[0][2] = b[2]; + At[0][3] = -b[3]; + + At[1][0] = b[1]; + At[1][1] = b[2]; + At[1][2] = b[3]; + At[1][3] = -b[4]; + + At[2][0] = b[2]; + At[2][1] = b[3]; + At[2][2] = b[4]; + At[2][3] = -b[5]; + + Gaussian_Elimination(3); + + p3 = At[0][3]; + p2 = At[1][3]; + p1 = At[2][3]; + /* + if (p3 < 0.0 || p2 < 0.0 || p1 < 0.0 || p1*p2 <= p3) + return(0); + */ + q1 = p1 + b[1]; + q2 = b[1] * p1 + p2 + b[2]; + q3 = p3 * a_b; + + if (find_roots(p1, p2, p3, x1, x2, x3)) { + /* + printf("complex roots : %e %e %e \n", *x1, *x2, *x3); + */ + *c1 = eval2(q1 - p1, q2 - p2, q3 - p3, *x1) / + eval2((double) 3.0, (double) 2.0 * p1, p2, *x1); + get_c(q1 - p1, q2 - p2, q3 - p3, p1, p2, *x2, *x3, c2, c3); + return(2); + } else { + /* new + printf("roots are %e %e %e \n", *x1, *x2, *x3); + */ + *c1 = eval2(q1 - p1, q2 - p2, q3 - p3, *x1) / + eval2((double) 3.0, (double) 2.0 * p1, p2, *x1); + *c2 = eval2(q1 - p1, q2 - p2, q3 - p3, *x2) / + eval2((double) 3.0, (double) 2.0 * p1, p2, *x2); + *c3 = eval2(q1 - p1, q2 - p2, q3 - p3, *x3) / + eval2((double) 3.0, (double) 2.0 * p1, p2, *x3); + return(1); + } +} + +static int +Gaussian_Elimination(dims) + int dims; +{ + register int i, j, k, dim; + register double f; + double max; + int imax; + + dim = dims; + + for (i = 0; i < dim; i++) { + imax = i; + max = ABS(At[i][i]); + for (j = i+1; j < dim; j++) + if (ABS(At[j][i]) > max) { + imax = j; + max = ABS(At[j][i]); + } + if (max < epsi_mult) { + fprintf(stderr, " can not choose a pivot (mult)\n"); + exit(0); + } + if (imax != i) + for (k = i; k <= dim; k++) { + f = At[i][k]; + At[i][k] = At[imax][k]; + At[imax][k] = f; + } + + f = 1.0 / At[i][i]; + At[i][i] = 1.0; + + for (j = i+1; j <= dim; j++) + At[i][j] *= f; + + for (j = 0; j < dim ; j++) { + if (i == j) + continue; + f = At[j][i]; + At[j][i] = 0.0; + for (k = i+1; k <= dim; k++) + At[j][k] -= f * At[i][k]; + } + } + return(1); +} + +static double +root3(a1, a2, a3, x) + double x; + double a1, a2, a3; +{ + double t1, t2; + + t1 = x * (x * (x + a1) + a2) + a3; + t2 = x * (2.0*a1 + 3.0*x) + a2; + + return(x - t1 / t2); +} + +static int +div3(a1, a2, a3, x, p1, p2) + double x; + double a1, a2, a3; + double *p1, *p2; +{ + *p1 = a1 + x; + + /* *p2 = a2 + (a1 + x) * x; */ + + *p2 = - a3 / x; + + return(1); +} + + +static int +find_roots(a1, a2, a3, x1, x2, x3) + double a1, a2, a3; + double *x1, *x2, *x3; +{ + double x, t; + double p, q; + + /*********************************************** + double m,n; + p = a1*a1/3.0 - a2; + q = a1*a2/3.0 - a3 - 2.0*a1*a1*a1/27.0; + p = p*p*p/27.0; + t = q*q - 4.0*p; + if (t < 0.0) { + if (q != 0.0) { + t = atan(sqrt((double)-t)/q); + if (t < 0.0) + t += 3.141592654; + t /= 3.0; + x = 2.0 * pow(p, 0.16666667) * cos(t) - a1 / 3.0; + } else { + t /= -4.0; + x = pow(t, 0.16666667) * 1.732 - a1 / 3.0; + } + } else { + t = sqrt(t); + m = 0.5*(q - t); + n = 0.5*(q + t); + if (m < 0.0) + m = -pow((double) -m, (double) 0.3333333); + else + m = pow((double) m, (double) 0.3333333); + if (n < 0.0) + n = -pow((double) -n, (double) 0.3333333); + else + n = pow((double) n, (double) 0.3333333); + x = m + n - a1 / 3.0; + } + ************************************************/ + q = (a1*a1-3.0*a2) / 9.0; + p = (2.0*a1*a1*a1-9.0*a1*a2+27.0*a3) / 54.0; + t = q*q*q - p*p; + if (t >= 0.0) { + t = acos((double) p /(q * sqrt(q))); + x = -2.0*sqrt(q)*cos(t / 3.0) - a1/3.0; + } else { + if (p > 0.0) { + t = pow(sqrt(-t)+p, (double) 1.0 / 3.0); + x = -(t + q / t) - a1/3.0; + } else if (p == 0.0) { + x = -a1/3.0; + } else { + t = pow(sqrt(-t)-p, (double) 1.0 / 3.0); + x = (t + q / t) - a1/3.0; + } + } + /* + fprintf(stderr, "..1.. %e\n", x*x*x+a1*x*x+a2*x+a3); + */ + { + double x1; + int i = 0; + x1 = x; + for (t = root3(a1, a2, a3, x); ABS(t-x) > 5.0e-4; + t = root3(a1, a2, a3, x)) + if (++i == 32) { + x = x1; + break; + } else + x = t; + } + /* + fprintf(stderr, "..2.. %e\n", x*x*x+a1*x*x+a2*x+a3); + */ + + + *x1 = x; + div3(a1, a2, a3, x, &a1, &a2); + + t = a1 * a1 - 4.0 * a2; + if (t < 0) { + /* + fprintf(stderr, "***** Two Imaginary Roots.\n Update.\n"); + *x2 = -0.5 * a1; + *x3 = a2 / *x2; + */ + *x3 = 0.5 * sqrt(-t); + *x2 = -0.5 * a1; + return(1); + } else { + t = sqrt(t); + if (a1 >= 0.0) + *x2 = t = -0.5 * (a1 + t); + else + *x2 = t = -0.5 * (a1 - t); + *x3 = a2 / t; + return(0); + } +} + + +static NDnamePt +insert_ND(name, ndn) + char *name; + NDnamePt *ndn; +{ + int cmp; + NDnamePt p; + + if (*ndn == NULL) { + p = *ndn = (NDnamePt) malloc(sizeof (NDname)); + p->nd = NULL; + p->right = p->left = NULL; + strcpy(p->id, name); + return(p); + } + cmp = strcmp((*ndn)->id, name); + if (cmp == 0) + return(*ndn); + else { + if (cmp < 0) + return(insert_ND(name, &((*ndn)->left))); + else + return(insert_ND(name, &((*ndn)->right))); + } +} + +static NODE * +insert_node(name) + char *name; +{ + NDnamePt n; + NODE *p; + + n = insert_ND(name, &ndn); + if (n->nd == NULL) { + p = NEW_node(); + p->name = n; + n->nd = p; + p->next = node_tab; + node_tab = p; + return(p); + } else + return(n->nd); +} +/*** +static int divC(ar, ai, br, bi, cr, ci) +double ar, ai, br, bi; +double *cr, *ci; +{ + double t; + + t = br*br + bi*bi; + *cr = (ar*br + ai*bi) / t; + *ci = (ai*br - ar*bi) / t; + + return(1); +} +***/ + +static NODE +*NEW_node() +{ + /* + char *malloc(); + */ + NODE *n; + + n = (NODE *) malloc (sizeof (NODE)); + n->mptr = NULL; + n->gptr = NULL; + n->cptr = NULL; + n->rptr = NULL; + n->tptr = NULL; + n->cplptr = NULL; + n->rlptr = NULL; + n->ddptr = NULL; + n->cvccsptr = NULL; + n->vccsptr = NULL; + n->CL = 0.001; + n->V = n->dv = 0.0; + n->gsum = n->cgsum = 0; + n->is = 0; + n->tag = 0; + n->flag = 0; + n->region = NULL; + n->ofile = NULL; + n->dvtag = 0; + + return(n); +} + + + +/**************************************************************** + diag.c This file contains the main(). + ****************************************************************/ + +#define epsi2 1.0e-8 + +static int dim; +static MAXE_PTR row; + +static MAXE_PTR +sort(list, val, r, c, e) + MAXE_PTR list, e; + float val; + int r, c; +{ + if (list == NULL || list->value < val) { + e->row = r; + e->col = c; + e->value = val; + e->next = list; + return(e); + } else { + list->next = sort(list->next, val, r, c, e); + return(list); + } +} + + +static void +ordering() +{ + MAXE_PTR e; + int i, j, m; + float mv; + + for (i = 0; i < dim-1; i++) { + m = i+1; + mv = ABS(ZY[i][m]); + for (j = m+1; j < dim; j++) + if ((int)(ABS(ZY[i][j]) * 1e7) > (int) (1e7 *mv)) { + + mv = ABS(ZY[i][j]); + m = j; + } + e = (MAXE_PTR) malloc(sizeof (MAXE)); + row = sort(row, mv, i, m, e); + } +} + + +static MAXE_PTR +delete_1(list, rc) + MAXE_PTR *list; + int rc; +{ + MAXE_PTR list1, e; + + list1 = *list; + if ((*list)->row == rc) { + *list = (*list)->next; + return(list1); + } + for (e = list1->next; e->row != rc; e = e->next) + list1 = e; + list1->next = e->next; + return(e); +} + + +static void +reordering(p, q) + int p, q; +{ + MAXE_PTR e; + int j, m; + float mv; + + m = p+1; + mv = ABS(ZY[p][m]); + for (j = m+1; j < dim; j++) + if ((int)(ABS(ZY[p][j]) * 1e7) > (int) (1e7 *mv)) { + mv = ABS(ZY[p][j]); + m = j; + } + e = delete_1(&row, p); + row = sort(row, mv, p, m, e); + + m = q+1; + if (m != dim) { + mv = ABS(ZY[q][m]); + for (j = m+1; j < dim; j++) + if ((int)(ABS(ZY[q][j]) * 1e7) > (int) (1e7 *mv)) { + + mv = ABS(ZY[q][j]); + m = j; + } + e = delete_1(&row, q); + row = sort(row, mv, q, m, e); + } + +} + +static void +diag(dims) + int dims; +{ + int i, j, c; + double fmin, fmax; + + dim = dims; + row = NULL; + + fmin = fmax = ABS(ZY[0][0]); + for (i = 0; i < dim; i++) + for (j = i; j < dim; j++) + if (ABS(ZY[i][j]) > fmax) + fmax = ABS(ZY[i][j]); + else if (ABS(ZY[i][j]) < fmin) + fmin = ABS(ZY[i][j]); + fmin = 2.0 / (fmin + fmax); + for (i = 0; i < dim; i++) + for (j = i; j < dim; j++) + ZY[i][j] *= fmin; + + for (i = 0; i < dim; i++) { + for (j = 0; j < dim; j++) + if (i == j) + Sv[i][i] = 1.0; + else + Sv[i][j] = 0.0; + } + + ordering(); + + if (row) + for (c = 0; row->value > epsi2; c++) { + int p, q; + + p = row->row; + q = row->col; + + rotate(dim, p, q); + reordering(p, q); + } + + for (i = 0; i < dim; i++) + D[i] = ZY[i][i] / fmin; +} + +/**************************************************************** + rotate() rotation of the Jacobi's method + ****************************************************************/ + +static int +rotate(dim, p, q) + int p, q, dim; +{ + int j; + double co, si; + double ve, mu, ld; + double T[MAX_DIM]; + double t; + + ld = - ZY[p][q]; + mu = 0.5 * (ZY[p][p] - ZY[q][q]); + ve = sqrt((double) ld*ld + mu*mu); + co = sqrt((double) (ve + ABS(mu)) / (2.0 * ve)); + si = SGN(mu) * ld / (2.0 * ve * co); + + for (j = p+1; j < dim; j++) + T[j] = ZY[p][j]; + for (j = 0; j < p; j++) + T[j] = ZY[j][p]; + + for (j = p+1; j < dim; j++) { + if (j == q) + continue; + if (j > q) + ZY[p][j] = T[j] * co - ZY[q][j] * si; + else + ZY[p][j] = T[j] * co - ZY[j][q] * si; + } + for (j = q+1; j < dim; j++) { + if (j == p) + continue; + ZY[q][j] = T[j] * si + ZY[q][j] * co; + } + for (j = 0; j < p; j++) { + if (j == q) + continue; + ZY[j][p] = T[j] * co - ZY[j][q] * si; + } + for (j = 0; j < q; j++) { + if (j == p) + continue; + ZY[j][q] = T[j] * si + ZY[j][q] * co; + } + + t = ZY[p][p]; + ZY[p][p] = t * co * co + ZY[q][q] * si * si - 2.0 * ZY[p][q] * si * co; + ZY[q][q] = t * si * si + ZY[q][q] * co * co + 2.0 * ZY[p][q] * si * co; + + ZY[p][q] = 0.0; + + { + double R[MAX_DIM]; + + for (j = 0; j < dim; j++) { + T[j] = Sv[j][p]; + R[j] = Sv[j][q]; + } + + for (j = 0; j < dim; j++) { + Sv[j][p] = T[j] * co - R[j] * si; + Sv[j][q] = T[j] * si + R[j] * co; + } + } + + return(1); + +} + diff --git a/src/spicelib/devices/txl/Makefile.am b/src/spicelib/devices/txl/Makefile.am new file mode 100755 index 000000000..6070d74b4 --- /dev/null +++ b/src/spicelib/devices/txl/Makefile.am @@ -0,0 +1,21 @@ +## Process this file with automake to produce Makefile.in + +noinst_LIBRARIES = libtxl.a + +libtxl_a_SOURCES = \ + txl.c \ + txlask.c \ + txldest.c \ + txlload.c \ + txlmdel.c \ + txlparam.c \ + txlacct.c \ + txldel.c \ + txlmask.c \ + txlmpar.c \ + txlsetup.c \ + txlinit.c + +INCLUDES = -I$(top_srcdir)/src/include + +MAINTAINERCLEANFILES = Makefile.in diff --git a/src/spicelib/devices/txl/txl.c b/src/spicelib/devices/txl/txl.c new file mode 100644 index 000000000..c1b3d2a8c --- /dev/null +++ b/src/spicelib/devices/txl/txl.c @@ -0,0 +1,38 @@ +/********** +Copyright 1992 Regents of the University of California. All rights +reserved. +Author: 1992 Charles Hough +**********/ + +#include "ngspice.h" +#include +#include "txldefs.h" +#include "devdefs.h" +#include "ifsim.h" +#include "suffix.h" + +IFparm TXLpTable[] = { + IP("pos_node", TXL_IN_NODE, IF_INTEGER,"Positive node of txl"), + IP("neg_node", TXL_OUT_NODE, IF_INTEGER,"Negative node of txl"), + IOP("length", TXL_LENGTH, IF_REAL,"length of line"), +}; + +IFparm TXLmPTable[] = { /* model parameters */ + IOP( "r", TXL_R, IF_REAL,"resistance per length"), + IOP( "l", TXL_L, IF_REAL,"inductance per length"), + IOP( "c", TXL_C, IF_REAL,"capacitance per length"), + IOP( "g", TXL_G, IF_REAL,"conductance per length"), + IOP( "length", TXL_length, IF_REAL,"length"), + IP( "txl", TXL_MOD_R, IF_FLAG,"Device is a txl model"), +}; + +char *TXLnames[] = { + "Y+", + "Y-" +}; + +int TXLnSize = NUMELEMS(TXLnames); +int TXLiSize = sizeof(TXLinstance); +int TXLmSize = sizeof(TXLmodel); +int TXLmPTSize = NUMELEMS(TXLmPTable); +int TXLpTSize = NUMELEMS(TXLpTable); diff --git a/src/spicelib/devices/txl/txlacct.c b/src/spicelib/devices/txl/txlacct.c new file mode 100644 index 000000000..bc4c979f6 --- /dev/null +++ b/src/spicelib/devices/txl/txlacct.c @@ -0,0 +1,76 @@ +/********** +Copyright 1992 Regents of the University of California. All rights +reserved. +Author: 1992 Charles Hough +**********/ + + +#include "ngspice.h" +#include +#include +#include "cktdefs.h" +#include "txldefs.h" +#include "sperror.h" +#include "suffix.h" + + +int +TXLaccept(ckt,inModel) + register CKTcircuit *ckt; + GENmodel *inModel; + /* set up the breakpoint table. + */ +{ + register TXLmodel *model = (TXLmodel *)inModel; + register TXLinstance *here; + int hint; + double h, v, v1; + NODE *nd; + TXLine *tx; + + /* loop through all the voltage source models */ + for( ; model != NULL; model = model->TXLnextModel ) { + + /* loop through all the instances of the model */ + for (here = model->TXLinstances; here != NULL ; + here=here->TXLnextInstance) { + + h = ckt->CKTdelta; + hint = (int) (h * 1e12); + if (hint != 0) { + tx = here->txline; + nd = tx->in_node; + if (nd->dvtag == 0) { + v = nd->V; + v1 = nd->V = *(ckt->CKTrhs + here->TXLposNode); + nd->dv = (v1 - v) / hint; + nd->dvtag = 1; + } + nd = tx->out_node; + if (nd->dvtag == 0) { + v = nd->V; + v1 = nd->V = *(ckt->CKTrhs + here->TXLnegNode); + nd->dv = (v1 - v) / hint; + nd->dvtag = 1; + } + } + else { + /* can't happen. */ + printf("zero h detected\n"); + exit(1); + } + } + } + model = (TXLmodel *)inModel; + for( ; model != NULL; model = model->TXLnextModel ) { + for (here = model->TXLinstances; here != NULL ; + here=here->TXLnextInstance) { + nd = here->txline->in_node; + nd->dvtag = 0; + nd = here->txline->out_node; + nd->dvtag = 0; + } + } + + return(OK); +} diff --git a/src/spicelib/devices/txl/txlask.c b/src/spicelib/devices/txl/txlask.c new file mode 100644 index 000000000..2fd2dde5f --- /dev/null +++ b/src/spicelib/devices/txl/txlask.c @@ -0,0 +1,43 @@ +/********** +Copyright 1992 Regents of the University of California. All rights +reserved. +Author: 1992 Charles Hough +**********/ + + +#include "ngspice.h" +#include +#include +#include "const.h" +#include "txldefs.h" +#include "ifsim.h" +#include "cktdefs.h" +#include "sperror.h" +#include "suffix.h" + + +/*ARGSUSED*/ +int +TXLask(ckt,inst,which,value,select) + CKTcircuit *ckt; + GENinstance *inst; + int which; + IFvalue *value; + IFvalue *select; +{ + TXLinstance *fast = (TXLinstance *)inst; + switch(which) { + case TXL_OUT_NODE: + value->iValue = fast->TXLnegNode; + return(OK); + case TXL_IN_NODE: + value->iValue = fast->TXLposNode; + return(OK); + case TXL_LENGTH: + value->rValue = fast->TXLlength; + return(OK); + default: + return(E_BADPARM); + } + /* NOTREACHED */ +} diff --git a/src/spicelib/devices/txl/txldefs.h b/src/spicelib/devices/txl/txldefs.h new file mode 100644 index 000000000..3bb520f10 --- /dev/null +++ b/src/spicelib/devices/txl/txldefs.h @@ -0,0 +1,92 @@ +#ifndef TXL +#define TXL + +#include "ifsim.h" +#include "cktdefs.h" +#include "gendefs.h" +#include "complex.h" +#include "noisedef.h" +#include "swec.h" + +/* information used to describe a single instance */ + +typedef struct sTXLinstance { + struct sTXLmodel *TXLmodPtr; /* backpointer to model */ + struct sTXLinstance *TXLnextInstance; /* pointer to next instance of + * current model*/ + + IFuid TXLname; /* pointer to character string naming this instance */ + + int TXLposNode; + int TXLnegNode; + double TXLlength; + int TXLibr1; + int TXLibr2; + TXLine *txline; /* pointer to SWEC txline type */ + TXLine *txline2; /* pointer to SWEC txline type. temporary storage */ + char *in_node_name; + char *out_node_name; + + double *TXLposPosptr; + double *TXLposNegptr; + double *TXLnegPosptr; + double *TXLnegNegptr; + double *TXLibr1Posptr; + double *TXLibr2Negptr; + double *TXLposIbr1ptr; + double *TXLnegIbr2ptr; + double *TXLibr1Negptr; + double *TXLibr2Posptr; + double *TXLibr1Ibr1ptr; + double *TXLibr2Ibr2ptr; + double *TXLibr1Ibr2ptr; + double *TXLibr2Ibr1ptr; + + unsigned TXLibr1Given : 1; + unsigned TXLibr2Given : 1; + unsigned TXLdcGiven : 1; + unsigned TXLlengthgiven : 1; /* flag to indicate C was specified */ + +} TXLinstance ; + + +/* per model data */ + +typedef struct sTXLmodel { /* model structure for a txl */ + int TXLmodType; /* type index of this device type */ + struct sTXLmodel *TXLnextModel; /* pointer to next possible model in + * linked list */ + TXLinstance * TXLinstances; /* pointer to list of instances that have this + * model */ + IFuid TXLmodName; /* pointer to character string naming this model */ + + double R; + double L; + double G; + double C; + double length; + unsigned Rgiven : 1; /* flag to indicate R was specified */ + unsigned Lgiven : 1; /* flag to indicate L was specified */ + unsigned Ggiven : 1; /* flag to indicate G was specified */ + unsigned Cgiven : 1; /* flag to indicate C was specified */ + unsigned lengthgiven : 1; /* flag to indicate C was specified */ + +} TXLmodel; + +/* instance parameters */ +#define TXL_IN_NODE 1 +#define TXL_OUT_NODE 2 +#define TXL_LENGTH 3 + +/* model parameters */ +#define TXL_R 101 +#define TXL_C 102 +#define TXL_G 103 +#define TXL_L 104 +#define TXL_length 105 +#define TXL_MOD_R 106 + +#include "txlext.h" +extern VI_list_txl *pool_vi_txl; + +#endif /*TXL*/ diff --git a/src/spicelib/devices/txl/txldel.c b/src/spicelib/devices/txl/txldel.c new file mode 100644 index 000000000..3817a3f65 --- /dev/null +++ b/src/spicelib/devices/txl/txldel.c @@ -0,0 +1,38 @@ +/********** +Copyright 1992 Regents of the University of California. All rights +reserved. +Author: 1992 Charles Hough +**********/ + + +#include "ngspice.h" +#include +#include "txldefs.h" +#include "sperror.h" +#include "suffix.h" + + +int +TXLdelete(inModel,name,inst) + GENmodel *inModel; + IFuid name; + GENinstance **inst; +{ + TXLmodel *model = (TXLmodel *)inModel; + TXLinstance **fast = (TXLinstance **)inst; + TXLinstance **prev = NULL; + TXLinstance *here; + + for( ; model ; model = model->TXLnextModel) { + prev = &(model->TXLinstances); + for(here = *prev; here ; here = *prev) { + if(here->TXLname == name || (fast && here==*fast) ) { + *prev= here->TXLnextInstance; + FREE(here); + return(OK); + } + prev = &(here->TXLnextInstance); + } + } + return(E_NODEV); +} diff --git a/src/spicelib/devices/txl/txldest.c b/src/spicelib/devices/txl/txldest.c new file mode 100644 index 000000000..6c371f9fe --- /dev/null +++ b/src/spicelib/devices/txl/txldest.c @@ -0,0 +1,36 @@ +/********** +Copyright 1992 Regents of the University of California. All rights +reserved. +Author: 1992 Charles Hough +**********/ + + +#include "ngspice.h" +#include +#include "txldefs.h" +#include "suffix.h" + + +void +TXLdestroy(inModel) + GENmodel **inModel; +{ + TXLmodel **model = (TXLmodel **)inModel; + TXLinstance *here; + TXLinstance *prev = NULL; + TXLmodel *mod = *model; + TXLmodel *oldmod = NULL; + + for( ; mod ; mod = mod->TXLnextModel) { + if(oldmod) FREE(oldmod); + oldmod = mod; + prev = (TXLinstance *)NULL; + for(here = mod->TXLinstances ; here ; here = here->TXLnextInstance) { + if(prev) FREE(prev); + prev = here; + } + if(prev) FREE(prev); + } + if(oldmod) FREE(oldmod); + *model = NULL; +} diff --git a/src/spicelib/devices/txl/txlext.h b/src/spicelib/devices/txl/txlext.h new file mode 100644 index 000000000..2ad036a7f --- /dev/null +++ b/src/spicelib/devices/txl/txlext.h @@ -0,0 +1,19 @@ +#ifdef __STDC__ +/* extern int TXLaccept(CKTcircuit*,GENmodel*); */ +extern int TXLdelete(GENmodel*,IFuid,GENinstance**); +extern void TXLdestroy(GENmodel**); +extern int TXLload(GENmodel*,CKTcircuit*); +extern int TXLmDelete(GENmodel**,IFuid,GENmodel*); +extern int TXLmParam(int,IFvalue*,GENmodel*); +extern int TXLparam(int,IFvalue*,GENinstance*,IFvalue*); +extern int TXLsetup(SMPmatrix*,GENmodel*,CKTcircuit*,int*); +#else /* stdc */ +/* extern int TXLaccept(); */ +extern int TXLdelete(); +extern void TXLdestroy(); +extern int TXLload(); +extern int TXLmDelete(); +extern int TXLmParam(); +extern int TXLparam(); +extern int TXLsetup(); +#endif /* stdc */ diff --git a/src/spicelib/devices/txl/txlfbr.c b/src/spicelib/devices/txl/txlfbr.c new file mode 100644 index 000000000..07d9a5b8f --- /dev/null +++ b/src/spicelib/devices/txl/txlfbr.c @@ -0,0 +1,41 @@ +/********** +Copyright 1992 Regents of the University of California. All rights +reserved. +Author: 1992 Charles Hough +**********/ + + +#include "ngspice.h" +#include +#include "cktdefs.h" +#include "txldefs.h" +#include "sperror.h" +#include "suffix.h" + + +int +TXLfindBr(ckt,inModel,name) + register CKTcircuit *ckt; + GENmodel *inModel; + register IFuid name; +{ + register TXLmodel *model = (TXLmodel *)inModel; + register TXLinstance *here; + int error; + CKTnode *tmp; + + for( ; model != NULL; model = model->TXLnextModel) { + for (here = model->TXLinstances; here != NULL; + here = here->TXLnextInstance) { + if(here->TXLname == name) { + if(here->TXLbranch == 0) { + error = CKTmkCur(ckt,&tmp,here->TXLname,"branch"); + if(error) return(error); + here->TXLbranch = tmp->number; + } + return(here->TXLbranch); + } + } + } + return(0); +} diff --git a/src/spicelib/devices/txl/txlinit.c b/src/spicelib/devices/txl/txlinit.c new file mode 100644 index 000000000..052420b20 --- /dev/null +++ b/src/spicelib/devices/txl/txlinit.c @@ -0,0 +1,90 @@ +/********** +Copyright 1992 Regents of the University of California. All rights +reserved. +Author: 1992 Charles Hough +**********/ +#include + +#include + +#include "txlitf.h" +#include "txlext.h" +#include "txlinit.h" + + +SPICEdev TXLinfo = { + { + "TransLine", + "Simple Lossy Transmission Line", + + &TXLnSize, + &TXLnSize, + TXLnames, + + &TXLpTSize, + TXLpTable, + + &TXLmPTSize, + TXLmPTable, + +#ifdef XSPICE +/*---- Fixed by SDB 5.2.2003 to enable XSPICE/tclspice integration -----*/ + NULL, /* This is a SPICE device, it has no MIF info data */ + + 0, /* This is a SPICE device, it has no MIF info data */ + NULL, /* This is a SPICE device, it has no MIF info data */ + + 0, /* This is a SPICE device, it has no MIF info data */ + NULL, /* This is a SPICE device, it has no MIF info data */ + + 0, /* This is a SPICE device, it has no MIF info data */ + NULL, /* This is a SPICE device, it has no MIF info data */ +/*--------------------------- End of SDB fix -------------------------*/ +#endif + + 0 + }, + + TXLparam, + TXLmParam, + TXLload, + TXLsetup, + NULL, + NULL, + NULL, + NULL, + NULL, /* TXLfindBranch, */ + TXLload, /* ac load */ + NULL, + TXLdestroy, +#ifdef DELETES + TXLmDelete, + TXLdelete, +#else /* DELETES */ + NULL, + NULL, +#endif /* DELETES */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + + &TXLiSize, + &TXLmSize + +}; + +SPICEdev * +get_txl_info(void) +{ + return &TXLinfo; +} diff --git a/src/spicelib/devices/txl/txlinit.h b/src/spicelib/devices/txl/txlinit.h new file mode 100644 index 000000000..7a64d3706 --- /dev/null +++ b/src/spicelib/devices/txl/txlinit.h @@ -0,0 +1,18 @@ +/********** +Copyright 1992 Regents of the University of California. All rights +reserved. +Author: 1992 Charles Hough +**********/ +#ifndef _TXLINIT_H +#define _TXLINIT_H + +extern IFparm TXLpTable[ ]; +extern IFparm TXLmPTable[ ]; +extern int TXLmPTSize; +extern int TXLpTSize; +extern char *TXLnames[ ]; +extern int TXLiSize; +extern int TXLmSize; +extern int TXLnSize; + +#endif diff --git a/src/spicelib/devices/txl/txlitf.h b/src/spicelib/devices/txl/txlitf.h new file mode 100644 index 000000000..b4e306300 --- /dev/null +++ b/src/spicelib/devices/txl/txlitf.h @@ -0,0 +1,12 @@ +/********** +Copyright 1992 Regents of the University of California. All rights +reserved. +Author: 1992 Charles Hough +**********/ + +#ifndef DEV_TXL +#define DEV_TXL + +SPICEdev *get_txl_info(void); + +#endif diff --git a/src/spicelib/devices/txl/txlload.c b/src/spicelib/devices/txl/txlload.c new file mode 100644 index 000000000..45ae8702a --- /dev/null +++ b/src/spicelib/devices/txl/txlload.c @@ -0,0 +1,689 @@ +/********** +Copyright 1992 Regents of the University of California. All rights +reserved. +Author: 1992 Charles Hough +**********/ + + +#include "ngspice.h" +#include +#include "txldefs.h" +#include "sperror.h" +#include "suffix.h" + + +static double ratio[MAX_CP_TX_LINES]; +static int update_cnv_txl(); +static VI_list_txl *new_vi_txl(); +static void free_vi_txl(); +static int add_new_vi_txl(); +static int get_pvs_vi_txl(); +static int right_consts_txl(); +static int update_delayed_cnv_txl(); +static int multC(); +static int expC(); +static void copy_tx(); +/*static char *message = "tau of txl line is larger than max time step";*/ + +/*ARGSUSED*/ +int +TXLload(inModel,ckt) + GENmodel *inModel; + CKTcircuit *ckt; +{ + register TXLmodel *model = (TXLmodel *)inModel; + register TXLinstance *here; + TXLine *tx, *tx2; + int k, l; + int time, time2; + double h, h1, f; + int hint; + float hf; + NODE *nd; + double v, v1, g; + int cond1; + CKTnode *node; + VI_list_txl *vi, *vi_before; + int i, before, delta; + + + /* debug + printf("before txlload\n"); + SMPprint(ckt->CKTmatrix, stdout); + */ + + h = ckt->CKTdelta; + h1 = 0.5 * h; + time2 = (int) (ckt->CKTtime * 1e12); + hint = (int)(h * 1e12); + hf = (float)(h * 1e12); + time = (int) ((ckt->CKTtime - ckt->CKTdelta) * 1e12); + + cond1= ckt->CKTmode & MODEDC; + + for( ; model != NULL; model = model->TXLnextModel ) { + for (here = model->TXLinstances; here != NULL ; + here=here->TXLnextInstance) { + + tx = here->txline; + if (cond1 || tx->vi_head == NULL) continue; + + if (time < tx->vi_tail->time) { + time = tx->vi_tail->time; + hint = time2 - time; + } + + vi_before = tx->vi_tail; + before = tx->vi_tail->time; + + if (time > tx->vi_tail->time) { + + copy_tx(tx, here->txline2); + add_new_vi_txl(here, ckt, time); + + delta = time - before; + + nd = tx->in_node; + v = vi_before->v_i; + nd->V = tx->vi_tail->v_i; + v1 = nd->V; + nd->dv = (v1 - v) / delta; + + nd = tx->out_node; + v = vi_before->v_o; + v1 = nd->V = tx->vi_tail->v_o; + nd->dv = (v1 - v) / delta; + + if (tx->lsl) continue; + update_cnv_txl(tx, (float) delta); + if (tx->ext) update_delayed_cnv_txl(tx, (float) delta); + } + } + } + + model = (TXLmodel *)inModel; + for( ; model != NULL; model = model->TXLnextModel ) { + for (here = model->TXLinstances; here != NULL ; + here=here->TXLnextInstance) { + + tx = here->txline; + tx2 = here->txline2; + + if (!tx->lsl && hf > tx->taul) { + + fprintf(stderr, "your time step is too large for tau.\n"); + fprintf(stderr, "please decrease max time step in .tran card.\n"); + fprintf(stderr, ".tran tstep tstop tstart tmax.\n"); + fprintf(stderr, "make tmax smaller than %e and try again.\n", + tx->taul * 1e-12); + + return (1111); + + + } + + if (cond1) { + if (here->TXLlengthgiven) + g = model->R * here->TXLlength; + else g = model->R * here->TXLmodPtr->length; + *(here->TXLposIbr1ptr) += 1.0; + *(here->TXLnegIbr2ptr) += 1.0; + *(here->TXLibr1Ibr1ptr) += 1.0; + *(here->TXLibr1Ibr2ptr) += 1.0; + *(here->TXLibr2Posptr) += 1.0; + *(here->TXLibr2Negptr) -= 1.0; + *(here->TXLibr2Ibr1ptr) -= g; + + continue; + + } + + /* dc setup */ + if (here->TXLdcGiven == 0 && !cond1) { + nd = tx->in_node; + for (node = ckt->CKTnodes;node; node = node->next) { + if (strcmp(nd->name->id, node->name) == 0) { + tx->dc1 = tx2->dc1 = ckt->CKTrhsOld[node->number]; + nd->V = tx->dc1; + break; + } + } + nd = tx->out_node; + for (node = ckt->CKTnodes;node; node = node->next) { + if (strcmp(nd->name->id, node->name) == 0) { + tx->dc2 = tx2->dc2 = ckt->CKTrhsOld[node->number]; + nd->V = tx->dc2; + break; + } + } + here->TXLdcGiven = 1; + + vi = new_vi_txl(); + vi->time = 0; + + vi->i_i = *(ckt->CKTrhsOld + here->TXLibr1); + vi->i_o = *(ckt->CKTrhsOld + here->TXLibr2); + + vi->v_i = tx->dc1; + vi->v_o = tx->dc2; + + for (i = 0; i < 3; i++) { + tx->h1_term[i].cnv_i = + - tx->dc1 * tx->h1_term[i].c / tx->h1_term[i].x; + tx->h1_term[i].cnv_o = + - tx->dc2 * tx->h1_term[i].c / tx->h1_term[i].x; + } + for (i = 0; i < 3; i++) { + tx->h2_term[i].cnv_i = 0.0; + tx->h2_term[i].cnv_o = 0.0; + } + for (i = 0; i < 6; i++) { + tx->h3_term[i].cnv_i = + - tx->dc1 * tx->h3_term[i].c / tx->h3_term[i].x; + tx->h3_term[i].cnv_o = + - tx->dc2 * tx->h3_term[i].c / tx->h3_term[i].x; + } + vi->next = NULL; + tx->vi_tail = vi; + tx->vi_head = vi; + here->txline2->vi_tail = vi; + here->txline2->vi_head = vi; + + } + + /* change 6,6 1/18/93 + *(here->TXLibr1Ibr1ptr) -= 1.0; + *(here->TXLibr2Ibr2ptr) -= 1.0; + *(here->TXLposIbr1ptr) += 1.0; + *(here->TXLnegIbr2ptr) += 1.0; + *(here->TXLibr1Posptr) += tx->sqtCdL + h1 * tx->h1C; + *(here->TXLibr2Negptr) += tx->sqtCdL + h1 * tx->h1C; + */ + *(here->TXLibr1Ibr1ptr) = -1.0; + *(here->TXLibr2Ibr2ptr) = -1.0; + *(here->TXLposIbr1ptr) = 1.0; + *(here->TXLnegIbr2ptr) = 1.0; + *(here->TXLibr1Posptr) = tx->sqtCdL + h1 * tx->h1C; + *(here->TXLibr2Negptr) = tx->sqtCdL + h1 * tx->h1C; + + k = here->TXLibr1; + l = here->TXLibr2; + + copy_tx(tx2, tx); + + if (right_consts_txl(tx2, time, time2, h, h1, k, l, ckt)) { + if (tx->lsl) { + f = ratio[0] * tx->h3_aten; + *(here->TXLibr1Negptr) = -f; + *(here->TXLibr2Posptr) = -f; + f = ratio[0] * tx->h2_aten; + *(here->TXLibr1Ibr2ptr) = -f; + *(here->TXLibr2Ibr1ptr) = -f; + } + else { + tx->ext = 1; + tx->ratio = ratio[0]; + if (ratio[0] > 0.0) { + f = ratio[0] * (h1 * (tx->h3_term[0].c + + tx->h3_term[1].c + tx->h3_term[2].c + + tx->h3_term[3].c + tx->h3_term[4].c + + tx->h3_term[5].c ) + tx->h3_aten); + *(here->TXLibr1Negptr) = -f; + *(here->TXLibr2Posptr) = -f; + f = ratio[0] * (h1 * ( tx->h2_term[0].c + + tx->h2_term[1].c + tx->h2_term[2].c ) + + tx->h2_aten); + *(here->TXLibr1Ibr2ptr) = -f; + *(here->TXLibr2Ibr1ptr) = -f; + } + } + } + else tx->ext = 0; + } + } + + if (cond1) return (OK); + + /* debug + printf("after txlload\n"); + SMPprint(ckt->CKTmatrix, stdout); + */ + + return(OK); +} + +static void copy_tx(new, old) +TXLine *new, *old; +{ + int i; + VI_list_txl *temp; + + new->lsl = old->lsl; + new->ext = old->ext; + new->ratio = old->ratio; + new->taul = old->taul; + new->sqtCdL = old->sqtCdL; + new->h2_aten = old->h2_aten; + new->h3_aten = old->h3_aten; + new->h1C = old->h1C; + for (i= 0; i < 3; i++) { + new->h1e[i] = old->h1e[i]; + + new->h1_term[i].c = old->h1_term[i].c; + new->h1_term[i].x = old->h1_term[i].x; + new->h1_term[i].cnv_i = old->h1_term[i].cnv_i; + new->h1_term[i].cnv_o = old->h1_term[i].cnv_o; + + new->h2_term[i].c = old->h2_term[i].c; + new->h2_term[i].x = old->h2_term[i].x; + new->h2_term[i].cnv_i = old->h2_term[i].cnv_i; + new->h2_term[i].cnv_o = old->h2_term[i].cnv_o; + } + for (i= 0; i < 6; i++) { + new->h3_term[i].c = old->h3_term[i].c; + new->h3_term[i].x = old->h3_term[i].x; + new->h3_term[i].cnv_i = old->h3_term[i].cnv_i; + new->h3_term[i].cnv_o = old->h3_term[i].cnv_o; + } + + new->ifImg = old->ifImg; + if (new->vi_tail != old->vi_tail) { + /* someting wrong */ + exit (0); + } + + while (new->vi_head->time < old->vi_head->time) { + temp = new->vi_head; + new->vi_head = new->vi_head->next; + free_vi_txl(temp); + } + +} + + +static int update_cnv_txl(tx, h) + TXLine *tx; + float h; +{ + int i; + + double ai, bi, ao, bo; + register double e, t; + + ai = tx->in_node->V; + ao = tx->out_node->V; + bi = tx->in_node->dv; + bo = tx->out_node->dv; + + for (i = 0; i < 3; i++) { + register TERM *tm; + tm = &(tx->h1_term[i]); + + e = tx->h1e[i]; + + t = tm->c / tm->x; + bi *= t; + bo *= t; + + tm->cnv_i = (tm->cnv_i - bi*h) * e + (e - 1.0)*(ai*t + 1.0e+12*bi/tm->x); + tm->cnv_o = (tm->cnv_o - bo*h) * e + (e - 1.0)*(ao*t + 1.0e+12*bo/tm->x); + } + return (1); +} + + +static VI_list_txl +*new_vi_txl() +{ + VI_list_txl *q; + + if (pool_vi_txl) { + q = pool_vi_txl; + pool_vi_txl = pool_vi_txl->pool; + return(q); + } else + return((VI_list_txl *) malloc (sizeof (VI_list_txl))); +} + +static void +free_vi_txl(q) + VI_list_txl *q; +{ + q->pool = pool_vi_txl; + pool_vi_txl = q; +} + + +static int add_new_vi_txl(here, ckt, time) +TXLinstance *here; +CKTcircuit *ckt; +int time; +{ + VI_list_txl *vi; + TXLine *tx, *tx2; + + tx = here->txline; + tx2 = here->txline2; + + vi = new_vi_txl(); + vi->time = time; + tx->vi_tail->next = vi; + tx2->vi_tail->next = vi; + vi->next = NULL; + tx->vi_tail = vi; + tx2->vi_tail = vi; + + vi->v_i = *(ckt->CKTrhsOld + here->TXLposNode); + vi->v_o = *(ckt->CKTrhsOld + here->TXLnegNode); + vi->i_i = *(ckt->CKTrhsOld + here->TXLibr1); + vi->i_o = *(ckt->CKTrhsOld + here->TXLibr2); + return(1); +} + + +static int +get_pvs_vi_txl(t1, t2, tx, v1_i, v2_i, i1_i, i2_i, v1_o, v2_o, i1_o, i2_o) + TXLine *tx; + int t1, t2; + double *v1_i, *v2_i, *i1_i, *i2_i, *v1_o, *v2_o, *i1_o, *i2_o; +{ + double ta, tb; + register VI_list_txl *vi, *vi1; + register double f; + int ext = 0; + + ta = t1 - tx->taul; + tb = t2 - tx->taul; + if (tb <= 0) { + *v1_i = *v2_i = tx->dc1; + *v2_o = *v1_o = tx->dc2; + *i1_i = *i2_i = *i1_o = *i2_o = 0; + return(ext); + } + + if (ta <= 0) { + *i1_i = *i1_o = 0.0; + *v1_i = tx->dc1; + *v1_o = tx->dc2; + vi1 = tx->vi_head; + vi = vi1->next; + } else { + vi1 = tx->vi_head; + for (vi = vi1->next; vi->time < ta; vi = vi->next) { + /* free_vi_txl(vi1); */ + vi1 = vi; + } + f = (ta - vi1->time) / (vi->time - vi1->time); + *v1_i = vi1->v_i + f * (vi->v_i - vi1->v_i); + *v1_o = vi1->v_o + f * (vi->v_o - vi1->v_o); + *i1_i = vi1->i_i + f * (vi->i_i - vi1->i_i); + *i1_o = vi1->i_o + f * (vi->i_o - vi1->i_o); + tx->vi_head = vi1; + } + + if (tb > t1) { + + /* fprintf(stderr, "pvs: time = %d\n", t2); */ + ext = 1; + /* + f = tb - t1; + *v2_i = tx->in_node->V + tx->in_node->dv * f; + *v2_o = tx->out_node->V + tx->out_node->dv * f; + + if (vi) { + for (; vi->time != t1; vi = vi->next) + vi1 = vi; + + f /= (double) (t1 - vi1->time); + *i2_i = vi->i_i + f * (vi->i_i - vi1->i_i); + *i2_o = vi->i_o + f * (vi->i_o - vi1->i_o); + } else { + *i2_i = vi1->i_i; + *i2_o = vi1->i_o; + } + */ + ratio[0] = f = (tb - t1) / (t2 - t1); + if (vi) + for (; vi->time != t1; vi = vi->next); + else + vi = vi1; + f = 1 - f; + *v2_i = vi->v_i * f; + *v2_o = vi->v_o * f; + *i2_i = vi->i_i * f; + *i2_o = vi->i_o * f; + } else { + for (; vi->time < tb; vi = vi->next) + vi1 = vi; + + f = (tb - vi1->time) / (vi->time - vi1->time); + *v2_i = vi1->v_i + f * (vi->v_i - vi1->v_i); + *v2_o = vi1->v_o + f * (vi->v_o - vi1->v_o); + *i2_i = vi1->i_i + f * (vi->i_i - vi1->i_i); + *i2_o = vi1->i_o + f * (vi->i_o - vi1->i_o); + } + + return(ext); +} + + +static int +right_consts_txl(tx, t, time, h, h1, l1, l2, ckt) +TXLine *tx; +int t, time; +double h, h1; /*** h1 = 0.5 * h ***/ +int l1, l2; +CKTcircuit *ckt; +{ + int i; + register double ff=0.0, gg=0.0, e; + double v1_i, v2_i, i1_i, i2_i; + double v1_o, v2_o, i1_o, i2_o; + int ext; + + if (! tx->lsl) { + register double ff1=0.0; + for (i = 0; i < 3; i++) { + tx->h1e[i] = e = exp((double) tx->h1_term[i].x * h); + ff1 -= tx->h1_term[i].c * e; + ff -= tx->h1_term[i].cnv_i * e; + gg -= tx->h1_term[i].cnv_o * e; + } + ff += ff1 * h1 * tx->in_node->V; + gg += ff1 * h1 * tx->out_node->V; + } + + ext = get_pvs_vi_txl(t, time, tx, &v1_i, &v2_i, &i1_i, &i2_i, &v1_o, &v2_o, &i1_o, &i2_o); + + if (tx->lsl) { + ff = tx->h3_aten * v2_o + tx->h2_aten * i2_o; + gg = tx->h3_aten * v2_i + tx->h2_aten * i2_i; + } else { + if (tx->ifImg) { + double a, b, er, ei, a1, b1, a2, b2; + + for (i = 0; i < 4; i++) { + register TERM *tm; + tm = &(tx->h3_term[i]); + e = exp((double) tm->x * h); + tm->cnv_i = tm->cnv_i * e + h1 * tm->c * (v1_i * e + v2_i); + tm->cnv_o = tm->cnv_o * e + h1 * tm->c * (v1_o * e + v2_o); + } + expC(tx->h3_term[4].x, tx->h3_term[5].x, h, &er, &ei); + a2 = h1 * tx->h3_term[4].c; + b2 = h1 * tx->h3_term[5].c; + + a = tx->h3_term[4].cnv_i; + b = tx->h3_term[5].cnv_i; + multC(a, b, er, ei, &a, &b); + multC(a2, b2, v1_i * er + v2_i, v1_i * ei, &a1, &b1); + tx->h3_term[4].cnv_i = a + a1; + tx->h3_term[5].cnv_i = b + b1; + + a = tx->h3_term[4].cnv_o; + b = tx->h3_term[5].cnv_o; + multC(a, b, er, ei, &a, &b); + multC(a2, b2, v1_o * er + v2_o, v1_o * ei, &a1, &b1); + tx->h3_term[4].cnv_o = a + a1; + tx->h3_term[5].cnv_o = b + b1; + + ff += tx->h3_aten * v2_o; + gg += tx->h3_aten * v2_i; + + for (i = 0; i < 5; i++) { + ff += tx->h3_term[i].cnv_o; + gg += tx->h3_term[i].cnv_i; + } + ff += tx->h3_term[4].cnv_o; + gg += tx->h3_term[4].cnv_i; + + { + register TERM *tm; + tm = &(tx->h2_term[0]); + + e = exp((double) tm->x * h); + tm->cnv_i = tm->cnv_i * e + h1 * tm->c * (i1_i * e + i2_i); + tm->cnv_o = tm->cnv_o * e + h1 * tm->c * (i1_o * e + i2_o); + } + expC(tx->h2_term[1].x, tx->h2_term[2].x, h, &er, &ei); + a2 = h1 * tx->h2_term[1].c; + b2 = h1 * tx->h2_term[2].c; + + a = tx->h2_term[1].cnv_i; + b = tx->h2_term[2].cnv_i; + multC(a, b, er, ei, &a, &b); + multC(a2, b2, i1_i * er + i2_i, i1_i * ei, &a1, &b1); + tx->h2_term[1].cnv_i = a + a1; + tx->h2_term[2].cnv_i = b + b1; + + a = tx->h2_term[1].cnv_o; + b = tx->h2_term[2].cnv_o; + multC(a, b, er, ei, &a, &b); + multC(a2, b2, i1_o * er + i2_o, i1_o * ei, &a1, &b1); + tx->h2_term[1].cnv_o = a + a1; + tx->h2_term[2].cnv_o = b + b1; + + ff += tx->h2_aten * i2_o + tx->h2_term[0].cnv_o + + 2.0 * tx->h2_term[1].cnv_o; + gg += tx->h2_aten * i2_i + tx->h2_term[0].cnv_i + + 2.0 * tx->h2_term[1].cnv_i; + } else { + for (i = 0; i < 6; i++) { + register TERM *tm; + tm = &(tx->h3_term[i]); + + e = exp((double) tm->x * h); + tm->cnv_i = tm->cnv_i * e + h1 * tm->c * (v1_i * e + v2_i); + tm->cnv_o = tm->cnv_o * e + h1 * tm->c * (v1_o * e + v2_o); + } + + ff += tx->h3_aten * v2_o; + gg += tx->h3_aten * v2_i; + + for (i = 0; i < 6; i++) { + ff += tx->h3_term[i].cnv_o; + gg += tx->h3_term[i].cnv_i; + } + + for (i = 0; i < 3; i++) { + register TERM *tm; + tm = &(tx->h2_term[i]); + + e = exp((double) tm->x * h); + tm->cnv_i = tm->cnv_i * e + h1 * tm->c * (i1_i * e + i2_i); + tm->cnv_o = tm->cnv_o * e + h1 * tm->c * (i1_o * e + i2_o); + } + + ff += tx->h2_aten * i2_o; + gg += tx->h2_aten * i2_i; + + for (i = 0; i < 3; i++) { + ff += tx->h2_term[i].cnv_o; + gg += tx->h2_term[i].cnv_i; + } + } + } + + *(ckt->CKTrhs + l1) = ff; + *(ckt->CKTrhs + l2) = gg; + + return(ext); +} + + +static int +update_delayed_cnv_txl(tx, h) + TXLine *tx; + float h; +{ + float ratio; + register double f; + register VI_list_txl *vi; + register TERM *tms; + + h *= 0.5e-12; + ratio = tx->ratio; + vi = tx->vi_tail; + + if (ratio > 0.0) { + tms = tx->h3_term; + f = h * ratio * vi->v_i; + tms[0].cnv_i += f * tms[0].c; + tms[1].cnv_i += f * tms[1].c; + tms[2].cnv_i += f * tms[2].c; + tms[3].cnv_i += f * tms[3].c; + tms[4].cnv_i += f * tms[4].c; + tms[5].cnv_i += f * tms[5].c; + + f = h * ratio * vi->v_o; + tms[0].cnv_o += f * tms[0].c; + tms[1].cnv_o += f * tms[1].c; + tms[2].cnv_o += f * tms[2].c; + tms[3].cnv_o += f * tms[3].c; + tms[4].cnv_o += f * tms[4].c; + tms[5].cnv_o += f * tms[5].c; + + tms = tx->h2_term; + f = h * ratio * vi->i_i; + tms[0].cnv_i += f * tms[0].c; + tms[1].cnv_i += f * tms[1].c; + tms[2].cnv_i += f * tms[2].c; + + f = h * ratio * vi->i_o; + tms[0].cnv_o += f * tms[0].c; + tms[1].cnv_o += f * tms[1].c; + tms[2].cnv_o += f * tms[2].c; + } + + return(1); +} + +static int expC(ar, ai, h, cr, ci) + double ar, ai, *cr, *ci; + float h; +{ + double e, cs, si; + + e = exp((double) ar * h); + cs = cos((double) ai * h); + si = sin((double) ai * h); + *cr = e * cs; + *ci = e * si; + + return(1); +} + +static int multC(ar, ai, br, bi, cr, ci) + double ar, ai, br, bi; + double *cr, *ci; +{ + register double tp; + + tp = ar*br - ai*bi; + *ci = ar*bi + ai*br; + *cr = tp; + + return (1); + +} + diff --git a/src/spicelib/devices/txl/txlmask.c b/src/spicelib/devices/txl/txlmask.c new file mode 100644 index 000000000..995a8bf74 --- /dev/null +++ b/src/spicelib/devices/txl/txlmask.c @@ -0,0 +1,49 @@ +/********** +Copyright 1992 Regents of the University of California. All rights +reserved. +Author: 1992 Charles Hough +**********/ + + +#include "ngspice.h" +#include +#include "const.h" +#include "cktdefs.h" +#include "ifsim.h" +#include "txldefs.h" +#include "sperror.h" +#include "devdefs.h" +#include "suffix.h" +#include "swec.h" + + +/* ARGSUSED */ +int +TXLmodAsk(ckt,inModel,which,value) + CKTcircuit *ckt; + GENmodel *inModel; + int which; + IFvalue *value; +{ + TXLmodel *model = (TXLmodel *)inModel; + switch(which) { + case TXL_R: + value->rValue = model->R; + return(OK); + case TXL_C: + value->rValue = model->C; + return(OK); + case TXL_G: + value->rValue = model->G; + return(OK); + case TXL_L: + value->rValue = model->L; + return(OK); + case TXL_length: + value->rValue = model->length; + return(OK); + default: + return(E_BADPARM); + } +} + diff --git a/src/spicelib/devices/txl/txlmdel.c b/src/spicelib/devices/txl/txlmdel.c new file mode 100644 index 000000000..434f03543 --- /dev/null +++ b/src/spicelib/devices/txl/txlmdel.c @@ -0,0 +1,45 @@ +/********** +Copyright 1992 Regents of the University of California. All rights +reserved. +Author: 1992 Charles Hough +**********/ + + +#include "ngspice.h" +#include +#include "txldefs.h" +#include "sperror.h" +#include "suffix.h" + + +int +TXLmDelete(inModel,modname,kill) + GENmodel **inModel; + IFuid modname; + GENmodel *kill; +{ + TXLmodel **model = (TXLmodel **)inModel; + TXLmodel *modfast = (TXLmodel *)kill; + TXLinstance *here; + TXLinstance *prev = NULL; + TXLmodel **oldmod; + oldmod = model; + + for( ; *model ; model = &((*model)->TXLnextModel)) { + if( (*model)->TXLmodName == modname || + (modfast && *model == modfast) ) goto delgot; + oldmod = model; + } + return(E_NOMOD); + +delgot: + *oldmod = (*model)->TXLnextModel; /* cut deleted device out of list */ + for(here = (*model)->TXLinstances ; here ; here = here->TXLnextInstance) { + if(prev) FREE(prev); + prev = here; + } + if(prev) FREE(prev); + FREE(*model); + return(OK); + +} diff --git a/src/spicelib/devices/txl/txlmpar.c b/src/spicelib/devices/txl/txlmpar.c new file mode 100644 index 000000000..f3346bf55 --- /dev/null +++ b/src/spicelib/devices/txl/txlmpar.c @@ -0,0 +1,51 @@ +/********** +Copyright 1992 Regents of the University of California. All rights +reserved. +Author: 1992 Charles Hough +**********/ + + +#include "ngspice.h" +#include +#include "const.h" +#include "ifsim.h" +#include "txldefs.h" +#include "sperror.h" +#include "suffix.h" + + +int +TXLmParam(param,value,inModel) + int param; + IFvalue *value; + GENmodel *inModel; +{ + register TXLmodel *model = (TXLmodel *)inModel; + switch(param) { + case TXL_R: + model->R = value->rValue; + model->Rgiven = TRUE; + break; + case TXL_L: + model->L = value->rValue; + model->Lgiven = TRUE; + break; + case TXL_G: + model->G = value->rValue; + model->Ggiven = TRUE; + break; + case TXL_C: + model->C = value->rValue; + model->Cgiven = TRUE; + break; + case TXL_length: + model->length = value->rValue; + model->lengthgiven = TRUE; + break; + case TXL_MOD_R: + break; + default: + return(E_BADPARM); + } + return(OK); +} diff --git a/src/spicelib/devices/txl/txlparam.c b/src/spicelib/devices/txl/txlparam.c new file mode 100644 index 000000000..83e9aaf93 --- /dev/null +++ b/src/spicelib/devices/txl/txlparam.c @@ -0,0 +1,40 @@ +/********** +Copyright 1992 Regents of the University of California. All rights +reserved. +Author: 1992 Charles Hough +**********/ + +#include "ngspice.h" +#include +#include "const.h" +#include "ifsim.h" +#include "txldefs.h" +#include "sperror.h" +#include "suffix.h" + + +/* ARGSUSED */ +int +TXLparam(param,value,inst,select) + int param; + IFvalue *value; + GENinstance *inst; + IFvalue *select; +{ + TXLinstance *here = (TXLinstance *)inst; + switch(param) { + case TXL_IN_NODE: + here->TXLposNode = value->iValue; + break; + case TXL_OUT_NODE: + here->TXLnegNode = value->iValue; + break; + case TXL_LENGTH: + here->TXLlength = value->rValue; + here->TXLlengthgiven = TRUE; + break; + default: + return(E_BADPARM); + } + return(OK); +} diff --git a/src/spicelib/devices/txl/txlsetup.c b/src/spicelib/devices/txl/txlsetup.c new file mode 100644 index 000000000..f9f728a42 --- /dev/null +++ b/src/spicelib/devices/txl/txlsetup.c @@ -0,0 +1,1140 @@ +/********** +Copyright 1992 Regents of the University of California. All rights +reserved. +Author: 1992 Charles Hough +**********/ + + +#include "ngspice.h" +#include +#include "smpdefs.h" +#include "txldefs.h" +#include "sperror.h" +#include "suffix.h" + +#include "../cap/capdefs.h" + +static int ReadTxL(); +/*static int multC();*/ +static int main_pade(); +static int mac(); +/*static int divC();*/ +static int div_C(); +static int div3(); +/*static double approx1();*/ +/*static double approx2();*/ +static int find_roots(); +/*static double f3();*/ +/*static double f2();*/ +/*static int expC();*/ +/*static double exp_approx1();*/ +/*static double exp_approx2();*/ +static int exp_pade(); +/*static int exp_div3();*/ +static int exp_find_roots(); +static double eval2(); +static int get_c(); +static int get_h3(); +static int Gaussian_Elimination2(); +static int Gaussian_Elimination1(); +static int pade(); +static int update_h1C_c(); +static void y_pade(); +static double root3(); +static NDnamePt insert_ND(); +static NODE *insert_node(); +static NODE *NEW_node(); +/*static VI_list_txl *new_vi_txl();*/ + +NODE *node_tab = NULL; +NDnamePt ndn = NULL; +VI_list_txl *pool_vi_txl = NULL; + +/* pade.c */ +/** +static double xx1, xx2, xx3, xx4, xx5, xx6; +static double cc1, cc2, cc3, cc4, cc5, cc6; +**/ + +/* y.c */ +static double sqtCdL; +static double b1, b2, b3, b4, b5; +static double p1, p2, p3, q1, q2, q3; +static double c1, c2, c3, x1, x2, x3; +static double A[3][4]; + +/* exp.c */ +static double RdL, GdC, RG, tau, RC, GL; +static double a0, a1, a2, a3, a4, a5; +static double ep1, ep2, ep3, eq1, eq2, eq3; +static double ec1, ec2, ec3, ex1, ex2, ex3; +static int ifImg; +static double AA[3][4]; + +#define epsi 1.0e-16 +#define epsi2 1.0e-28 + +/* ARGSUSED */ +int +TXLsetup(matrix,inModel,ckt,state) + register SMPmatrix *matrix; + GENmodel *inModel; + CKTcircuit*ckt; + int *state; +{ + register TXLmodel *model = (TXLmodel *)inModel; + register TXLinstance *here; + CKTnode *tmp; + int error; + + /* loop through all the models */ + for( ; model != NULL; model = model->TXLnextModel ) { + + /* loop through all the instances of the model */ + for (here = model->TXLinstances; here != NULL ; + here=here->TXLnextInstance) { + +/* macro to make elements with built in test for out of memory */ +#define TSTALLOC(ptr,first,second) \ +if((here->ptr = SMPmakeElt(matrix,here->first,here->second))==(double *)NULL){\ + return(E_NOMEM);\ +} + + if (! here->TXLibr1Given) { + error = CKTmkCur(ckt, &tmp, here->TXLname, "branch1"); + if (error) return (error); + here->TXLibr1 = tmp->number; + } + if (! here->TXLibr2Given) { + error = CKTmkCur(ckt, &tmp, here->TXLname, "branch2"); + if (error) return (error); + here->TXLibr2 = tmp->number; + } + + TSTALLOC(TXLposPosptr, TXLposNode, TXLposNode); + TSTALLOC(TXLposNegptr, TXLposNode, TXLnegNode); + TSTALLOC(TXLnegPosptr, TXLnegNode, TXLposNode); + TSTALLOC(TXLnegNegptr, TXLnegNode, TXLnegNode); + TSTALLOC(TXLibr1Posptr, TXLibr1, TXLposNode); + TSTALLOC(TXLibr2Negptr, TXLibr2, TXLnegNode); + TSTALLOC(TXLnegIbr2ptr, TXLnegNode, TXLibr2); + TSTALLOC(TXLposIbr1ptr, TXLposNode, TXLibr1); + TSTALLOC(TXLibr1Ibr1ptr, TXLibr1, TXLibr1); + TSTALLOC(TXLibr2Ibr2ptr, TXLibr2, TXLibr2); + TSTALLOC(TXLibr1Negptr, TXLibr1, TXLnegNode); + TSTALLOC(TXLibr2Posptr, TXLibr2, TXLposNode); + TSTALLOC(TXLibr1Ibr2ptr, TXLibr1, TXLibr2); + TSTALLOC(TXLibr2Ibr1ptr, TXLibr2, TXLibr1); + + here->in_node_name = CKTnodName(ckt,here->TXLposNode); + here->out_node_name = CKTnodName(ckt,here->TXLnegNode); + ReadTxL(here, ckt); + + } + } + + return(OK); +} + +/*** +static VI_list_txl +*new_vi_txl() +{ + VI_list_txl *q; + + if (pool_vi_txl) { + q = pool_vi_txl; + pool_vi_txl = pool_vi_txl->pool; + return(q); + } else + return((VI_list_txl *) malloc (sizeof (VI_list_txl))); +} +***/ + +static int ReadTxL(tx, ckt) +TXLinstance *tx; +CKTcircuit *ckt; +{ + double R, L, G, C, l; + char *p, *n; + NODE *nd; + ETXLine *et; + TXLine *t, *t2; + RLINE *line; + ERLINE *er; + double LL = 1e-12; + + p = tx->in_node_name; + n = tx->out_node_name; + + line = (RLINE *) malloc(sizeof (RLINE)); + er = (ERLINE *) malloc(sizeof (ERLINE)); + et = (ETXLine *) malloc(sizeof (ETXLine)); + t = (TXLine *) malloc(sizeof (TXLine)); + t2 = (TXLine *) malloc(sizeof (TXLine)); + tx->txline = t; + tx->txline2 = t2; + t->newtp = 0; + t2->newtp = 0; + t->vi_head = t->vi_tail = NULL; + nd = insert_node(p); + et->link = nd->tptr; + nd->tptr = et; + et->line = t; + t->in_node = nd; + t2->in_node = nd; + er->link = nd->rlptr; + nd->rlptr = er; + er->rl = line; + line->in_node = nd; + et = (ETXLine *) malloc(sizeof (ETXLine)); + nd = insert_node(n); + et->link = nd->tptr; + nd->tptr = et; + et->line = t; + t->out_node = nd; + t2->out_node = nd; + er = (ERLINE *) malloc(sizeof (ERLINE)); + er->link = nd->rlptr; + nd->rlptr = er; + er->rl = line; + line->out_node = nd; + t->dc1 = t->dc2 = 0.0; + t2->dc1 = t2->dc2 = 0.0; + t->lsl = 0; + t2->lsl = 0; + l = 0.0; + + R = tx->TXLmodPtr->R; + L = tx->TXLmodPtr->L; + L = MAX(L, LL); + C = tx->TXLmodPtr->C; + G = tx->TXLmodPtr->G; + if (tx->TXLlengthgiven == TRUE) + l = tx->TXLlength; + else l = tx->TXLmodPtr->length; + + + if (l == 0.0) { + fprintf(stderr, "(Error) transmission line of zero length\n"); + exit(0); + } + else { + if (R / L < 5.0e+5) { + line->g = 1.0e+2; + if (G < 1.0e-2) { + t->lsl = 1; /* lossless line */ + t->taul = sqrt((double) C * L) * l * 1.0e12; + t->h3_aten = t->sqtCdL = sqrt((double) C / L); + t->h2_aten = 1.0; + t->h1C = 0.0; + } + } + else line->g = 1.0 / (R * l); + } + + if (! t->lsl) + main_pade(R, L, G, C, l, t); + + return(1); +} + + +/**************************************************************** + pade.c : Calculate the Pade Approxximation of Y(s) + ****************************************************************/ + + +static int main_pade(R, L, G, C, l, h) + double R, L, G, C, l; + TXLine *h; +{ + y_pade(R, L, G, C, h); + h->ifImg = exp_pade(R, L, G, C, l, h); + get_h3(h); + h->taul *= 1.0e12; + update_h1C_c(h); + + return(1); +} + +static int div_C(ar, ai, br, bi, cr, ci) + double ar, ai, br, bi; + double *cr, *ci; +{ + *cr = ar * br + ai * bi; + *ci = - ar * bi + ai * br; + *cr = *cr / (br * br + bi * bi); + *ci = *ci / (br * br + bi * bi); + return (1); +} + +/*** +static int expC(ar, ai, h, cr, ci) + double ar, ai, *cr, *ci; + float h; +{ + double e, cs, si; + + e = exp((double) ar * h); + cs = cos((double) ai * h); + si = sin((double) ai * h); + *cr = e * cs; + *ci = e * si; + + return(1); +} +***/ + +/*** +static int multC(ar, ai, br, bi, cr, ci) + double ar, ai, br, bi; + double *cr, *ci; +{ + *cr = ar*br - ai*bi; + *ci = ar*bi + ai*br; + + return(1); +} +***/ + +/*** +static int divC(ar, ai, br, bi, cr, ci) + double ar, ai, br, bi; + double *cr, *ci; +{ + double t; + t = br*br + bi*bi; + *cr = (ar*br + ai*bi) / t; + *ci = (ai*br - ar*bi) / t; + + return(1); +} +***/ + +static int get_h3(h) + TXLine *h; +{ + double cc1, cc2, cc3, cc4, cc5, cc6; + double xx1, xx2, xx3, xx4, xx5, xx6; + + h->h3_aten = h->h2_aten * h->sqtCdL; + h->h3_term[0].x = xx1 = h->h1_term[0].x; + h->h3_term[1].x = xx2 = h->h1_term[1].x; + h->h3_term[2].x = xx3 = h->h1_term[2].x; + h->h3_term[3].x = xx4 = h->h2_term[0].x; + h->h3_term[4].x = xx5 = h->h2_term[1].x; + h->h3_term[5].x = xx6 = h->h2_term[2].x; + cc1 = h->h1_term[0].c; + cc2 = h->h1_term[1].c; + cc3 = h->h1_term[2].c; + cc4 = h->h2_term[0].c; + cc5 = h->h2_term[1].c; + cc6 = h->h2_term[2].c; + + if (h->ifImg) { + double r, i; + + h->h3_term[0].c = cc1 + cc1 * (cc4/(xx1-xx4) + + 2.0*(cc5*xx1-xx6*cc6-xx5*cc5)/(xx1*xx1-2.0*xx5*xx1+xx5*xx5+xx6*xx6)); + h->h3_term[1].c = cc2 + cc2 * (cc4/(xx2-xx4) + + 2.0*(cc5*xx2-xx6*cc6-xx5*cc5)/(xx2*xx2-2.0*xx5*xx2+xx5*xx5+xx6*xx6)); + h->h3_term[2].c = cc3 + cc3 * (cc4/(xx3-xx4) + + 2.0*(cc5*xx3-xx6*cc6-xx5*cc5)/(xx3*xx3-2.0*xx5*xx3+xx5*xx5+xx6*xx6)); + + h->h3_term[3].c = cc4 + cc4 * (cc1/(xx4-xx1) + cc2/(xx4-xx2) + cc3/(xx4-xx3)); + + h->h3_term[4].c = cc5; + h->h3_term[5].c = cc6; + div_C(cc5, cc6, xx5-xx1, xx6, &r, &i); + h->h3_term[4].c += r * cc1; + h->h3_term[5].c += i * cc1; + div_C(cc5, cc6, xx5-xx2, xx6, &r, &i); + h->h3_term[4].c += r * cc2; + h->h3_term[5].c += i * cc2; + div_C(cc5, cc6, xx5-xx3, xx6, &r, &i); + h->h3_term[4].c += r * cc3; + h->h3_term[5].c += i * cc3; + } else { + h->h3_term[0].c = cc1 + cc1 * (cc4/(xx1-xx4) + cc5/(xx1-xx5) + cc6/(xx1-xx6)); + h->h3_term[1].c = cc2 + cc2 * (cc4/(xx2-xx4) + cc5/(xx2-xx5) + cc6/(xx2-xx6)); + h->h3_term[2].c = cc3 + cc3 * (cc4/(xx3-xx4) + cc5/(xx3-xx5) + cc6/(xx3-xx6)); + + h->h3_term[3].c = cc4 + cc4 * (cc1/(xx4-xx1) + cc2/(xx4-xx2) + cc3/(xx4-xx3)); + h->h3_term[4].c = cc5 + cc5 * (cc1/(xx5-xx1) + cc2/(xx5-xx2) + cc3/(xx5-xx3)); + h->h3_term[5].c = cc6 + cc6 * (cc1/(xx6-xx1) + cc2/(xx6-xx2) + cc3/(xx6-xx3)); + } + + return(1); +} + +static int update_h1C_c(h) + TXLine *h; +{ + int i; + double d = 0; + + for (i = 0; i < 3; i++) { + h->h1_term[i].c *= h->sqtCdL; + d += h->h1_term[i].c; + } + h->h1C = d; + + for (i = 0; i < 3; i++) + h->h2_term[i].c *= h->h2_aten; + + for (i = 0; i < 6; i++) + h->h3_term[i].c *= h->h3_aten; + + return(1); +} +/**************************************************************** + y.c : Calculate the Pade Approximation of Y(s) + ****************************************************************/ + + +static double eval2(a, b, c, x) + double a, b, c, x; +{ + return(a*x*x + b*x + c); +} + +/*** +static double approx1(st) + double st; +{ + double s3, s2, s1; + + s1 = st; + s2 = s1 * s1; + s3 = s2 * s1; + + return((s3 + q1*s2 + q2*s1 + q3) / (s3 + p1*s2 + p2*s1 + p3)); +} +***/ +/*** +static double approx2(st) + double st; +{ + return(1.0 + c1/(st - x1) + c2/(st - x2) + c3/(st - x3)); +} +***/ + +static void y_pade(R, L, G, C, h) + double R, L, G, C; + TXLine *h; +{ + + /* float RdL, GdC; */ + double RdL, GdC; + + sqtCdL = sqrt((double) C / L); + RdL = R / L; + GdC = G / C; + + mac(GdC, RdL, &b1, &b2, &b3, &b4, &b5); + + A[0][0] = 1.0 - sqrt((double) (GdC / RdL)); + A[0][1] = b1; + A[0][2] = b2; + A[0][3] = -b3; + + A[1][0] = b1; + A[1][1] = b2; + A[1][2] = b3; + A[1][3] = -b4; + + A[2][0] = b2; + A[2][1] = b3; + A[2][2] = b4; + A[2][3] = -b5; + + Gaussian_Elimination1(3); + + p3 = A[0][3]; + p2 = A[1][3]; + p1 = A[2][3]; + + q1 = p1 + b1; + q2 = b1 * p1 + p2 + b2; + q3 = p3 * sqrt((double) (GdC / RdL)); + + find_roots(p1, p2, p3, &x1, &x2, &x3); + c1 = eval2(q1 - p1, q2 - p2, q3 - p3, x1) / + eval2((double) 3.0, (double) 2.0 * p1, p2, x1); + c2 = eval2(q1 - p1, q2 - p2, q3 - p3, x2) / + eval2((double) 3.0, (double) 2.0 * p1, p2, x2); + c3 = eval2(q1 - p1, q2 - p2, q3 - p3, x3) / + eval2((double) 3.0, (double) 2.0 * p1, p2, x3); + + h->sqtCdL = sqtCdL; + h->h1_term[0].c = c1; + h->h1_term[1].c = c2; + h->h1_term[2].c = c3; + h->h1_term[0].x = x1; + h->h1_term[1].x = x2; + h->h1_term[2].x = x3; + +} + +static int Gaussian_Elimination1(dims) + int dims; +{ + register int i, j, k, dim; + register double f; + int imax; + double max; + + dim = dims; + + for (i = 0; i < dim; i++) { + imax = i; + max = ABS(A[i][i]); + for (j = i+1; j < dim; j++) + if (ABS(A[j][i]) > max) { + imax = j; + max = ABS(A[j][i]); + } + if (max < epsi) { + fprintf(stderr, " can not choose a pivot \n"); + exit(0); + } + if (imax != i) + for (k = i; k <= dim; k++) { + f = A[i][k]; + A[i][k] = A[imax][k]; + A[imax][k] = f; + } + + f = 1.0 / A[i][i]; + A[i][i] = 1.0; + + for (j = i+1; j <= dim; j++) + A[i][j] *= f; + + for (j = 0; j < dim ; j++) { + if (i == j) + continue; + f = A[j][i]; + A[j][i] = 0.0; + for (k = i+1; k <= dim; k++) + A[j][k] -= f * A[i][k]; + } + } + return(1); +} + +static double root3(a1, a2, a3, x) + double x; + double a1, a2, a3; +{ + double t1, t2; + + t1 = x*x*x + a1*x*x + a2*x + a3; + t2 = 3.0*x*x + 2.0*a1*x + a2; + + return(x - t1 / t2); +} + +static int div3(a1, a2, a3, x, p1, p2) + double x; + double a1, a2, a3; + double *p1, *p2; +{ + *p1 = a1 + x; + *p2 = - a3 / x; + + return(1); +} + + +/**************************************************************** + Calculate the Maclaurin series of F(z) + + F(z) = sqrt((1+az) / (1+bz)) + = 1 + b1 z + b2 z^2 + b3 z^3 + b4 z^4 + b5 z^5 + ****************************************************************/ + +/*** +static double f3(a, b, z) + double a, b, z; +{ + double t4, t3, t2, t1; + double t14, t13, t12, t11; + double sqt11; + + t1 = 1 / (1.0 + b * z); + t2 = t1 * t1; + t3 = t2 * t1; + t4 = t3 * t1; + + t11 = (1.0 + a * z) * t1; + t12 = (1.0 + a * z) * t2; + t13 = (1.0 + a * z) * t3; + t14 = (1.0 + a * z) * t4; + + sqt11 = sqrt(t11); + + + return( + -0.5 * (-2.0*a*b*t2 + 2.0*b*b*t13) * (a*t1 - b*t12) / (t11*sqt11) + +3.0/8.0 * (a*t1-b*t12)*(a*t1-b*t12)*(a*t1-b*t12) / (t11*t11*sqt11) + +0.5 * (4.0*a*b*b*t3 + 2.0*a*b*b*t3 - 6.0*b*b*b*t14) / sqt11 + -0.25 * (-2.0*a*b*t2 + 2.0*b*b*t13) * (a*t1-b*(1.0+a*z)) / + (t11*sqt11) + ); +} +***/ + +/*** +static double f2(a, b, z) + double a, b, z; +{ + double t3, t2, t1; + double t13, t12, t11; + double sqt11; + + t1 = 1 / (1.0 + b * z); + t2 = t1 * t1; + t3 = t2 * t1; + + t11 = (1.0 + a * z) * t1; + t12 = (1.0 + a * z) * t2; + t13 = (1.0 + a * z) * t3; + + sqt11 = sqrt(t11); + + return( + -0.25 * (a*t1-b*t12) * (a*t1-b*t12) / (t11*sqt11) + +0.5 * (-2.0*a*b*t2 + 2.0*b*b*t13) / sqt11 + ); +} +***/ + +static int mac(at, bt, b1, b2, b3, b4, b5) + /* float at, bt; */ + double at, bt; + double *b1, *b2, *b3, *b4, *b5; +{ + double a, b; + double y1, y2, y3, y4, y5; + + a = at; + b = bt; + + y1 = *b1 = 0.5 * (a - b); + y2 = 0.5 * (3.0 * b * b - 2.0 * a * b - a * a) * y1 / (a - b); + y3 = ((3.0 * b * b + a * a) * y1 * y1 + 0.5 * (3.0 * b * b + - 2.0 * a * b - a * a) * y2) / (a - b); + y4 = ((3.0 * b * b - 3.0 * a * a) * y1 * y1 * y1 + (9.0 * b * b + + 3.0 * a * a) * y1 * y2 + 0.5 * (3.0 * b * b - 2.0 * a * b + - a * a) * y3) / (a - b); + y5 = (12.0 * a * a * y1 * y1 * y1 * y1 + y1 * y1 * y2 * ( + 18.0 * b * b - 18.0 * a * a) + (9.0 * b * b + 3.0 * a * a) * + (y2 * y2 + y1 * y3) + (3.0 * b * b + a * a) * y1 * y3 + + 0.5 * (3.0 * b * b - 2.0 * a * b - a * a) * y4) / (a - b); + + *b2 = y2 / 2.0; + *b3 = y3 / 6.0; + *b4 = y4 / 24.0; + *b5 = y5 / 120.0; + + return(1); +} + + +/**************************************************** + exp.c + ****************************************************/ + +/*** +static double exp_approx1(st) + double st; +{ + double s3, s2, s1; + + s1 = st; + s2 = s1 * s1; + s3 = s2 * s1; + + return(exp((double) - st * tau - a0) * + (s3 + eq1*s2 + eq2*s1 + eq3) / (s3 + ep1*s2 + ep2*s1 + ep3)); +} +***/ + +static int get_c(eq1, eq2, eq3, ep1, ep2, a, b, cr, ci) + double eq1, eq2, eq3, ep1, ep2, a, b; + double *cr, *ci; +{ + double d, n; + + d = (3.0*(a*a-b*b)+2.0*ep1*a+ep2)*(3.0*(a*a-b*b)+2.0*ep1*a+ep2); + d += (6.0*a*b+2.0*ep1*b)*(6.0*a*b+2.0*ep1*b); + n = -(eq1*(a*a-b*b)+eq2*a+eq3)*(6.0*a*b+2.0*ep1*b); + n += (2.0*eq1*a*b+eq2*b)*(3.0*(a*a-b*b)+2.0*ep1*a+ep2); + *ci = n/d; + n = (3.0*(a*a-b*b)+2.0*ep1*a+ep2)*(eq1*(a*a-b*b)+eq2*a+eq3); + n += (6.0*a*b+2.0*ep1*b)*(2.0*eq1*a*b+eq2*b); + *cr = n/d; + + return(1); +} + +/*** +static double exp_approx2(st) + double st; +{ + if (ifImg) + return(1.0 + ec1/(st - ex1) + 2.0*(ec2*(st-ex2)-ec3*ex3) / + ((st-ex2)*(st-ex2) + ex3*ex3)); + else + return(1.0 + ec1/(st - ex1) + ec2/(st - ex2) + ec3/(st - ex3)); +} +***/ + +static int exp_pade(R, L, G, C, l, h) + float R, L, G, C, l; + TXLine *h; +{ + + tau = sqrt((double) L*C); + RdL = R / L; + GdC = G / C; + RG = R * G; + RC = R * C; + GL = G * L; + + { + double a, b, t; + double y1, y2, y3, y4, y5, y6; + + a = RdL; + b = GdC; + t = tau; + + /* + y1 = 0.5 * (a + b); + y2 = a * b - y1 * y1; + y3 = - a * b * y1 - 2.0 * y1 * y2 + y1 * y1 * y1; + y4 = 2.0 * a * b * y1 * y1 - a * b * y2 - 2.0 * y2 * y2 + - 2.0 * y1 * y3 + 5.0 * y1 * y1 * y2 + - 2.0 * y1 * y1 * y1 * y1; + y5 = 6.0 * a * b * (y1 * y2 - y1 * y1 * y1) - a * b * y3 + - 2.0 * y1 * y4 + - 6.0 * y2 * y3 + 12.0 * y2 * y2 * y1 + 7.0 * y1 * y1 * y3 + -10.0 * y1 * y1 * y1 * y2 - 8.0 * y1 * y1 * y1 * y2 + + 6.0 * y1 * y1 * y1 * y1 * y1; + y6 = 24.0 * a * b * y1 * y1 * y1 * y1 - 36.0 * a * b * y1 * y1 * y2 + + 6.0 * a * b * y2 * y2 + 8.0 * a * b * y1 * y3 - 2.0 * y2 * y4 + - 2.0 * y1 * y5 + 2.0 * y1 * y1 * y4 - a * b * y4 -6.0 * y3 * y3 + + 44.0 * y1 * y2 * y3 + 60.0 * y1 * y1 * y1 * y1 * y2 + -24.0 * y1 * y1 * y1 * y1 * y1 * y1 + 12.0 * y2 * y2 * y2 + -54.0 * y1 * y1 * y2 * y2 + 7.0 * y1 * y1 * y4 + -24.0 * y1 * y1 * y1 * y3 - 24.0 * y1 * y1 * y2 * y2 + -8.0 * y1 * y1 * y1 * y3 + 24.0 * y1 * y1 * y1 * y1 * y2 + - 6.0 * y2 * y4; + */ + + y1 = 0.5 * (a + b); + y2 = a * b - y1 * y1; + y3 = -3.0 * y1 * y2; + y4 = -3.0 * y2 * y2 - 4.0 * y1 * y3; + y5 = - 5.0 * y1 * y4 -10.0 * y2 * y3; + y6 = -10.0 * y3 * y3 - 15.0 * y2 * y4 - 6.0 * y1 * y5; + + a0 = y1 * t; + a1 = y2 * t * t / 2.0; + a2 = y3 * t * t * t / 6.0; + a3 = y4 * t * t * t * t / 24.0; + a4 = y5 * t * t * t * t * t / 120.0; + a5 = y6 * t * t * t * t * t * t / 720.0; + + } + + a0 *= l; + a1 *= l; + a2 *= l; + a3 *= l; + a4 *= l; + a5 *= l; + + pade(l); + + h->taul = tau * l; + h->h2_aten = exp(- a0); + h->h2_term[0].c = ec1; + h->h2_term[1].c = ec2; + h->h2_term[2].c = ec3; + h->h2_term[0].x = ex1; + h->h2_term[1].x = ex2; + h->h2_term[2].x = ex3; + + return(ifImg); +} + +static int pade(l) + float l; +{ + int i, j; + double a[6]; + double b[6]; + + a[1] = -a1; + a[2] = -a2; + a[3] = -a3; + a[4] = -a4; + a[5] = -a5; + + b[0] = 1.0; + b[1] = a[1]; + for (i = 2; i <= 5; i++) { + b[i] = 0.0; + for (j = 1; j <= i; j++) + b[i] += j * a[j] * b[i-j]; + b[i] = b[i] / (double) i; + } + + AA[0][0] = 1.0 - exp((double) a0 - l * sqrt(RG)); + AA[0][1] = b[1]; + AA[0][2] = b[2]; + AA[0][3] = -b[3]; + + AA[1][0] = b[1]; + AA[1][1] = b[2]; + AA[1][2] = b[3]; + AA[1][3] = -b[4]; + + AA[2][0] = b[2]; + AA[2][1] = b[3]; + AA[2][2] = b[4]; + AA[2][3] = -b[5]; + + Gaussian_Elimination2(3); + + ep3 = AA[0][3]; + ep2 = AA[1][3]; + ep1 = AA[2][3]; + + eq1 = ep1 + b[1]; + eq2 = b[1] * ep1 + ep2 + b[2]; + eq3 = ep3 * exp((double) a0 - l * sqrt(RG)); + + ep3 = ep3 / (tau*tau*tau); + ep2 = ep2 / (tau*tau); + ep1 = ep1 / tau; + eq3 = eq3 / (tau*tau*tau); + eq2 = eq2 / (tau*tau); + eq1 = eq1 / tau; + /* + printf("factor = %e\n", exp(-a0)); + printf("ep1 = %e ep2 = %e ep3 = %e\n", ep1, ep2, ep3); + */ + exp_find_roots(ep1, ep2, ep3, &ex1, &ex2, &ex3); + /* + printf("roots are %e %e %e \n", ex1, ex2, ex3); + */ + ec1 = eval2(eq1 - ep1, eq2 - ep2, eq3 - ep3, ex1) / + eval2((double) 3.0, (double) 2.0 * ep1, ep2, ex1); + if (ifImg) + get_c(eq1 - ep1, eq2 - ep2, eq3 - ep3, ep1, ep2, ex2, ex3, &ec2, &ec3); + else { + ec2 = eval2(eq1 - ep1, eq2 - ep2, eq3 - ep3, ex2) / + eval2((double) 3.0, (double) 2.0 * ep1, ep2, ex2); + ec3 = eval2(eq1 - ep1, eq2 - ep2, eq3 - ep3, ex3) / + eval2((double) 3.0, (double) 2.0 * ep1, ep2, ex3); + } + return (1); +} + +static int Gaussian_Elimination2(dims) + int dims; +{ + register int i, j, k, dim; + register double f; + double max; + int imax; + + dim = dims; + + for (i = 0; i < dim; i++) { + imax = i; + max = ABS(AA[i][i]); + for (j = i+1; j < dim; j++) + if (ABS(AA[j][i]) > max) { + imax = j; + max = ABS(AA[j][i]); + } + if (max < epsi2) { + fprintf(stderr, " can not choose a pivot \n"); + exit(0); + } + if (imax != i) + for (k = i; k <= dim; k++) { + f = AA[i][k]; + AA[i][k] = AA[imax][k]; + AA[imax][k] = f; + } + + f = 1.0 / AA[i][i]; + AA[i][i] = 1.0; + + for (j = i+1; j <= dim; j++) + AA[i][j] *= f; + + for (j = 0; j < dim ; j++) { + if (i == j) + continue; + f = AA[j][i]; + AA[j][i] = 0.0; + for (k = i+1; k <= dim; k++) + AA[j][k] -= f * AA[i][k]; + } + } + return(1); +} + +/*** +static int exp_div3(a1, a2, a3, x, p1, p2) + double x; + double a1, a2, a3; + double *p1, *p2; + { + *p1 = a1 + x; + *p2 = - a3 / x; + + return(1); +} +***/ + +/*** + ***/ + +static int exp_find_roots(a1, a2, a3, ex1, ex2, ex3) + double a1, a2, a3; + double *ex1, *ex2, *ex3; +{ + double x, t; + double p, q; + + q = (a1*a1-3.0*a2) / 9.0; + p = (2.0*a1*a1*a1-9.0*a1*a2+27.0*a3) / 54.0; + t = q*q*q - p*p; + if (t >= 0.0) { + t = acos((double) p /(q * sqrt(q))); + x = -2.0*sqrt(q)*cos(t / 3.0) - a1/3.0; + } else { + if (p > 0.0) { + t = pow(sqrt(-t)+p, (double) 1.0 / 3.0); + x = -(t + q / t) - a1/3.0; + } else if (p == 0.0) { + x = -a1/3.0; + } else { + t = pow(sqrt(-t)-p, (double) 1.0 / 3.0); + x = (t + q / t) - a1/3.0; + } + } + { + double ex1; + int i = 0; + ex1 = x; + for (t = root3(a1, a2, a3, x); ABS(t-x) > 5.0e-4; + t = root3(a1, a2, a3, x)) + if (++i == 32) { + x = ex1; + break; + } else + x = t; + } + /*** + x = a1; + for (t = root3(a1, a2, a3, x); ABS(t-x) > epsi2; + t = root3(a1, a2, a3, x)) { + x = t; + i++; + if (i > 1000) { + x = 0.5 * (x + root3(a1, a2, a3, x)); + j++; + if (j == 3) + break; + i = 0; + } + } + ***/ + *ex1 = x; + div3(a1, a2, a3, x, &a1, &a2); + + t = a1 * a1 - 4.0 * a2; + if (t < 0) { + ifImg = 1; + printf("***** Two Imaginary Roots.\n"); + *ex3 = 0.5 * sqrt(-t); + *ex2 = -0.5 * a1; + } else { + ifImg = 0; + t *= 1.0e-16; + t = sqrt(t)*1.0e8; + if (a1 >= 0.0) + *ex2 = t = -0.5 * (a1 + t); + else + *ex2 = t = -0.5 * (a1 - t); + *ex3 = a2 / t; + /* + *ex2 = 0.5 * (-a1 + t); + *ex3 = 0.5 * (-a1 - t); + */ + } + + return(1); +} +static NDnamePt +insert_ND(name, ndn) + char *name; + NDnamePt *ndn; +{ + int cmp; + NDnamePt p; + + if (*ndn == NULL) { + p = *ndn = (NDnamePt) malloc(sizeof (NDname)); + p->nd = NULL; + p->right = p->left = NULL; + strcpy(p->id, name); + return(p); + } + cmp = strcmp((*ndn)->id, name); + if (cmp == 0) + return(*ndn); + else { + if (cmp < 0) + return(insert_ND(name, &((*ndn)->left))); + else + return(insert_ND(name, &((*ndn)->right))); + } +} + + +static NODE +*insert_node(name) + char *name; +{ + NDnamePt n; + NODE *p; + + n = insert_ND(name, &ndn); + if (n->nd == NULL) { + p = NEW_node(); + p->name = n; + n->nd = p; + p->next = node_tab; + node_tab = p; + return(p); + } else + return(n->nd); +} + +static NODE +*NEW_node() +{ + NODE *n; + + n = (NODE *) malloc (sizeof (NODE)); + n->mptr = NULL; + n->gptr = NULL; + n->cptr = NULL; + n->rptr = NULL; + n->tptr = NULL; + n->cplptr = NULL; + n->rlptr = NULL; + n->ddptr = NULL; + n->cvccsptr = NULL; + n->vccsptr = NULL; + n->CL = 0.0; + n->V = n->dv = 0.0; + n->gsum = n->cgsum = 0; + n->is = 0; + n->tag = 0; + n->flag = 0; + n->region = NULL; + n->ofile = NULL; + n->dvtag = 0; + + return(n); +} + +static int find_roots(a1, a2, a3, x1, x2, x3) + double a1, a2, a3; + double *x1, *x2, *x3; +{ + double x, t; + double p, q; + + q = (a1*a1-3.0*a2) / 9.0; + p = (2.0*a1*a1*a1-9.0*a1*a2+27.0*a3) / 54.0; + t = q*q*q - p*p; + if (t >= 0.0) { + t = acos((double) p /(q * sqrt(q))); + x = -2.0*sqrt(q)*cos(t / 3.0) - a1/3.0; + } else { + if (p > 0.0) { + t = pow(sqrt(-t)+p, (double) 1.0 / 3.0); + x = -(t + q / t) - a1/3.0; + } else if (p == 0.0) { + x = -a1/3.0; + } else { + t = pow(sqrt(-t)-p, (double) 1.0 / 3.0); + x = (t + q / t) - a1/3.0; + } + } + { + double x1; + int i = 0; + x1 = x; + for (t = root3(a1, a2, a3, x); ABS(t-x) > 5.0e-4; + t = root3(a1, a2, a3, x)) + if (++i == 32) { + x = x1; + break; + } else + x = t; + } + /* + x = a1; + i = 0; + j = 0; + for (t = root3(a1, a2, a3, x); ABS(t-x) > epsi; + t = root3(a1, a2, a3, x)) { + x = t; + i++; + if (i > 1000) { + x = 0.5 * (x + root3(a1, a2, a3, x)); + j++; + if (j == 3) + break; + i = 0; + } + } + */ + + *x1 = x; + div3(a1, a2, a3, x, &a1, &a2); + + t = a1 * a1 - 4.0 * a2; + if (t < 0) { + printf("***** Two Imaginary Roots in Characteristic Admittance.\n"); + exit(0); + } + + t *= 1.0e-18; + t = sqrt(t) * 1.0e9; + if (a1 >= 0.0) + *x2 = t = -0.5 * (a1 + t); + else + *x2 = t = -0.5 * (a1 - t); + *x3 = a2 / t; + /* + *x2 = 0.5 * (-a1 + t); + *x3 = 0.5 * (-a1 - t); + */ + return(1); +} +