199 changed files with 0 additions and 34329 deletions
-
24src/frontend/com_dl.c
-
12src/frontend/com_dl.h
-
24src/include/cluster.h
-
49src/include/cm.h
-
57src/include/cmconstants.h
-
95src/include/cmproto.h
-
71src/include/cmtypes.h
-
79src/include/dllitf.h
-
109src/include/enh.h
-
371src/include/evt.h
-
124src/include/evtproto.h
-
123src/include/evtudn.h
-
122src/include/ipc.h
-
52src/include/ipcproto.h
-
96src/include/ipctiein.h
-
84src/include/mif.h
-
373src/include/mifcmdat.h
-
111src/include/mifdefs.h
-
120src/include/mifparse.h
-
157src/include/mifproto.h
-
226src/include/miftypes.h
-
33src/include/tclspice.h
-
3028src/pkgIndex.tcl.in
-
426src/spicelib/analysis/cluster.c
-
18src/spicelib/devices/cpl/Makefile.am
-
39src/spicelib/devices/cpl/cpl.c
-
97src/spicelib/devices/cpl/cpldefs.h
-
38src/spicelib/devices/cpl/cpldel.c
-
34src/spicelib/devices/cpl/cpldest.c
-
19src/spicelib/devices/cpl/cplext.h
-
68src/spicelib/devices/cpl/cplinit.c
-
13src/spicelib/devices/cpl/cplinit.h
-
6src/spicelib/devices/cpl/cplitf.h
-
890src/spicelib/devices/cpl/cplload.c
-
45src/spicelib/devices/cpl/cplmdel.c
-
51src/spicelib/devices/cpl/cplmpar.c
-
45src/spicelib/devices/cpl/cplparam.c
-
2101src/spicelib/devices/cpl/cplsetup.c
-
21src/spicelib/devices/txl/Makefile.am
-
38src/spicelib/devices/txl/txl.c
-
76src/spicelib/devices/txl/txlacct.c
-
43src/spicelib/devices/txl/txlask.c
-
92src/spicelib/devices/txl/txldefs.h
-
38src/spicelib/devices/txl/txldel.c
-
36src/spicelib/devices/txl/txldest.c
-
19src/spicelib/devices/txl/txlext.h
-
41src/spicelib/devices/txl/txlfbr.c
-
73src/spicelib/devices/txl/txlinit.c
-
18src/spicelib/devices/txl/txlinit.h
-
12src/spicelib/devices/txl/txlitf.h
-
689src/spicelib/devices/txl/txlload.c
-
49src/spicelib/devices/txl/txlmask.c
-
45src/spicelib/devices/txl/txlmdel.c
-
51src/spicelib/devices/txl/txlmpar.c
-
40src/spicelib/devices/txl/txlparam.c
-
1140src/spicelib/devices/txl/txlsetup.c
-
131src/spicelib/parser/inp2p.c
-
236src/spicelib/parser/inp2y.c
-
34src/tcl/ChangeLog
-
170src/tcl/README
-
587src/tcl/example.cir
-
12src/tcl/plot.tcl
-
50src/tcl/vector_test.tcl
-
1323src/tclspice.c
-
16src/xspice/Makefile.am
-
24src/xspice/README
-
17src/xspice/cm/Makefile.am
-
701src/xspice/cm/cm.c
-
267src/xspice/cm/cmevt.c
-
314src/xspice/cm/cmmeters.c
-
523src/xspice/cm/cmutil.c
-
13src/xspice/enh/Makefile.am
-
99src/xspice/enh/enh.c
-
437src/xspice/enh/enhtrans.c
-
27src/xspice/evt/Makefile.am
-
170src/xspice/evt/evtaccept.c
-
645src/xspice/evt/evtbackup.c
-
78src/xspice/evt/evtcall_hybrids.c
-
366src/xspice/evt/evtdeque.c
-
350src/xspice/evt/evtdump.c
-
437src/xspice/evt/evtinit.c
-
300src/xspice/evt/evtiter.c
-
613src/xspice/evt/evtload.c
-
93src/xspice/evt/evtnext_time.c
-
159src/xspice/evt/evtnode_copy.c
-
321src/xspice/evt/evtop.c
-
218src/xspice/evt/evtplot.c
-
369src/xspice/evt/evtprint.c
-
252src/xspice/evt/evtqueue.c
-
578src/xspice/evt/evtsetup.c
-
512src/xspice/evt/evttermi.c
-
67src/xspice/examples/analog_models1_ac.deck
-
61src/xspice/examples/analog_models1_dc.deck
-
61src/xspice/examples/analog_models1_swept_dc.deck
-
62src/xspice/examples/analog_models1_transient.deck
-
66src/xspice/examples/analog_models2_ac.deck
-
63src/xspice/examples/analog_models2_dc.deck
-
64src/xspice/examples/analog_models2_swept_dc.deck
-
67src/xspice/examples/analog_models2_transient.deck
-
81src/xspice/examples/analog_models3_ac.deck
@ -1,24 +0,0 @@ |
|||
#include <ngspice.h> /* for wl */ |
|||
#include "ftedefs.h" |
|||
#include <devdefs.h> /* 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 |
|||
|
|||
@ -1,12 +0,0 @@ |
|||
#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 |
|||
@ -1,24 +0,0 @@ |
|||
#ifndef _CLUSTER_H_ |
|||
#define _CLUSTER_H_ |
|||
#include <cktdefs.h> |
|||
|
|||
/* 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 |
|||
@ -1,49 +0,0 @@ |
|||
#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 |
|||
|
|||
<date> <person name> <nature of 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 */ |
|||
@ -1,57 +0,0 @@ |
|||
#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 |
|||
|
|||
<date> <person name> <nature of 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 */ |
|||
@ -1,95 +0,0 @@ |
|||
#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 |
|||
|
|||
<date> <person name> <nature of 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 */ |
|||
@ -1,71 +0,0 @@ |
|||
#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 |
|||
|
|||
<date> <person name> <nature of 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 */ |
|||
@ -1,79 +0,0 @@ |
|||
/* |
|||
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 |
|||
@ -1,109 +0,0 @@ |
|||
#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 |
|||
|
|||
<date> <person name> <nature of 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 */ |
|||
@ -1,371 +0,0 @@ |
|||
#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 |
|||
|
|||
<date> <person name> <nature of 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 */ |
|||
@ -1,124 +0,0 @@ |
|||
#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 |
|||
|
|||
<date> <person name> <nature of 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 */ |
|||
@ -1,123 +0,0 @@ |
|||
#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 |
|||
|
|||
<date> <person name> <nature of 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 */ |
|||
@ -1,122 +0,0 @@ |
|||
/* $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 |
|||
|
|||
<date> <person name> <nature of 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 */ |
|||
@ -1,52 +0,0 @@ |
|||
|
|||
/* 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 ); |
|||
|
|||
@ -1,96 +0,0 @@ |
|||
/*============================================================================ |
|||
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 |
|||
|
|||
<date> <person name> <nature of 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 */ |
|||
|
|||
@ -1,84 +0,0 @@ |
|||
#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 |
|||
|
|||
<date> <person name> <nature of 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; |
|||
|
|||
|
|||
|
|||
extern Mif_Info_t g_mif_info; |
|||
|
|||
|
|||
#endif /* MIF */ |
|||
@ -1,373 +0,0 @@ |
|||
#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 |
|||
|
|||
<date> <person name> <nature of 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(<name>) 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 */ |
|||
@ -1,111 +0,0 @@ |
|||
#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 |
|||
|
|||
<date> <person name> <nature of 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 */ |
|||
@ -1,120 +0,0 @@ |
|||
#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 |
|||
|
|||
<date> <person name> <nature of 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 */ |
|||
@ -1,157 +0,0 @@ |
|||
#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 |
|||
|
|||
<date> <person name> <nature of 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 */ |
|||
@ -1,226 +0,0 @@ |
|||
#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 |
|||
|
|||
<date> <person name> <nature of 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, /* <identifier> - 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 */ |
|||
@ -1,33 +0,0 @@ |
|||
/*Include file to allow spice to export certain data */ |
|||
#ifndef TCLSPICE_H |
|||
#define TCLSPICE_H |
|||
|
|||
extern int steps_completed; |
|||
extern void blt_init(void *run); |
|||
extern void blt_add(int index,double value); |
|||
extern void blt_relink(int index, void* v); |
|||
extern void blt_lockvec(int index); |
|||
|
|||
/* For things to do per loop */ |
|||
int Tcl_ExecutePerLoop(); |
|||
|
|||
/* For tk ploting */ |
|||
extern int sp_Tk_Init(void); |
|||
#include <graph.h> |
|||
extern int sp_Tk_NewViewport(GRAPH *graph); |
|||
extern int sp_Tk_Close(void); |
|||
extern int sp_Tk_Clear(void); |
|||
extern int sp_Tk_DrawLine(int x1, int y1, int x2, int y2); |
|||
extern int sp_Tk_Arc(int x0, int y0, int radius, double theta1, double theta2); |
|||
extern int sp_Tk_Text(char *text, int x, int y); |
|||
extern int sp_Tk_DefineColor(int colorid, double red, double green, double blue); |
|||
extern int sp_Tk_DefineLinestyle(int linestyleid, int mask); |
|||
extern int sp_Tk_SetLinestyle(int linestyleid); |
|||
extern int sp_Tk_SetColor(int colorid); |
|||
extern int sp_Tk_Update(void); |
|||
|
|||
/* The blt callback method */ |
|||
#include <dvec.h> |
|||
extern int blt_plot(struct dvec *y,struct dvec *x); |
|||
|
|||
#endif |
|||
3028
src/pkgIndex.tcl.in
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -1,426 +0,0 @@ |
|||
/* Spice hooks */ |
|||
#include <ngspice.h> |
|||
#ifdef CLUSTER |
|||
#include <inpdefs.h> |
|||
#include "cluster.h" |
|||
#include <cktdefs.h> |
|||
#include <gendefs.h> |
|||
|
|||
/* Misc stuff */ |
|||
#include <pthread.h> |
|||
#include <string.h> |
|||
|
|||
/*Network stuff*/ |
|||
#include <arpa/inet.h> |
|||
#include <netinet/in.h> |
|||
#include <sys/socket.h> |
|||
#include <netdb.h> |
|||
#include <unistd.h> |
|||
|
|||
|
|||
struct input_pipe { |
|||
/*the names of the local and remote nodes*/ |
|||
char remote[32]; |
|||
char local[32]; |
|||
int fd; |
|||
FILE *stream; |
|||
/* the data recieved */ |
|||
double time; |
|||
double data; |
|||
/*resistance of this link*/ |
|||
double res; |
|||
/* The value controled */ |
|||
double *currentPtr; |
|||
/*The output it is linked to*/ |
|||
struct output_pipe *link; |
|||
struct input_pipe *next; |
|||
}; |
|||
|
|||
struct output_pipe { |
|||
int fd; |
|||
FILE *stream; |
|||
/*the names of the local and remote nodes*/ |
|||
char local[32]; |
|||
char remote[32]; |
|||
/* The index of the local node value in the ckt->CKTrhsOld array */ |
|||
int outIndex; |
|||
/*Last values sent*/ |
|||
double time,data; |
|||
struct input_pipe *link; |
|||
struct output_pipe *next; |
|||
}; |
|||
|
|||
static double lastTimeSent=0; |
|||
|
|||
static int time_sock=0; |
|||
static FILE *time_outfile=NULL; |
|||
static FILE *time_infile=NULL; |
|||
|
|||
static struct input_pipe* input_pipes=NULL; |
|||
static struct output_pipe* output_pipes=NULL; |
|||
|
|||
/* sets up deamon which waits for connections |
|||
*and sets up input pipes as it recieves them */ |
|||
static void *start_listener(void *); |
|||
|
|||
/* Setup the output pipes*/ |
|||
static int setup_output(CKTcircuit *ckt); |
|||
static int setup_input(CKTcircuit *ckt); |
|||
static int setup_time(); |
|||
|
|||
int CLUsetup(CKTcircuit *ckt){ |
|||
pthread_t tid; |
|||
struct input_pipe *curr; |
|||
int i, connections=0; |
|||
GENmodel *mod; |
|||
GENinstance *inst; |
|||
|
|||
/* count the number of connections expected */ |
|||
i = INPtypelook("Isource"); |
|||
for(mod = (GENmodel *)ckt->CKThead[i]; |
|||
mod != NULL; |
|||
mod = mod->GENnextModel) |
|||
for (inst = mod->GENinstances; |
|||
inst != NULL; |
|||
inst = inst->GENnextInstance) |
|||
if(strncmp("ipcx",inst->GENname,4) == 0) |
|||
connections++; |
|||
|
|||
/* allocate the input connections */ |
|||
for(i=0;i<connections;i++) { |
|||
curr = (struct input_pipe *)tmalloc(sizeof(struct input_pipe)); |
|||
if(input_pipes) |
|||
curr->next = input_pipes; |
|||
else |
|||
curr->next = NULL; |
|||
input_pipes = curr; |
|||
} |
|||
|
|||
pthread_create(&tid,NULL,start_listener,(void *)&connections); |
|||
setup_output(ckt); |
|||
pthread_join(tid,NULL); |
|||
setup_input(ckt); |
|||
setup_time(); |
|||
return 0; |
|||
} |
|||
|
|||
#include "../devices/isrc/isrcdefs.h" |
|||
/*Connect to remote machine and find the data*/ |
|||
static int setup_output(CKTcircuit *ckt){ |
|||
int type; |
|||
GENmodel *mod; |
|||
GENinstance *inst; |
|||
char hostname[64]; |
|||
|
|||
lastTimeSent = 0; |
|||
type = INPtypelook("Isource"); |
|||
|
|||
for(mod = (GENmodel *)ckt->CKThead[type]; |
|||
mod != NULL; |
|||
mod = mod->GENnextModel) |
|||
|
|||
for (inst = mod->GENinstances; |
|||
inst != NULL; |
|||
inst = inst->GENnextInstance) |
|||
|
|||
if(strncmp("ipcx",inst->GENname,4) == 0){ |
|||
ISRCinstance *isrc = (ISRCinstance *)inst; |
|||
CKTnode *node; |
|||
struct output_pipe *curr; |
|||
struct sockaddr_in address; |
|||
struct hostent *host=NULL; |
|||
int sock,nodeNum,i; |
|||
|
|||
/*Create the struct*/ |
|||
curr = (struct output_pipe *)tmalloc(sizeof(struct output_pipe)); |
|||
if(output_pipes) |
|||
curr->next = output_pipes; |
|||
else |
|||
curr->next = NULL; |
|||
output_pipes = curr; |
|||
|
|||
/* The node names */ |
|||
strcpy(curr->local,CKTnodName(ckt,isrc->ISRCnegNode));/*weird*/ |
|||
strcpy(curr->remote,isrc->ISRCname); |
|||
|
|||
/* extract remote node number */ |
|||
nodeNum = /*Xcoord*/(curr->remote[4] - '0') * CLUSTER_WIDTH |
|||
+ /*Ycoord*/(curr->remote[9] - '0'); |
|||
sprintf(hostname,"n%d."DOMAIN_NAME,nodeNum); |
|||
|
|||
/* network stuff */ |
|||
host = gethostbyname(hostname); |
|||
if(!host){ |
|||
printf("Host not found in setup_output\n"); |
|||
exit(0); |
|||
} |
|||
|
|||
if((sock = socket(PF_INET,SOCK_STREAM,0)) < 0){ |
|||
printf("Socket open in setup_output\n"); |
|||
exit(0); |
|||
} |
|||
|
|||
address.sin_family = AF_INET; |
|||
address.sin_port = htons(PORT); |
|||
memcpy(&address.sin_addr,host->h_addr_list[0], |
|||
sizeof(address.sin_addr)); |
|||
|
|||
printf("connecting to %s ...... ",hostname); |
|||
fflush(stdout); |
|||
|
|||
while(connect(sock,(struct sockaddr *)&address,sizeof(address))){ |
|||
usleep(500);/*wait for the sever to start*/ |
|||
} |
|||
|
|||
printf("connected\n"); |
|||
|
|||
curr->fd = sock; |
|||
|
|||
/* send stuff */ |
|||
/* buffer */ |
|||
i = (strlen(curr->remote) + strlen(curr->local) + 2)*sizeof(char); |
|||
setsockopt(sock,SOL_SOCKET,SO_SNDBUF,&i,sizeof(i)); |
|||
|
|||
curr->stream = fdopen(curr->fd,"w"); |
|||
|
|||
fwrite(curr->remote,sizeof(char),strlen(curr->remote),curr->stream); |
|||
fputc('\0',curr->stream); |
|||
fwrite(curr->local,sizeof(char),strlen(curr->local),curr->stream); |
|||
fputc('\0',curr->stream); |
|||
fflush(curr->stream); |
|||
|
|||
/* buffer, what is done per time point */ |
|||
i = sizeof(double)*2; |
|||
setsockopt(sock,SOL_SOCKET,SO_SNDBUF,&i,sizeof(i)); |
|||
|
|||
/* find the index in ckt->rhsOld which contains the local node */ |
|||
i = 0; |
|||
for(node = ckt->CKTnodes->next;node;node = node->next){ |
|||
i++; |
|||
if(strcmp(node->name,curr->local)==0){ |
|||
curr->outIndex = i; |
|||
goto next; |
|||
} |
|||
} |
|||
printf("Local node %s not found\n",curr->local); |
|||
exit(0); |
|||
next: |
|||
|
|||
} |
|||
return 0; |
|||
} |
|||
|
|||
/*Processes the connections recieved by start_listener*/ |
|||
static int setup_input(CKTcircuit *ckt){ |
|||
int type; |
|||
GENmodel *mod; |
|||
GENinstance *inst; |
|||
struct input_pipe *input; |
|||
type = INPtypelook("Isource"); |
|||
|
|||
for(input = input_pipes;input;input = input->next){ |
|||
int i; |
|||
|
|||
input->stream = fdopen(input->fd,"r"); |
|||
|
|||
/*Get the local and remote node names*/ |
|||
i=0; |
|||
do { |
|||
while(fread(&input->local[i],sizeof(char),1,input->stream) != 1); |
|||
}while(input->local[i++] != '\0'); |
|||
|
|||
i=0; |
|||
do { |
|||
while(fread(&input->remote[i],sizeof(char),1,input->stream) != 1); |
|||
}while(input->remote[i++] != '\0'); |
|||
|
|||
/* initilise */ |
|||
input->time = -1; |
|||
|
|||
/*Find the Isource to control*/ |
|||
for(mod = (GENmodel *)ckt->CKThead[type]; |
|||
mod != NULL; |
|||
mod = mod->GENnextModel) |
|||
|
|||
for (inst = mod->GENinstances; |
|||
inst != NULL; |
|||
inst = inst->GENnextInstance) |
|||
|
|||
if(strcmp(input->remote,&inst->GENname[11]) == 0){ |
|||
|
|||
ISRCinstance *isrc = (ISRCinstance *)inst; |
|||
input->res = isrc->ISRCdcValue; |
|||
isrc->ISRCdcValue = 0; |
|||
input->currentPtr = &isrc->ISRCdcValue; |
|||
goto next; |
|||
} |
|||
/* We get here if no Isource matches */ |
|||
printf("Current source %s not found\n",input->remote); |
|||
exit(0); |
|||
|
|||
next: |
|||
|
|||
/* Now find the corresponding output */ |
|||
{ |
|||
struct output_pipe *output; |
|||
for(output = output_pipes;output;output = output->next) |
|||
if(strcmp(&input->local[11],output->local)==0){ |
|||
input->link = output; |
|||
output->link = input; |
|||
goto next2; |
|||
} |
|||
printf("Parent to %s not found\n",&input->local[11]); |
|||
exit(0); |
|||
next2: |
|||
} |
|||
} |
|||
return 0; |
|||
} |
|||
|
|||
/* This starts a server and waits for connections, number given by argument*/ |
|||
static void *start_listener(void *v){ |
|||
int *connections = (int *)v; |
|||
int count=0; |
|||
struct sockaddr_in address; |
|||
int sock, conn,i; |
|||
size_t addrLength = sizeof(struct sockaddr_in); |
|||
struct input_pipe *curr; |
|||
|
|||
if((sock = socket(PF_INET,SOCK_STREAM,0)) < 0){ |
|||
printf("socket in start_listener\n"); |
|||
exit(0); |
|||
} |
|||
|
|||
/* Allow reuse of the socket */ |
|||
i = 1; |
|||
setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&i,sizeof(i)); |
|||
|
|||
/* port, inferface ..*/ |
|||
address.sin_family = AF_INET; |
|||
address.sin_port = htons(PORT); |
|||
memset(&address.sin_addr,0,sizeof(address.sin_addr)); |
|||
|
|||
if(bind(sock, (struct sockaddr *)&address,sizeof(address))){ |
|||
printf("bind in start_listener\n"); |
|||
exit(0); |
|||
} |
|||
if(listen(sock,5)){ |
|||
printf("listen in start_listener\n"); |
|||
exit(0); |
|||
} |
|||
|
|||
/* Loop till recieved all connections */ |
|||
curr = input_pipes; |
|||
while (count < *connections){ |
|||
if((conn = accept(sock, (struct sockaddr *)&address,&addrLength)) < 0){ |
|||
printf("accept in start_listener\n"); |
|||
exit(0); |
|||
} |
|||
|
|||
curr->fd = conn; |
|||
/* will fill rest of structure later in setup_input*/ |
|||
count ++; |
|||
curr = curr->next; |
|||
} |
|||
|
|||
close(sock); |
|||
|
|||
return NULL; |
|||
} |
|||
|
|||
/*Writes data to remote computer*/ |
|||
int CLUoutput(CKTcircuit *ckt){ |
|||
struct output_pipe *output; |
|||
lastTimeSent = ckt->CKTtime; |
|||
for(output = output_pipes; |
|||
output; |
|||
output = output->next){ |
|||
output->time = ckt->CKTtime; |
|||
output->data = ckt->CKTrhsOld[output->outIndex]; |
|||
fwrite(&output->time,sizeof(double),1,output->stream); |
|||
fwrite(&output->data, |
|||
sizeof(double),1,output->stream); |
|||
fflush(output->stream); |
|||
} |
|||
return 0; |
|||
} |
|||
|
|||
/*Maniputates the local circuit based on the links*/ |
|||
int CLUinput(CKTcircuit *ckt){ |
|||
struct input_pipe *input; |
|||
double tmp; |
|||
for(input= input_pipes;input;input = input->next){ |
|||
/*recieve data till we get a good time point*/ |
|||
while (input->time < lastTimeSent){ |
|||
while(fread(&input->time, sizeof(double), 1, input->stream) != 1){} |
|||
while(fread(&input->data, sizeof(double), 1, input->stream) != 1){} |
|||
} |
|||
tmp = (input->link->data - input->data) / input->res; |
|||
|
|||
/*dampen out large currents*/ |
|||
if(tmp > 0) |
|||
*input->currentPtr = 0.2 * (1 - exp(-tmp/0.2)); |
|||
else |
|||
*input->currentPtr = -0.2 * (1 - exp(tmp/0.2)); |
|||
|
|||
/*GND is the posNode, local node is the negNode*/ |
|||
} |
|||
return 0; |
|||
} |
|||
|
|||
static int setup_time(){ |
|||
struct sockaddr_in address; |
|||
struct hostent *host=NULL; |
|||
char *hostname = TIME_HOST; |
|||
int sock,i; |
|||
|
|||
/* network stuff */ |
|||
host = gethostbyname(hostname); |
|||
if(!host){ |
|||
printf("Host not found in setup_time\n"); |
|||
exit(0); |
|||
} |
|||
if((sock = socket(PF_INET,SOCK_STREAM,0)) < 0){ |
|||
printf("Socket open in setup_time\n"); |
|||
exit(0); |
|||
} |
|||
|
|||
i = sizeof(double)*2; |
|||
setsockopt(sock,SOL_SOCKET,SO_SNDBUF ,&i,sizeof(i)); |
|||
|
|||
address.sin_family = AF_INET; |
|||
address.sin_port = htons(TIME_PORT); |
|||
memcpy(&address.sin_addr,host->h_addr_list[0], |
|||
sizeof(address.sin_addr)); |
|||
|
|||
|
|||
while(connect(sock,(struct sockaddr *)&address,sizeof(address))){ |
|||
usleep(500);/*wait for the sever to start*/ |
|||
} |
|||
time_sock=sock; |
|||
time_outfile=fdopen(sock,"w"); |
|||
time_infile=fdopen(sock,"r"); |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
|
|||
int CLUsync(double time,double *delta, int error){ |
|||
double tmp; |
|||
if(error) |
|||
tmp = *delta * (-1); |
|||
else |
|||
tmp = *delta; |
|||
fwrite(&time,sizeof(double),1,time_outfile); |
|||
fwrite(&tmp,sizeof(double),1,time_outfile); |
|||
fflush(time_outfile); |
|||
while(fread(&tmp,sizeof(double),1,time_infile) != 1); |
|||
if(tmp < 0){ |
|||
*delta = -tmp; |
|||
return 0; |
|||
} else { |
|||
*delta = tmp; |
|||
return 1; |
|||
} |
|||
} |
|||
#endif |
|||
@ -1,18 +0,0 @@ |
|||
## Process this file with automake to produce Makefile.in
|
|||
|
|||
pkglib_LTLIBRARIES = libcpl.la |
|||
|
|||
libcpl_la_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 |
|||
@ -1,39 +0,0 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights |
|||
reserved. |
|||
Author: 1992 Charles Hough |
|||
**********/ |
|||
|
|||
#include "ngspice.h" |
|||
#include <stdio.h> |
|||
#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); |
|||
@ -1,97 +0,0 @@ |
|||
#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*/ |
|||
@ -1,38 +0,0 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights |
|||
reserved. |
|||
Author: 1992 Charles Hough |
|||
**********/ |
|||
|
|||
|
|||
#include "ngspice.h" |
|||
#include <stdio.h> |
|||
#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); |
|||
} |
|||
@ -1,34 +0,0 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights |
|||
reserved. |
|||
Author: 1992 Charles Hough |
|||
**********/ |
|||
|
|||
#include "ngspice.h" |
|||
#include <stdio.h> |
|||
#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; |
|||
} |
|||
@ -1,19 +0,0 @@ |
|||
#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 */ |
|||
@ -1,68 +0,0 @@ |
|||
#include <config.h> |
|||
|
|||
#include <devdefs.h> |
|||
|
|||
#include "cplitf.h" |
|||
#include "cplext.h" |
|||
#include "cplinit.h" |
|||
|
|||
SPICEdev CPLinfo = { |
|||
{ |
|||
"CplLines", |
|||
"Simple Coupled Multiconductor Lines", |
|||
|
|||
&CPLnSize, |
|||
&CPLnSize, |
|||
CPLnames, |
|||
|
|||
&CPLpTSize, |
|||
CPLpTable, |
|||
|
|||
&CPLmPTSize, |
|||
CPLmPTable, |
|||
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; |
|||
} |
|||
@ -1,13 +0,0 @@ |
|||
#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 |
|||
@ -1,6 +0,0 @@ |
|||
#ifndef DEV_CPL |
|||
#define DEV_CPL |
|||
|
|||
SPICEdev *get_cpl_info(void); |
|||
|
|||
#endif |
|||
@ -1,890 +0,0 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights |
|||
reserved. |
|||
Author: 1992 Charles Hough |
|||
**********/ |
|||
|
|||
|
|||
#include "ngspice.h" |
|||
#include <stdio.h> |
|||
#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); |
|||
} |
|||
|
|||
@ -1,45 +0,0 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights |
|||
reserved. |
|||
Author: 1992 Charles Hough |
|||
**********/ |
|||
|
|||
|
|||
#include "ngspice.h" |
|||
#include <stdio.h> |
|||
#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); |
|||
|
|||
} |
|||
@ -1,51 +0,0 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights |
|||
reserved. |
|||
Author: 1992 Charles Hough |
|||
**********/ |
|||
|
|||
|
|||
#include "ngspice.h" |
|||
#include <stdio.h> |
|||
#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); |
|||
} |
|||
@ -1,45 +0,0 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights |
|||
reserved. |
|||
Author: 1992 Charles Hough |
|||
**********/ |
|||
|
|||
|
|||
#include "ngspice.h" |
|||
#include <stdio.h> |
|||
#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); |
|||
} |
|||
2101
src/spicelib/devices/cpl/cplsetup.c
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -1,21 +0,0 @@ |
|||
## Process this file with automake to produce Makefile.in
|
|||
|
|||
pkglib_LTLIBRARIES = libtxl.la |
|||
|
|||
libtxl_la_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 |
|||
@ -1,38 +0,0 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights |
|||
reserved. |
|||
Author: 1992 Charles Hough |
|||
**********/ |
|||
|
|||
#include "ngspice.h" |
|||
#include <stdio.h> |
|||
#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); |
|||
@ -1,76 +0,0 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights |
|||
reserved. |
|||
Author: 1992 Charles Hough |
|||
**********/ |
|||
|
|||
|
|||
#include "ngspice.h" |
|||
#include <stdio.h> |
|||
#include <math.h> |
|||
#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); |
|||
} |
|||
@ -1,43 +0,0 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights |
|||
reserved. |
|||
Author: 1992 Charles Hough |
|||
**********/ |
|||
|
|||
|
|||
#include "ngspice.h" |
|||
#include <stdio.h> |
|||
#include <math.h> |
|||
#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 */ |
|||
} |
|||
@ -1,92 +0,0 @@ |
|||
#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*/ |
|||
@ -1,38 +0,0 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights |
|||
reserved. |
|||
Author: 1992 Charles Hough |
|||
**********/ |
|||
|
|||
|
|||
#include "ngspice.h" |
|||
#include <stdio.h> |
|||
#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); |
|||
} |
|||
@ -1,36 +0,0 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights |
|||
reserved. |
|||
Author: 1992 Charles Hough |
|||
**********/ |
|||
|
|||
|
|||
#include "ngspice.h" |
|||
#include <stdio.h> |
|||
#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; |
|||
} |
|||
@ -1,19 +0,0 @@ |
|||
#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 */ |
|||
@ -1,41 +0,0 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights |
|||
reserved. |
|||
Author: 1992 Charles Hough |
|||
**********/ |
|||
|
|||
|
|||
#include "ngspice.h" |
|||
#include <stdio.h> |
|||
#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); |
|||
} |
|||
@ -1,73 +0,0 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights |
|||
reserved. |
|||
Author: 1992 Charles Hough |
|||
**********/ |
|||
#include <config.h> |
|||
|
|||
#include <devdefs.h> |
|||
|
|||
#include "txlitf.h" |
|||
#include "txlext.h" |
|||
#include "txlinit.h" |
|||
|
|||
|
|||
SPICEdev TXLinfo = { |
|||
{ |
|||
"TransLine", |
|||
"Simple Lossy Transmission Line", |
|||
|
|||
&TXLnSize, |
|||
&TXLnSize, |
|||
TXLnames, |
|||
|
|||
&TXLpTSize, |
|||
TXLpTable, |
|||
|
|||
&TXLmPTSize, |
|||
TXLmPTable, |
|||
}, |
|||
|
|||
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; |
|||
} |
|||
@ -1,18 +0,0 @@ |
|||
/********** |
|||
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 |
|||
@ -1,12 +0,0 @@ |
|||
/********** |
|||
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 |
|||
@ -1,689 +0,0 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights |
|||
reserved. |
|||
Author: 1992 Charles Hough |
|||
**********/ |
|||
|
|||
|
|||
#include "ngspice.h" |
|||
#include <stdio.h> |
|||
#include "txldefs.h" |
|||
#include "sperror.h" |
|||
#include "suffix.h" |
|||
|
|||
VI_list_txl *pool_vi_txl; |
|||
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); |
|||
|
|||
} |
|||
|
|||
@ -1,49 +0,0 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights |
|||
reserved. |
|||
Author: 1992 Charles Hough |
|||
**********/ |
|||
|
|||
|
|||
#include "ngspice.h" |
|||
#include <stdio.h> |
|||
#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); |
|||
} |
|||
} |
|||
|
|||
@ -1,45 +0,0 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights |
|||
reserved. |
|||
Author: 1992 Charles Hough |
|||
**********/ |
|||
|
|||
|
|||
#include "ngspice.h" |
|||
#include <stdio.h> |
|||
#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); |
|||
|
|||
} |
|||
@ -1,51 +0,0 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights |
|||
reserved. |
|||
Author: 1992 Charles Hough |
|||
**********/ |
|||
|
|||
|
|||
#include "ngspice.h" |
|||
#include <stdio.h> |
|||
#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); |
|||
} |
|||
@ -1,40 +0,0 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights |
|||
reserved. |
|||
Author: 1992 Charles Hough |
|||
**********/ |
|||
|
|||
#include "ngspice.h" |
|||
#include <stdio.h> |
|||
#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); |
|||
} |
|||
1140
src/spicelib/devices/txl/txlsetup.c
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -1,131 +0,0 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights |
|||
reserved. |
|||
Author: 1992 Charles Hough |
|||
**********/ |
|||
|
|||
#include "ngspice.h" |
|||
#include <stdio.h> |
|||
#include "ifsim.h" |
|||
#include "inpdefs.h" |
|||
#include "inpmacs.h" |
|||
#include "fteext.h" |
|||
#include "inp.h" |
|||
|
|||
void |
|||
INP2P(ckt,tab,current) |
|||
void *ckt; |
|||
INPtables *tab; |
|||
card *current; |
|||
|
|||
{ |
|||
|
|||
int mytype; /* the type we determine cpls are */ |
|||
int type; /* the type the model says it is */ |
|||
char *line; /* the part of the current line left to parse */ |
|||
char *name, *tempname; /* the cpl's name */ |
|||
char *model; /* the name of the cpl's model */ |
|||
char **nname1; /* the first node's name */ |
|||
char **nname2; /* the second node's name */ |
|||
char *ground; |
|||
void **node1; /* the first node's node pointer */ |
|||
void **node2; /* the second node's node pointer */ |
|||
void *groundnode; |
|||
int error; /* error code temporary */ |
|||
int error1; /* secondary error code temporary */ |
|||
INPmodel *thismodel; /* pointer to model structure describing our model */ |
|||
void *mdfast; /* pointer to the actual model */ |
|||
void *fast; /* pointer to the actual instance */ |
|||
IFvalue ptemp; /* a value structure to package cpl into */ |
|||
IFuid uid; /* uid for default model */ |
|||
double lenval = 0; |
|||
int lenvalgiven = 0; |
|||
int num, i; |
|||
|
|||
mytype = INPtypelook("CplLines"); |
|||
if(mytype < 0 ) { |
|||
LITERR("Device type CplLines not supported by this binary\n") |
|||
return; |
|||
} |
|||
line = current->line; |
|||
INPgetTok(&line,&name,1); |
|||
INPinsert(&name,tab); |
|||
/* num = (int) INPevaluate(&line,&error1,1); */ |
|||
num = 0; |
|||
|
|||
/* first pass to determine the dimension */ |
|||
while (*line != '\0') { |
|||
INPgetTok(&line, &tempname,1); |
|||
if (strcmp(tempname, "len") == 0) break; |
|||
num ++; |
|||
} |
|||
num = (num - 2) / 2; |
|||
line = current->line; |
|||
INPgetTok(&line,&name,1); |
|||
|
|||
nname1 = (char **) malloc(num * sizeof(char *)); |
|||
nname2 = (char **) malloc(num * sizeof(char *)); |
|||
node1 = (void **) malloc(num * sizeof(void *)); |
|||
node2 = (void **) malloc(num * sizeof(void *)); |
|||
|
|||
|
|||
for (i = 0; i < num; i++) { |
|||
INPgetTok(&line,&(nname1[i]),1); |
|||
INPtermInsert(ckt,&(nname1[i]),tab,&(node1[i])); |
|||
} |
|||
INPgetTok(&line,&ground,1); |
|||
INPtermInsert(ckt,&ground,tab,&groundnode); |
|||
for (i = 0; i < num; i++) { |
|||
INPgetTok(&line,&(nname2[i]),1); |
|||
INPtermInsert(ckt,&(nname2[i]),tab,&(node2[i])); |
|||
} |
|||
INPgetTok(&line,&ground,1); |
|||
INPtermInsert(ckt,&ground,tab,&groundnode); |
|||
|
|||
INPgetTok(&line,&model,1); |
|||
if (strcmp(model, "len") == 0) { |
|||
lenval = INPevaluate(&line,&error1,1); |
|||
lenvalgiven = 1; |
|||
INPgetTok(&line,&model,1); |
|||
} |
|||
if(*model) { /* token isn't null */ |
|||
INPinsert(&model,tab); |
|||
thismodel = (INPmodel *)NULL; |
|||
current->error = INPgetMod(ckt,model,&thismodel,tab); |
|||
if(thismodel != NULL) { |
|||
if(mytype != thismodel->INPmodType) { |
|||
LITERR("incorrect model type") |
|||
return; |
|||
} |
|||
mdfast = thismodel->INPmodfast; |
|||
type = thismodel->INPmodType; |
|||
} else { |
|||
type = mytype; |
|||
if(!tab->defPmod) { |
|||
/* create default P model */ |
|||
IFnewUid(ckt,&uid,(IFuid)NULL,"P",UID_MODEL,(void**)NULL); |
|||
IFC(newModel, (ckt,type,&(tab->defPmod),uid)) |
|||
} |
|||
mdfast = tab->defPmod; |
|||
} |
|||
IFC(newInstance,(ckt,mdfast,&fast,name)) |
|||
} else { |
|||
LITERR("model name is not found") |
|||
return; |
|||
} |
|||
|
|||
/* IFC(bindNode,(ckt,fast,1,fakename)) */ |
|||
|
|||
ptemp.iValue = num; |
|||
GCA(INPpName,("dimension", &ptemp,ckt,type,fast)) |
|||
ptemp.v.vec.sVec = nname1; |
|||
GCA(INPpName,("pos_nodes", &ptemp,ckt,type,fast)) |
|||
ptemp.v.vec.sVec = nname2; |
|||
GCA(INPpName,("neg_nodes", &ptemp,ckt,type,fast)) |
|||
if (error1 == 0 && lenvalgiven) { |
|||
ptemp.rValue = lenval; |
|||
GCA(INPpName,("length",&ptemp,ckt,type,fast)) |
|||
} |
|||
|
|||
return; |
|||
} |
|||
@ -1,236 +0,0 @@ |
|||
/********** |
|||
Copyright 1992 Regents of the University of California. All rights |
|||
reserved. |
|||
Author: 1992 Charles Hough |
|||
**********/ |
|||
|
|||
#include "ngspice.h" |
|||
#include <stdio.h> |
|||
#include "ifsim.h" |
|||
#include "inpdefs.h" |
|||
#include "inpmacs.h" |
|||
#include "fteext.h" |
|||
#include "inp.h" |
|||
|
|||
void |
|||
INP2Y(ckt,tab,current) |
|||
void *ckt; |
|||
INPtables *tab; |
|||
card *current; |
|||
|
|||
{ |
|||
/* parse a txl card */ |
|||
/* Yxxxx node1 node2 name */ |
|||
|
|||
int mytype; /* the type to determine txl */ |
|||
int mytype2; /* the type to determine cpl */ |
|||
int type; /* the type the model says it is */ |
|||
char *line; /* the part of the current line left to parse */ |
|||
char *name; /* the resistor's name */ |
|||
char *buf; /* temporary buffer for parsing */ |
|||
char *model; /* the name of the resistor's model */ |
|||
char *nname1; /* the first node's name */ |
|||
char *nname2; /* the second node's name */ |
|||
char rname1[10], rname2[10], rname3[10]; |
|||
char cname1[10], cname2[10], cname3[10], cname4[10]; |
|||
char *internal1, *internal2; |
|||
char *ground1, *ground2; |
|||
void *node1; /* the first node's node pointer */ |
|||
void *node2; /* the second node's node pointer */ |
|||
void *gnode1, *gnode2, *inode1, *inode2; |
|||
int error; /* error code temporary */ |
|||
int error1; /* secondary error code temporary */ |
|||
INPmodel *thismodel; /* pointer to model structure describing our model */ |
|||
void *mdfast; /* pointer to the actual model */ |
|||
void *fast; /* pointer to the actual instance */ |
|||
void *mdfast2, *mdfast3, *mdfast4, *mdfast5, *mdfast6; |
|||
void *fast2, *fast3, *fast4, *fast5, *fast6; |
|||
IFuid uid; /* uid for default model */ |
|||
GENinstance *txl; |
|||
IFvalue ptemp; /* a value structure to package into */ |
|||
double lval=0, rval=0, cval=0, lenval=0; |
|||
int lenvalgiven = 0; |
|||
|
|||
mytype = INPtypelook("TransLine"); |
|||
mytype2 = INPtypelook("CplLines"); |
|||
|
|||
if(mytype < 0 ) { |
|||
LITERR("Device type TransLine not supported by this binary\n") |
|||
return; |
|||
} |
|||
line = current->line; |
|||
INPgetTok(&line,&name,1); |
|||
INPinsert(&name,tab); |
|||
INPgetTok(&line,&nname1,1); |
|||
INPtermInsert(ckt,&nname1,tab,&node1); |
|||
INPgetTok(&line,&ground1,1); |
|||
INPtermInsert(ckt,&ground1,tab,&gnode1); |
|||
INPgetTok(&line,&nname2,1); |
|||
INPtermInsert(ckt,&nname2,tab,&node2); |
|||
INPgetTok(&line,&ground2,1); |
|||
INPtermInsert(ckt,&ground2,tab,&gnode2); |
|||
|
|||
INPgetTok(&line,&model,1); |
|||
if (strcmp(model, "len") == 0) { |
|||
lenval = INPevaluate(&line,&error1,1); |
|||
lenvalgiven = 1; |
|||
INPgetTok(&line,&model,1); |
|||
} |
|||
if(*model) { /* token isn't null */ |
|||
INPinsert(&model,tab); |
|||
thismodel = (INPmodel *)NULL; |
|||
current->error = INPgetMod(ckt,model,&thismodel,tab); |
|||
if(thismodel != NULL) { |
|||
if (thismodel->INPmodType == mytype2) { |
|||
INP2P(ckt,tab,current); |
|||
return; |
|||
} |
|||
else if (mytype != thismodel->INPmodType) { |
|||
LITERR("incorrect model type") |
|||
return; |
|||
} |
|||
line = thismodel->INPmodLine->line; |
|||
INPgetTok(&line,&buf,1); /* throw out .model */ |
|||
INPgetTok(&line,&buf,1); /* throw out model name */ |
|||
INPgetTok(&line,&buf,1); /* throw out txl */ |
|||
INPgetTok(&line,&buf,1); |
|||
while (*line != '\0') { |
|||
if (*buf == 'R' || *buf == 'r') { |
|||
INPgetTok(&line,&buf,1); |
|||
rval = atof(buf); |
|||
} |
|||
if ((strcmp(buf,"L") == 0) || (strcmp(buf,"l") == 0)) { |
|||
INPgetTok(&line,&buf,1); |
|||
lval = atof(buf); |
|||
} |
|||
if ((strcmp(buf,"C") == 0) || (strcmp(buf,"c") == 0)) { |
|||
INPgetTok(&line,&buf,1); |
|||
cval = atof(buf); |
|||
} |
|||
if (lenvalgiven == 0) { |
|||
if (strcmp(buf,"length")== 0) { |
|||
INPgetTok(&line,&buf,1); |
|||
lenval = atof(buf); |
|||
} |
|||
} |
|||
INPgetTok(&line,&buf,1); |
|||
} |
|||
if (lenval && rval && lval && rval/lval > 1.6e10) { |
|||
/* use 3-pi model */ |
|||
rval = 3.0 / (rval * lenval); |
|||
cval = cval * lenval / 6.0; |
|||
|
|||
type = INPtypelook("Resistor"); |
|||
|
|||
/* resistor between node1 and internal1 */ |
|||
internal1 = (char *) malloc (10); |
|||
strcpy(internal1, "txlnd1"); |
|||
INPtermInsert(ckt, &internal1, tab, &inode1); |
|||
if(!tab->defRmod) { |
|||
/* create default R model */ |
|||
IFnewUid(ckt,&uid,(IFuid)NULL,"R",UID_MODEL,(void**)NULL); |
|||
IFC(newModel, (ckt,type,&(tab->defRmod),uid)) |
|||
} |
|||
mdfast = tab->defRmod; |
|||
strcpy(rname1, "txlres1"); |
|||
IFC(newInstance,(ckt,mdfast,&fast,rname1)) |
|||
IFC(bindNode,(ckt,fast,1,node1)) |
|||
IFC(bindNode,(ckt,fast,2,inode1)) |
|||
ptemp.rValue = rval; |
|||
GCA(INPpName,("resistance",&ptemp,ckt,type,fast)) |
|||
|
|||
/* resistor between internal1 and internal2 */ |
|||
internal2 = (char *) malloc (10); |
|||
strcpy(internal2, "txlnd2"); |
|||
INPtermInsert(ckt, &internal2, tab, &inode2); |
|||
strcpy(rname2, "txlres2"); |
|||
mdfast2 = tab->defRmod; |
|||
IFC(newInstance,(ckt,mdfast2,&fast2,rname2)) |
|||
IFC(bindNode,(ckt,fast2,1,inode1)) |
|||
IFC(bindNode,(ckt,fast2,2,inode2)) |
|||
ptemp.rValue = rval; |
|||
GCA(INPpName,("resistance",&ptemp,ckt,type,fast2)) |
|||
|
|||
/* resistor between internal2 and node2 */ |
|||
strcpy(rname3, "txlres3"); |
|||
mdfast3 = tab->defRmod; |
|||
IFC(newInstance,(ckt,mdfast3,&fast3,rname3)) |
|||
IFC(bindNode,(ckt,fast3,1,inode2)) |
|||
IFC(bindNode,(ckt,fast3,2,node2)) |
|||
ptemp.rValue = rval; |
|||
GCA(INPpName,("resistance",&ptemp,ckt,type,fast3)) |
|||
|
|||
/* capacitor on node1 */ |
|||
type = INPtypelook("Capacitor"); |
|||
if(!tab->defCmod) { |
|||
IFnewUid(ckt,&uid,(IFuid)NULL,"C",UID_MODEL,(void**)NULL); |
|||
IFC(newModel,(ckt,type,&(tab->defCmod),uid)) |
|||
} |
|||
mdfast4 = tab->defCmod; |
|||
strcpy(cname1, "txlcap1"); |
|||
IFC(newInstance,(ckt,mdfast4,&fast4,cname1)) |
|||
IFC(bindNode,(ckt,fast4,1,node1)) |
|||
IFC(bindNode,(ckt,fast4,2,gnode1)) |
|||
ptemp.rValue = cval; |
|||
GCA(INPpName,("capacitance",&ptemp,ckt,type,fast4)) |
|||
|
|||
/* capacitor on internal1 */ |
|||
strcpy(cname2, "txlcap2"); |
|||
mdfast4 = tab->defCmod; |
|||
IFC(newInstance,(ckt,mdfast4,&fast4,cname2)) |
|||
IFC(bindNode,(ckt,fast4,1,inode1)) |
|||
IFC(bindNode,(ckt,fast4,2,gnode1)) |
|||
ptemp.rValue = cval * 2; |
|||
GCA(INPpName,("capacitance",&ptemp,ckt,type,fast4)) |
|||
|
|||
/* capacitor on internal2 */ |
|||
strcpy(cname3, "txlcap3"); |
|||
mdfast5 = tab->defCmod; |
|||
IFC(newInstance,(ckt,mdfast5,&fast5,cname3)) |
|||
IFC(bindNode,(ckt,fast5,1,inode2)) |
|||
IFC(bindNode,(ckt,fast5,2,gnode1)) |
|||
ptemp.rValue = cval * 2; |
|||
GCA(INPpName,("capacitance",&ptemp,ckt,type,fast5)) |
|||
|
|||
/* capacitor on node2 */ |
|||
strcpy(cname4, "txlcap4"); |
|||
mdfast6 = tab->defCmod; |
|||
IFC(newInstance,(ckt,mdfast6,&fast6,cname4)) |
|||
IFC(bindNode,(ckt,fast6,1,node2)) |
|||
IFC(bindNode,(ckt,fast6,2,gnode1)) |
|||
ptemp.rValue = cval; |
|||
GCA(INPpName,("capacitance",&ptemp,ckt,type,fast6)) |
|||
return; |
|||
|
|||
} |
|||
|
|||
/* use regular txl model */ |
|||
mdfast = thismodel->INPmodfast; |
|||
type = thismodel->INPmodType; |
|||
} else { |
|||
type = mytype; |
|||
if(!tab->defYmod) { |
|||
/* create default Y model */ |
|||
IFnewUid(ckt,&uid,(IFuid)NULL,"Y",UID_MODEL,(void**)NULL); |
|||
IFC(newModel, (ckt,type,&(tab->defYmod),uid)) |
|||
} |
|||
mdfast = tab->defYmod; |
|||
} |
|||
IFC(newInstance,(ckt,mdfast,&fast,name)) |
|||
} else { |
|||
LITERR("model name is not found") |
|||
return; |
|||
} |
|||
|
|||
if (error1 == 0 && lenvalgiven) { |
|||
ptemp.rValue = lenval; |
|||
GCA(INPpName,("length",&ptemp,ckt,type,fast)) |
|||
} |
|||
|
|||
IFC(bindNode,(ckt,fast,1,node1)) |
|||
IFC(bindNode,(ckt,fast,2,node2)) |
|||
|
|||
txl = (GENinstance *)fast; |
|||
|
|||
return; |
|||
} |
|||
@ -1,34 +0,0 @@ |
|||
25/07/2002: |
|||
* Modified configure/Makefiles so use --enable-tcl to make module |
|||
* Added option --enable-cluster to configure for cluster version |
|||
* Swig no longer needed to compile |
|||
23/07/2002: |
|||
* Added display device Tk plot |
|||
* Added function bltplot |
|||
17/04/2002: |
|||
* Merged a version of cluster spice. |
|||
26/03/2002: |
|||
* New TCL function lastVector. |
|||
19/02/2002: |
|||
* User nodes and codemodels now work in DCtrans analysis, |
|||
calculated results are now correct. |
|||
* Fixed bug where the first timestep always seems to fail to converge |
|||
after a resume or a step, thus cutting delta. |
|||
30/01/2002: |
|||
* Precompiled Opus/XSpice models are now supported with |
|||
--enable-xspice flag, load them using codemodel "opus spice module" |
|||
22/01/2002: |
|||
* Fixed parameters being ignored when mosfet model is not found |
|||
16/01/2002: |
|||
* Fixed crash when a mosfet model is not found |
|||
In the mists of time: |
|||
* Changed spicelib/parser/inpgtok.c to allow / * ^ in node names (/ needed for ext2spice) |
|||
* Modifed files in |
|||
spicelib/analysis/(acan.c, dctran.c, dctrcurv.c, noisean.c), frontend/outitf.c, |
|||
frontend/runcoms.c, frontend/runcoms2.c |
|||
so rawfiles continue to be written to after a pause then a resume |
|||
* Small modification to main.c to make the struct nutmeginfo global, so tclspice can use it. |
|||
* Added ifdefed code to frontend/outitf.c which links output to tclspice. |
|||
* Modified main.c and frontend/inp.c so .save lines are always processed |
|||
* ifdefed code in misc/alloc.c so the functions use Tcl_Mutex to stop memory allocation conflicts. |
|||
* Fixed crash in com_resume() when run without circuit loaded |
|||
@ -1,170 +0,0 @@ |
|||
Spice Tcl module |
|||
$Id$ |
|||
DESCRIPTION |
|||
|
|||
Contained in this package is the source code for a spice tcl module and ng-spice-rework-14. |
|||
It allows you run spice commands in tcl and run the spice simulator in the background |
|||
so you can manipulate the results while spice is running. |
|||
|
|||
THANKS: |
|||
|
|||
Ng-Spice at http://ngspice.sourceforge.net for the spice simulator |
|||
|
|||
ScriptEDA ( http://www-cad.eecs.berkeley.edu/~pinhong/scriptEDA ) for the idea and examples. |
|||
|
|||
INSTALLATION |
|||
|
|||
Requirements: |
|||
ngspice, included (only tested with ng-spice-rework-13 and 14, should work with all rework versions) |
|||
tcl WITH thread support compiled in (tested with tcl-8.3.3-65 and tcl8.3.4) |
|||
BTL for tcl (tested with blt2.4y) |
|||
pthreads (most modern OS's have this) |
|||
|
|||
Installation: |
|||
This package contains the ng-spice-rework-14 source code, which has been slightly modifed, and the tcl module source. |
|||
The spice source is contained in the ng-spice-rework directory. |
|||
Tcl modules's documentation is in the ng-spice-rework/src/tcl directory |
|||
|
|||
Please hide libgc.so (the garbage collector library), if you have it. You can put it back afterwards! |
|||
This is because you don't want tclspice to compile with it included! |
|||
|
|||
Also if you want to run spice in the background you need to recompile |
|||
tcl and tk to enable thread support if they haven't got it enabled already (redhat packages haven't). |
|||
If you don't then tclspice will crash frequently!!!! |
|||
|
|||
The install commands are: |
|||
From the root directory of the source: |
|||
./configure --enable-tcl --enable-experimental --enable-xspice --disable-shared |
|||
make tcl |
|||
And as root: |
|||
make tcl_install |
|||
|
|||
USAGE |
|||
|
|||
example: |
|||
|
|||
$tclsh |
|||
|
|||
%package require spice |
|||
(to load the module) |
|||
|
|||
Then you can run commands either by typing spice command directly or by typing spice <spice command> |
|||
For example: |
|||
%spice::version |
|||
%spice::source ./example.cir |
|||
%spice::bg run |
|||
%spice::halt |
|||
%spice::show |
|||
%spice::plot_nvars 0 |
|||
%spice::plot_variables 0 |
|||
%spice::plot_datapoints 0 |
|||
%spice::bg resume |
|||
%spice::halt |
|||
%exit |
|||
|
|||
Commands availiabe: |
|||
|
|||
spice has it's own namespace (spice::) which can be imported. |
|||
Although there are a few conflicts, so not all commands are imported. |
|||
|
|||
|
|||
spice::spice <command> |
|||
runs the spicified spice command in the foreground |
|||
spice::bg <command> |
|||
runs the spice command in the background |
|||
All spice commands should be recognised |
|||
spice::halt |
|||
Stops(or attempts to) a spice background command (like run) (it simulates a ^C) |
|||
|
|||
spice::running |
|||
returns 1 if a background process is running, 0 otherwise |
|||
|
|||
spice::get_output script ?stderr? |
|||
runs the tcl script "script", catching std_out and maping it to the return value. |
|||
It can also catch the std_err and put it into the stderr variable. |
|||
|
|||
spice::get_param device param |
|||
Returns the parameter of the device |
|||
|
|||
spice::spice_data |
|||
Returns the names and types of avaliable spice |
|||
variables |
|||
{name type} {name type} ... {name type} |
|||
|
|||
spice::spice_header |
|||
Returns the current run's title, analysis name, date, and the number of signals as follows: |
|||
{title ??} {name ???} {date ????} {variables ???} |
|||
|
|||
spice::delta ?value? |
|||
Sets the value of delta to the given value, if given. |
|||
It returns the current setting of delta |
|||
|
|||
spice::maxstep ?value? |
|||
Same as spice::delta but for the maximum stepsize allowed |
|||
|
|||
variables: |
|||
|
|||
spice::steps_completed |
|||
The number of simulation steps done so far. |
|||
|
|||
The following concern the BLT vectors generated; |
|||
|
|||
functions: |
|||
spice::spicetoblt vecName signal ?start? ?end? |
|||
Sets the blt vector vecName with the contents of the spice signal, signal, |
|||
using the optional start and end index. |
|||
|
|||
spice::lastVector vecName |
|||
Sets the blt vector vecName to contain the last spice state vector |
|||
|
|||
variables: |
|||
spice::blt_vnum |
|||
The number of signals avalible |
|||
|
|||
The following only work if there is a plot stored; |
|||
|
|||
spice::plot_variables plot |
|||
returns a list of variables in plot "plot" |
|||
plot is from 0-numofplots, newest plot being 0. |
|||
|
|||
spice::plot_get_value name plot index |
|||
returns value of varable "name" in plot "plot", at position "index" |
|||
|
|||
spice::plot_datapoints plot |
|||
returns number of time steps saved so far |
|||
|
|||
spice::plot_title plot |
|||
returns plot title |
|||
|
|||
spice::plot_date plot |
|||
returns date string |
|||
|
|||
spice::plot_name plot |
|||
returns plot name |
|||
|
|||
spice::plot_nvars plot |
|||
returns number of variables in the plot |
|||
|
|||
Plotting functions; |
|||
|
|||
spice::plot |
|||
The standard plot function has been wrapped to a Tk canvas ".c" See Tcl source in |
|||
pkgIndex.tcl The callback functions are named gr_*, modify/override at will. |
|||
spice::bltplot |
|||
Instead of plotting: For each pair of vectors to plot spice::gr_Plot is called, |
|||
"proc spice_gr_Plot { Xname Xtype Xunits Yname Ytype Yunits }" which you can override |
|||
With the static Blt vectors "spice::X_Data" and "spice::Y_Data" containing the plot data. |
|||
WARNING: |
|||
If any of the Tcl callback functions cause an error then a crash may occour as tcl |
|||
overwrites random data in the spice code. Not sure why. |
|||
|
|||
TODO & BUGS |
|||
|
|||
1) plot and iplot don't work: window opens then tclsh stops, Xserver doesn't respond to spice requests |
|||
They aren't really needed anymore, as you now have the blt vectors to play with, |
|||
and the Tk plot output and bltplot output. |
|||
2) Spice prints to stdout, unavoidable, sorry if it mucks up your commandline |
|||
3) tclreadline doesn't like this module very much |
|||
|
|||
Stefan Jones |
|||
<stefan.jones@multigig.com> |
|||
@ -1,587 +0,0 @@ |
|||
TITLE: proj1.cir.cir - Rotary Traveling Wave Oscillator |
|||
.control |
|||
set filetype=ascii |
|||
.endc |
|||
|
|||
VDD0 VDD0 VDD DC 0 |
|||
VSS0 VSS0 0 DC 0 |
|||
VDD_A0 VDD_A0 VDD0 DC 0 |
|||
VSS_A0 VSS_A0 VSS0 DC 0 |
|||
VDD_B0 VDD_B0 VDD0 DC 0 |
|||
VSS_B0 VSS_B0 VSS0 DC 0 |
|||
LA0 A0 LCA0 3.69030941553353e-11 |
|||
RA0 LCA0 A1 0.266535044422507 |
|||
LB0 B0 LCB0 3.69030941553353e-11 |
|||
RB0 LCB0 B1 0.266535044422507 |
|||
C0 A1 B1 2.50418376625721e-14 |
|||
MNA0 B0 A0 VSS_B0 VSS_B0 Nmod L=2.53696435353243e-07 W= |
|||
+4.24857778403814e-05 AD=3.125e-11 AS=3.125e-11 PD= |
|||
+8.49715556807627e-05 PS=8.49715556807627e-05 NQSMOD=1 |
|||
MPA0 B0 A0 VDD_B0 VDD_B0 Pmod L=2.55343565546106e-07 W= |
|||
+0.000101772203908557 AD=7.8125e-11 AS=7.8125e-11 PD= |
|||
+0.000203544407817114 PS=0.000203544407817114 NQSMOD=1 |
|||
MNB0 A0 B0 VSS_A0 VSS_A0 Nmod L=2.53941602497219e-07 W= |
|||
+4.10652659629401e-05 AD=3.125e-11 AS=3.125e-11 PD= |
|||
+8.21305319258802e-05 PS=8.21305319258802e-05 NQSMOD=1 |
|||
MPB0 A0 B0 VDD_A0 VDD_A0 Pmod L=2.52010168145607e-07 W= |
|||
+0.000103533977891464 AD=7.8125e-11 AS=7.8125e-11 PD= |
|||
+0.000207067955782928 PS=0.000207067955782928 NQSMOD=1 |
|||
LA1 A1 LCA1 3.69030941553353e-11 |
|||
RA1 LCA1 A2 0.266535044422507 |
|||
LB1 B1 LCB1 3.69030941553353e-11 |
|||
RB1 LCB1 B2 0.266535044422507 |
|||
C1 A2 B2 2.50418376625721e-14 |
|||
MNA1 B1 A1 0 0 Nmod L=2.52370578161099e-07 W=4.12246995102289e-05 AD= |
|||
+3.125e-11 AS=3.125e-11 PD=8.24493990204578e-05 PS= |
|||
+8.24493990204578e-05 NQSMOD=1 |
|||
MPA1 B1 A1 VDD VDD Pmod L=2.45709468983316e-07 W=0.000103710764679465 |
|||
+AD=7.8125e-11 AS=7.8125e-11 PD=0.000207421529358929 PS= |
|||
+0.000207421529358929 NQSMOD=1 |
|||
MNB1 A1 B1 0 0 Nmod L=2.48115895523017e-07 W=4.26306134285554e-05 AD= |
|||
+3.125e-11 AS=3.125e-11 PD=8.52612268571108e-05 PS= |
|||
+8.52612268571108e-05 NQSMOD=1 |
|||
MPB1 A1 B1 VDD VDD Pmod L=2.55265156192223e-07 W=0.000102043840486507 |
|||
+AD=7.8125e-11 AS=7.8125e-11 PD=0.000204087680973014 PS= |
|||
+0.000204087680973014 NQSMOD=1 |
|||
LA2 A2 LCA2 3.69030941553353e-11 |
|||
RA2 LCA2 A3 0.266535044422507 |
|||
LB2 B2 LCB2 3.69030941553353e-11 |
|||
RB2 LCB2 B3 0.266535044422507 |
|||
C2 A3 B3 2.50418376625721e-14 |
|||
MNA2 B2 A2 0 0 Nmod L=2.53484220592882e-07 W=4.16915225420459e-05 AD= |
|||
+3.125e-11 AS=3.125e-11 PD=8.33830450840917e-05 PS= |
|||
+8.33830450840917e-05 NQSMOD=1 |
|||
MPA2 B2 A2 VDD VDD Pmod L=2.44256748076514e-07 W=0.00010549295960702 |
|||
+AD=7.8125e-11 AS=7.8125e-11 PD=0.000210985919214039 PS= |
|||
+0.000210985919214039 NQSMOD=1 |
|||
MNB2 A2 B2 0 0 Nmod L=2.48805892712811e-07 W=4.15734692647458e-05 AD= |
|||
+3.125e-11 AS=3.125e-11 PD=8.31469385294916e-05 PS= |
|||
+8.31469385294916e-05 NQSMOD=1 |
|||
MPB2 A2 B2 VDD VDD Pmod L=2.54004987710956e-07 W=0.00010229621219808 |
|||
+AD=7.8125e-11 AS=7.8125e-11 PD=0.00020459242439616 PS= |
|||
+0.00020459242439616 NQSMOD=1 |
|||
LA3 A3 LCA3 3.69030941553353e-11 |
|||
RA3 LCA3 A4 0.266535044422507 |
|||
LB3 B3 LCB3 3.69030941553353e-11 |
|||
RB3 LCB3 B4 0.266535044422507 |
|||
C3 A4 B4 2.50418376625721e-14 |
|||
MNA3 B3 A3 0 0 Nmod L=2.54307430347219e-07 W=4.11339076756089e-05 AD= |
|||
+3.125e-11 AS=3.125e-11 PD=8.22678153512179e-05 PS= |
|||
+8.22678153512179e-05 NQSMOD=1 |
|||
MPA3 B3 A3 VDD VDD Pmod L=2.52369109463781e-07 W=0.000103371681055656 |
|||
+AD=7.8125e-11 AS=7.8125e-11 PD=0.000206743362111311 PS= |
|||
+0.000206743362111311 NQSMOD=1 |
|||
MNB3 A3 B3 0 0 Nmod L=2.4960708801709e-07 W=4.21794611046917e-05 AD= |
|||
+3.125e-11 AS=3.125e-11 PD=8.43589222093833e-05 PS= |
|||
+8.43589222093833e-05 NQSMOD=1 |
|||
MPB3 A3 B3 VDD VDD Pmod L=2.53834779766428e-07 W=0.000105556314711602 |
|||
+AD=7.8125e-11 AS=7.8125e-11 PD=0.000211112629423204 PS= |
|||
+0.000211112629423204 NQSMOD=1 |
|||
LA4 A4 LCA4 3.69030941553353e-11 |
|||
RA4 LCA4 A5 0.266535044422507 |
|||
LB4 B4 LCB4 3.69030941553353e-11 |
|||
RB4 LCB4 B5 0.266535044422507 |
|||
C4 A5 B5 2.50418376625721e-14 |
|||
MNA4 B4 A4 0 0 Nmod L=2.48091656083177e-07 W=4.11207568141106e-05 AD= |
|||
+3.125e-11 AS=3.125e-11 PD=8.22415136282211e-05 PS= |
|||
+8.22415136282211e-05 NQSMOD=1 |
|||
MPA4 B4 A4 VDD VDD Pmod L=2.47723605289033e-07 W=0.000103463392309261 |
|||
+AD=7.8125e-11 AS=7.8125e-11 PD=0.000206926784618522 PS= |
|||
+0.000206926784618522 NQSMOD=1 |
|||
MNB4 A4 B4 0 0 Nmod L=2.49254771880382e-07 W=4.25122425012226e-05 AD= |
|||
+3.125e-11 AS=3.125e-11 PD=8.50244850024452e-05 PS= |
|||
+8.50244850024452e-05 NQSMOD=1 |
|||
MPB4 A4 B4 VDD VDD Pmod L=2.49689766979065e-07 W=0.000103227993619608 |
|||
+AD=7.8125e-11 AS=7.8125e-11 PD=0.000206455987239216 PS= |
|||
+0.000206455987239216 NQSMOD=1 |
|||
LA5 A5 LCA5 3.69030941553353e-11 |
|||
RA5 LCA5 A6 0.266535044422507 |
|||
LB5 B5 LCB5 3.69030941553353e-11 |
|||
RB5 LCB5 B6 0.266535044422507 |
|||
C5 A6 B6 2.50418376625721e-14 |
|||
MNA5 B5 A5 0 0 Nmod L=2.53960031106522e-07 W=4.1129961792588e-05 AD= |
|||
+3.125e-11 AS=3.125e-11 PD=8.22599235851759e-05 PS= |
|||
+8.22599235851759e-05 NQSMOD=1 |
|||
MPA5 B5 A5 VDD VDD Pmod L=2.47418707088064e-07 W=0.000101621693062467 |
|||
+AD=7.8125e-11 AS=7.8125e-11 PD=0.000203243386124935 PS= |
|||
+0.000203243386124935 NQSMOD=1 |
|||
MNB5 A5 B5 0 0 Nmod L=2.49659687529522e-07 W=4.2524931640785e-05 AD= |
|||
+3.125e-11 AS=3.125e-11 PD=8.50498632815701e-05 PS= |
|||
+8.50498632815701e-05 NQSMOD=1 |
|||
MPB5 A5 B5 VDD VDD Pmod L=2.46328059754468e-07 W=0.000102061546065548 |
|||
+AD=7.8125e-11 AS=7.8125e-11 PD=0.000204123092131096 PS= |
|||
+0.000204123092131096 NQSMOD=1 |
|||
LA6 A6 LCA6 3.69030941553353e-11 |
|||
RA6 LCA6 A7 0.266535044422507 |
|||
LB6 B6 LCB6 3.69030941553353e-11 |
|||
RB6 LCB6 B7 0.266535044422507 |
|||
C6 A7 B7 2.50418376625721e-14 |
|||
MNA6 B6 A6 0 0 Nmod L=2.54326804653788e-07 W=4.17332976706085e-05 AD= |
|||
+3.125e-11 AS=3.125e-11 PD=8.34665953412171e-05 PS= |
|||
+8.34665953412171e-05 NQSMOD=1 |
|||
MPA6 B6 A6 VDD VDD Pmod L=2.48727427835127e-07 W=0.000103244611103459 |
|||
+AD=7.8125e-11 AS=7.8125e-11 PD=0.000206489222206918 PS= |
|||
+0.000206489222206918 NQSMOD=1 |
|||
MNB6 A6 B6 0 0 Nmod L=2.49697035135609e-07 W=4.23570035518e-05 AD= |
|||
+3.125e-11 AS=3.125e-11 PD=8.47140071036001e-05 PS= |
|||
+8.47140071036001e-05 NQSMOD=1 |
|||
MPB6 A6 B6 VDD VDD Pmod L=2.48995485890626e-07 W=0.000103695454759978 |
|||
+AD=7.8125e-11 AS=7.8125e-11 PD=0.000207390909519956 PS= |
|||
+0.000207390909519956 NQSMOD=1 |
|||
LA7 A7 LCA7 3.69030941553353e-11 |
|||
RA7 LCA7 A8 0.266535044422507 |
|||
LB7 B7 LCB7 3.69030941553353e-11 |
|||
RB7 LCB7 B8 0.266535044422507 |
|||
C7 A8 B8 2.50418376625721e-14 |
|||
MNA7 B7 A7 0 0 Nmod L=2.53418975114981e-07 W=4.06421756574473e-05 AD= |
|||
+3.125e-11 AS=3.125e-11 PD=8.12843513148946e-05 PS= |
|||
+8.12843513148946e-05 NQSMOD=1 |
|||
MPA7 B7 A7 VDD VDD Pmod L=2.4471861043622e-07 W=0.000104600862141835 |
|||
+AD=7.8125e-11 AS=7.8125e-11 PD=0.00020920172428367 PS= |
|||
+0.00020920172428367 NQSMOD=1 |
|||
MNB7 A7 B7 0 0 Nmod L=2.50159056393584e-07 W=4.06845582724173e-05 AD= |
|||
+3.125e-11 AS=3.125e-11 PD=8.13691165448345e-05 PS= |
|||
+8.13691165448345e-05 NQSMOD=1 |
|||
MPB7 A7 B7 VDD VDD Pmod L=2.55032245177227e-07 W=0.000106482118141681 |
|||
+AD=7.8125e-11 AS=7.8125e-11 PD=0.000212964236283363 PS= |
|||
+0.000212964236283363 NQSMOD=1 |
|||
LA8 A8 LCA8 3.69030941553353e-11 |
|||
RA8 LCA8 A9 0.266535044422507 |
|||
LB8 B8 LCB8 3.69030941553353e-11 |
|||
RB8 LCB8 B9 0.266535044422507 |
|||
C8 A9 B9 2.50418376625721e-14 |
|||
MNA8 B8 A8 0 0 Nmod L=2.45729547191971e-07 W=4.18266198665335e-05 AD= |
|||
+3.125e-11 AS=3.125e-11 PD=8.3653239733067e-05 PS=8.3653239733067e-05 |
|||
+NQSMOD=1 |
|||
MPA8 B8 A8 VDD VDD Pmod L=2.45156004861421e-07 W=0.000101593205477244 |
|||
+AD=7.8125e-11 AS=7.8125e-11 PD=0.000203186410954489 PS= |
|||
+0.000203186410954489 NQSMOD=1 |
|||
MNB8 A8 B8 0 0 Nmod L=2.49014342219656e-07 W=4.14314219478801e-05 AD= |
|||
+3.125e-11 AS=3.125e-11 PD=8.28628438957603e-05 PS= |
|||
+8.28628438957603e-05 NQSMOD=1 |
|||
MPB8 A8 B8 VDD VDD Pmod L=2.50396673007567e-07 W=0.000103029640740115 |
|||
+AD=7.8125e-11 AS=7.8125e-11 PD=0.00020605928148023 PS= |
|||
+0.00020605928148023 NQSMOD=1 |
|||
LA9 A9 LCA9 3.69030941553353e-11 |
|||
RA9 LCA9 A10 0.266535044422507 |
|||
LB9 B9 LCB9 3.69030941553353e-11 |
|||
RB9 LCB9 B10 0.266535044422507 |
|||
C9 A10 B10 2.50418376625721e-14 |
|||
MNA9 B9 A9 0 0 Nmod L=2.51066307645916e-07 W=4.17044186844862e-05 AD= |
|||
+3.125e-11 AS=3.125e-11 PD=8.34088373689724e-05 PS= |
|||
+8.34088373689724e-05 NQSMOD=1 |
|||
MPA9 B9 A9 VDD VDD Pmod L=2.4945438501494e-07 W=0.000104601836030031 |
|||
+AD=7.8125e-11 AS=7.8125e-11 PD=0.000209203672060063 PS= |
|||
+0.000209203672060063 NQSMOD=1 |
|||
MNB9 A9 B9 0 0 Nmod L=2.56178041422984e-07 W=4.17990098329256e-05 AD= |
|||
+3.125e-11 AS=3.125e-11 PD=8.35980196658511e-05 PS= |
|||
+8.35980196658511e-05 NQSMOD=1 |
|||
MPB9 A9 B9 VDD VDD Pmod L=2.5274010042983e-07 W=0.000103578149162769 |
|||
+AD=7.8125e-11 AS=7.8125e-11 PD=0.000207156298325537 PS= |
|||
+0.000207156298325537 NQSMOD=1 |
|||
LA10 A10 LCA10 3.69030941553353e-11 |
|||
RA10 LCA10 A11 0.266535044422507 |
|||
LB10 B10 LCB10 3.69030941553353e-11 |
|||
RB10 LCB10 B11 0.266535044422507 |
|||
C10 A11 B11 2.50418376625721e-14 |
|||
MNA10 B10 A10 0 0 Nmod L=2.45772611943267e-07 W=4.24345922952649e-05 |
|||
+AD=3.125e-11 AS=3.125e-11 PD=8.48691845905299e-05 PS= |
|||
+8.48691845905299e-05 NQSMOD=1 |
|||
MPA10 B10 A10 VDD VDD Pmod L=2.55544710347746e-07 W= |
|||
+0.000105625826497323 AD=7.8125e-11 AS=7.8125e-11 PD= |
|||
+0.000211251652994645 PS=0.000211251652994645 NQSMOD=1 |
|||
MNB10 A10 B10 0 0 Nmod L=2.55886308364338e-07 W=4.0850956346516e-05 |
|||
+AD=3.125e-11 AS=3.125e-11 PD=8.17019126930321e-05 PS= |
|||
+8.17019126930321e-05 NQSMOD=1 |
|||
MPB10 A10 B10 VDD VDD Pmod L=2.44778614470725e-07 W= |
|||
+0.000105511594248206 AD=7.8125e-11 AS=7.8125e-11 PD= |
|||
+0.000211023188496411 PS=0.000211023188496411 NQSMOD=1 |
|||
LA11 A11 LCA11 3.69030941553353e-11 |
|||
RA11 LCA11 A12 0.266535044422507 |
|||
LB11 B11 LCB11 3.69030941553353e-11 |
|||
RB11 LCB11 B12 0.266535044422507 |
|||
C11 A12 B12 2.50418376625721e-14 |
|||
MNA11 B11 A11 0 0 Nmod L=2.4768739676619e-07 W=4.14724461551725e-05 |
|||
+AD=3.125e-11 AS=3.125e-11 PD=8.29448923103449e-05 PS= |
|||
+8.29448923103449e-05 NQSMOD=1 |
|||
MPA11 B11 A11 VDD VDD Pmod L=2.46276216123912e-07 W= |
|||
+0.000101782633723501 AD=7.8125e-11 AS=7.8125e-11 PD= |
|||
+0.000203565267447002 PS=0.000203565267447002 NQSMOD=1 |
|||
MNB11 A11 B11 0 0 Nmod L=2.54985612770668e-07 W=4.24608643314108e-05 |
|||
+AD=3.125e-11 AS=3.125e-11 PD=8.49217286628216e-05 PS= |
|||
+8.49217286628216e-05 NQSMOD=1 |
|||
MPB11 A11 B11 VDD VDD Pmod L=2.45772463970764e-07 W= |
|||
+0.000106109588792745 AD=7.8125e-11 AS=7.8125e-11 PD= |
|||
+0.00021221917758549 PS=0.00021221917758549 NQSMOD=1 |
|||
LA12 A12 LCA12 3.69030941553353e-11 |
|||
RA12 LCA12 A13 0.266535044422507 |
|||
LB12 B12 LCB12 3.69030941553353e-11 |
|||
RB12 LCB12 B13 0.266535044422507 |
|||
C12 A13 B13 2.50418376625721e-14 |
|||
MNA12 B12 A12 0 0 Nmod L=2.45480481009462e-07 W=4.20858793029857e-05 |
|||
+AD=3.125e-11 AS=3.125e-11 PD=8.41717586059714e-05 PS= |
|||
+8.41717586059714e-05 NQSMOD=1 |
|||
MPA12 B12 A12 VDD VDD Pmod L=2.48462320158069e-07 W= |
|||
+0.00010650127744954 AD=7.8125e-11 AS=7.8125e-11 PD= |
|||
+0.00021300255489908 PS=0.00021300255489908 NQSMOD=1 |
|||
MNB12 A12 B12 0 0 Nmod L=2.51992945030792e-07 W=4.17981435096244e-05 |
|||
+AD=3.125e-11 AS=3.125e-11 PD=8.35962870192489e-05 PS= |
|||
+8.35962870192489e-05 NQSMOD=1 |
|||
MPB12 A12 B12 VDD VDD Pmod L=2.49941922576661e-07 W= |
|||
+0.0001044851795426 AD=7.8125e-11 AS=7.8125e-11 PD= |
|||
+0.000208970359085199 PS=0.000208970359085199 NQSMOD=1 |
|||
LA13 A13 LCA13 3.69030941553353e-11 |
|||
RA13 LCA13 A14 0.266535044422507 |
|||
LB13 B13 LCB13 3.69030941553353e-11 |
|||
RB13 LCB13 B14 0.266535044422507 |
|||
C13 A14 B14 2.50418376625721e-14 |
|||
MNA13 B13 A13 0 0 Nmod L=2.51146190542173e-07 W=4.23276196447018e-05 |
|||
+AD=3.125e-11 AS=3.125e-11 PD=8.46552392894035e-05 PS= |
|||
+8.46552392894035e-05 NQSMOD=1 |
|||
MPA13 B13 A13 VDD VDD Pmod L=2.46359362747576e-07 W= |
|||
+0.00010249565409785 AD=7.8125e-11 AS=7.8125e-11 PD= |
|||
+0.0002049913081957 PS=0.0002049913081957 NQSMOD=1 |
|||
MNB13 A13 B13 0 0 Nmod L=2.44656485453628e-07 W=4.11044634633624e-05 |
|||
+AD=3.125e-11 AS=3.125e-11 PD=8.22089269267248e-05 PS= |
|||
+8.22089269267248e-05 NQSMOD=1 |
|||
MPB13 A13 B13 VDD VDD Pmod L=2.56119611942636e-07 W= |
|||
+0.0001064085618438 AD=7.8125e-11 AS=7.8125e-11 PD=0.0002128171236876 |
|||
+PS=0.0002128171236876 NQSMOD=1 |
|||
LA14 A14 LCA14 3.69030941553353e-11 |
|||
RA14 LCA14 A15 0.266535044422507 |
|||
LB14 B14 LCB14 3.69030941553353e-11 |
|||
RB14 LCB14 B15 0.266535044422507 |
|||
C14 A15 B15 2.50418376625721e-14 |
|||
MNA14 B14 A14 0 0 Nmod L=2.47663439668801e-07 W=4.20889991075918e-05 |
|||
+AD=3.125e-11 AS=3.125e-11 PD=8.41779982151835e-05 PS= |
|||
+8.41779982151835e-05 NQSMOD=1 |
|||
MPA14 B14 A14 VDD VDD Pmod L=2.51252450429323e-07 W= |
|||
+0.000103622229824819 AD=7.8125e-11 AS=7.8125e-11 PD= |
|||
+0.000207244459649638 PS=0.000207244459649638 NQSMOD=1 |
|||
MNB14 A14 B14 0 0 Nmod L=2.5044796612668e-07 W=4.24685059762319e-05 |
|||
+AD=3.125e-11 AS=3.125e-11 PD=8.49370119524638e-05 PS= |
|||
+8.49370119524638e-05 NQSMOD=1 |
|||
MPB14 A14 B14 VDD VDD Pmod L=2.4786360459861e-07 W= |
|||
+0.000104258615459431 AD=7.8125e-11 AS=7.8125e-11 PD= |
|||
+0.000208517230918863 PS=0.000208517230918863 NQSMOD=1 |
|||
LA15 A15 LCA15 3.69030941553353e-11 |
|||
RA15 LCA15 A16 0.266535044422507 |
|||
LB15 B15 LCB15 3.69030941553353e-11 |
|||
RB15 LCB15 B16 0.266535044422507 |
|||
C15 A16 B16 2.50418376625721e-14 |
|||
MNA15 B15 A15 0 0 Nmod L=2.5213362488047e-07 W=4.26610931467994e-05 |
|||
+AD=3.125e-11 AS=3.125e-11 PD=8.53221862935989e-05 PS= |
|||
+8.53221862935989e-05 NQSMOD=1 |
|||
MPA15 B15 A15 VDD VDD Pmod L=2.44411053097269e-07 W= |
|||
+0.000104344399065411 AD=7.8125e-11 AS=7.8125e-11 PD= |
|||
+0.000208688798130821 PS=0.000208688798130821 NQSMOD=1 |
|||
MNB15 A15 B15 0 0 Nmod L=2.44947739168727e-07 W=4.18061319080677e-05 |
|||
+AD=3.125e-11 AS=3.125e-11 PD=8.36122638161354e-05 PS= |
|||
+8.36122638161354e-05 NQSMOD=1 |
|||
MPB15 A15 B15 VDD VDD Pmod L=2.45133067349567e-07 W= |
|||
+0.000103673770597555 AD=7.8125e-11 AS=7.8125e-11 PD= |
|||
+0.00020734754119511 PS=0.00020734754119511 NQSMOD=1 |
|||
LA16 A16 LCA16 3.69030941553353e-11 |
|||
RA16 LCA16 A17 0.266535044422507 |
|||
LB16 B16 LCB16 3.69030941553353e-11 |
|||
RB16 LCB16 B17 0.266535044422507 |
|||
C16 A17 B17 2.50418376625721e-14 |
|||
MNA16 B16 A16 0 0 Nmod L=2.5558903414348e-07 W=4.23651981762607e-05 |
|||
+AD=3.125e-11 AS=3.125e-11 PD=8.47303963525215e-05 PS= |
|||
+8.47303963525215e-05 NQSMOD=1 |
|||
MPA16 B16 A16 VDD VDD Pmod L=2.46968507923118e-07 W= |
|||
+0.000101577430536373 AD=7.8125e-11 AS=7.8125e-11 PD= |
|||
+0.000203154861072746 PS=0.000203154861072746 NQSMOD=1 |
|||
MNB16 A16 B16 0 0 Nmod L=2.52441475326891e-07 W=4.0963445615255e-05 |
|||
+AD=3.125e-11 AS=3.125e-11 PD=8.192689123051e-05 PS= |
|||
+8.192689123051e-05 NQSMOD=1 |
|||
MPB16 A16 B16 VDD VDD Pmod L=2.49958772476576e-07 W= |
|||
+0.000102341104143712 AD=7.8125e-11 AS=7.8125e-11 PD= |
|||
+0.000204682208287424 PS=0.000204682208287424 NQSMOD=1 |
|||
LA17 A17 LCA17 3.69030941553353e-11 |
|||
RA17 LCA17 A18 0.266535044422507 |
|||
LB17 B17 LCB17 3.69030941553353e-11 |
|||
RB17 LCB17 B18 0.266535044422507 |
|||
C17 A18 B18 2.50418376625721e-14 |
|||
MNA17 B17 A17 0 0 Nmod L=2.46623947628415e-07 W=4.07033737509309e-05 |
|||
+AD=3.125e-11 AS=3.125e-11 PD=8.14067475018618e-05 PS= |
|||
+8.14067475018618e-05 NQSMOD=1 |
|||
MPA17 B17 A17 VDD VDD Pmod L=2.52274212428759e-07 W= |
|||
+0.000105423152156798 AD=7.8125e-11 AS=7.8125e-11 PD= |
|||
+0.000210846304313596 PS=0.000210846304313596 NQSMOD=1 |
|||
MNB17 A17 B17 0 0 Nmod L=2.51233452024547e-07 W=4.12815452669714e-05 |
|||
+AD=3.125e-11 AS=3.125e-11 PD=8.25630905339429e-05 PS= |
|||
+8.25630905339429e-05 NQSMOD=1 |
|||
MPB17 A17 B17 VDD VDD Pmod L=2.49324495416238e-07 W= |
|||
+0.000104142717459091 AD=7.8125e-11 AS=7.8125e-11 PD= |
|||
+0.000208285434918183 PS=0.000208285434918183 NQSMOD=1 |
|||
LA18 A18 LCA18 3.69030941553353e-11 |
|||
RA18 LCA18 A19 0.266535044422507 |
|||
LB18 B18 LCB18 3.69030941553353e-11 |
|||
RB18 LCB18 B19 0.266535044422507 |
|||
C18 A19 B19 2.50418376625721e-14 |
|||
MNA18 B18 A18 0 0 Nmod L=2.52038203439398e-07 W=4.17044670825126e-05 |
|||
+AD=3.125e-11 AS=3.125e-11 PD=8.34089341650252e-05 PS= |
|||
+8.34089341650252e-05 NQSMOD=1 |
|||
MPA18 B18 A18 VDD VDD Pmod L=2.46465042965348e-07 W= |
|||
+0.000102305682920291 AD=7.8125e-11 AS=7.8125e-11 PD= |
|||
+0.000204611365840582 PS=0.000204611365840582 NQSMOD=1 |
|||
MNB18 A18 B18 0 0 Nmod L=2.45695550122768e-07 W=4.2510656912981e-05 |
|||
+AD=3.125e-11 AS=3.125e-11 PD=8.50213138259621e-05 PS= |
|||
+8.50213138259621e-05 NQSMOD=1 |
|||
MPB18 A18 B18 VDD VDD Pmod L=2.56212134001568e-07 W= |
|||
+0.000101696358889307 AD=7.8125e-11 AS=7.8125e-11 PD= |
|||
+0.000203392717778614 PS=0.000203392717778614 NQSMOD=1 |
|||
LA19 A19 LCA19 3.69030941553353e-11 |
|||
RA19 LCA19 A20 0.266535044422507 |
|||
LB19 B19 LCB19 3.69030941553353e-11 |
|||
RB19 LCB19 B20 0.266535044422507 |
|||
C19 A20 B20 2.50418376625721e-14 |
|||
MNA19 B19 A19 0 0 Nmod L=2.46298724559332e-07 W=4.26183323927543e-05 |
|||
+AD=3.125e-11 AS=3.125e-11 PD=8.52366647855085e-05 PS= |
|||
+8.52366647855085e-05 NQSMOD=1 |
|||
MPA19 B19 A19 VDD VDD Pmod L=2.53903413760174e-07 W= |
|||
+0.000103580270078538 AD=7.8125e-11 AS=7.8125e-11 PD= |
|||
+0.000207160540157077 PS=0.000207160540157077 NQSMOD=1 |
|||
MNB19 A19 B19 0 0 Nmod L=2.4541336381424e-07 W=4.1471197163819e-05 AD= |
|||
+3.125e-11 AS=3.125e-11 PD=8.2942394327638e-05 PS=8.2942394327638e-05 |
|||
+NQSMOD=1 |
|||
MPB19 A19 B19 VDD VDD Pmod L=2.51953325753565e-07 W= |
|||
+0.0001019745929959 AD=7.8125e-11 AS=7.8125e-11 PD=0.0002039491859918 |
|||
+PS=0.0002039491859918 NQSMOD=1 |
|||
LA20 A20 LCA20 3.69030941553353e-11 |
|||
RA20 LCA20 A21 0.266535044422507 |
|||
LB20 B20 LCB20 3.69030941553353e-11 |
|||
RB20 LCB20 B21 0.266535044422507 |
|||
C20 A21 B21 2.50418376625721e-14 |
|||
MNA20 B20 A20 0 0 Nmod L=2.55318350883171e-07 W=4.2257523363596e-05 |
|||
+AD=3.125e-11 AS=3.125e-11 PD=8.4515046727192e-05 PS= |
|||
+8.4515046727192e-05 NQSMOD=1 |
|||
MPA20 B20 A20 VDD VDD Pmod L=2.50733395598687e-07 W= |
|||
+0.000105848300738233 AD=7.8125e-11 AS=7.8125e-11 PD= |
|||
+0.000211696601476467 PS=0.000211696601476467 NQSMOD=1 |
|||
MNB20 A20 B20 0 0 Nmod L=2.53961238224852e-07 W=4.07467605160825e-05 |
|||
+AD=3.125e-11 AS=3.125e-11 PD=8.1493521032165e-05 PS= |
|||
+8.1493521032165e-05 NQSMOD=1 |
|||
MPB20 A20 B20 VDD VDD Pmod L=2.52173406118976e-07 W= |
|||
+0.000104205251139887 AD=7.8125e-11 AS=7.8125e-11 PD= |
|||
+0.000208410502279773 PS=0.000208410502279773 NQSMOD=1 |
|||
LA21 A21 LCA21 3.69030941553353e-11 |
|||
RA21 LCA21 A22 0.266535044422507 |
|||
LB21 B21 LCB21 3.69030941553353e-11 |
|||
RB21 LCB21 B22 0.266535044422507 |
|||
C21 A22 B22 2.50418376625721e-14 |
|||
MNA21 B21 A21 0 0 Nmod L=2.46323292867561e-07 W=4.1601573531982e-05 |
|||
+AD=3.125e-11 AS=3.125e-11 PD=8.32031470639639e-05 PS= |
|||
+8.32031470639639e-05 NQSMOD=1 |
|||
MPA21 B21 A21 VDD VDD Pmod L=2.54613442115316e-07 W= |
|||
+0.000104931161465525 AD=7.8125e-11 AS=7.8125e-11 PD= |
|||
+0.00020986232293105 PS=0.00020986232293105 NQSMOD=1 |
|||
MNB21 A21 B21 0 0 Nmod L=2.55836584454404e-07 W=4.10424160274173e-05 |
|||
+AD=3.125e-11 AS=3.125e-11 PD=8.20848320548346e-05 PS= |
|||
+8.20848320548346e-05 NQSMOD=1 |
|||
MPB21 A21 B21 VDD VDD Pmod L=2.54709741956022e-07 W= |
|||
+0.000102062091080516 AD=7.8125e-11 AS=7.8125e-11 PD= |
|||
+0.000204124182161031 PS=0.000204124182161031 NQSMOD=1 |
|||
LA22 A22 LCA22 3.69030941553353e-11 |
|||
RA22 LCA22 A23 0.266535044422507 |
|||
LB22 B22 LCB22 3.69030941553353e-11 |
|||
RB22 LCB22 B23 0.266535044422507 |
|||
C22 A23 B23 2.50418376625721e-14 |
|||
MNA22 B22 A22 0 0 Nmod L=2.54430620981417e-07 W=4.19307535657001e-05 |
|||
+AD=3.125e-11 AS=3.125e-11 PD=8.38615071314001e-05 PS= |
|||
+8.38615071314001e-05 NQSMOD=1 |
|||
MPA22 B22 A22 VDD VDD Pmod L=2.46694525572975e-07 W= |
|||
+0.000103108817734331 AD=7.8125e-11 AS=7.8125e-11 PD= |
|||
+0.000206217635468663 PS=0.000206217635468663 NQSMOD=1 |
|||
MNB22 A22 B22 0 0 Nmod L=2.4991048194413e-07 W=4.12343575509987e-05 |
|||
+AD=3.125e-11 AS=3.125e-11 PD=8.24687151019974e-05 PS= |
|||
+8.24687151019974e-05 NQSMOD=1 |
|||
MPB22 A22 B22 VDD VDD Pmod L=2.53435790976082e-07 W= |
|||
+0.000105540213369592 AD=7.8125e-11 AS=7.8125e-11 PD= |
|||
+0.000211080426739185 PS=0.000211080426739185 NQSMOD=1 |
|||
LA23 A23 LCA23 3.69030941553353e-11 |
|||
RA23 LCA23 A24 0.266535044422507 |
|||
LB23 B23 LCB23 3.69030941553353e-11 |
|||
RB23 LCB23 B24 0.266535044422507 |
|||
C23 A24 B24 2.50418376625721e-14 |
|||
MNA23 B23 A23 0 0 Nmod L=2.47985427798248e-07 W=4.14939059451511e-05 |
|||
+AD=3.125e-11 AS=3.125e-11 PD=8.29878118903023e-05 PS= |
|||
+8.29878118903023e-05 NQSMOD=1 |
|||
MPA23 B23 A23 VDD VDD Pmod L=2.50625862917368e-07 W= |
|||
+0.000104857443713713 AD=7.8125e-11 AS=7.8125e-11 PD= |
|||
+0.000209714887427425 PS=0.000209714887427425 NQSMOD=1 |
|||
MNB23 A23 B23 0 0 Nmod L=2.48906363214973e-07 W=4.09072154111792e-05 |
|||
+AD=3.125e-11 AS=3.125e-11 PD=8.18144308223583e-05 PS= |
|||
+8.18144308223583e-05 NQSMOD=1 |
|||
MPB23 A23 B23 VDD VDD Pmod L=2.544246792556e-07 W= |
|||
+0.000106667496188909 AD=7.8125e-11 AS=7.8125e-11 PD= |
|||
+0.000213334992377817 PS=0.000213334992377817 NQSMOD=1 |
|||
RCROSS1 A0 B24 0.001 |
|||
RCROSS2 B0 A24 0.001 |
|||
|
|||
.SAVE VDD0 |
|||
.SAVE VSS0 |
|||
.SAVE VDD_A0 |
|||
.SAVE VSS_A0 |
|||
.SAVE VDD_B0 |
|||
.SAVE VSS_B0 |
|||
.SAVE A0 B0 LA0#branch LB0#branch A1 B1 LA1#branch LB1#branch A2 B2 |
|||
+LA2#branch LB2#branch A3 B3 LA3#branch LB3#branch A4 B4 LA4#branch |
|||
+LB4#branch A5 B5 LA5#branch LB5#branch A6 B6 LA6#branch LB6#branch |
|||
+A7 B7 LA7#branch LB7#branch A8 B8 LA8#branch LB8#branch A9 B9 |
|||
+LA9#branch LB9#branch A10 B10 LA10#branch LB10#branch A11 B11 |
|||
+LA11#branch LB11#branch A12 B12 LA12#branch LB12#branch A13 B13 |
|||
+LA13#branch LB13#branch A14 B14 LA14#branch LB14#branch A15 B15 |
|||
+LA15#branch LB15#branch A16 B16 LA16#branch LB16#branch A17 B17 |
|||
+LA17#branch LB17#branch A18 B18 LA18#branch LB18#branch A19 B19 |
|||
+LA19#branch LB19#branch A20 B20 LA20#branch LB20#branch A21 B21 |
|||
+LA21#branch LB21#branch A22 B22 LA22#branch LB22#branch A23 B23 |
|||
+LA23#branch LB23#branch |
|||
|
|||
|
|||
** |
|||
**INCLUDING FILE: ./proj1/process.models.... |
|||
* |
|||
* Typical N Typical P - from process corners (taken from tsmc025_corners.bsim3 fron NCSU) |
|||
* |
|||
* TSMC 0.25u 5M 1P process. 2.5V transistor models |
|||
|
|||
|
|||
.MODEL Nmod NMOS LEVEL=8 |
|||
+TNOM = 25 |
|||
+VERSION = 3.2.2 TOX = 5.8e-9 |
|||
+XJ = 1E-07 NCH = 2.354946E+17 LLN = 1 |
|||
+LWN = 1 WLN = 1 WWN = 1 |
|||
+LINT = 1.76E-08 WINT = 6.75E-09 MOBMOD = 1 |
|||
+BINUNIT = 2 DWG = 0 DWB = 0 |
|||
+VTH0 = 0.4321336 LVTH0 = 2.081814E-08 WVTH0 = -5.470342E-11 |
|||
+PVTH0 = -6.721795E-16 K1 = 0.3281252 LK1 = 9.238362E-08 |
|||
+WK1 = 2.878255E-08 PK1 = -2.426481E-14 K2 = 0.0402824 |
|||
+LK2 = -3.208392E-08 WK2 = -1.154091E-08 PK2 = 9.192045E-15 |
|||
+K3 = 0 DVT0 = 0 DVT1 = 0 |
|||
+DVT2 = 0 DVT0W = 0 DVT1W = 0 |
|||
+DVT2W = 0 NLX = 0 W0 = 0 |
|||
+K3B = 0 VSAT = 7.586954E+04 LVSAT = 3.094656E-03 |
|||
+WVSAT = -1.747416E-03 PVSAT = 8.820956E-10 UA = 8.924498E-10 |
|||
+LUA = -1.511745E-16 WUA = -3.509821E-17 PUA = -3.08778E-23 |
|||
+UB = 8.928832E-21 LUB = -1.655745E-27 WUB = -2.03282E-27 |
|||
+PUB = 3.4578E-34 UC = -1.364265E-11 LUC = 1.170473E-17 |
|||
+WUC = -1.256705E-18 PUC = -6.249644E-24 RDSW = 447.8871 |
|||
+PRWB = 0 PRWG = 0 WR = 0.99 |
|||
+U0 = 0.06005258 LU0 = -6.31976E-09 WU0 = -8.819531E-09 |
|||
+PU0 = 3.57209E-15 A0 = -1.468837 LA0 = 6.419548E-07 |
|||
+WA0 = 5.512414E-07 PA0 = -9.222928E-14 KETA = -0.04922795 |
|||
+LKETA = 2.360844E-08 WKETA = 1.560385E-08 PKETA = -5.98377E-15 |
|||
+A1 = 0.02659908 LA1 = -6.511454E-09 A2 = 1 |
|||
+AGS = -4.01637 LAGS = 1.090294E-06 WAGS = 1.162021E-06 |
|||
+PAGS = -3.108579E-13 B0 = 0 B1 = 0 |
|||
+VOFF = -0.1829426 LVOFF = 9.941631E-09 WVOFF = 1.568082E-08 |
|||
+PVOFF = -2.832958E-15 NFACTOR = 0.6790636 LNFACTOR= 3.454948E-08 |
|||
+WNFACTOR= 1.501016E-07 PNFACTOR= -2.955591E-14 CIT = 2.218499E-04 |
|||
+LCIT = -1.076934E-10 WCIT = -3.286884E-10 PCIT = 1.658928E-16 |
|||
+CDSC = 0 CDSCB = 0 CDSCD = 0 |
|||
+ETA0 = 1.215578E-04 LETA0 = -1.037758E-11 WETA0 = -3.030225E-11 |
|||
+PETA0 = 1.529658E-17 ETAB = 3.548681E-03 LETAB = -1.791374E-09 |
|||
+WETAB = -6.897268E-10 PETAB = 3.481742E-16 DSUB = 0 |
|||
+PCLM = 3.583838 PDIBLC1 = 0 PDIBLC2 = 5.379674E-03 |
|||
+LPDIBLC2= 7.808481E-09 WPDIBLC2= 5.516945E-10 PPDIBLC2= -2.784957E-16 |
|||
+PDIBLCB = -0.1229374 LPDIBLCB= 4.956215E-08 WPDIBLCB= 3.299946E-08 |
|||
+PPDIBLCB= -9.624918E-15 DROUT = 0 PSCBE1 = 4.472639E+08 |
|||
+LPSCBE1 = 28.64041 WPSCBE1 = 15.7154 PPSCBE1 = -7.933138E-06 |
|||
+PSCBE2 = 1.842585E-06 LPSCBE2 = 2.871008E-12 WPSCBE2 = 2.579183E-12 |
|||
+PPSCBE2 = -1.301972E-18 PVAG = -2.015254E-03 LPVAG = 1.017757E-09 |
|||
+WPVAG = 3.07622E-10 PPVAG = -1.55418E-16 DELTA = -0.02862256 |
|||
+LDELTA = 1.492454E-08 WDELTA = -6.71663E-09 PDELTA = 3.407521E-15 |
|||
+ALPHA0 = 0 BETA0 = 30 KT1 = -0.2579945 |
|||
+LKT1 = -1.664895E-08 WKT1 = -1.633463E-08 PKT1 = 3.755864E-15 |
|||
+KT2 = -0.05347481 LKT2 = 8.244731E-09 WKT2 = 1.13705E-09 |
|||
+PKT2 = -1.240924E-15 AT = -1.132632E+04 LAT = 6.469047E-03 |
|||
+WAT = 6.829220E-04 PAT = -4.154249E-10 UTE = -2.309089 |
|||
+LUTE = 1.662427E-07 WUTE = 1.244801E-07 PUTE = -5.627924E-14 |
|||
+UA1 = -3.461758E-10 LUA1 = 1.747495E-16 WUA1 = -1.42065E-16 |
|||
+PUA1 = 7.171442E-23 UB1 = 0 UC1 = -2.38157E-12 |
|||
+LUC1 = -2.895726E-18 WUC1 = -1.990052E-17 PUC1 = 1.004497E-23 |
|||
+KT1L = 0 PRT = -1E-18 CJ = 2.024128E-3 |
|||
+MJ = 0.4960069 PB = 0.9173808 CJSW = 2.751528E-10 |
|||
+MJSW = 0.443145 PBSW = 0.9173808 CJSWG = 2.135064E-10 |
|||
+MJSWG = 0.443145 PBSWG = 0.9173808 |
|||
+RSH = 4.5 |
|||
+XTI = 3 |
|||
+CGDO = 3.11E-10 CGSO = 3.11E-10 CAPMOD = 2 |
|||
+XPART = 1 CF = 0 |
|||
+JS = 1E-06 |
|||
+JSW = 5E-11 |
|||
|
|||
|
|||
|
|||
.MODEL Pmod PMOS LEVEL=8 |
|||
+VERSION = 3.2.2 |
|||
+TNOM = 25 TOX = 5.8e-9 |
|||
+XJ = 1E-7 NCH = 4.1589E17 |
|||
+LLN = 1 LWN = 1 WLN = 1 |
|||
+WWN = 1 LINT = 1.2365E-8 WINT = 7.8E-9 |
|||
+MOBMOD = 1 BINUNIT = 2 DWG = 0 |
|||
+DWB = 0 VTH0 = -0.6236538 LVTH0 = 2.649834E-8 |
|||
+WVTH0 = 3.214189E-8 PVTH0 = -3.22268E-15 K1 = 0.4198155 |
|||
+LK1 = 5.770498E-8 WK1 = 5.577151E-8 PK1 = -2.81684E-14 |
|||
+K2 = 0.0429467 LK2 = -2.296405E-8 WK2 = -1.355302E-8 |
|||
+PK2 = 6.848271E-15 K3 = 0 DVT0 = 0 |
|||
+DVT1 = 0 DVT2 = 0 DVT0W = 0 |
|||
+DVT1W = 0 DVT2W = 0 NLX = 0 |
|||
+W0 = 0 K3B = 0 VSAT = 1.443912E5 |
|||
+LVSAT = -7.688012E-4 WVSAT = -6.083648E-3 PVSAT = 2.186471E-10 |
|||
+UA = 1.846811E-9 LUA = -3.27694E-16 WUA = -2.82106E-16 |
|||
+PUA = 7.180233E-23 UB = -7.84535E-19 LUB = 4.772849E-25 |
|||
+WUB = 2.599205E-25 PUB = -1.46530E-31 UC = -1.75560E-10 |
|||
+LUC = 3.360832E-17 WUC = 1.504425E-17 PUC = -1.30556E-23 |
|||
+RDSW = 1.03E3 PRWB = 0 PRWG = 0 |
|||
+WR = 1 U0 = 0.0136443 LU0 = -7.22084E-10 |
|||
+WU0 = -1.088554E-9 PU0 = 2.730854E-16 A0 = 0.1071803 |
|||
+LA0 = 4.64252E-7 WA0 = 5.383179E-7 PA0 = -1.32033E-13 |
|||
+KETA = -4.943762E-3 LKETA = -3.565304E-9 WKETA = -5.226247E-9 |
|||
+PKETA = 2.640665E-15 A1 = 0 A2 = 0.4 |
|||
+AGS = 0.1664005 LAGS = 1.19106E-7 WAGS = 5.29237E-8 |
|||
+PAGS = -2.67304E-14 B0 = 0 B1 = 0 |
|||
+VOFF = -0.0592623 LVOFF = -1.96686E-8 WVOFF = -1.486398E-8 |
|||
+PVOFF = 7.510321E-15 NFACTOR = 0.8588103 LNFACTOR= -1.158881E-7 |
|||
+WNFACTOR= 1.210664E-8 PNFACTOR= -6.11712E-15 CIT = 6.439495E-5 |
|||
+LCIT = 2.916437E-10 WCIT = -3.11284E-11 PCIT = 1.572825E-17 |
|||
+CDSC = 0 CDSCB = 0 CDSCD = 0 |
|||
+ETA0 = -3.819468E-3 LETA0 = 2.155422E-9 WETA0 = 8.235612E-10 |
|||
+PETA0 = -4.16037E-16 ETAB = 1.334637E-3 LETAB = -7.93631E-10 |
|||
+WETAB = 5.284657E-11 PETAB = -2.68353E-17 DSUB = 0 |
|||
+PCLM = 0.1098002 LPCLM = 6.874263E-7 WPCLM = 6.724724E-7 |
|||
+PPCLM = -1.97766E-13 PDIBLC1 = 0 PDIBLC2 = 5.801323E-3 |
|||
+LPDIBLC2= -1.81964E-9 WPDIBLC2= -5.853396E-9 PPDIBLC2= 2.957545E-15 |
|||
+PDIBLCB = 0.1921199 DROUT = 0 PSCBE1 = 7.19E8 |
|||
+PSCBE2 = 1E-20 PVAG = 0 DELTA = 0.01 |
|||
+ALPHA0 = 0 BETA0 = 30 KT1 = -0.3248987 |
|||
+LKT1 = -1.160393E-8 WKT1 = 4.153356E-8 PKT1 = -4.62347E-15 |
|||
+KT2 = -0.0367632 AT = 1E4 UTE = -1.04 |
|||
+UA1 = 3.992421E-10 UB1 = -9.23294E-19 LUB1 = -5.28718E-26 |
|||
+WUB1 = -6.13069E-26 PUB1 = 1.503674E-32 UC1 = -1.00699E-12 |
|||
+KT1L = 0 PRT = 0 CJ = 1.931092e-3 |
|||
+MJ = 0.4812153 PB = 0.9134669 CJSW = 2.232277e-10 |
|||
+MJSW = 0.3237595 PBSW = 0.9134669 CJSWG = 1.607088e-10 |
|||
+MJSWG = 0.3237595 PBSWG = 0.9134669 |
|||
+RSH = 3.5 |
|||
+CGDO = 2.68e-10 CGSO = 2.68e-10 |
|||
+CAPMOD = 2 |
|||
+XPART = 1 |
|||
+CF = 0 XTI = 3 |
|||
+JS = 3E-7 |
|||
+JSW = 5E-12 |
|||
|
|||
**.... FINISHED INCLUDING: ./proj1/process.models |
|||
** |
|||
.OPTIONS TEMP=25 |
|||
VSLEW_CONTROL VSLEW 0 (PULSE 0 1 0 1e-09) |
|||
EVLOGIC VRAMP 0 VSLEW 0 2.5 |
|||
VDDPOWER VDD VRAMP DC 0 |
|||
VARACTOR_V VARACTOR_V 0 DC 2.5 |
|||
.SAVE vddpower#branch |
|||
.SAVE vdd |
|||
.SAVE varactor_v |
|||
.TRAN 0.02n 3000n 0n 0.5n |
|||
.END |
|||
@ -1,12 +0,0 @@ |
|||
#!/bin/sh |
|||
# WishFix \ |
|||
exec wish -f "$0" ${1+"$@"} |
|||
### |
|||
|
|||
package require spice |
|||
|
|||
spice::source example.cir |
|||
spice::step 100 |
|||
|
|||
spice::plot a0 vs b0 |
|||
spice::bltplot a0 |
|||
@ -1,50 +0,0 @@ |
|||
#!/bin/sh |
|||
# WishFix \ |
|||
exec wish -f "$0" ${1+"$@"} |
|||
### |
|||
|
|||
package require BLT |
|||
namespace import blt::* |
|||
|
|||
package require spice |
|||
|
|||
wm title . "Vector Test script" |
|||
wm geometry . 800x600+40+40 |
|||
pack propagate . false |
|||
|
|||
stripchart .chart |
|||
pack .chart -side top -fill both -expand true |
|||
.chart axis configure x -title "Time" |
|||
|
|||
|
|||
# Create a vector (and call it $vector) |
|||
#vector create v1 |
|||
spice::source example.cir |
|||
spice::bg run |
|||
|
|||
after 1000 |
|||
|
|||
vector create a0 |
|||
vector create b0 |
|||
vector create a1 |
|||
vector create b1 |
|||
vector create stime |
|||
proc bltupdate {} { |
|||
spice::spicetoblt a0 a0 |
|||
spice::spicetoblt b0 b0 |
|||
spice::spicetoblt a1 a1 |
|||
spice::spicetoblt b1 b1 |
|||
spice::spicetoblt time stime |
|||
#puts $spice::lastitercount |
|||
after 100 bltupdate |
|||
} |
|||
bltupdate |
|||
|
|||
|
|||
|
|||
.chart element create a0 -color red -xdata stime -ydata a0 |
|||
.chart element create b0 -color blue -xdata stime -ydata b0 |
|||
.chart element create a1 -color yellow -xdata stime -ydata a1 |
|||
.chart element create b1 -color black -xdata stime -ydata b1 |
|||
|
|||
|
|||
1323
src/tclspice.c
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -1,16 +0,0 @@ |
|||
# Process this file with automake
|
|||
CFLAGS = -g -O2 -Wall |
|||
CC = gcc |
|||
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) |
|||
|
|||
EXTRA_DIST = README |
|||
|
|||
SUBDIRS = mif cm enh evt ipc idn |
|||
|
|||
INCLUDES = -I$(top_srcdir)/src/include -I$(top_srcdir) |
|||
|
|||
MAINTAINERCLEANFILES = Makefile.in |
|||
|
|||
all: xspice.o |
|||
xspice.o: |
|||
$(COMPILE) -c xspice.c |
|||
@ -1,24 +0,0 @@ |
|||
Spice Opus / XSpice code model support. |
|||
-------------------------------------- |
|||
|
|||
Use configure flag --enable-xspice to compile the support in, |
|||
when you run the ./configure script. |
|||
This creates a new command, "codemodel", which you can |
|||
use to load a codemodel. |
|||
|
|||
Some codemodels are included in the xspice/lib directory |
|||
with some examples in xspice/examples, compiled for linux glibc. |
|||
|
|||
Make sure the the library dir, xspice/lib, is in your LD_LIBRARY_PATH |
|||
enviromental variable, otherwise the libs will not be found! |
|||
|
|||
To create codemodels go to http://www.fe.uni-lj.si/spice/welcome.html |
|||
and download their trial version of spice opus for the codemodel toolkit! |
|||
|
|||
TODO: |
|||
Intergrate the ipc stuff from XSpice. |
|||
Create ng-spice capacity to create codemodels (a perl script) |
|||
Ngspice crashes when you try to plot a digital node |
|||
|
|||
Stefan Jones |
|||
19/2/2002 |
|||
@ -1,17 +0,0 @@ |
|||
## Process this file with automake to produce Makefile.in
|
|||
#
|
|||
# JW 3/9/01 - had a go and makeing an autoconf script.
|
|||
|
|||
noinst_LIBRARIES = libcmxsp.a |
|||
|
|||
libcmxsp_a_SOURCES = \
|
|||
cm.c \ |
|||
cmevt.c \ |
|||
cmmeters.c \ |
|||
cmutil.c |
|||
|
|||
|
|||
|
|||
INCLUDES = -I$(top_srcdir)/src/include -I$(top_srcdir)/src/spicelib/devices |
|||
|
|||
MAINTAINERCLEANFILES = Makefile.in |
|||
@ -1,701 +0,0 @@ |
|||
/* =========================================================================== |
|||
FILE CM.c |
|||
|
|||
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 |
|||
|
|||
<date> <person name> <nature of modifications> |
|||
|
|||
SUMMARY |
|||
|
|||
This file contains functions callable from user code models. |
|||
|
|||
INTERFACES |
|||
|
|||
cm_analog_alloc() |
|||
cm_analog_get_ptr() |
|||
cm_analog_integrate() |
|||
cm_analog_converge() |
|||
cm_analog_set_temp_bkpt() |
|||
cm_analog_set_perm_bkpt() |
|||
cm_analog_ramp_factor() |
|||
cm_analog_not_converged() |
|||
cm_analog_auto_partial() |
|||
|
|||
cm_message_get_errmsg() |
|||
cm_message_send() |
|||
|
|||
REFERENCED FILES |
|||
|
|||
None. |
|||
|
|||
NON-STANDARD FEATURES |
|||
|
|||
None. |
|||
|
|||
=========================================================================== */ |
|||
#include "ngspice.h" |
|||
#include "cm.h" |
|||
#include "mif.h" |
|||
#include "cktdefs.h" |
|||
//#include "util.h" |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
static void cm_static_integrate(int byte_index, |
|||
double integrand, |
|||
double *integral, |
|||
double *partial); |
|||
|
|||
/* |
|||
|
|||
cm_analog_alloc() |
|||
|
|||
This function is called from code model C functions to allocate |
|||
state storage for a particular instance. It computes the number |
|||
of doubles that need to be allocated in SPICE's state storage |
|||
vectors from the number of bytes specified in it's argument and |
|||
then allocates space for the states. An index into the SPICE |
|||
state-vectors is stored in the instance's data structure along |
|||
with a ``tag'' variable supplied by the caller so that the location |
|||
of the state storage area can be found by cm_analog_get_ptr(). |
|||
|
|||
*/ |
|||
|
|||
void *cm_analog_alloc( |
|||
int tag, /* The user-specified tag for this block of memory */ |
|||
int bytes) /* The number of bytes to allocate */ |
|||
{ |
|||
MIFinstance *here; |
|||
CKTcircuit *ckt; |
|||
|
|||
Mif_State_t *state; |
|||
|
|||
int doubles_needed; |
|||
int i; |
|||
|
|||
|
|||
/* Get the address of the ckt and instance structs from g_mif_info */ |
|||
here = g_mif_info.instance; |
|||
ckt = g_mif_info.ckt; |
|||
|
|||
/* Scan states in instance struct and see if tag has already been used */ |
|||
for(i = 0; i < here->num_state; i++) { |
|||
if(tag == here->state[i].tag) { |
|||
g_mif_info.errmsg = "ERROR - cm_analog_alloc() - Tag already used in previous call\n"; |
|||
return(NULL); |
|||
} |
|||
} |
|||
|
|||
/* Compute number of doubles needed and allocate space in ckt->CKTstates[i] */ |
|||
doubles_needed = bytes / sizeof(double) + 1; |
|||
|
|||
/* Allocate space in instance struct for this state descriptor */ |
|||
if(here->num_state == 0) { |
|||
here->num_state = 1; |
|||
here->state = (void *) MALLOC(sizeof(Mif_State_t)); |
|||
} |
|||
else { |
|||
here->num_state++; |
|||
here->state = (void *) REALLOC(here->state, |
|||
here->num_state * sizeof(Mif_State_t)); |
|||
} |
|||
|
|||
/* Fill in the members of the state descriptor struct */ |
|||
state = &(here->state[here->num_state - 1]); |
|||
state->tag = tag; |
|||
state->index = ckt->CKTnumStates; |
|||
state->doubles = doubles_needed; |
|||
state->bytes = bytes; |
|||
|
|||
|
|||
/* Add the states to the ckt->CKTstates vectors */ |
|||
ckt->CKTnumStates += doubles_needed; |
|||
for(i=0;i<=ckt->CKTmaxOrder+1;i++) { |
|||
if(ckt->CKTnumStates == doubles_needed) |
|||
ckt->CKTstates[i] = (double *) MALLOC(ckt->CKTnumStates * sizeof(double)); |
|||
else |
|||
ckt->CKTstates[i] = (double *) REALLOC(ckt->CKTstates[i], |
|||
ckt->CKTnumStates * sizeof(double)); |
|||
} |
|||
|
|||
/* Return pointer to the allocated space in state 0 */ |
|||
return( (void *) (ckt->CKTstates[0] + (ckt->CKTnumStates - doubles_needed))); |
|||
|
|||
} |
|||
|
|||
|
|||
/* |
|||
cm_analog_get_ptr() |
|||
|
|||
This function is called from code model C functions to return a |
|||
pointer to state storage allocated with cm_analog_alloc(). A tag |
|||
specified in its argument list is used to locate the state in |
|||
question. A second argument specifies whether the desired state |
|||
is for the current timestep or from a preceding timestep. The |
|||
location of the state in memory is then computed and returned. |
|||
*/ |
|||
|
|||
void *cm_analog_get_ptr( |
|||
int tag, /* The user-specified tag for this block of memory */ |
|||
int timepoint) /* The timepoint of interest - 0=current 1=previous */ |
|||
{ |
|||
MIFinstance *here; |
|||
CKTcircuit *ckt; |
|||
|
|||
Mif_State_t *state=NULL; |
|||
|
|||
Mif_Boolean_t got_tag; |
|||
|
|||
int i; |
|||
|
|||
|
|||
/* Get the address of the ckt and instance structs from g_mif_info */ |
|||
here = g_mif_info.instance; |
|||
ckt = g_mif_info.ckt; |
|||
|
|||
/* Scan states in instance struct and see if tag exists */ |
|||
for(got_tag = MIF_FALSE, i = 0; i < here->num_state; i++) { |
|||
if(tag == here->state[i].tag) { |
|||
state = &(here->state[i]); |
|||
got_tag = MIF_TRUE; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
/* Return error if tag not found */ |
|||
if(! got_tag) { |
|||
g_mif_info.errmsg = "ERROR - cm_analog_get_ptr() - Bad tag\n"; |
|||
return(NULL); |
|||
} |
|||
|
|||
/* Return error if timepoint is not 0 or 1 */ |
|||
if((timepoint < 0) || (timepoint > 1)) { |
|||
g_mif_info.errmsg = "ERROR - cm_analog_get_ptr() - Bad timepoint\n"; |
|||
return(NULL); |
|||
} |
|||
|
|||
/* Return address of requested state in ckt->CKTstates[timepoint] vector */ |
|||
return( (void *) (ckt->CKTstates[timepoint] + state->index) ); |
|||
|
|||
} |
|||
|
|||
|
|||
/* |
|||
cm_analog_integrate() |
|||
|
|||
This function performs a numerical integration on the state |
|||
supplied in its argument list according to the integrand also |
|||
supplied in the argument list. The next value of the integral |
|||
and the partial derivative with respect to the integrand input is |
|||
returned. The integral argument must be a pointer to memory |
|||
previously allocated through a call to cm_analog_alloc(). If this is |
|||
the first call to cm_analog_integrate(), information is entered into the |
|||
instance structure to mark that the integral should be processed |
|||
by MIFtrunc and MIFconvTest. |
|||
*/ |
|||
|
|||
int cm_analog_integrate( |
|||
double integrand, /* The integrand */ |
|||
double *integral, /* The current and returned value of integral */ |
|||
double *partial) /* The partial derivative of integral wrt integrand */ |
|||
{ |
|||
|
|||
MIFinstance *here; |
|||
CKTcircuit *ckt; |
|||
|
|||
Mif_Intgr_t *intgr; |
|||
Mif_Boolean_t got_index; |
|||
|
|||
char *char_state0; |
|||
char *char_state; |
|||
|
|||
int byte_index; |
|||
int i; |
|||
|
|||
|
|||
/* Get the address of the ckt and instance structs from g_mif_info */ |
|||
here = g_mif_info.instance; |
|||
ckt = g_mif_info.ckt; |
|||
|
|||
/* Check to be sure we're in transient analysis */ |
|||
if(g_mif_info.circuit.anal_type != MIF_TRAN) { |
|||
g_mif_info.errmsg = |
|||
"ERROR - cm_analog_integrate() - Called in non-transient analysis\n"; |
|||
*partial = 0.0; |
|||
return(MIF_ERROR); |
|||
} |
|||
|
|||
/* Preliminary check to be sure argument was allocated by cm_analog_alloc() */ |
|||
if(ckt->CKTnumStates <= 0) { |
|||
g_mif_info.errmsg = |
|||
"ERROR - cm_analog_integrate() - Integral must be memory allocated by cm_analog_alloc()\n"; |
|||
*partial = 0.0; |
|||
return(MIF_ERROR); |
|||
} |
|||
|
|||
/* Compute byte offset from start of state0 vector */ |
|||
char_state0 = (char *) ckt->CKTstate0; |
|||
char_state = (char *) integral; |
|||
byte_index = char_state - char_state0; |
|||
|
|||
/* Check to be sure argument address is in range of state0 vector */ |
|||
if((byte_index < 0) || |
|||
(byte_index > ((ckt->CKTnumStates - 1) * sizeof(double)) ) ) { |
|||
g_mif_info.errmsg = |
|||
"ERROR - cm_analog_integrate() - Argument must be in state vector 0\n"; |
|||
*partial = 0.0; |
|||
return(MIF_ERROR); |
|||
} |
|||
|
|||
/* Scan the intgr array in the instance struct to see if already exists */ |
|||
for(got_index = MIF_FALSE, i = 0; i < here->num_intgr; i++) { |
|||
if(here->intgr[i].byte_index == byte_index) { |
|||
got_index = MIF_TRUE; |
|||
} |
|||
} |
|||
|
|||
/* Report error if not found and this is not the first load pass in tran analysis */ |
|||
if((! got_index) && (! g_mif_info.circuit.anal_init)) { |
|||
g_mif_info.errmsg = |
|||
"ERROR - cm_analog_integrate() - New integral and not initialization pass\n"; |
|||
*partial = 0.0; |
|||
return(MIF_ERROR); |
|||
} |
|||
|
|||
/* If new integral state, allocate space in instance */ |
|||
/* struct for this intgr descriptor and register it with */ |
|||
/* the cm_analog_converge() function */ |
|||
if(! got_index) { |
|||
if(here->num_intgr == 0) { |
|||
here->num_intgr = 1; |
|||
here->intgr = (void *) MALLOC(sizeof(Mif_Intgr_t)); |
|||
} |
|||
else { |
|||
here->num_intgr++; |
|||
here->intgr = (void *) REALLOC(here->intgr, |
|||
here->num_intgr * sizeof(Mif_Intgr_t)); |
|||
} |
|||
intgr = &(here->intgr[here->num_intgr - 1]); |
|||
intgr->byte_index = byte_index; |
|||
if(cm_analog_converge(integral)) { |
|||
printf("%s\n",g_mif_info.errmsg); |
|||
g_mif_info.errmsg = "ERROR - cm_analog_integrate() - Failure in cm_analog_converge() call\n"; |
|||
return(MIF_ERROR); |
|||
} |
|||
} |
|||
|
|||
/* Compute the new integral and the partial */ |
|||
cm_static_integrate(byte_index, integrand, integral, partial); |
|||
|
|||
return(MIF_OK); |
|||
} |
|||
|
|||
|
|||
/* |
|||
cm_analog_converge() |
|||
|
|||
This function registers a state variable allocated with |
|||
cm_analog_alloc() to be subjected to a convergence test at the end of |
|||
each iteration. The state variable must be a double. |
|||
Information is entered into the instance structure to mark that |
|||
the state variable should be processed by MIFconvTest. |
|||
*/ |
|||
|
|||
int cm_analog_converge( |
|||
double *state) /* The state to be converged */ |
|||
{ |
|||
MIFinstance *here; |
|||
CKTcircuit *ckt; |
|||
|
|||
Mif_Conv_t *conv; |
|||
|
|||
char *char_state0; |
|||
char *char_state; |
|||
|
|||
int byte_index; |
|||
int i; |
|||
|
|||
|
|||
/* Get the address of the ckt and instance structs from g_mif_info */ |
|||
here = g_mif_info.instance; |
|||
ckt = g_mif_info.ckt; |
|||
|
|||
/* Preliminary check to be sure argument was allocated by cm_analog_alloc() */ |
|||
if(ckt->CKTnumStates <= 0) { |
|||
g_mif_info.errmsg = |
|||
"ERROR - cm_analog_converge() - Argument must be memory allocated by cm_analog_alloc()\n"; |
|||
return(MIF_ERROR); |
|||
} |
|||
|
|||
/* Compute byte offset from start of state0 vector */ |
|||
char_state0 = (char *) ckt->CKTstate0; |
|||
char_state = (char *) state; |
|||
byte_index = char_state - char_state0; |
|||
|
|||
/* Check to be sure argument address is in range of state0 vector */ |
|||
if((byte_index < 0) || |
|||
(byte_index > ((ckt->CKTnumStates - 1) * sizeof(double)) ) ) { |
|||
g_mif_info.errmsg = |
|||
"ERROR - cm_analog_converge() - Argument must be in state vector 0\n"; |
|||
return(MIF_ERROR); |
|||
} |
|||
|
|||
/* Scan the conv array in the instance struct to see if already registered */ |
|||
/* If so, do nothing, just return */ |
|||
for(i = 0; i < here->num_conv; i++) { |
|||
if(here->conv[i].byte_index == byte_index) |
|||
return(MIF_OK); |
|||
} |
|||
|
|||
/* Allocate space in instance struct for this conv descriptor */ |
|||
if(here->num_conv == 0) { |
|||
here->num_conv = 1; |
|||
here->conv = (void *) MALLOC(sizeof(Mif_Conv_t)); |
|||
} |
|||
else { |
|||
here->num_conv++; |
|||
here->conv = (void *) REALLOC(here->conv, |
|||
here->num_conv * sizeof(Mif_Conv_t)); |
|||
} |
|||
|
|||
/* Fill in the conv descriptor data */ |
|||
conv = &(here->conv[here->num_conv - 1]); |
|||
conv->byte_index = byte_index; |
|||
conv->last_value = 1.0e30; /* There should be a better way ... */ |
|||
|
|||
return(MIF_OK); |
|||
} |
|||
|
|||
|
|||
|
|||
/* |
|||
cm_message_get_errmsg() |
|||
|
|||
This function returns the address of an error message string set |
|||
by a call to some code model support function. |
|||
*/ |
|||
|
|||
char *cm_message_get_errmsg(void) |
|||
{ |
|||
return(g_mif_info.errmsg); |
|||
} |
|||
|
|||
|
|||
|
|||
|
|||
/* |
|||
cm_analog_set_temp_bkpt() |
|||
|
|||
This function is called by a code model C function to set a |
|||
temporary breakpoint. These temporary breakpoints remain in |
|||
effect only until the next timestep is taken. A temporary |
|||
breakpoint added with a time less than the current time, but |
|||
greater than the last successful timestep causes the simulator to |
|||
abandon the current timestep and decrease the timestep to hit the |
|||
breakpoint. A temporary breakpoint with a time greater than the |
|||
current time causes the simulator to make the breakpoint the next |
|||
timepoint if the next timestep would produce a time greater than |
|||
that of the breakpoint. |
|||
*/ |
|||
|
|||
|
|||
int cm_analog_set_temp_bkpt( |
|||
double time) /* The time of the breakpoint to be set */ |
|||
{ |
|||
CKTcircuit *ckt; |
|||
|
|||
|
|||
/* Get the address of the ckt and instance structs from g_mif_info */ |
|||
ckt = g_mif_info.ckt; |
|||
|
|||
/* Make sure breakpoint is not prior to last accepted timepoint */ |
|||
if(time < ((ckt->CKTtime - ckt->CKTdelta) + ckt->CKTminBreak)) { |
|||
g_mif_info.errmsg = |
|||
"ERROR - cm_analog_set_temp_bkpt() - Time < last accepted timepoint\n"; |
|||
return(MIF_ERROR); |
|||
} |
|||
|
|||
/* If too close to a permanent breakpoint or the current time, discard it */ |
|||
if( (fabs(time - ckt->CKTbreaks[0]) < ckt->CKTminBreak) || |
|||
(fabs(time - ckt->CKTbreaks[1]) < ckt->CKTminBreak) || |
|||
(fabs(time - ckt->CKTtime) < ckt->CKTminBreak) ) |
|||
return(MIF_OK); |
|||
|
|||
/* If < current dynamic breakpoint, make it the current breakpoint */ |
|||
if( time < g_mif_info.breakpoint.current) |
|||
g_mif_info.breakpoint.current = time; |
|||
|
|||
return(MIF_OK); |
|||
} |
|||
|
|||
|
|||
|
|||
|
|||
/* |
|||
cm_analog_set_perm_bkpt() |
|||
|
|||
This function is called by a code model C function to set a |
|||
permanent breakpoint. These permanent breakpoints remain in |
|||
effect from the time they are introduced until the simulation |
|||
time equals or exceeds the breakpoint time. A permanent |
|||
breakpoint added with a time less than the current time, but |
|||
greater than the last successful timestep causes the simulator to |
|||
abandon the current timestep and decrease the timestep to hit the |
|||
breakpoint. A permanent breakpoint with a time greater than the |
|||
current time causes the simulator to make the breakpoint the next |
|||
timepoint if the next timestep would produce a time greater than |
|||
that of the breakpoint. |
|||
*/ |
|||
|
|||
|
|||
int cm_analog_set_perm_bkpt( |
|||
double time) /* The time of the breakpoint to be set */ |
|||
{ |
|||
CKTcircuit *ckt; |
|||
|
|||
|
|||
/* Get the address of the ckt and instance structs from g_mif_info */ |
|||
ckt = g_mif_info.ckt; |
|||
|
|||
/* Call cm_analog_set_temp_bkpt() to force backup if less than current time */ |
|||
if(time < (ckt->CKTtime + ckt->CKTminBreak)) |
|||
return(cm_analog_set_temp_bkpt(time)); |
|||
else |
|||
CKTsetBreak(ckt,time); |
|||
|
|||
return(MIF_OK); |
|||
} |
|||
|
|||
|
|||
/* |
|||
cm_analog_ramp_factor() |
|||
|
|||
This function returns the current value of the ramp factor |
|||
associated with the ``ramptime'' option. For this option |
|||
to work best, models with analog outputs that may be non-zero at |
|||
time zero should call this function and scale their outputs |
|||
and partials by the ramp factor. |
|||
*/ |
|||
|
|||
|
|||
double cm_analog_ramp_factor(void) |
|||
{ |
|||
|
|||
CKTcircuit *ckt; |
|||
|
|||
/* Get the address of the ckt and instance structs from g_mif_info */ |
|||
ckt = g_mif_info.ckt; |
|||
|
|||
|
|||
/* if ramptime == 0.0, no ramptime option given, so return 1.0 */ |
|||
/* this is the most common case, so it goes first */ |
|||
if(ckt->enh->ramp.ramptime == 0.0) |
|||
return(1.0); |
|||
|
|||
/* else if not transient analysis, return 1.0 */ |
|||
else if( (!(ckt->CKTmode & MODETRANOP)) && (!(ckt->CKTmode & MODETRAN)) ) |
|||
return(1.0); |
|||
|
|||
/* else if time >= ramptime, return 1.0 */ |
|||
else if(ckt->CKTtime >= ckt->enh->ramp.ramptime) |
|||
return(1.0); |
|||
|
|||
/* else time < end of ramp, so compute and return factor based on time */ |
|||
else |
|||
return(ckt->CKTtime / ckt->enh->ramp.ramptime); |
|||
} |
|||
|
|||
|
|||
/* ************************************************************ */ |
|||
|
|||
|
|||
/* |
|||
* Copyright (c) 1985 Thomas L. Quarles |
|||
* |
|||
* This is a modified version of the function NIintegrate() |
|||
* |
|||
* Modifications are Copyright 1991 Georgia Tech Research Institute |
|||
* |
|||
*/ |
|||
|
|||
static void cm_static_integrate(int byte_index, |
|||
double integrand, |
|||
double *integral, |
|||
double *partial) |
|||
{ |
|||
CKTcircuit *ckt; |
|||
|
|||
double intgr[7]; |
|||
double cur=0; |
|||
double *double_ptr; |
|||
|
|||
double ceq; |
|||
double geq; |
|||
|
|||
char *char_ptr; |
|||
|
|||
int i; |
|||
|
|||
|
|||
/* Get the address of the ckt struct from g_mif_info */ |
|||
ckt = g_mif_info.ckt; |
|||
|
|||
/* Get integral values from current and previous timesteps */ |
|||
for(i = 0; i <= ckt->CKTorder; i++) { |
|||
char_ptr = (char *) ckt->CKTstates[i]; |
|||
char_ptr += byte_index; |
|||
double_ptr = (double *) char_ptr; |
|||
intgr[i] = *double_ptr; |
|||
} |
|||
|
|||
|
|||
/* Do what SPICE3C1 does for its implicit integration */ |
|||
|
|||
switch(ckt->CKTintegrateMethod) { |
|||
|
|||
case TRAPEZOIDAL: |
|||
|
|||
switch(ckt->CKTorder) { |
|||
|
|||
case 1: |
|||
cur = ckt->CKTag[1] * intgr[1]; |
|||
break; |
|||
|
|||
case 2: |
|||
/* WARNING - This code needs to be redone. */ |
|||
/* The correct code should rely on one previous value */ |
|||
/* of cur as done in NIintegrate() */ |
|||
cur = -0.5 * ckt->CKTag[0] * intgr[1]; |
|||
break; |
|||
} |
|||
|
|||
break; |
|||
|
|||
case GEAR: |
|||
cur = 0.0; |
|||
|
|||
switch(ckt->CKTorder) { |
|||
|
|||
case 6: |
|||
cur += ckt->CKTag[6] * intgr[6]; |
|||
/* fall through */ |
|||
case 5: |
|||
cur += ckt->CKTag[5] * intgr[5]; |
|||
/* fall through */ |
|||
case 4: |
|||
cur += ckt->CKTag[4] * intgr[4]; |
|||
/* fall through */ |
|||
case 3: |
|||
cur += ckt->CKTag[3] * intgr[3]; |
|||
/* fall through */ |
|||
case 2: |
|||
cur += ckt->CKTag[2] * intgr[2]; |
|||
/* fall through */ |
|||
case 1: |
|||
cur += ckt->CKTag[1] * intgr[1]; |
|||
break; |
|||
|
|||
} |
|||
break; |
|||
|
|||
} |
|||
|
|||
ceq = cur; |
|||
geq = ckt->CKTag[0]; |
|||
|
|||
/* WARNING: Take this out when the case 2: above is fixed */ |
|||
if((ckt->CKTintegrateMethod == TRAPEZOIDAL) && |
|||
(ckt->CKTorder == 2)) |
|||
geq *= 0.5; |
|||
|
|||
|
|||
/* The following code is equivalent to */ |
|||
/* the solution of one matrix iteration to produce the */ |
|||
/* integral value. */ |
|||
|
|||
*integral = (integrand - ceq) / geq; |
|||
*partial = 1.0 / geq; |
|||
|
|||
} |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
/* |
|||
cm_analog_not_converged() |
|||
|
|||
This function tells the simulator not to allow the current |
|||
iteration to be the final iteration. It is called when |
|||
a code model performs internal limiting on one or more of |
|||
its inputs to assist convergence. |
|||
*/ |
|||
|
|||
void cm_analog_not_converged(void) |
|||
{ |
|||
(g_mif_info.ckt->CKTnoncon)++; |
|||
} |
|||
|
|||
|
|||
|
|||
|
|||
/* |
|||
cm_message_send() |
|||
|
|||
This function prints a message output from a code model, prepending |
|||
the instance name. |
|||
*/ |
|||
|
|||
|
|||
int cm_message_send( |
|||
char *msg) /* The message to output. */ |
|||
{ |
|||
MIFinstance *here; |
|||
|
|||
/* Get the address of the instance struct from g_mif_info */ |
|||
here = g_mif_info.instance; |
|||
|
|||
/* Print the name of the instance and the message */ |
|||
printf("\nInstance: %s Message: %s\n", (char *) here->MIFname, msg); |
|||
|
|||
return(0); |
|||
} |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
/* |
|||
cm_analog_auto_partial() |
|||
|
|||
This function tells the simulator to automatically compute |
|||
approximations of partial derivatives of analog outputs |
|||
with respect to analog inputs. When called from a code |
|||
model, it sets a flag in the g_mif_info structure |
|||
which tells function MIFload() and it's associated |
|||
MIFauto_partial() function to perform the necessary |
|||
calculations. |
|||
*/ |
|||
|
|||
|
|||
void cm_analog_auto_partial(void) |
|||
{ |
|||
g_mif_info.auto_partial.local = MIF_TRUE; |
|||
} |
|||
|
|||
@ -1,267 +0,0 @@ |
|||
/* =========================================================================== |
|||
FILE CMevt.c |
|||
|
|||
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 |
|||
|
|||
<date> <person name> <nature of modifications> |
|||
|
|||
SUMMARY |
|||
|
|||
This file contains functions callable from user code models |
|||
that are associated with the event-driven algorithm. |
|||
|
|||
INTERFACES |
|||
|
|||
cm_event_alloc() |
|||
cm_event_get_ptr() |
|||
cm_event_queue() |
|||
|
|||
REFERENCED FILES |
|||
|
|||
None. |
|||
|
|||
NON-STANDARD FEATURES |
|||
|
|||
None. |
|||
|
|||
=========================================================================== */ |
|||
|
|||
#include "ngspice.h" |
|||
#include "cktdefs.h" |
|||
//#include "util.h" |
|||
|
|||
#include "cm.h" |
|||
#include "mif.h" |
|||
#include "evt.h" |
|||
|
|||
#include "evtproto.h" |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
/* |
|||
cm_event_alloc() |
|||
|
|||
This function is called from code model C functions to allocate |
|||
state storage for a particular event-driven |
|||
instance. It is similar to the |
|||
function cm_analog_alloc() used by analog models, but allocates states |
|||
that are rotated during event-driven 'timesteps' instead of analog |
|||
timesteps. |
|||
*/ |
|||
|
|||
|
|||
void *cm_event_alloc( |
|||
int tag, /* The user-specified tag for the memory block */ |
|||
int bytes) /* The number of bytes to be allocated */ |
|||
{ |
|||
|
|||
int inst_index; |
|||
int num_tags; |
|||
|
|||
MIFinstance *here; |
|||
CKTcircuit *ckt; |
|||
|
|||
void *ptr; |
|||
|
|||
Evt_State_Desc_t **desc_ptr; |
|||
Evt_State_Desc_t *desc; |
|||
|
|||
Evt_State_Data_t *state_data; |
|||
Evt_State_t *state; |
|||
|
|||
|
|||
/* Get the address of the ckt and instance structs from g_mif_info */ |
|||
here = g_mif_info.instance; |
|||
ckt = g_mif_info.ckt; |
|||
|
|||
|
|||
/* If not initialization pass, return error */ |
|||
if(here->initialized) { |
|||
g_mif_info.errmsg = |
|||
"ERROR - cm_event_alloc() - Cannot alloc when not initialization pass\n"; |
|||
return(NULL); |
|||
} |
|||
|
|||
|
|||
/* Get pointers for fast access */ |
|||
inst_index = here->inst_index; |
|||
state_data = ckt->evt->data.state; |
|||
|
|||
|
|||
/* Scan state descriptor list to determine if tag is present and to */ |
|||
/* find the end of the list. Report error if duplicate tag */ |
|||
desc_ptr = &(state_data->desc[inst_index]); |
|||
desc = *desc_ptr; |
|||
num_tags = 1; |
|||
while(desc) { |
|||
if(desc->tag == tag) { |
|||
g_mif_info.errmsg = |
|||
"ERROR - cm_event_alloc() - Duplicate tag\n"; |
|||
return(NULL); |
|||
} |
|||
desc_ptr = &(desc->next); |
|||
desc = *desc_ptr; |
|||
num_tags++; |
|||
} |
|||
|
|||
/* Create a new state description structure at end of list */ |
|||
/* and fill in the data and update the total size */ |
|||
*desc_ptr = (void *) MALLOC(sizeof(Evt_State_Desc_t)); |
|||
desc = *desc_ptr; |
|||
desc->tag = tag; |
|||
desc->size = bytes; |
|||
desc->offset = state_data->total_size[inst_index]; |
|||
state_data->total_size[inst_index] += bytes; |
|||
|
|||
/* Create a new state structure if list starting at head is null */ |
|||
state = state_data->head[inst_index]; |
|||
if(state == NULL) { |
|||
state = (void *) MALLOC(sizeof(Evt_State_t)); |
|||
state_data->head[inst_index] = state; |
|||
} |
|||
|
|||
/* Create or enlarge the block and set the time */ |
|||
if(num_tags == 1) |
|||
state->block = MALLOC(state_data->total_size[inst_index]); |
|||
else |
|||
state->block = REALLOC(state->block, |
|||
state_data->total_size[inst_index]); |
|||
|
|||
state->step = g_mif_info.circuit.evt_step; |
|||
|
|||
|
|||
/* Return allocated memory */ |
|||
ptr = ((char *)state->block) + desc->offset; |
|||
return(ptr); |
|||
} |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
/* |
|||
cm_event_get_ptr() |
|||
|
|||
This function is called from code model C functions to return a |
|||
pointer to state storage allocated with cm_event_alloc(). A tag |
|||
specified in its argument list is used to locate the state in |
|||
question. A second argument specifies whether the desired state |
|||
is for the current timestep or from a preceding timestep. The |
|||
location of the state in memory is then computed and returned. |
|||
*/ |
|||
|
|||
|
|||
void *cm_event_get_ptr( |
|||
int tag, /* The user-specified tag for the memory block */ |
|||
int timepoint) /* The timepoint - 0=current, 1=previous */ |
|||
{ |
|||
|
|||
int i; |
|||
int inst_index; |
|||
|
|||
MIFinstance *here; |
|||
CKTcircuit *ckt; |
|||
|
|||
void *ptr; |
|||
|
|||
Evt_State_Desc_t *desc; |
|||
|
|||
Evt_State_Data_t *state_data; |
|||
Evt_State_t *state; |
|||
|
|||
|
|||
/* Get the address of the ckt and instance structs from g_mif_info */ |
|||
here = g_mif_info.instance; |
|||
ckt = g_mif_info.ckt; |
|||
|
|||
|
|||
/* If initialization pass, return error */ |
|||
if((! here->initialized) && (timepoint > 0)) { |
|||
g_mif_info.errmsg = |
|||
"ERROR - cm_event_get_ptr() - Cannot get_ptr(tag,1) during initialization pass\n"; |
|||
return(NULL); |
|||
} |
|||
|
|||
/* Get pointers for fast access */ |
|||
inst_index = here->inst_index; |
|||
state_data = ckt->evt->data.state; |
|||
|
|||
/* Scan state descriptor list to find the descriptor for this tag. */ |
|||
/* Report error if tag not found */ |
|||
desc = state_data->desc[inst_index]; |
|||
while(desc) { |
|||
if(desc->tag == tag) |
|||
break; |
|||
desc = desc->next; |
|||
} |
|||
|
|||
if(desc == NULL) { |
|||
g_mif_info.errmsg = |
|||
"ERROR - cm_event_get_ptr() - Specified tag not found\n"; |
|||
return(NULL); |
|||
} |
|||
|
|||
/* Get the state pointer from the current array */ |
|||
state = *(state_data->tail[inst_index]); |
|||
|
|||
/* Backup the specified number of timesteps */ |
|||
for(i = 0; i < timepoint; i++) |
|||
if(state->prev) |
|||
state = state->prev; |
|||
|
|||
/* Return pointer */ |
|||
ptr = ((char *) state->block) + desc->offset; |
|||
return(ptr); |
|||
} |
|||
|
|||
|
|||
|
|||
|
|||
/* |
|||
cm_event_queue() |
|||
|
|||
This function queues an event for an instance participating |
|||
in the event-driven algorithm. |
|||
*/ |
|||
|
|||
|
|||
int cm_event_queue( |
|||
double time) /* The time of the event to be queued */ |
|||
{ |
|||
|
|||
MIFinstance *here; |
|||
CKTcircuit *ckt; |
|||
|
|||
|
|||
/* Get the address of the ckt and instance structs from g_mif_info */ |
|||
here = g_mif_info.instance; |
|||
ckt = g_mif_info.ckt; |
|||
|
|||
/* If breakpoint time <= current event time, return error */ |
|||
if(time <= g_mif_info.circuit.evt_step) { |
|||
g_mif_info.errmsg = |
|||
"ERROR - cm_event_queue() - Event time cannot be <= current time\n"; |
|||
return(MIF_ERROR); |
|||
} |
|||
|
|||
/* Add the event time to the inst queue */ |
|||
EVTqueue_inst(ckt, here->inst_index, g_mif_info.circuit.evt_step, |
|||
time); |
|||
|
|||
return(MIF_OK); |
|||
} |
|||
@ -1,314 +0,0 @@ |
|||
/* =========================================================================== |
|||
FILE CMmeters.c |
|||
|
|||
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 |
|||
|
|||
<date> <person name> <nature of modifications> |
|||
|
|||
SUMMARY |
|||
|
|||
This file contains functions callable from code models. |
|||
These functions are primarily designed for use by the |
|||
"cmeter" and "lmeter" models provided in the XSPICE |
|||
code model library. |
|||
|
|||
INTERFACES |
|||
|
|||
cm_netlist_get_c() |
|||
cm_netlist_get_l() |
|||
|
|||
REFERENCED FILES |
|||
|
|||
None. |
|||
|
|||
NON-STANDARD FEATURES |
|||
|
|||
None. |
|||
|
|||
=========================================================================== */ |
|||
#include "ngspice.h" |
|||
#include "cm.h" |
|||
#include "mif.h" |
|||
|
|||
#include "cktdefs.h" |
|||
|
|||
#include "mifdefs.h" |
|||
#include "cap/capdefs.h" |
|||
#include "ind/inddefs.h" |
|||
#include "vsrc/vsrcdefs.h" |
|||
#include "inpdefs.h" |
|||
|
|||
|
|||
|
|||
/* |
|||
cm_netlist_get_c() |
|||
|
|||
This is a special function designed for use with the c_meter |
|||
model. It returns the parallel combination of the capacitance |
|||
connected to the first port on the instance. |
|||
*/ |
|||
|
|||
double cm_netlist_get_c() |
|||
{ |
|||
CKTcircuit *ckt; |
|||
|
|||
MIFinstance *cmeter_inst; |
|||
CAPinstance *cap_inst; |
|||
VSRCinstance *vsrc_inst; |
|||
|
|||
CAPmodel *cap_head; |
|||
CAPmodel *cap_model; |
|||
VSRCmodel *vsrc_head; |
|||
VSRCmodel *vsrc_model; |
|||
|
|||
int cap_type; |
|||
int vsrc_type; |
|||
|
|||
int cmeter_node; |
|||
int vsrc_node; |
|||
|
|||
double c; |
|||
|
|||
|
|||
/* Get the circuit data structure and current instance */ |
|||
ckt = g_mif_info.ckt; |
|||
cmeter_inst = g_mif_info.instance; |
|||
|
|||
/* Get internal node number for positive node of cmeter input */ |
|||
cmeter_node = cmeter_inst->conn[0]->port[0]->smp_data.pos_node; |
|||
|
|||
/* Initialize total capacitance value to zero */ |
|||
c = 0.0; |
|||
|
|||
|
|||
/* ****************************************************** */ |
|||
/* Look for capacitors connected directly to cmeter input */ |
|||
/* ****************************************************** */ |
|||
|
|||
/* Get the head of the list of capacitor models in the circuit */ |
|||
cap_type = INPtypelook("Capacitor"); |
|||
if(cap_type < 0) { |
|||
printf("\nERROR - Capacitor type not supported in this binary\n"); |
|||
return(0); |
|||
} |
|||
cap_head = (CAPmodel *) ckt->CKThead[cap_type]; |
|||
|
|||
/* Scan through all capacitor instances and add in values */ |
|||
/* of any capacitors connected to cmeter input */ |
|||
|
|||
for(cap_model = cap_head; cap_model; cap_model = cap_model->CAPnextModel) { |
|||
for(cap_inst = cap_model->CAPinstances; |
|||
cap_inst; |
|||
cap_inst = cap_inst->CAPnextInstance) { |
|||
if((cmeter_node == cap_inst->CAPposNode) || |
|||
(cmeter_node == cap_inst->CAPnegNode)) { |
|||
c += cap_inst->CAPcapac; |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
/* ***************************************************************** */ |
|||
/* Look for capacitors connected through zero-valued voltage sources */ |
|||
/* ***************************************************************** */ |
|||
|
|||
/* Get the head of the list of voltage source models in the circuit */ |
|||
vsrc_type = INPtypelook("Vsource"); |
|||
if(vsrc_type < 0) { |
|||
printf("\nERROR - Vsource type not supported in this binary\n"); |
|||
return(0); |
|||
} |
|||
vsrc_head = (VSRCmodel *) ckt->CKThead[vsrc_type]; |
|||
|
|||
/* Scan through all voltage source instances and add in values */ |
|||
/* of any capacitors connected to cmeter input through voltage source */ |
|||
|
|||
for(vsrc_model = vsrc_head; vsrc_model; vsrc_model = vsrc_model->VSRCnextModel) { |
|||
for(vsrc_inst = vsrc_model->VSRCinstances; |
|||
vsrc_inst; |
|||
vsrc_inst = vsrc_inst->VSRCnextInstance) { |
|||
|
|||
/* Skip to next if not DC source with value = 0.0 */ |
|||
if((vsrc_inst->VSRCfunctionType != 0) || |
|||
(vsrc_inst->VSRCdcValue != 0.0)) |
|||
continue; |
|||
|
|||
/* See if voltage source is connected to cmeter input */ |
|||
/* If so, get other node voltage source is connected to */ |
|||
/* If not, skip to next source */ |
|||
if(cmeter_node == vsrc_inst->VSRCposNode) |
|||
vsrc_node = vsrc_inst->VSRCnegNode; |
|||
else if(cmeter_node == vsrc_inst->VSRCnegNode) |
|||
vsrc_node = vsrc_inst->VSRCposNode; |
|||
else |
|||
continue; |
|||
|
|||
|
|||
/* Scan through all capacitor instances and add in values */ |
|||
/* of any capacitors connected to the voltage source node */ |
|||
|
|||
for(cap_model = cap_head; cap_model; cap_model = cap_model->CAPnextModel) { |
|||
for(cap_inst = cap_model->CAPinstances; |
|||
cap_inst; |
|||
cap_inst = cap_inst->CAPnextInstance) { |
|||
if((vsrc_node == cap_inst->CAPposNode) || |
|||
(vsrc_node == cap_inst->CAPnegNode)) { |
|||
c += cap_inst->CAPcapac; |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
} /* end for all vsrc instances */ |
|||
} /* end for all vsrc models */ |
|||
|
|||
|
|||
/* Return the total capacitance value */ |
|||
return(c); |
|||
} |
|||
|
|||
|
|||
|
|||
|
|||
/* |
|||
cm_netlist_get_l() |
|||
|
|||
This is a special function designed for use with the l_meter |
|||
model. It returns the equivalent value of inductance |
|||
connected to the first port on the instance. |
|||
*/ |
|||
|
|||
|
|||
double cm_netlist_get_l() |
|||
{ |
|||
CKTcircuit *ckt; |
|||
|
|||
MIFinstance *lmeter_inst; |
|||
INDinstance *ind_inst; |
|||
VSRCinstance *vsrc_inst; |
|||
|
|||
INDmodel *ind_head; |
|||
INDmodel *ind_model; |
|||
VSRCmodel *vsrc_head; |
|||
VSRCmodel *vsrc_model; |
|||
|
|||
int ind_type; |
|||
int vsrc_type; |
|||
|
|||
int lmeter_node; |
|||
int vsrc_node; |
|||
|
|||
double l; |
|||
|
|||
|
|||
/* Get the circuit data structure and current instance */ |
|||
ckt = g_mif_info.ckt; |
|||
lmeter_inst = g_mif_info.instance; |
|||
|
|||
/* Get internal node number for positive node of lmeter input */ |
|||
lmeter_node = lmeter_inst->conn[0]->port[0]->smp_data.pos_node; |
|||
|
|||
/* Initialize total inductance to infinity */ |
|||
l = 1.0e12; |
|||
|
|||
|
|||
/* ****************************************************** */ |
|||
/* Look for inductors connected directly to lmeter input */ |
|||
/* ****************************************************** */ |
|||
|
|||
/* Get the head of the list of inductor models in the circuit */ |
|||
ind_type = INPtypelook("Inductor"); |
|||
if(ind_type < 0) { |
|||
printf("\nERROR - Inductor type not supported in this binary\n"); |
|||
return(0); |
|||
} |
|||
ind_head = (INDmodel *) ckt->CKThead[ind_type]; |
|||
|
|||
/* Scan through all inductor instances and add in values */ |
|||
/* of any inductors connected to lmeter input */ |
|||
|
|||
for(ind_model = ind_head; ind_model; ind_model = ind_model->INDnextModel) { |
|||
for(ind_inst = ind_model->INDinstances; |
|||
ind_inst; |
|||
ind_inst = ind_inst->INDnextInstance) { |
|||
if((lmeter_node == ind_inst->INDposNode) || |
|||
(lmeter_node == ind_inst->INDnegNode)) { |
|||
l = 1.0 / ( (1.0 / l) + (1.0 / ind_inst->INDinduct) ); |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
/* ***************************************************************** */ |
|||
/* Look for inductors connected through zero-valued voltage sources */ |
|||
/* ***************************************************************** */ |
|||
|
|||
/* Get the head of the list of voltage source models in the circuit */ |
|||
vsrc_type = INPtypelook("Vsource"); |
|||
if(vsrc_type < 0) { |
|||
printf("\nERROR - Vsource type not supported in this binary\n"); |
|||
return(0); |
|||
} |
|||
vsrc_head = (VSRCmodel *) ckt->CKThead[vsrc_type]; |
|||
|
|||
/* Scan through all voltage source instances and add in values */ |
|||
/* of any inductors connected to lmeter input through voltage source */ |
|||
|
|||
for(vsrc_model = vsrc_head; vsrc_model; vsrc_model = vsrc_model->VSRCnextModel) { |
|||
for(vsrc_inst = vsrc_model->VSRCinstances; |
|||
vsrc_inst; |
|||
vsrc_inst = vsrc_inst->VSRCnextInstance) { |
|||
|
|||
/* Skip to next if not DC source with value = 0.0 */ |
|||
if((vsrc_inst->VSRCfunctionType != 0) || |
|||
(vsrc_inst->VSRCdcValue != 0.0)) |
|||
continue; |
|||
|
|||
/* See if voltage source is connected to lmeter input */ |
|||
/* If so, get other node voltage source is connected to */ |
|||
/* If not, skip to next source */ |
|||
if(lmeter_node == vsrc_inst->VSRCposNode) |
|||
vsrc_node = vsrc_inst->VSRCnegNode; |
|||
else if(lmeter_node == vsrc_inst->VSRCnegNode) |
|||
vsrc_node = vsrc_inst->VSRCposNode; |
|||
else |
|||
continue; |
|||
|
|||
|
|||
/* Scan through all inductor instances and add in values */ |
|||
/* of any inductors connected to the voltage source node */ |
|||
|
|||
for(ind_model = ind_head; ind_model; ind_model = ind_model->INDnextModel) { |
|||
for(ind_inst = ind_model->INDinstances; |
|||
ind_inst; |
|||
ind_inst = ind_inst->INDnextInstance) { |
|||
if((vsrc_node == ind_inst->INDposNode) || |
|||
(vsrc_node == ind_inst->INDnegNode)) { |
|||
l = 1.0 / ( (1.0 / l) + (1.0 / ind_inst->INDinduct) ); |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
} /* end for all vsrc instances */ |
|||
} /* end for all vsrc models */ |
|||
|
|||
|
|||
/* Return the total capacitance value */ |
|||
return(l); |
|||
} |
|||
|
|||
|
|||
@ -1,523 +0,0 @@ |
|||
/* =========================================================================== |
|||
FILE CMutil.c |
|||
|
|||
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 |
|||
|
|||
MODIFICATIONS |
|||
|
|||
<date> <person name> <nature of modifications> |
|||
|
|||
SUMMARY |
|||
|
|||
This file contains functions callable from user code models. |
|||
These functions were written to support code models in the |
|||
XSPICE library, but may be useful in general. |
|||
|
|||
INTERFACES |
|||
|
|||
cm_smooth_corner() |
|||
cm_smooth_discontinuity() |
|||
cm_smooth_pwl() |
|||
|
|||
cm_climit_fcn() |
|||
|
|||
cm_complex_set() |
|||
cm_complex_add() |
|||
cm_complex_subtract() |
|||
cm_complex_multiply() |
|||
cm_complex_divide() |
|||
|
|||
|
|||
REFERENCED FILES |
|||
|
|||
None. |
|||
|
|||
NON-STANDARD FEATURES |
|||
|
|||
None. |
|||
|
|||
=========================================================================== */ |
|||
#include <stdio.h> |
|||
#include <math.h> |
|||
#include "cm.h" |
|||
|
|||
/* Corner Smoothing Function ************************************ |
|||
* * |
|||
* The following function smooths the transition between two * |
|||
* slopes into a quadratic (parabolic) curve. The calling * |
|||
* function passes an x,y coordinate representing the * |
|||
* "breakpoint", a smoothing domain value (d), and the slopes at * |
|||
* both endpoints, and the x value itself. The situation is * |
|||
* shown below: B C * |
|||
* A |<-d->| ^ y * |
|||
* ---------*-----* | | * |
|||
* lower_slope-^ |<-d->|\ | | * |
|||
* \ | | * |
|||
* \ | *------>x * |
|||
* At A<x<C, cm_smooth_corner \ | * |
|||
* returns a "y" value which \| * |
|||
* smoothly transitions from *__ * |
|||
* f(A) to f(C) in a parabolic \ | upper_slope * |
|||
* fashion...the slope of the new \| * |
|||
* function is also returned. \ * |
|||
* * |
|||
*****************************************************************/ |
|||
|
|||
void cm_smooth_corner( |
|||
double x_input, /* The value of the x input */ |
|||
double x_center, /* The x intercept of the two slopes */ |
|||
double y_center, /* The y intercept of the two slopes */ |
|||
double domain, /* The smoothing domain */ |
|||
double lower_slope, /* The lower slope */ |
|||
double upper_slope, /* The upper slope */ |
|||
double *y_output, /* The smoothed y output */ |
|||
double *dy_dx) /* The partial of y wrt x */ |
|||
{ |
|||
double x_upper,y_upper,a,b,c,dy_dx_temp; |
|||
|
|||
/* Set up parabolic constants */ |
|||
|
|||
x_upper = x_center + domain; |
|||
y_upper = y_center + (upper_slope * domain); |
|||
a = ((upper_slope - lower_slope) / 4.0) * (1 / domain); |
|||
b = upper_slope - (2.0 * a * x_upper); |
|||
c = y_upper - (a * x_upper * x_upper) - (b * x_upper); |
|||
|
|||
/* Calculate y value & derivative */ |
|||
|
|||
dy_dx_temp = 2.0*a*x_input + b; /* Prevents reassignment problems */ |
|||
/* for x-limiting cases. */ |
|||
|
|||
*y_output = a*x_input*x_input + b*x_input + c; |
|||
*dy_dx = dy_dx_temp; |
|||
} |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
/* Discontinuity Smoothing Function ***************************** |
|||
* * |
|||
* The following function smooths the transition between two * |
|||
* values using an x^2 function. The calling function * |
|||
* function passes an x1,y1 coordinate representing the * |
|||
* starting point, an x2,y2 coordinate representing an ending * |
|||
* point, and the x value itself. The situation is shown below: * |
|||
* * |
|||
* ^ y (xu,yu) * |
|||
* | ---*----------- * |
|||
* | --- | * |
|||
* | -- * |
|||
* | - | * |
|||
* | - * |
|||
* | - | * |
|||
* | -- * |
|||
* | (xl,yl) --- | * |
|||
* ----|----*--- * |
|||
* | | | * |
|||
* O------------------------------------->x * |
|||
*****************************************************************/ |
|||
|
|||
void cm_smooth_discontinuity( |
|||
double x_input, /* The x value at which to compute y */ |
|||
double x_lower, /* The x value of the lower corner */ |
|||
double y_lower, /* The y value of the lower corner */ |
|||
double x_upper, /* The x value of the upper corner */ |
|||
double y_upper, /* The y value of the upper corner */ |
|||
double *y_output, /* The computed smoothed y value */ |
|||
double *dy_dx) /* The partial of y wrt x */ |
|||
{ |
|||
double x_center,y_center,a,b,c,center_slope; |
|||
|
|||
|
|||
/* Derive x_center, y_center & center_slope values */ |
|||
x_center = (x_upper + x_lower) / 2.0; |
|||
y_center = (y_upper + y_lower) / 2.0; |
|||
center_slope = 2.0 * (y_upper - y_lower) / (x_upper - x_lower); |
|||
|
|||
|
|||
if (x_input < x_lower) { /* x_input @ lower level */ |
|||
*y_output = y_lower; |
|||
*dy_dx = 0.0; |
|||
} |
|||
else { |
|||
if (x_input < x_center) { /* x_input in lower transition */ |
|||
a = center_slope / (x_upper - x_lower); |
|||
b = center_slope - 2.0 * a * x_center; |
|||
c = y_center - a * x_center * x_center - b * x_center; |
|||
*y_output = a * x_input * x_input + b * x_input + c; |
|||
*dy_dx = 2.0 * a * x_input + b; |
|||
} |
|||
else { /* x_input in upper transition */ |
|||
if (x_input < x_upper) { |
|||
a = -center_slope / (x_upper - x_lower); |
|||
b = -2.0 * a * x_upper; |
|||
c = y_upper - a * x_upper * x_upper - b * x_upper; |
|||
*y_output = a * x_input * x_input + b * x_input + c; |
|||
*dy_dx = 2.0 * a * x_input + b; |
|||
} |
|||
else { /* x_input @ upper level */ |
|||
*y_output = y_upper; |
|||
*dy_dx = 0.0; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
|
|||
/* Controlled Limiter Function (modified CLIMIT) */ |
|||
|
|||
/* |
|||
This is a special function created for use with the CLIMIT |
|||
controlled limiter model. |
|||
*/ |
|||
|
|||
void cm_climit_fcn( |
|||
double in, /* The input value */ |
|||
double in_offset, /* The input offset */ |
|||
double cntl_upper, /* The upper control input value */ |
|||
double cntl_lower, /* The lower control input value */ |
|||
double lower_delta, /* The delta from control to limit value */ |
|||
double upper_delta, /* The delta from control to limit value */ |
|||
double limit_range, /* The limiting range */ |
|||
double gain, /* The gain from input to output */ |
|||
int percent, /* The fraction vs. absolute range flag */ |
|||
double *out_final, /* The output value */ |
|||
double *pout_pin_final, /* The partial of output wrt input */ |
|||
double *pout_pcntl_lower_final, /* The partial of output wrt lower control input */ |
|||
double *pout_pcntl_upper_final) /* The partial of output wrt upper control input */ |
|||
{ |
|||
|
|||
/* Define error message string constants */ |
|||
|
|||
char *climit_range_error = "\n**** ERROR ****\n* CLIMIT function linear range less than zero. *\n"; |
|||
|
|||
|
|||
double threshold_upper,threshold_lower,linear_range, |
|||
out_lower_limit,out_upper_limit,limited_out, |
|||
out,pout_pin,pout_pcntl_lower,pout_pcntl_upper,junk; |
|||
|
|||
/* Find Upper & Lower Limits */ |
|||
|
|||
out_lower_limit = cntl_lower + lower_delta; |
|||
out_upper_limit = cntl_upper - upper_delta; |
|||
|
|||
|
|||
if (percent == TRUE) /* Set range to absolute value */ |
|||
limit_range = limit_range * |
|||
(out_upper_limit - out_lower_limit); |
|||
|
|||
|
|||
|
|||
threshold_upper = out_upper_limit - /* Set Upper Threshold */ |
|||
limit_range; |
|||
threshold_lower = out_lower_limit + /* Set Lower Threshold */ |
|||
limit_range; |
|||
linear_range = threshold_upper - threshold_lower; |
|||
|
|||
|
|||
/* Test the linear region & make sure there IS one... */ |
|||
if (linear_range < 0.0) { |
|||
printf("%s\n",climit_range_error); |
|||
/* limited_out = 0.0; |
|||
pout_pin = 0.0; |
|||
pout_pcntl_lower = 0.0; |
|||
pout_pcntl_upper = 0.0; |
|||
return; |
|||
*/ } |
|||
|
|||
/* Compute Un-Limited Output */ |
|||
out = gain * (in_offset + in); |
|||
|
|||
|
|||
if (out < threshold_lower) { /* Limit Out @ Lower Bound */ |
|||
|
|||
pout_pcntl_upper= 0.0; |
|||
|
|||
if (out > (out_lower_limit - limit_range)) { /* Parabolic */ |
|||
cm_smooth_corner(out,out_lower_limit,out_lower_limit, |
|||
limit_range,0.0,1.0,&limited_out, |
|||
&pout_pin); |
|||
pout_pin = gain * pout_pin; |
|||
cm_smooth_discontinuity(out,out_lower_limit,1.0,threshold_lower, |
|||
0.0,&pout_pcntl_lower,&junk); |
|||
} |
|||
else { /* Hard-Limited Region */ |
|||
limited_out = out_lower_limit; |
|||
pout_pin = 0.0; |
|||
pout_pcntl_lower = 1.0; |
|||
} |
|||
} |
|||
else { |
|||
if (out > threshold_upper) { /* Limit Out @ Upper Bound */ |
|||
|
|||
pout_pcntl_lower= 0.0; |
|||
|
|||
if (out < (out_upper_limit+limit_range)) { /* Parabolic */ |
|||
cm_smooth_corner(out,out_upper_limit,out_upper_limit, |
|||
limit_range,1.0,0.0,&limited_out, |
|||
&pout_pin); |
|||
pout_pin = gain * pout_pin; |
|||
cm_smooth_discontinuity(out,threshold_upper,0.0,out_upper_limit, |
|||
1.0,&pout_pcntl_upper,&junk); |
|||
} |
|||
else { /* Hard-Limited Region */ |
|||
limited_out = out_upper_limit; |
|||
pout_pin = 0.0; |
|||
pout_pcntl_upper = 1.0; |
|||
} |
|||
} |
|||
else { /* No Limiting Needed */ |
|||
limited_out = out; |
|||
pout_pin = gain; |
|||
pout_pcntl_lower = 0.0; |
|||
pout_pcntl_upper = 0.0; |
|||
} |
|||
} |
|||
|
|||
|
|||
*out_final = limited_out; |
|||
*pout_pin_final = pout_pin; |
|||
*pout_pcntl_lower_final = pout_pcntl_lower; |
|||
*pout_pcntl_upper_final = pout_pcntl_upper; |
|||
|
|||
} |
|||
|
|||
/**** End Controlled Limiter Function ****/ |
|||
|
|||
/*=============================================================================*/ |
|||
|
|||
|
|||
/* Piecewise Linear Smoothing Function ********************* |
|||
* The following is a transfer curve function which * |
|||
* accepts as input an "x" value, and returns a "y" * |
|||
* value. The transfer characteristic is a smoothed * |
|||
* piece-wise linear curve described by *x and *y array * |
|||
* coordinate pairs. * |
|||
* * |
|||
* Created 8/14/91 * |
|||
* Last Modified 8/14/91 J.P.Murray * |
|||
***********************************************************/ |
|||
|
|||
/*********************************************************** |
|||
* * |
|||
* ^ x[4] * |
|||
* x[1] | * * |
|||
* | midpoint /|\ * |
|||
* | | / \ * |
|||
* | V | / | \ * |
|||
* *----*----* \ * |
|||
* midpoint /| | | \ * |
|||
* | / || * <- midpoint * |
|||
* V/ | |x[3] \ * |
|||
* <-----------*------------O------------\-------------> * |
|||
* | / | \ | | * |
|||
* / | \ * |
|||
* |/ | \| | * |
|||
* * | *-----*---> * |
|||
* /| | x[5] x[6] * |
|||
* / | * |
|||
* / x[0] | * |
|||
* / | * |
|||
* / | * |
|||
* / | * |
|||
* V * |
|||
* * |
|||
***********************************************************/ |
|||
|
|||
/*********************************************************** |
|||
* * |
|||
* Note that for the cm_smooth_pwl function, the arguments * |
|||
* are as listed below: * |
|||
* * |
|||
* * |
|||
* double x_input; input * * |
|||
* double *x; pointer to the x-coordinate * |
|||
* array * * |
|||
* double *y; pointer to the y-coordinate * |
|||
* array * * |
|||
* int size; size of the arrays * |
|||
* * |
|||
* double input_domain; smoothing range * * |
|||
* double dout_din; partial derivative of the * |
|||
* output w.r.t. the input * * |
|||
* * |
|||
***********************************************************/ |
|||
|
|||
|
|||
double cm_smooth_pwl(double x_input, double *x, double *y, int size, |
|||
double input_domain, double *dout_din) |
|||
{ |
|||
|
|||
int i; /* generic loop counter index */ |
|||
|
|||
double lower_seg; /* x segment below which input resides */ |
|||
double upper_seg; /* x segment above which the input resides */ |
|||
double lower_slope; /* slope of the lower segment */ |
|||
double upper_slope; /* slope of the upper segment */ |
|||
double out; /* output */ |
|||
double threshold_lower; /* value below which the output begins smoothing */ |
|||
double threshold_upper; /* value above which the output begins smoothing */ |
|||
|
|||
|
|||
/* char *limit_error="\n***ERROR***\nViolation of 50% rule in breakpoints!\n";*/ |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
/* Determine segment boundaries within which x_input resides */ |
|||
|
|||
if (x_input <= (*(x+1) + *x)/2.0) {/*** x_input below lowest midpoint ***/ |
|||
*dout_din = (*(y+1) - *y)/(*(x+1) - *x); |
|||
out = *y + (x_input - *x) * *dout_din; |
|||
} |
|||
else { |
|||
if (x_input >= (*(x+size-2) + *(x+size-1))/2.0) { |
|||
/*** x_input above highest midpoint ***/ |
|||
*dout_din = (*(y+size-1) - *(y+size-2)) / |
|||
(*(x+size-1) - *(x+size-2)); |
|||
out = *(y+size-1) + (x_input - *(x+size-1)) * *dout_din; |
|||
} |
|||
else { /*** x_input within bounds of end midpoints... ***/ |
|||
/*** must determine position progressively & then ***/ |
|||
/*** calculate required output. ***/ |
|||
|
|||
for (i=1; i<size; i++) { |
|||
|
|||
if (x_input < (*(x+i) + *(x+i+1))/2.0) { |
|||
/* approximate position known... */ |
|||
|
|||
lower_seg = (*(x+i) - *(x+i-1)); |
|||
upper_seg = (*(x+i+1) - *(x+i)); |
|||
|
|||
|
|||
/* Calculate input_domain about this region's breakpoint.*/ |
|||
|
|||
/* Translate input_domain into an absolute.... */ |
|||
if ( lower_seg <= upper_seg ) /* Use lower */ |
|||
/* segment */ |
|||
/* for % calc.*/ |
|||
input_domain = input_domain * lower_seg; |
|||
else /* Use upper */ |
|||
/* segment */ |
|||
/* for % calc.*/ |
|||
input_domain = input_domain * upper_seg; |
|||
|
|||
|
|||
/* Set up threshold values about breakpoint... */ |
|||
threshold_lower = *(x+i) - input_domain; |
|||
threshold_upper = *(x+i) + input_domain; |
|||
|
|||
/* Determine where x_input is within region & determine */ |
|||
/* output and partial values.... */ |
|||
if (x_input < threshold_lower) { /* Lower linear region */ |
|||
*dout_din = (*(y+i) - *(y+i-1))/lower_seg; |
|||
out = *(y+i) + (x_input - *(x+i)) * *dout_din; |
|||
} |
|||
else { |
|||
if (x_input < threshold_upper) { /* Parabolic region */ |
|||
lower_slope = (*(y+i) - *(y+i-1))/lower_seg; |
|||
upper_slope = (*(y+i+1) - *(y+i))/upper_seg; |
|||
cm_smooth_corner(x_input,*(x+i),*(y+i),input_domain, |
|||
lower_slope,upper_slope,&out,dout_din); |
|||
} |
|||
else { /* Upper linear region */ |
|||
*dout_din = (*(y+i+1) - *(y+i))/upper_seg; |
|||
out = *(y+i) + (x_input - *(x+i)) * *dout_din; |
|||
} |
|||
} |
|||
break; /* Break search loop...x_input has been found, */ |
|||
/* and out and *dout_din have been assigned. */ |
|||
} |
|||
} |
|||
} |
|||
} |
|||
return out; |
|||
} |
|||
|
|||
|
|||
Complex_t cm_complex_set(double real, double imag) |
|||
{ |
|||
/* Create a complex number with the real and imaginary */ |
|||
/* parts specified in the argument list, and return it */ |
|||
|
|||
Complex_t c; |
|||
|
|||
c.real = real; |
|||
c.imag = imag; |
|||
|
|||
return(c); |
|||
} |
|||
|
|||
Complex_t cm_complex_add(Complex_t x, Complex_t y) |
|||
{ |
|||
/* Add the two complex numbers and return the result */ |
|||
|
|||
Complex_t c; |
|||
|
|||
c.real = x.real + y.real; |
|||
c.imag = x.imag + y.imag; |
|||
|
|||
return(c); |
|||
} |
|||
|
|||
Complex_t cm_complex_subtract(Complex_t x, Complex_t y) |
|||
{ |
|||
/* Subtract the second arg from the first and return the result */ |
|||
|
|||
Complex_t c; |
|||
|
|||
c.real = x.real - y.real; |
|||
c.imag = x.imag - y.imag; |
|||
|
|||
return(c); |
|||
} |
|||
|
|||
Complex_t cm_complex_multiply(Complex_t x, Complex_t y) |
|||
{ |
|||
/* Multiply the two complex numbers and return the result */ |
|||
|
|||
Complex_t c; |
|||
|
|||
c.real = (x.real * y.real) - (x.imag * y.imag); |
|||
c.imag = (x.real * y.imag) + (x.imag * y.real); |
|||
|
|||
return(c); |
|||
} |
|||
|
|||
Complex_t cm_complex_divide(Complex_t x, Complex_t y) |
|||
{ |
|||
/* Divide the first number by the second and return the result */ |
|||
|
|||
Complex_t c; |
|||
double mag_y_squared; |
|||
|
|||
mag_y_squared = (y.real * y.real) + (y.imag * y.imag); |
|||
|
|||
if(mag_y_squared < 1e-100) { |
|||
printf("\nWARNING: cm_complex_divide() - divide by zero\n"); |
|||
mag_y_squared = 1e-100; |
|||
} |
|||
|
|||
c.real = ((x.real * y.real) + (x.imag * y.imag)) / mag_y_squared; |
|||
c.imag = ((x.imag * y.real) - (y.imag * x.real)) / mag_y_squared; |
|||
|
|||
return(c); |
|||
} |
|||
|
|||
|
|||
@ -1,13 +0,0 @@ |
|||
## Process this file with automake to produce Makefile.in
|
|||
#
|
|||
# JW 3/9/01 - had a go and makeing an autoconf script.
|
|||
|
|||
noinst_LIBRARIES = libenhxsp.a |
|||
|
|||
libenhxsp_a_SOURCES = \
|
|||
enh.c \ |
|||
enhtrans.c |
|||
|
|||
INCLUDES = -I$(top_srcdir)/src/include |
|||
|
|||
MAINTAINERCLEANFILES = Makefile.in |
|||
@ -1,99 +0,0 @@ |
|||
/*============================================================================ |
|||
FILE ENH.c |
|||
|
|||
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 |
|||
|
|||
<date> <person name> <nature of modifications> |
|||
|
|||
SUMMARY |
|||
|
|||
This file contains routines used for general enhancements made |
|||
to the Berkeley SPICE3 core. |
|||
|
|||
INTERFACES |
|||
|
|||
ENHreport_conv_prob() |
|||
|
|||
REFERENCED FILES |
|||
|
|||
None. |
|||
|
|||
NON-STANDARD FEATURES |
|||
|
|||
None. |
|||
|
|||
============================================================================*/ |
|||
|
|||
/*=== INCLUDE FILES ===*/ |
|||
|
|||
|
|||
#include <stdio.h> |
|||
#include "enh.h" |
|||
|
|||
/* |
|||
ENHreport_conv_prob() |
|||
|
|||
Report convergence problem messages from nodes, branch currents, |
|||
or instances. This function is setup to allow providing the SI |
|||
with information identifying the type of convergence problem. |
|||
For now, it simply writes to stdout. |
|||
*/ |
|||
|
|||
|
|||
void ENHreport_conv_prob( |
|||
Enh_Conv_Source_t type, /* node, branch, or instance */ |
|||
char *name, /* the name of the node/branch/instance */ |
|||
char *msg) /* an optional message */ |
|||
{ |
|||
|
|||
char *type_str; |
|||
char *msg_str; |
|||
|
|||
/* Convert the type enum to a string for printing */ |
|||
switch(type) { |
|||
|
|||
case ENH_ANALOG_NODE: |
|||
case ENH_EVENT_NODE: |
|||
type_str = "node"; |
|||
break; |
|||
|
|||
case ENH_ANALOG_BRANCH: |
|||
type_str = "branch current"; |
|||
break; |
|||
|
|||
case ENH_ANALOG_INSTANCE: |
|||
case ENH_EVENT_INSTANCE: |
|||
case ENH_HYBRID_INSTANCE: |
|||
type_str = "instance"; |
|||
break; |
|||
|
|||
default: |
|||
printf("\nERROR: Internal error in ENHreport_conv_prob - impossible type\n"); |
|||
return; |
|||
} |
|||
|
|||
/* Check for msg == NULL and turn into null string */ |
|||
if(msg) |
|||
msg_str = msg; |
|||
else |
|||
msg_str = ""; |
|||
|
|||
/* Print the convergence problem report */ |
|||
printf("\nWARNING: Convergence problems at %s (%s). %s\n", |
|||
type_str, name, msg_str); |
|||
|
|||
} /* ENHreport_conv_prob */ |
|||
|
|||
@ -1,437 +0,0 @@ |
|||
/* =========================================================================== |
|||
FILE ENHtranslate_poly.c |
|||
|
|||
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 |
|||
|
|||
<date> <person name> <nature of modifications> |
|||
|
|||
SUMMARY |
|||
|
|||
This file contains functions used by the simulator in |
|||
calling the internal "poly" code model to substitute for |
|||
SPICE 2G6 style poly sources found in the input deck. |
|||
|
|||
INTERFACES |
|||
|
|||
ENHtranslate_poly() |
|||
|
|||
REFERENCED FILES |
|||
|
|||
None. |
|||
|
|||
NON-STANDARD FEATURES |
|||
|
|||
None. |
|||
|
|||
=========================================================================== */ |
|||
|
|||
/*=== FUNCTION PROTOTYPES ===*/ |
|||
|
|||
//void free(void *); //ka removed compiler error |
|||
/* int atoi(char *); */ |
|||
|
|||
|
|||
/*=== INCLUDE FILES ===*/ |
|||
|
|||
|
|||
/* #include "prefix.h" */ |
|||
|
|||
#include "ngspice.h" |
|||
//#include "misc.h" |
|||
|
|||
#include "fteinp.h" |
|||
#include "enh.h" |
|||
#include "cpdefs.h" |
|||
#include "ftedefs.h" |
|||
#include "mifproto.h" |
|||
|
|||
/* #include "suffix.h" */ |
|||
|
|||
|
|||
/*=== FUNCTION PROTOTYPES ===*/ |
|||
|
|||
static int needs_translating(char *card); |
|||
static int count_tokens(char *card); |
|||
static char *translate(char *orig_card, char **inst_card, |
|||
char **mod_card); |
|||
static int get_poly_dimension(char *card); |
|||
|
|||
// added as a quick bug fix, a lot of standard models have a linear poly(1) which |
|||
// fails in this code, Kevin Aylward April 15th 2000 |
|||
char * (*FPConvertSpicePoly1ToBsource)(char *card); // this is so I can use the MFC class libary |
|||
/* |
|||
ENHtranslate_poly() |
|||
|
|||
Translate all 2G6 style polynomial controlled sources in the deck |
|||
to new polynomial controlled source code model syntax. |
|||
*/ |
|||
|
|||
|
|||
struct line * ENHtranslate_poly( |
|||
struct line *deck) /* Linked list of lines in input deck */ |
|||
{ |
|||
struct line *d; |
|||
struct line *l1; |
|||
struct line *l2; |
|||
|
|||
char *card; |
|||
int poly_dimension; |
|||
char *buff; |
|||
|
|||
|
|||
/* Iterate through each card in the deck and translate as needed */ |
|||
for(d = deck; d; d = d->li_next) |
|||
{ |
|||
|
|||
/* If doesn't need to be translated, continue to next card */ |
|||
if(! needs_translating(d->li_line)) |
|||
continue; |
|||
|
|||
// Start added as a quick fix to a xspice translation bug in poly(1) code |
|||
// Kevin Aylward April 15th 2000, fuck knows where it is |
|||
poly_dimension = get_poly_dimension(d->li_line); |
|||
|
|||
if(poly_dimension == 1)// |
|||
{ |
|||
buff = (FPConvertSpicePoly1ToBsource)(d->li_line); |
|||
|
|||
if(buff) |
|||
{ |
|||
FREE(d->li_line); |
|||
|
|||
d->li_line = buff; |
|||
} |
|||
|
|||
continue; |
|||
} |
|||
// End added as a quick fix to a xspice translation bug in poly(1) code |
|||
// Kevin Aylward April 15th 2000 |
|||
|
|||
|
|||
/* Create two new line structs and splice into deck */ |
|||
/* l1 = alloc(line); */ /* jgroves */ |
|||
/* l2 = alloc(line); */ /* jgroves */ |
|||
l1 = alloc(struct line); |
|||
l2 = alloc(struct line); |
|||
l2->li_next = d->li_next; |
|||
l1->li_next = l2; |
|||
d->li_next = l1; |
|||
|
|||
/* Create the translated cards */ |
|||
d->li_error = translate(d->li_line, &(l1->li_line), &(l2->li_line)); |
|||
|
|||
/* Comment out the original line */ |
|||
card = (void *) MALLOC(strlen(d->li_line) + 2); |
|||
strcpy(card,"*"); |
|||
strcat(card, d->li_line); |
|||
d->li_line = card; |
|||
|
|||
/* Advance deck pointer to last line added */ |
|||
d = l2; |
|||
} |
|||
|
|||
/* Return head of deck */ |
|||
return(deck); |
|||
|
|||
} /* ENHtranslate_poly */ |
|||
|
|||
|
|||
|
|||
/* |
|||
needs_translating() |
|||
|
|||
Test to see if card needs translating. Return true if card defines |
|||
an e,f,g, or h controlled source and has too many tokens to be |
|||
a simple linear dependent source. Otherwise return false. |
|||
*/ |
|||
|
|||
|
|||
static int needs_translating( |
|||
char *card) /* the card text to check */ |
|||
{ |
|||
|
|||
switch(*card) { |
|||
|
|||
case 'e': |
|||
case 'g': |
|||
if(count_tokens(card) <=6) |
|||
return(0); |
|||
else |
|||
return(1); |
|||
|
|||
case 'f': |
|||
case 'h': |
|||
if(count_tokens(card) <= 5) |
|||
return(0); |
|||
else |
|||
return(1); |
|||
|
|||
default: |
|||
return(0); |
|||
} |
|||
|
|||
} /* needs_translating */ |
|||
|
|||
|
|||
|
|||
|
|||
/* |
|||
count_tokens() |
|||
|
|||
Count and return the number of tokens on the card. |
|||
*/ |
|||
|
|||
|
|||
static int count_tokens( |
|||
char *card) /* the card text on which to count tokens */ |
|||
{ |
|||
int i; |
|||
|
|||
/* Get and count tokens until end of line reached */ |
|||
for(i = 0; *card != '\0'; i++) |
|||
txfree(MIFgettok(&card)); |
|||
|
|||
return(i); |
|||
|
|||
} /* count_tokens */ |
|||
|
|||
|
|||
|
|||
/* |
|||
translate() |
|||
|
|||
Do the syntax translation of the 2G6 source to the new code model syntax. |
|||
*/ |
|||
|
|||
static char *translate( |
|||
char *orig_card, /* the original untranslated card */ |
|||
char **inst_card, /* the instance card created by the translation */ |
|||
char **mod_card) /* the model card created by the translation */ |
|||
{ |
|||
int dim; |
|||
int num_tokens; |
|||
|
|||
int num_conns; |
|||
int num_coefs; |
|||
int inst_card_len; |
|||
int mod_card_len; |
|||
|
|||
int i; |
|||
|
|||
char type; |
|||
|
|||
char *name; |
|||
char **out_conn; |
|||
char **in_conn; |
|||
char **coef; |
|||
|
|||
char *card; |
|||
|
|||
|
|||
/* Get the first character into local storage for checking type */ |
|||
type = *orig_card; |
|||
|
|||
/* Count the number of tokens for use in parsing */ |
|||
num_tokens = count_tokens(orig_card); |
|||
|
|||
/* Determine the dimension of the poly source */ |
|||
dim = get_poly_dimension(orig_card); |
|||
if(dim <= 0) |
|||
return("ERROR - Argument to poly() is not an integer\n"); |
|||
|
|||
/* Compute number of input connections based on type and dimension */ |
|||
switch(type) { |
|||
case 'e': |
|||
case 'g': |
|||
num_conns = 2 * dim; |
|||
break; |
|||
|
|||
default: |
|||
num_conns = dim; |
|||
} |
|||
|
|||
/* Compute number of coefficients. Return error if less than one. */ |
|||
if(dim == 1) |
|||
num_coefs = num_tokens - num_conns - 3; |
|||
else |
|||
num_coefs = num_tokens - num_conns - 5; |
|||
|
|||
if(num_coefs < 1) |
|||
return("ERROR - Number of connections differs from poly dimension\n"); |
|||
|
|||
/* Split card into name, output connections, input connections, */ |
|||
/* and coefficients */ |
|||
|
|||
card = orig_card; |
|||
name = MIFgettok(&card); |
|||
|
|||
out_conn = (void *) MALLOC(2 * sizeof(char *)); |
|||
for(i = 0; i < 2; i++) |
|||
out_conn[i] = MIFgettok(&card); |
|||
|
|||
if(dim > 1) |
|||
for(i = 0; i < 2; i++) |
|||
txfree(MIFgettok(&card)); |
|||
|
|||
in_conn = (void *) MALLOC(num_conns * sizeof(char *)); |
|||
for(i = 0; i < num_conns; i++) |
|||
in_conn[i] = MIFgettok(&card); |
|||
|
|||
coef = (void *) MALLOC(num_coefs * sizeof(char *)); |
|||
for(i = 0; i < num_coefs; i++) |
|||
coef[i] = MIFgettok(&card); |
|||
|
|||
/* Compute the size needed for the new cards to be created */ |
|||
/* Allow a fair amount of extra space for connection types, etc. */ |
|||
/* to be safe... */ |
|||
|
|||
inst_card_len = 50; |
|||
inst_card_len += 2 * (strlen(name) + 1); |
|||
for(i = 0; i < 2; i++) |
|||
inst_card_len += strlen(out_conn[i]) + 1; |
|||
for(i = 0; i < num_conns; i++) |
|||
inst_card_len += strlen(in_conn[i]) + 1; |
|||
|
|||
mod_card_len = 50; |
|||
mod_card_len += strlen(name) + 1; |
|||
for(i = 0; i < num_coefs; i++) |
|||
mod_card_len += strlen(coef[i]) + 1; |
|||
|
|||
/* Allocate space for the cards and write them into the strings */ |
|||
|
|||
*inst_card = (void *) MALLOC(inst_card_len); |
|||
*mod_card = (void *) MALLOC(mod_card_len); |
|||
|
|||
strcpy(*inst_card, "a$poly$"); |
|||
sprintf(*inst_card + strlen(*inst_card), "%s ", name); |
|||
|
|||
if((type == 'e') || (type == 'g')) |
|||
sprintf(*inst_card + strlen(*inst_card), "%%vd [ "); |
|||
else |
|||
sprintf(*inst_card + strlen(*inst_card), "%%vnam [ "); |
|||
|
|||
for(i = 0; i < num_conns; i++) |
|||
sprintf(*inst_card + strlen(*inst_card), "%s ", in_conn[i]); |
|||
|
|||
sprintf(*inst_card + strlen(*inst_card), "] "); |
|||
|
|||
if((type == 'e') || (type == 'h')) |
|||
sprintf(*inst_card + strlen(*inst_card), "%%vd "); |
|||
else |
|||
sprintf(*inst_card + strlen(*inst_card), "%%id "); |
|||
|
|||
for(i = 0; i < 2; i++) |
|||
sprintf(*inst_card + strlen(*inst_card), "%s ", out_conn[i]); |
|||
|
|||
sprintf(*inst_card + strlen(*inst_card), "a$poly$%s", name); |
|||
|
|||
|
|||
sprintf(*mod_card, ".model a$poly$%s poly coef = [ ", name); |
|||
for(i = 0; i < num_coefs; i++) |
|||
sprintf(*mod_card + strlen(*mod_card), "%s ", coef[i]); |
|||
sprintf(*mod_card + strlen(*mod_card), "]"); |
|||
|
|||
|
|||
/* Free the temporary space */ |
|||
FREE(name); |
|||
name = NULL; |
|||
|
|||
for(i = 0; i < 2; i++) |
|||
{ |
|||
FREE(out_conn[i]); |
|||
|
|||
out_conn[i] = NULL; |
|||
} |
|||
|
|||
FREE(out_conn); |
|||
|
|||
out_conn = NULL; |
|||
|
|||
for(i = 0; i < num_conns; i++) |
|||
{ |
|||
FREE(in_conn[i]); |
|||
|
|||
in_conn[i] = NULL; |
|||
} |
|||
|
|||
FREE(in_conn); |
|||
|
|||
in_conn = NULL; |
|||
|
|||
for(i = 0; i < num_coefs; i++) |
|||
{ |
|||
FREE(coef[i]); |
|||
coef[i] = NULL; |
|||
} |
|||
|
|||
FREE(coef); |
|||
|
|||
coef = NULL; |
|||
|
|||
/* Return NULL to indicate no error */ |
|||
return(NULL); |
|||
|
|||
} /* translate */ |
|||
|
|||
|
|||
/* |
|||
get_poly_dimension() |
|||
|
|||
Get the poly source dimension from the token immediately following |
|||
the 'poly' if any. If 'poly' is not present, return 1. If poly is |
|||
present and token following is a valid integer, return it. Else |
|||
return 0. |
|||
*/ |
|||
|
|||
|
|||
static int get_poly_dimension( |
|||
char *card) /* the card text */ |
|||
{ |
|||
|
|||
int i; |
|||
int dim; |
|||
char *tok; |
|||
|
|||
|
|||
/* Skip over name and output connections */ |
|||
for(i = 0; i < 3; i++) |
|||
txfree(MIFgettok(&card)); |
|||
|
|||
/* Check the next token to see if it is "poly" */ |
|||
/* If not, return a dimension of 1 */ |
|||
tok = MIFgettok(&card); |
|||
if(strcmp(tok, "poly")) |
|||
{ |
|||
FREE(tok); |
|||
|
|||
tok = NULL; |
|||
|
|||
return(1); |
|||
} |
|||
|
|||
FREE(tok); |
|||
|
|||
/* Must have been "poly", so next line must be a number */ |
|||
/* Try to convert it. If successful, return the number */ |
|||
/* else, return 0 to indicate an error... */ |
|||
tok = MIFgettok(&card); |
|||
dim = atoi(tok); |
|||
FREE(tok); |
|||
|
|||
return(dim); |
|||
|
|||
} /* get_poly_dimension */ |
|||
|
|||
@ -1,27 +0,0 @@ |
|||
## Process this file with automake to produce Makefile.in
|
|||
#
|
|||
# JW 3/9/01 - had a go and makeing an autoconf script.
|
|||
|
|||
noinst_LIBRARIES = libevtxsp.a |
|||
|
|||
libevtxsp_a_SOURCES = \
|
|||
evtaccept.c \ |
|||
evtcall_hybrids.c \ |
|||
evtdump.c \ |
|||
evtiter.c \ |
|||
evtnext_time.c \ |
|||
evtop.c \ |
|||
evtprint.c \ |
|||
evtsetup.c \ |
|||
evtbackup.c \ |
|||
evtdeque.c \ |
|||
evtinit.c \ |
|||
evtload.c \ |
|||
evtnode_copy.c \ |
|||
evtplot.c \ |
|||
evtqueue.c \ |
|||
evttermi.c |
|||
|
|||
INCLUDES = -I$(top_srcdir)/src/include |
|||
|
|||
MAINTAINERCLEANFILES = Makefile.in |
|||
@ -1,170 +0,0 @@ |
|||
/*============================================================================ |
|||
FILE EVTaccept.c |
|||
|
|||
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 |
|||
|
|||
<date> <person name> <nature of modifications> |
|||
|
|||
SUMMARY |
|||
|
|||
This file contains a function called at the end of a |
|||
successful (accepted) analog timepoint. It saves pointers |
|||
to the states of the queues and data at this accepted time. |
|||
|
|||
INTERFACES |
|||
|
|||
void EVTaccept(CKTcircuit *ckt, double time) |
|||
|
|||
REFERENCED FILES |
|||
|
|||
None. |
|||
|
|||
NON-STANDARD FEATURES |
|||
|
|||
None. |
|||
|
|||
============================================================================*/ |
|||
|
|||
/*=== INCLUDE FILES ===*/ |
|||
|
|||
#include <config.h> |
|||
#include <stdio.h> |
|||
#include "cktdefs.h" |
|||
|
|||
#include "mif.h" |
|||
#include "evt.h" |
|||
|
|||
|
|||
|
|||
/* |
|||
EVTaccept() |
|||
|
|||
This function is called at the end of a successful (accepted) |
|||
analog timepoint. It saves pointers to the states of the |
|||
queues and data at this accepted time. |
|||
*/ |
|||
|
|||
|
|||
|
|||
void EVTaccept( |
|||
CKTcircuit *ckt, /* main circuit struct */ |
|||
double time) /* time at which analog soln was accepted */ |
|||
{ |
|||
|
|||
int i; |
|||
int index; |
|||
int num_modified; |
|||
|
|||
Evt_Inst_Queue_t *inst_queue; |
|||
Evt_Output_Queue_t *output_queue; |
|||
|
|||
Evt_Node_Data_t *node_data; |
|||
Evt_State_Data_t *state_data; |
|||
Evt_Msg_Data_t *msg_data; |
|||
|
|||
|
|||
/* Exit if no event instances */ |
|||
if(ckt->evt->counts.num_insts == 0) |
|||
return; |
|||
|
|||
/* Get often used pointers */ |
|||
inst_queue = &(ckt->evt->queue.inst); |
|||
output_queue = &(ckt->evt->queue.output); |
|||
|
|||
node_data = ckt->evt->data.node; |
|||
state_data = ckt->evt->data.state; |
|||
msg_data = ckt->evt->data.msg; |
|||
|
|||
|
|||
/* Process the inst queue */ |
|||
num_modified = inst_queue->num_modified; |
|||
/* Loop through list of items modified since last time */ |
|||
for(i = 0; i < num_modified; i++) { |
|||
/* Get the index of the inst modified */ |
|||
index = inst_queue->modified_index[i]; |
|||
/* Update last_step for this index */ |
|||
inst_queue->last_step[index] = inst_queue->current[index]; |
|||
/* Reset the modified flag */ |
|||
inst_queue->modified[index] = MIF_FALSE; |
|||
} |
|||
/* Record the new last_time and reset number modified to zero */ |
|||
inst_queue->last_time = time; |
|||
inst_queue->num_modified = 0; |
|||
|
|||
|
|||
/* Process the output queue */ |
|||
num_modified = output_queue->num_modified; |
|||
/* Loop through list of items modified since last time */ |
|||
for(i = 0; i < num_modified; i++) { |
|||
/* Get the index of the output modified */ |
|||
index = output_queue->modified_index[i]; |
|||
/* Update last_step for this index */ |
|||
output_queue->last_step[index] = output_queue->current[index]; |
|||
/* Reset the modified flag */ |
|||
output_queue->modified[index] = MIF_FALSE; |
|||
} |
|||
/* Record the new last_time and reset number modified to zero */ |
|||
output_queue->last_time = time; |
|||
output_queue->num_modified = 0; |
|||
|
|||
|
|||
/* Process the node data */ |
|||
num_modified = node_data->num_modified; |
|||
/* Loop through list of items modified since last time */ |
|||
for(i = 0; i < num_modified; i++) { |
|||
/* Get the index of the node modified */ |
|||
index = node_data->modified_index[i]; |
|||
/* Update last_step for this index */ |
|||
node_data->last_step[index] = node_data->tail[index]; |
|||
/* Reset the modified flag */ |
|||
node_data->modified[index] = MIF_FALSE; |
|||
} |
|||
/* Reset number modified to zero */ |
|||
node_data->num_modified = 0; |
|||
|
|||
|
|||
/* Process the state data */ |
|||
num_modified = state_data->num_modified; |
|||
/* Loop through list of items modified since last time */ |
|||
for(i = 0; i < num_modified; i++) { |
|||
/* Get the index of the state modified */ |
|||
index = state_data->modified_index[i]; |
|||
/* Update last_step for this index */ |
|||
state_data->last_step[index] = state_data->tail[index]; |
|||
/* Reset the modified flag */ |
|||
state_data->modified[index] = MIF_FALSE; |
|||
} |
|||
/* Reset number modified to zero */ |
|||
state_data->num_modified = 0; |
|||
|
|||
|
|||
/* Process the msg data */ |
|||
num_modified = msg_data->num_modified; |
|||
/* Loop through list of items modified since last time */ |
|||
for(i = 0; i < num_modified; i++) { |
|||
/* Get the index of the msg modified */ |
|||
index = msg_data->modified_index[i]; |
|||
/* Update last_step for this index */ |
|||
msg_data->last_step[index] = msg_data->tail[index]; |
|||
/* Reset the modified flag */ |
|||
msg_data->modified[index] = MIF_FALSE; |
|||
} |
|||
/* Reset number modified to zero */ |
|||
msg_data->num_modified = 0; |
|||
|
|||
} /* EVTaccept */ |
|||
|
|||
|
|||
@ -1,645 +0,0 @@ |
|||
/*============================================================================ |
|||
FILE EVTbackup.c |
|||
|
|||
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 |
|||
|
|||
<date> <person name> <nature of modifications> |
|||
|
|||
SUMMARY |
|||
|
|||
This file contains a function that resets the queues and data |
|||
structures to their state at the new analog simulation time specified |
|||
following the rejection of an analog timestep by the DCtran routine. |
|||
|
|||
INTERFACES |
|||
|
|||
void EVTbackup(CKTcircuit *ckt, double new_time) |
|||
|
|||
REFERENCED FILES |
|||
|
|||
None. |
|||
|
|||
NON-STANDARD FEATURES |
|||
|
|||
None. |
|||
|
|||
============================================================================*/ |
|||
|
|||
|
|||
/*=== INCLUDE FILES ===*/ |
|||
#include <stdio.h> |
|||
#include "ngspice.h" |
|||
|
|||
#include "cktdefs.h" |
|||
//#include "util.h" |
|||
|
|||
#include "mif.h" |
|||
#include "evt.h" |
|||
|
|||
#include "evtproto.h" |
|||
|
|||
|
|||
|
|||
/*=== FUNCTION PROTOTYPES ===*/ |
|||
|
|||
|
|||
static void EVTbackup_node_data(CKTcircuit *ckt, double new_time); |
|||
static void EVTbackup_state_data(CKTcircuit *ckt, double new_time); |
|||
static void EVTbackup_msg_data(CKTcircuit *ckt, double new_time); |
|||
static void EVTbackup_inst_queue(CKTcircuit *ckt, double new_time); |
|||
static void EVTbackup_output_queue(CKTcircuit *ckt, double new_time); |
|||
|
|||
|
|||
|
|||
/* |
|||
EVTbackup() |
|||
|
|||
This function resets the queues and data structures to their state |
|||
at the new analog simulation time specified. The algorithms in this file |
|||
assume the following timestep coordination between |
|||
analog and event-driven algorithms: |
|||
|
|||
while(not end of analysis) { |
|||
|
|||
while (next event time <= next analog time) { |
|||
do event solution with call_type = event_driven |
|||
if any instance set analog breakpoint < next analog time |
|||
set next analog time to breakpoint |
|||
} |
|||
|
|||
do analog timestep solution with call_type = analog |
|||
call all hybrid models with call_type = event_driven |
|||
|
|||
if(analog solution doesn't converge) |
|||
Call EVTbackup |
|||
else |
|||
Call EVTaccept |
|||
} |
|||
*/ |
|||
|
|||
|
|||
void EVTbackup( |
|||
CKTcircuit *ckt, /* the main circuit structure */ |
|||
double new_time) /* the time to backup to */ |
|||
{ |
|||
|
|||
|
|||
/* Backup the node data */ |
|||
EVTbackup_node_data(ckt, new_time); |
|||
|
|||
/* Backup the state data */ |
|||
EVTbackup_state_data(ckt, new_time); |
|||
|
|||
/* Backup the msg data */ |
|||
EVTbackup_msg_data(ckt, new_time); |
|||
|
|||
/* Backup the inst queue */ |
|||
EVTbackup_inst_queue(ckt, new_time); |
|||
|
|||
/* Backup the output queue */ |
|||
EVTbackup_output_queue(ckt, new_time); |
|||
|
|||
/* Record statistics */ |
|||
(ckt->evt->data.statistics->tran_time_backups)++; |
|||
|
|||
} /* EVTbackup */ |
|||
|
|||
|
|||
|
|||
|
|||
/* |
|||
EVTbackup_node_data() |
|||
|
|||
Reset the node structure data. |
|||
*/ |
|||
|
|||
|
|||
static void EVTbackup_node_data( |
|||
CKTcircuit *ckt, /* the main circuit structure */ |
|||
double new_time) /* the time to backup to */ |
|||
{ |
|||
|
|||
int i; |
|||
int j; |
|||
|
|||
int num_modified; |
|||
int node_index; |
|||
|
|||
Evt_Node_Info_t **node_table; |
|||
Evt_Node_Data_t *node_data; |
|||
Evt_Node_t **node_ptr; |
|||
Evt_Node_t *node; |
|||
Evt_Node_t *from_node; |
|||
Evt_Node_t *to_node; |
|||
Evt_Node_t *head; |
|||
Evt_Node_t *tail; |
|||
Evt_Node_t *free_head; |
|||
|
|||
/* Get pointers for quick access */ |
|||
node_data = ckt->evt->data.node; |
|||
node_table = ckt->evt->info.node_table; |
|||
|
|||
/* Loop through list of indexes modified since last accepted timepoint */ |
|||
num_modified = node_data->num_modified; |
|||
for(i = 0; i < num_modified; i++) { |
|||
|
|||
/* Get the needed node and udn indexes */ |
|||
node_index = node_data->modified_index[i]; |
|||
|
|||
/* Scan data for this node from last_step to determine new setting */ |
|||
/* for tail, and splice later data into the free list */ |
|||
node_ptr = node_data->last_step[node_index]; |
|||
node = *node_ptr; |
|||
while(1) { |
|||
if((node->next == NULL) || (node->next->step > new_time)) { |
|||
|
|||
/* Splice rest of list, if any, into free list */ |
|||
head = node->next; |
|||
if(head) { |
|||
tail = *(node_data->tail[node_index]); |
|||
free_head = node_data->free[node_index]; |
|||
node_data->free[node_index] = head; |
|||
tail->next = free_head; |
|||
} |
|||
|
|||
/* Set the tail */ |
|||
node_data->tail[node_index] = node_ptr; |
|||
node->next = NULL; |
|||
|
|||
break; |
|||
} |
|||
node_ptr = &(node->next); |
|||
node = node->next; |
|||
} |
|||
|
|||
/* Copy data from the location at tail to rhs and rhsold */ |
|||
from_node = *(node_data->tail[node_index]); |
|||
to_node = &(node_data->rhs[node_index]); |
|||
EVTnode_copy(ckt, node_index, from_node, &to_node); |
|||
to_node = &(node_data->rhsold[node_index]); |
|||
EVTnode_copy(ckt, node_index, from_node, &to_node); |
|||
|
|||
} /* end for number modified */ |
|||
|
|||
/* Update/compact the modified list */ |
|||
for(i = 0, j = 0; i < num_modified; i++) { |
|||
node_index = node_data->modified_index[i]; |
|||
/* If nothing after last_step, remove this index from the modified list */ |
|||
if((*(node_data->last_step[node_index]))->next == NULL) { |
|||
node_data->modified[node_index] = MIF_FALSE; |
|||
(node_data->num_modified)--; |
|||
} |
|||
/* else, keep the index */ |
|||
else { |
|||
node_data->modified_index[j] = node_data->modified_index[i]; |
|||
j++; |
|||
} |
|||
} |
|||
|
|||
} /* EVTbackup_node_data */ |
|||
|
|||
|
|||
|
|||
/* |
|||
EVTbackup_state_data() |
|||
|
|||
Reset the state structure data. |
|||
*/ |
|||
|
|||
|
|||
static void EVTbackup_state_data( |
|||
CKTcircuit *ckt, /* the main circuit structure */ |
|||
double new_time) /* the time to backup to */ |
|||
{ |
|||
int i; |
|||
int j; |
|||
|
|||
int num_modified; |
|||
int inst_index; |
|||
|
|||
Evt_State_Data_t *state_data; |
|||
|
|||
Evt_State_t **state_ptr; |
|||
Evt_State_t *state; |
|||
Evt_State_t *head; |
|||
Evt_State_t *tail; |
|||
Evt_State_t *free_head; |
|||
|
|||
/* Get pointers for quick access */ |
|||
state_data = ckt->evt->data.state; |
|||
|
|||
/* Loop through list of indexes modified since last accepted timepoint */ |
|||
num_modified = state_data->num_modified; |
|||
for(i = 0; i < num_modified; i++) { |
|||
|
|||
/* Get the inst index */ |
|||
inst_index = state_data->modified_index[i]; |
|||
|
|||
/* Scan data for this inst from last_step to determine new setting */ |
|||
/* for tail, and splice later data into the free list */ |
|||
state_ptr = state_data->last_step[inst_index]; |
|||
state = *state_ptr; |
|||
while(1) { |
|||
if((state->next == NULL) || (state->next->step > new_time)) { |
|||
|
|||
/* Splice rest of list, if any, into free list */ |
|||
head = state->next; |
|||
if(head) { |
|||
tail = *(state_data->tail[inst_index]); |
|||
free_head = state_data->free[inst_index]; |
|||
state_data->free[inst_index] = head; |
|||
tail->next = free_head; |
|||
} |
|||
|
|||
/* Set the tail */ |
|||
state_data->tail[inst_index] = state_ptr; |
|||
state->next = NULL; |
|||
|
|||
break; |
|||
} |
|||
state_ptr = &(state->next); |
|||
state = state->next; |
|||
} |
|||
} /* end for number modified */ |
|||
|
|||
/* Update/compact the modified list */ |
|||
for(i = 0, j = 0; i < num_modified; i++) { |
|||
inst_index = state_data->modified_index[i]; |
|||
/* If nothing after last_step, remove this index from the modified list */ |
|||
if((*(state_data->last_step[inst_index]))->next == NULL) { |
|||
state_data->modified[inst_index] = MIF_FALSE; |
|||
(state_data->num_modified)--; |
|||
} |
|||
/* else, keep the index */ |
|||
else { |
|||
state_data->modified_index[j] = state_data->modified_index[i]; |
|||
j++; |
|||
} |
|||
} |
|||
|
|||
} /* EVTbackup_state_data */ |
|||
|
|||
|
|||
|
|||
/* |
|||
EVTbackup_msg_data() |
|||
|
|||
Backup the message data. |
|||
*/ |
|||
|
|||
|
|||
static void EVTbackup_msg_data( |
|||
CKTcircuit *ckt, /* the main circuit structure */ |
|||
double new_time) /* the time to backup to */ |
|||
{ |
|||
int i; |
|||
int j; |
|||
|
|||
int num_modified; |
|||
int port_index; |
|||
|
|||
Evt_Msg_Data_t *msg_data; |
|||
|
|||
Evt_Msg_t **msg_ptr; |
|||
Evt_Msg_t *msg; |
|||
Evt_Msg_t *head; |
|||
Evt_Msg_t *tail; |
|||
Evt_Msg_t *free_head; |
|||
|
|||
/* Get pointers for quick access */ |
|||
msg_data = ckt->evt->data.msg; |
|||
|
|||
/* Loop through list of indexes modified since last accepted timepoint */ |
|||
num_modified = msg_data->num_modified; |
|||
for(i = 0; i < num_modified; i++) { |
|||
|
|||
/* Get the port index */ |
|||
port_index = msg_data->modified_index[i]; |
|||
|
|||
/* Scan data for this port from last_step to determine new setting */ |
|||
/* for tail, and splice later data into the free list */ |
|||
msg_ptr = msg_data->last_step[port_index]; |
|||
msg = *msg_ptr; |
|||
while(1) { |
|||
if((msg->next == NULL) || (msg->next->step > new_time)) { |
|||
|
|||
/* Splice rest of list, if any, into free list */ |
|||
head = msg->next; |
|||
if(head) { |
|||
tail = *(msg_data->tail[port_index]); |
|||
free_head = msg_data->free[port_index]; |
|||
msg_data->free[port_index] = head; |
|||
tail->next = free_head; |
|||
} |
|||
|
|||
/* Set the tail */ |
|||
msg_data->tail[port_index] = msg_ptr; |
|||
msg->next = NULL; |
|||
|
|||
break; |
|||
} |
|||
msg_ptr = &(msg->next); |
|||
msg = msg->next; |
|||
} |
|||
|
|||
} /* end for number modified */ |
|||
|
|||
/* Update/compact the modified list */ |
|||
for(i = 0, j = 0; i < num_modified; i++) { |
|||
port_index = msg_data->modified_index[i]; |
|||
/* If nothing after last_step, remove this index from the modified list */ |
|||
if((*(msg_data->last_step[port_index]))->next == NULL) { |
|||
msg_data->modified[port_index] = MIF_FALSE; |
|||
(msg_data->num_modified)--; |
|||
} |
|||
/* else, keep the index */ |
|||
else { |
|||
msg_data->modified_index[j] = msg_data->modified_index[i]; |
|||
j++; |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
|
|||
/* |
|||
EVTbackup_inst_queue() |
|||
|
|||
Backup data in inst queue. |
|||
*/ |
|||
|
|||
|
|||
static void EVTbackup_inst_queue( |
|||
CKTcircuit *ckt, /* the main circuit structure */ |
|||
double new_time) /* the time to backup to */ |
|||
{ |
|||
|
|||
int i; |
|||
int j; |
|||
|
|||
int num_modified; |
|||
int num_pending; |
|||
int inst_index; |
|||
|
|||
Evt_Inst_Queue_t *inst_queue; |
|||
|
|||
Evt_Inst_Event_t **inst_ptr; |
|||
Evt_Inst_Event_t *inst; |
|||
|
|||
double next_time; |
|||
double event_time; |
|||
|
|||
|
|||
/* Get pointers for quick access */ |
|||
inst_queue = &(ckt->evt->queue.inst); |
|||
|
|||
/* Loop through list of indexes modified since last accepted timepoint */ |
|||
/* and remove events with posted time > new_time */ |
|||
num_modified = inst_queue->num_modified; |
|||
for(i = 0; i < num_modified; i++) { |
|||
|
|||
/* Get the inst index */ |
|||
inst_index = inst_queue->modified_index[i]; |
|||
|
|||
/* Scan forward from last_step and cut out data with posted time */ |
|||
/* > new_time and add it to the free list */ |
|||
|
|||
inst_ptr = inst_queue->last_step[inst_index]; |
|||
inst = *inst_ptr; |
|||
|
|||
while(inst) { |
|||
if(inst->posted_time > new_time) { |
|||
*inst_ptr = inst->next; |
|||
inst->next = inst_queue->free[inst_index]; |
|||
inst_queue->free[inst_index] = inst; |
|||
inst = *inst_ptr; |
|||
} |
|||
else { |
|||
inst_ptr = &(inst->next); |
|||
inst = *inst_ptr; |
|||
} |
|||
} |
|||
|
|||
/* Scan forward from last_step and set current to first */ |
|||
/* event with event_time > new_time */ |
|||
|
|||
inst_ptr = inst_queue->last_step[inst_index]; |
|||
inst = *inst_ptr; |
|||
|
|||
while(inst) { |
|||
if(inst->event_time > new_time) |
|||
break; |
|||
inst_ptr = &((*inst_ptr)->next); |
|||
inst = *inst_ptr; |
|||
} |
|||
inst_queue->current[inst_index] = inst_ptr; |
|||
} |
|||
|
|||
/* Add set of items modified to set of items pending before updating the */ |
|||
/* pending list because things may have been pulled from the pending list */ |
|||
for(i = 0; i < num_modified; i++) { |
|||
j = inst_queue->modified_index[i]; |
|||
if(! inst_queue->pending[j]) { |
|||
inst_queue->pending[j] = MIF_TRUE; |
|||
inst_queue->pending_index[(inst_queue->num_pending)++] = j; |
|||
} |
|||
} |
|||
|
|||
/* Update the pending list and the next time by seeing if there */ |
|||
/* is anything at the location pointed to by current */ |
|||
next_time = 1e30; |
|||
num_pending = inst_queue->num_pending; |
|||
for(i = 0, j = 0; i < num_pending; i++) { |
|||
inst_index = inst_queue->pending_index[i]; |
|||
inst = *(inst_queue->current[inst_index]); |
|||
/* If nothing in queue at last_step, remove this index from the pending list */ |
|||
if(! inst) { |
|||
inst_queue->pending[inst_index] = MIF_FALSE; |
|||
(inst_queue->num_pending)--; |
|||
} |
|||
/* else, keep the index and update the next time */ |
|||
else { |
|||
inst_queue->pending_index[j] = inst_queue->pending_index[i]; |
|||
j++; |
|||
event_time = inst->event_time; |
|||
if(event_time < next_time) |
|||
next_time = event_time; |
|||
} |
|||
} |
|||
inst_queue->next_time = next_time; |
|||
|
|||
/* Update the modified list by looking for any queued events */ |
|||
/* with posted time > last_time */ |
|||
for(i = 0, j = 0; i < num_modified; i++) { |
|||
|
|||
inst_index = inst_queue->modified_index[i]; |
|||
inst = *(inst_queue->last_step[inst_index]); |
|||
|
|||
while(inst) { |
|||
if(inst->posted_time > inst_queue->last_time) |
|||
break; |
|||
inst = inst->next; |
|||
} |
|||
|
|||
if(! inst) { |
|||
inst_queue->modified[inst_index] = MIF_FALSE; |
|||
(inst_queue->num_modified)--; |
|||
} |
|||
else { |
|||
inst_queue->modified_index[j] = inst_queue->modified_index[i]; |
|||
j++; |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
/* |
|||
EVTbackup_output_queue() |
|||
|
|||
Backup data in output queue. |
|||
*/ |
|||
|
|||
|
|||
|
|||
static void EVTbackup_output_queue( |
|||
CKTcircuit *ckt, /* the main circuit structure */ |
|||
double new_time) /* the time to backup to */ |
|||
{ |
|||
|
|||
int i; |
|||
int j; |
|||
|
|||
int num_modified; |
|||
int num_pending; |
|||
|
|||
int output_index; |
|||
|
|||
Evt_Output_Queue_t *output_queue; |
|||
|
|||
Evt_Output_Event_t **output_ptr; |
|||
Evt_Output_Event_t *output; |
|||
|
|||
double next_time; |
|||
double event_time; |
|||
|
|||
|
|||
/* Get pointers for quick access */ |
|||
output_queue = &(ckt->evt->queue.output); |
|||
|
|||
/* Loop through list of indexes modified since last accepted timepoint */ |
|||
/* and remove events with posted time > new_time */ |
|||
num_modified = output_queue->num_modified; |
|||
for(i = 0; i < num_modified; i++) { |
|||
|
|||
/* Get the output index */ |
|||
output_index = output_queue->modified_index[i]; |
|||
|
|||
/* Scan forward from last_step and cut out data with posted time */ |
|||
/* > new_time and add it to the free list */ |
|||
/* Also, unremove anything with removed time > new_time */ |
|||
|
|||
output_ptr = output_queue->last_step[output_index]; |
|||
output = *output_ptr; |
|||
|
|||
while(output) { |
|||
if(output->posted_time > new_time) { |
|||
*output_ptr = output->next; |
|||
output->next = output_queue->free[output_index]; |
|||
output_queue->free[output_index] = output; |
|||
output = *output_ptr; |
|||
} |
|||
else { |
|||
if(output->removed && (output->removed_time > new_time)) |
|||
output->removed = MIF_FALSE; |
|||
output_ptr = &(output->next); |
|||
output = *output_ptr; |
|||
} |
|||
} |
|||
|
|||
/* Scan forward from last_step and set current to first */ |
|||
/* event with event_time > new_time */ |
|||
|
|||
output_ptr = output_queue->last_step[output_index]; |
|||
output = *output_ptr; |
|||
|
|||
while(output) { |
|||
if(output->event_time > new_time) |
|||
break; |
|||
output_ptr = &((*output_ptr)->next); |
|||
output = *output_ptr; |
|||
} |
|||
output_queue->current[output_index] = output_ptr; |
|||
} |
|||
|
|||
/* Add set of items modified to set of items pending before updating the */ |
|||
/* pending list because things may have been pulled from the pending list */ |
|||
for(i = 0; i < num_modified; i++) { |
|||
j = output_queue->modified_index[i]; |
|||
if(! output_queue->pending[j]) { |
|||
output_queue->pending[j] = MIF_TRUE; |
|||
output_queue->pending_index[(output_queue->num_pending)++] = j; |
|||
} |
|||
} |
|||
|
|||
/* Update the pending list and the next time by seeing if there */ |
|||
/* is anything at the location pointed to by current */ |
|||
next_time = 1e30; |
|||
num_pending = output_queue->num_pending; |
|||
for(i = 0, j = 0; i < num_pending; i++) { |
|||
output_index = output_queue->pending_index[i]; |
|||
output = *(output_queue->current[output_index]); |
|||
/* If nothing in queue at last_step, remove this index from the pending list */ |
|||
if(! output) { |
|||
output_queue->pending[output_index] = MIF_FALSE; |
|||
(output_queue->num_pending)--; |
|||
} |
|||
/* else, keep the index and update the next time */ |
|||
else { |
|||
output_queue->pending_index[j] = output_queue->pending_index[i]; |
|||
j++; |
|||
event_time = output->event_time; |
|||
if(event_time < next_time) |
|||
next_time = event_time; |
|||
} |
|||
} |
|||
output_queue->next_time = next_time; |
|||
|
|||
/* Update the modified list by looking for any queued events */ |
|||
/* with posted time > last_time */ |
|||
for(i = 0, j = 0; i < num_modified; i++) { |
|||
|
|||
output_index = output_queue->modified_index[i]; |
|||
output = *(output_queue->last_step[output_index]); |
|||
|
|||
while(output) { |
|||
if(output->posted_time > output_queue->last_time) |
|||
break; |
|||
output = output->next; |
|||
} |
|||
|
|||
if(! output) { |
|||
output_queue->modified[output_index] = MIF_FALSE; |
|||
(output_queue->num_modified)--; |
|||
} |
|||
else { |
|||
output_queue->modified_index[j] = output_queue->modified_index[i]; |
|||
j++; |
|||
} |
|||
} |
|||
} |
|||
@ -1,78 +0,0 @@ |
|||
/*============================================================================ |
|||
FILE EVTcall_hybrids.c |
|||
|
|||
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 |
|||
|
|||
<date> <person name> <nature of modifications> |
|||
|
|||
SUMMARY |
|||
|
|||
This file contains function EVTcall_hybrids which calls all models |
|||
which have both analog and event-driven ports. It is called following |
|||
successful evaluation of an analog iteration attempt to allow |
|||
events to be scheduled by the hybrid models. The 'CALL_TYPE' is set |
|||
to 'EVENT_DRIVEN' when the model is called from this function. |
|||
|
|||
INTERFACES |
|||
|
|||
void EVTcall_hybrids(CKTcircuit *ckt) |
|||
|
|||
REFERENCED FILES |
|||
|
|||
None. |
|||
|
|||
NON-STANDARD FEATURES |
|||
|
|||
None. |
|||
|
|||
============================================================================*/ |
|||
|
|||
|
|||
#include "ngspice.h" |
|||
#include "cktdefs.h" |
|||
|
|||
#include "evt.h" |
|||
|
|||
#include "evtproto.h" |
|||
|
|||
|
|||
/* |
|||
EVTcall_hybrids |
|||
|
|||
This function calls all the hybrid instances. It is called following |
|||
the successful evaluation of an analog iteration. |
|||
*/ |
|||
|
|||
|
|||
void EVTcall_hybrids( |
|||
CKTcircuit *ckt) /* the main circuit structure */ |
|||
{ |
|||
|
|||
int i; |
|||
int num_hybrids; |
|||
|
|||
int *hybrid_index; |
|||
|
|||
|
|||
/* Get needed data for fast access */ |
|||
num_hybrids = ckt->evt->counts.num_hybrids; |
|||
hybrid_index = ckt->evt->info.hybrid_index; |
|||
|
|||
/* Call EVTload for all hybrids */ |
|||
for(i = 0; i < num_hybrids; i++) |
|||
EVTload(ckt, hybrid_index[i]); |
|||
|
|||
} |
|||
@ -1,366 +0,0 @@ |
|||
/*============================================================================ |
|||
FILE EVTdequeue.c |
|||
|
|||
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 |
|||
|
|||
<date> <person name> <nature of modifications> |
|||
|
|||
SUMMARY |
|||
|
|||
This file contains function EVTdequeue which removes any items on the |
|||
output and instance queues with event times matching the specified |
|||
simulation time. |
|||
|
|||
INTERFACES |
|||
|
|||
void EVTdequeue(CKTcircuit *ckt, double time) |
|||
|
|||
REFERENCED FILES |
|||
|
|||
None. |
|||
|
|||
NON-STANDARD FEATURES |
|||
|
|||
None. |
|||
|
|||
============================================================================*/ |
|||
|
|||
#include <stdio.h> |
|||
|
|||
#include "ngspice.h" |
|||
|
|||
#include "cktdefs.h" |
|||
//#include "util.h" |
|||
|
|||
#include "mif.h" |
|||
#include "evt.h" |
|||
#include "evtudn.h" |
|||
|
|||
#include "evtproto.h" |
|||
|
|||
|
|||
static void EVTdequeue_output(CKTcircuit *ckt, double time); |
|||
static void EVTdequeue_inst(CKTcircuit *ckt, double time); |
|||
|
|||
static void EVTprocess_output( |
|||
CKTcircuit *ckt, |
|||
int output_index, |
|||
void *value); |
|||
|
|||
|
|||
/* |
|||
EVTdequeue |
|||
|
|||
This function removes any items on the output and instance queues |
|||
with event times matching the specified simulation time. EVTiter |
|||
is then called to determine which instances need to be called. |
|||
|
|||
*/ |
|||
|
|||
|
|||
void EVTdequeue( |
|||
CKTcircuit *ckt, /* The circuit structure */ |
|||
double time) /* The event time of the events to dequeue */ |
|||
{ |
|||
|
|||
/* Take all items on output queue with matching time */ |
|||
/* and set changed flags in output queue */ |
|||
EVTdequeue_output(ckt, time); |
|||
|
|||
/* Take all items on inst queue with matching time */ |
|||
/* and set to_call flags in inst queue */ |
|||
EVTdequeue_inst(ckt, time); |
|||
|
|||
} |
|||
|
|||
|
|||
/* |
|||
EVTdequeue_output |
|||
|
|||
This function de-queues output events with times matching the |
|||
specified time. |
|||
*/ |
|||
|
|||
static void EVTdequeue_output( |
|||
CKTcircuit *ckt, /* The circuit structure */ |
|||
double time) /* The event time of the events to dequeue */ |
|||
{ |
|||
|
|||
int i; |
|||
int j; |
|||
|
|||
int num_pending; |
|||
int index; |
|||
int output_index; |
|||
|
|||
double next_time; |
|||
double event_time; |
|||
|
|||
Evt_Output_Queue_t *output_queue; |
|||
|
|||
Evt_Output_Event_t *output; |
|||
Evt_Output_Event_t **output_ptr; |
|||
|
|||
|
|||
/* Get pointers for fast access */ |
|||
output_queue = &(ckt->evt->queue.output); |
|||
|
|||
/* Exit if nothing pending on output queue or if next_time */ |
|||
/* != specified time */ |
|||
if(output_queue->num_pending == 0) |
|||
return; |
|||
if(output_queue->next_time != time) |
|||
return; |
|||
|
|||
/* Scan the list of outputs pending */ |
|||
num_pending = output_queue->num_pending; |
|||
for(i = 0; i < num_pending; i++) { |
|||
|
|||
/* Get the index of the output */ |
|||
index = output_queue->pending_index[i]; |
|||
|
|||
/* Get pointer to next event in queue at this index */ |
|||
output = *(output_queue->current[index]); |
|||
|
|||
/* If event time does not match current time, skip */ |
|||
if(output->event_time != time) |
|||
continue; |
|||
|
|||
/* It must match, so pull the event from the queue and process it */ |
|||
EVTprocess_output(ckt, index, output->value); |
|||
|
|||
/* Move current to point to next non-removed item in list */ |
|||
output_ptr = &(output->next); |
|||
output = *output_ptr; |
|||
while(output) { |
|||
if(! output->removed) |
|||
break; |
|||
output_ptr = &(output->next); |
|||
output = *output_ptr; |
|||
} |
|||
output_queue->current[index] = output_ptr; |
|||
|
|||
/* Mark that this index in the queue has been modified */ |
|||
if(! output_queue->modified[index]) { |
|||
output_queue->modified[index] = MIF_TRUE; |
|||
output_queue->modified_index[(output_queue->num_modified)++] = index; |
|||
} |
|||
} |
|||
|
|||
|
|||
/* Update/compact the pending list and update the next_time */ |
|||
next_time = 1e30; |
|||
for(i = 0, j = 0; i < num_pending; i++) { |
|||
output_index = output_queue->pending_index[i]; |
|||
output = *(output_queue->current[output_index]); |
|||
/* If nothing in queue at last_step, remove this index from the pending list */ |
|||
if(! output) { |
|||
output_queue->pending[output_index] = MIF_FALSE; |
|||
(output_queue->num_pending)--; |
|||
} |
|||
/* else, keep the index and update the next time */ |
|||
else { |
|||
output_queue->pending_index[j] = output_queue->pending_index[i]; |
|||
j++; |
|||
event_time = output->event_time; |
|||
if(event_time < next_time) |
|||
next_time = event_time; |
|||
} |
|||
} |
|||
output_queue->next_time = next_time; |
|||
|
|||
|
|||
} |
|||
|
|||
|
|||
|
|||
/* |
|||
EVTdequeue_inst |
|||
|
|||
This function de-queues instance events with times matching the |
|||
specified time. |
|||
*/ |
|||
|
|||
|
|||
void EVTdequeue_inst( |
|||
CKTcircuit *ckt, /* The circuit structure */ |
|||
double time) /* The event time of the events to dequeue */ |
|||
{ |
|||
|
|||
int i; |
|||
int j; |
|||
|
|||
int num_pending; |
|||
int index; |
|||
int inst_index; |
|||
|
|||
double next_time; |
|||
double event_time; |
|||
|
|||
Evt_Inst_Queue_t *inst_queue; |
|||
|
|||
Evt_Inst_Event_t *inst; |
|||
|
|||
|
|||
/* Get pointers for fast access */ |
|||
inst_queue = &(ckt->evt->queue.inst); |
|||
|
|||
/* Exit if nothing pending on inst queue or if next_time */ |
|||
/* != specified time */ |
|||
if(inst_queue->num_pending == 0) |
|||
return; |
|||
if(inst_queue->next_time != time) |
|||
return; |
|||
|
|||
/* Scan the list of insts pending */ |
|||
num_pending = inst_queue->num_pending; |
|||
for(i = 0; i < num_pending; i++) { |
|||
|
|||
/* Get the index of the inst */ |
|||
index = inst_queue->pending_index[i]; |
|||
|
|||
/* Get pointer to next event in queue at this index */ |
|||
inst = *(inst_queue->current[index]); |
|||
|
|||
/* If event time does not match current time, skip */ |
|||
if(inst->event_time != time) |
|||
continue; |
|||
|
|||
/* It must match, so pull the event from the queue and process it */ |
|||
if(! inst_queue->to_call[index]) { |
|||
inst_queue->to_call[index] = MIF_TRUE; |
|||
inst_queue->to_call_index[(inst_queue->num_to_call)++] = |
|||
index; |
|||
} |
|||
|
|||
/* Move current to point to next item in list */ |
|||
inst_queue->current[index] = &(inst->next); |
|||
|
|||
/* Mark that this index in the queue has been modified */ |
|||
if(! inst_queue->modified[index]) { |
|||
inst_queue->modified[index] = MIF_TRUE; |
|||
inst_queue->modified_index[(inst_queue->num_modified)++] = index; |
|||
} |
|||
} |
|||
|
|||
|
|||
/* Update/compact the pending list and update the next_time */ |
|||
next_time = 1e30; |
|||
for(i = 0, j = 0; i < num_pending; i++) { |
|||
inst_index = inst_queue->pending_index[i]; |
|||
inst = *(inst_queue->current[inst_index]); |
|||
/* If nothing in queue at last_step, remove this index from the pending list */ |
|||
if(! inst) { |
|||
inst_queue->pending[inst_index] = MIF_FALSE; |
|||
(inst_queue->num_pending)--; |
|||
} |
|||
/* else, keep the index and update the next time */ |
|||
else { |
|||
inst_queue->pending_index[j] = inst_queue->pending_index[i]; |
|||
j++; |
|||
event_time = inst->event_time; |
|||
if(event_time < next_time) |
|||
next_time = event_time; |
|||
} |
|||
} |
|||
inst_queue->next_time = next_time; |
|||
|
|||
|
|||
|
|||
} |
|||
|
|||
|
|||
|
|||
/* |
|||
EVTprocess_output |
|||
|
|||
This function processes a specified output after it is pulled |
|||
from the queue. |
|||
*/ |
|||
|
|||
|
|||
static void EVTprocess_output( |
|||
CKTcircuit *ckt, /* The circuit structure */ |
|||
int output_index, /* The index of the output to process */ |
|||
void *value) /* The output value */ |
|||
{ |
|||
|
|||
int num_outputs; |
|||
int node_index; |
|||
int udn_index; |
|||
int output_subindex; |
|||
|
|||
Evt_Output_Info_t **output_table; |
|||
Evt_Node_Info_t **node_table; |
|||
|
|||
Evt_Node_t *rhs; |
|||
Evt_Node_t *rhsold; |
|||
|
|||
Evt_Output_Queue_t *output_queue; |
|||
|
|||
Mif_Boolean_t equal; |
|||
|
|||
|
|||
output_table = ckt->evt->info.output_table; |
|||
node_table = ckt->evt->info.node_table; |
|||
|
|||
node_index = output_table[output_index]->node_index; |
|||
num_outputs = node_table[node_index]->num_outputs; |
|||
udn_index = node_table[node_index]->udn_index; |
|||
|
|||
rhs = ckt->evt->data.node->rhs; |
|||
rhsold = ckt->evt->data.node->rhsold; |
|||
|
|||
/* Determine if output is different from rhsold value */ |
|||
/* and copy it to rhs AND rhsold if so */ |
|||
/* This is somewhat inefficient, but that's the way */ |
|||
/* we have setup the structures (rhs and rhsold must match)... */ |
|||
if(num_outputs > 1) { |
|||
output_subindex = output_table[output_index]->output_subindex; |
|||
(*(g_evt_udn_info[udn_index]->compare)) |
|||
(value, |
|||
rhsold[node_index].output_value[output_subindex], |
|||
&equal); |
|||
if(! equal) { |
|||
(*(g_evt_udn_info[udn_index]->copy)) |
|||
(value, rhs[node_index].output_value[output_subindex]); |
|||
(*(g_evt_udn_info[udn_index]->copy)) |
|||
(value, rhsold[node_index].output_value[output_subindex]); |
|||
} |
|||
} |
|||
else { |
|||
(*(g_evt_udn_info[udn_index]->compare)) |
|||
(value, |
|||
rhsold[node_index].node_value, |
|||
&equal); |
|||
if(! equal) { |
|||
(*(g_evt_udn_info[udn_index]->copy)) |
|||
(value, rhs[node_index].node_value); |
|||
(*(g_evt_udn_info[udn_index]->copy)) |
|||
(value, rhsold[node_index].node_value); |
|||
} |
|||
} |
|||
|
|||
/* If different, put in changed list of output queue */ |
|||
if(! equal) { |
|||
output_queue = &(ckt->evt->queue.output); |
|||
if(! output_queue->changed[output_index]) { |
|||
output_queue->changed[output_index] = MIF_TRUE; |
|||
output_queue->changed_index[(output_queue->num_changed)++] = |
|||
output_index; |
|||
} |
|||
} |
|||
} |
|||
@ -1,350 +0,0 @@ |
|||
/*============================================================================ |
|||
FILE EVTdump.c |
|||
|
|||
MEMBER OF process XSPICE |
|||
|
|||
Copyright 1991 |
|||
Georgia Tech Research Corporation |
|||
Atlanta, Georgia 30332 |
|||
All Rights Reserved |
|||
|
|||
PROJECT A-8503 |
|||
|
|||
AUTHORS |
|||
|
|||
6/15/92 Bill Kuhn |
|||
|
|||
MODIFICATIONS |
|||
|
|||
<date> <person name> <nature of modifications> |
|||
|
|||
SUMMARY |
|||
|
|||
This file contains functions used |
|||
to send event-driven node results data to the IPC channel when |
|||
the simulator is used with CAE software. |
|||
|
|||
INTERFACES |
|||
|
|||
EVTdump() |
|||
|
|||
REFERENCED FILES |
|||
|
|||
None. |
|||
|
|||
NON-STANDARD FEATURES |
|||
|
|||
None. |
|||
|
|||
============================================================================*/ |
|||
|
|||
|
|||
#include <stdio.h> |
|||
#include <string.h> |
|||
|
|||
#include "ngspice.h" |
|||
//#include "misc.h" |
|||
|
|||
#include "cktdefs.h" |
|||
//#include "util.h" |
|||
#include "sperror.h" |
|||
|
|||
#include "mif.h" |
|||
#include "evt.h" |
|||
#include "evtproto.h" |
|||
#include "evtudn.h" |
|||
|
|||
#include "ipc.h" |
|||
#include "ipctiein.h" |
|||
#include "ipcproto.h" |
|||
|
|||
|
|||
|
|||
static void EVTsend_line( |
|||
int ipc_index, /* The index used in the dictionary */ |
|||
double step, /* The analysis step */ |
|||
void *node_value, /* The node value */ |
|||
int udn_index); /* The user-defined node index */ |
|||
|
|||
|
|||
|
|||
/* |
|||
EVTdump |
|||
|
|||
This function is called to send event-driven node data to the IPC |
|||
channel. A ``mode'' argument determines how the data is located in |
|||
the event data structure and what data is sent. |
|||
|
|||
If the mode is DCOP, then this is necessarily the first call to |
|||
the function. In this case, the set of event-driven nodes is |
|||
scanned to determine which should be sent. Only nodes that are |
|||
not inside subcircuits are sent. Next, the function sends |
|||
a ``dictionary'' of node names/types vs. node indexes. |
|||
Finally, the function sends the DC operating point solutions |
|||
for the event-driven nodes in the dictionary. |
|||
|
|||
If the mode is DCTRCURVE, it is assumed that the function has |
|||
already been called with mode = DCOP. The function scans the solution |
|||
vector and sends data for any nodes that have changed. |
|||
|
|||
If the mode is TRAN, it is assumed that the function has already |
|||
been called once with mode = DCOP. The function scans the |
|||
event data for nodes that have changed since the last accepted |
|||
analog timepoint and sends the new data. |
|||
|
|||
Note: This function must be called BEFORE calling EVTop_save or |
|||
EVTaccept() so that the state of the node data structure will allow |
|||
it to determine what has changed. |
|||
*/ |
|||
|
|||
|
|||
typedef struct evtdump_s { |
|||
Mif_Boolean_t send; /* True if this node should be sent */ |
|||
int ipc_index; /* Index for this node in dict sent to CAE system */ |
|||
char *node_name_str; /* Node name */ |
|||
char *udn_type_str; /* UDN type */ |
|||
} evtdump_dict_t; |
|||
|
|||
|
|||
|
|||
void EVTdump( |
|||
CKTcircuit *ckt, /* The circuit structure */ |
|||
Ipc_Anal_t mode, /* The analysis mode for this call */ |
|||
double step) /* The sweep step for a DCTRCURVE analysis, or */ |
|||
/* 0.0 for DCOP and TRAN */ |
|||
{ |
|||
static evtdump_dict_t *node_dict = NULL; |
|||
static int num_send_nodes; |
|||
|
|||
int i; |
|||
int j; |
|||
int num_nodes; |
|||
int num_modified; |
|||
int index; |
|||
|
|||
char *name; |
|||
int name_len; |
|||
|
|||
Mif_Boolean_t firstcall; |
|||
|
|||
Evt_Node_Data_t *node_data; |
|||
|
|||
Evt_Node_t *rhsold; |
|||
Evt_Node_t **head; |
|||
Evt_Node_t *here; |
|||
|
|||
Evt_Node_Info_t **node_table; |
|||
|
|||
char buff[10000]; |
|||
|
|||
Mif_Boolean_t equal; |
|||
|
|||
|
|||
/* Return immediately if IPC is not enabled */ |
|||
if(! g_ipc.enabled) |
|||
return; |
|||
|
|||
/* Get number of event-driven nodes */ |
|||
num_nodes = ckt->evt->counts.num_nodes; |
|||
|
|||
/* Exit immediately if no event-driven nodes in circuit */ |
|||
if(num_nodes <= 0) |
|||
return; |
|||
|
|||
|
|||
/* Get pointers for fast access to event data */ |
|||
node_data = ckt->evt->data.node; |
|||
node_table = ckt->evt->info.node_table; |
|||
rhsold = node_data->rhsold; |
|||
head = node_data->head; |
|||
|
|||
|
|||
/* Determine if this is the first call */ |
|||
if(node_dict == NULL) |
|||
firstcall = MIF_TRUE; |
|||
else |
|||
firstcall = MIF_FALSE; |
|||
|
|||
|
|||
/* If this is the first call, get the dictionary info */ |
|||
if(firstcall) { |
|||
|
|||
/* Allocate local data structure used to process nodes */ |
|||
node_dict = (void *) MALLOC(num_nodes * sizeof(evtdump_dict_t)); |
|||
|
|||
/* Loop through all nodes to determine which nodes should be sent. */ |
|||
/* Only nodes not within subcircuits qualify. */ |
|||
|
|||
num_send_nodes = 0; |
|||
for(i = 0; i < num_nodes; i++) { |
|||
|
|||
/* Get the name of the node. */ |
|||
name = node_table[i]->name; |
|||
|
|||
/* If name is in a subcircuit, mark that node should not be sent */ |
|||
/* and continue to next node. */ |
|||
name_len = strlen(name); |
|||
for(j = 0; j < name_len; j++) { |
|||
if(name[j] == ':') |
|||
break; |
|||
} |
|||
if(j < name_len) { |
|||
node_dict[i].send = MIF_FALSE; |
|||
continue; |
|||
} |
|||
|
|||
/* Otherwise, fill in info in dictionary. */ |
|||
node_dict[i].send = MIF_TRUE; |
|||
node_dict[i].ipc_index = num_send_nodes; |
|||
node_dict[i].node_name_str = name; |
|||
node_dict[i].udn_type_str = g_evt_udn_info[node_table[i]->udn_index]->name; |
|||
|
|||
/* Increment the count of nodes to be sent. */ |
|||
num_send_nodes++; |
|||
} /* end for */ |
|||
} /* end if first call */ |
|||
|
|||
|
|||
/* Exit if there are no nodes to be sent */ |
|||
if(num_send_nodes <= 0) |
|||
return; |
|||
|
|||
|
|||
/* If this is the first call, send the dictionary */ |
|||
if(firstcall) { |
|||
ipc_send_evtdict_prefix(); |
|||
for(i = 0; i < num_nodes; i++) { |
|||
if(node_dict[i].send) { |
|||
sprintf(buff, "%d %s %s", node_dict[i].ipc_index, |
|||
node_dict[i].node_name_str, |
|||
node_dict[i].udn_type_str); |
|||
ipc_send_line(buff); |
|||
} |
|||
} |
|||
ipc_send_evtdict_suffix(); |
|||
} |
|||
|
|||
/* If this is the first call, send the operating point solution */ |
|||
/* and return. */ |
|||
if(firstcall) { |
|||
ipc_send_evtdata_prefix(); |
|||
for(i = 0; i < num_nodes; i++) { |
|||
if(node_dict[i].send) { |
|||
EVTsend_line(node_dict[i].ipc_index, |
|||
step, |
|||
rhsold[i].node_value, |
|||
node_table[i]->udn_index); |
|||
} |
|||
} |
|||
ipc_send_evtdata_suffix(); |
|||
return; |
|||
} |
|||
|
|||
/* Otherwise, this must be DCTRCURVE or TRAN mode and we need to */ |
|||
/* send only stuff that has changed since the last call. */ |
|||
/* The determination of what to send is modeled after code in */ |
|||
/* EVTop_save() for DCTRCURVE and EVTaccept() for TRAN. */ |
|||
|
|||
if(mode == IPC_ANAL_DCTRCURVE) { |
|||
/* Send data prefix */ |
|||
ipc_send_evtdata_prefix(); |
|||
/* Loop through event nodes */ |
|||
for(i = 0; i < num_nodes; i++) { |
|||
/* If dictionary indicates this node should be sent */ |
|||
if(node_dict[i].send) { |
|||
/* Locate end of node data */ |
|||
here = head[i]; |
|||
for(;;) { |
|||
if(here->next) |
|||
here = here->next; |
|||
else |
|||
break; |
|||
} |
|||
/* Compare entry at end of list to rhsold */ |
|||
(*(g_evt_udn_info[node_table[i]->udn_index]->compare)) ( |
|||
rhsold[i].node_value, |
|||
here->node_value, |
|||
&equal); |
|||
/* If value in rhsold is different, send it */ |
|||
if(!equal) { |
|||
EVTsend_line(node_dict[i].ipc_index, |
|||
step, |
|||
rhsold[i].node_value, |
|||
node_table[i]->udn_index); |
|||
} |
|||
} |
|||
} |
|||
/* Send data suffix and return */ |
|||
ipc_send_evtdata_suffix(); |
|||
return; |
|||
} |
|||
|
|||
|
|||
if(mode == IPC_ANAL_TRAN) { |
|||
/* Send data prefix */ |
|||
ipc_send_evtdata_prefix(); |
|||
/* Loop through list of nodes modified since last time */ |
|||
num_modified = node_data->num_modified; |
|||
for(i = 0; i < num_modified; i++) { |
|||
/* Get the index of the node modified */ |
|||
index = node_data->modified_index[i]; |
|||
/* If dictionary indicates this node should be sent */ |
|||
if(node_dict[index].send) { |
|||
/* Scan through new events and send the data for each event */ |
|||
here = *(node_data->last_step[index]); |
|||
while((here = here->next)) { |
|||
EVTsend_line(node_dict[index].ipc_index, |
|||
here->step, |
|||
here->node_value, |
|||
node_table[index]->udn_index); |
|||
} |
|||
} |
|||
} |
|||
/* Send data suffix and return */ |
|||
ipc_send_evtdata_suffix(); |
|||
return; |
|||
} |
|||
|
|||
} |
|||
|
|||
|
|||
|
|||
/* |
|||
EVTsend_line |
|||
|
|||
This function formats the event node data and sends it to the IPC channel. |
|||
*/ |
|||
|
|||
|
|||
static void EVTsend_line( |
|||
int ipc_index, /* The index used in the dictionary */ |
|||
double step, /* The analysis step */ |
|||
void *node_value, /* The node value */ |
|||
int udn_index) /* The user-defined node index */ |
|||
{ |
|||
double dvalue; |
|||
char *svalue; |
|||
void *pvalue; |
|||
int len; |
|||
|
|||
/* Get the data to send */ |
|||
if(g_evt_udn_info[udn_index]->plot_val) |
|||
(*(g_evt_udn_info[udn_index]->plot_val)) (node_value, "", &dvalue); |
|||
else |
|||
dvalue = 0.0; |
|||
|
|||
if(g_evt_udn_info[udn_index]->print_val) |
|||
(*(g_evt_udn_info[udn_index]->print_val)) (node_value, "", &svalue); |
|||
else |
|||
svalue = ""; |
|||
|
|||
if(g_evt_udn_info[udn_index]->ipc_val) |
|||
(*(g_evt_udn_info[udn_index]->ipc_val)) (node_value, &pvalue, &len); |
|||
else { |
|||
pvalue = NULL; |
|||
len = 0; |
|||
} |
|||
|
|||
/* Send it to the IPC channel */ |
|||
ipc_send_event(ipc_index, step, dvalue, svalue, pvalue, len); |
|||
} |
|||
@ -1,437 +0,0 @@ |
|||
/*============================================================================ |
|||
FILE EVTinit.c |
|||
|
|||
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 |
|||
|
|||
<date> <person name> <nature of modifications> |
|||
|
|||
SUMMARY |
|||
|
|||
This file contains function EVTinit which allocates and initializes |
|||
evt structure elements after the number of instances, nodes, etc. |
|||
have been determined in parsing during INPpas2. EVTinit also checks |
|||
to be sure no nodes have been used for both analog and event-driven |
|||
algorithms simultaneously. |
|||
|
|||
INTERFACES |
|||
|
|||
int EVTinit(CKTcircuit *ckt) |
|||
|
|||
REFERENCED FILES |
|||
|
|||
None. |
|||
|
|||
NON-STANDARD FEATURES |
|||
|
|||
None. |
|||
|
|||
============================================================================*/ |
|||
|
|||
#include <string.h> |
|||
#include <stdio.h> |
|||
#include "ngspice.h" |
|||
#include "cktdefs.h" |
|||
//#include "util.h" |
|||
#include "sperror.h" |
|||
|
|||
#include "evtproto.h" |
|||
|
|||
|
|||
|
|||
static int EVTcheck_nodes(CKTcircuit *ckt); |
|||
static int EVTcount_hybrids(CKTcircuit *ckt); |
|||
static int EVTinit_info(CKTcircuit *ckt); |
|||
static int EVTinit_queue(CKTcircuit *ckt); |
|||
static int EVTinit_limits(CKTcircuit *ckt); |
|||
|
|||
|
|||
|
|||
/* Allocation macro with built-in check for out-of-memory */ |
|||
/* Adapted from SPICE 3C1 code in CKTsetup.c */ |
|||
#define CKALLOC(var,size,type) \ |
|||
if(size) { \ |
|||
if(!(var = (void *) MALLOC((size) * sizeof(type)))) \ |
|||
return(E_NOMEM); \ |
|||
} |
|||
|
|||
|
|||
/* |
|||
EVTinit |
|||
|
|||
Allocate and initialize additional evt structure elements now that |
|||
we can determine the number of instances, nodes, etc. |
|||
|
|||
Also check to be sure that no nodes have been used in both event-driven |
|||
and analog domains. |
|||
|
|||
In this version, we also report an error if there are no hybrids in the |
|||
circuit. This restriction may be removed in the future to allow the |
|||
simulator to be used with digital only circuits... |
|||
*/ |
|||
|
|||
|
|||
int EVTinit( |
|||
CKTcircuit *ckt) /* the circuit structure */ |
|||
{ |
|||
|
|||
int err; /* SPICE error return code 0 = OK */ |
|||
|
|||
/* static char *err_no_hybrids = "ERROR - no hybrids found in input deck";*/ |
|||
|
|||
|
|||
/* Exit immediately if there are no event-driven instances */ |
|||
/* but don't complain */ |
|||
if(ckt->evt->counts.num_insts == 0) |
|||
return(OK); |
|||
|
|||
/* Count the number of hybrids and hybrid outputs */ |
|||
err = EVTcount_hybrids(ckt); |
|||
if(err) |
|||
return(err); |
|||
|
|||
/* Exit with error if there are no hybrids in the circuit. */ |
|||
/* Will probably remove this restriction later... */ |
|||
/* |
|||
if(ckt->evt->counts.num_hybrids == 0) { |
|||
errMsg = MALLOC(strlen(err_no_hybrids) + 1); |
|||
strcpy(errMsg, err_no_hybrids); |
|||
return(E_PRIVATE); |
|||
} |
|||
*/ |
|||
/* Check that event nodes have not been used as analog nodes also */ |
|||
err = EVTcheck_nodes(ckt); |
|||
if(err) |
|||
return(err); |
|||
|
|||
/* Create info table arrays */ |
|||
err = EVTinit_info(ckt); |
|||
if(err) |
|||
return(err); |
|||
|
|||
/* Setup queues */ |
|||
err = EVTinit_queue(ckt); |
|||
if(err) |
|||
return(err); |
|||
|
|||
/* Initialize limits */ |
|||
err = EVTinit_limits(ckt); |
|||
if(err) |
|||
return(err); |
|||
|
|||
/* Note: Options were initialized in CKTinit so that INPpas2 */ |
|||
/* could set values according to .options cards in deck. The */ |
|||
/* structure 'jobs' will be setup immediately prior to each */ |
|||
/* simulation job. The results data structure is also */ |
|||
/* allocated immediately prior to each simulation job. */ |
|||
|
|||
/* Return */ |
|||
return(OK); |
|||
} |
|||
|
|||
|
|||
/* |
|||
EVTcount_hybrids |
|||
|
|||
Count the number of hybrids and the number of outputs on all hybrids. |
|||
*/ |
|||
|
|||
static int EVTcount_hybrids( |
|||
CKTcircuit *ckt) /* The circuit structure */ |
|||
{ |
|||
|
|||
int i; |
|||
int j; |
|||
|
|||
int num_hybrids; |
|||
int num_hybrid_outputs; |
|||
int num_conn; |
|||
int num_port; |
|||
|
|||
MIFinstance *fast; |
|||
|
|||
Evt_Inst_Info_t *inst; |
|||
|
|||
|
|||
/* Count number of hybrids and hybrid outputs in the inst list */ |
|||
/* created during parsing. Note: other counts */ |
|||
/* are created during parsing, but these were */ |
|||
/* too difficult to do until now... */ |
|||
num_hybrids = 0; |
|||
num_hybrid_outputs = 0; |
|||
inst = ckt->evt->info.inst_list; |
|||
while(inst) { |
|||
fast = inst->inst_ptr; |
|||
if(fast->analog && fast->event_driven) { |
|||
num_hybrids++; |
|||
num_conn = fast->num_conn; |
|||
for(i = 0; i < num_conn; i++) { |
|||
if((! fast->conn[i]->is_null) && (fast->conn[i]->is_output)) { |
|||
num_port = fast->conn[i]->size; |
|||
for(j = 0; j < num_port; j++) |
|||
if(! fast->conn[i]->port[j]->is_null) |
|||
num_hybrid_outputs++; |
|||
} |
|||
} |
|||
} |
|||
inst = inst->next; |
|||
} |
|||
ckt->evt->counts.num_hybrids = num_hybrids; |
|||
ckt->evt->counts.num_hybrid_outputs = num_hybrid_outputs; |
|||
|
|||
return(OK); |
|||
} |
|||
|
|||
|
|||
/* |
|||
EVTcheck_nodes |
|||
|
|||
Report error if any event node name is also used as an analog node. |
|||
*/ |
|||
|
|||
|
|||
static int EVTcheck_nodes( |
|||
CKTcircuit *ckt) /* The circuit structure */ |
|||
{ |
|||
|
|||
CKTnode *analog_node; |
|||
Evt_Node_Info_t *event_node; |
|||
|
|||
static char *err_prefix = "ERROR - node "; |
|||
static char *err_collide = " cannot be both analog and digital"; |
|||
|
|||
|
|||
/* Report error if any analog node name matches any event node name */ |
|||
event_node = ckt->evt->info.node_list; |
|||
while(event_node) { |
|||
analog_node = ckt->CKTnodes; |
|||
while(analog_node) { |
|||
if(strcmp(event_node->name, analog_node->name) == 0) { |
|||
errMsg = MALLOC(strlen(err_prefix) + strlen(event_node->name) + |
|||
strlen(err_collide) + 1); |
|||
sprintf(errMsg, "%s%s%s", err_prefix, |
|||
event_node->name, |
|||
err_collide); |
|||
|
|||
fprintf(stdout,errMsg); |
|||
|
|||
return(E_PRIVATE); |
|||
} |
|||
analog_node = analog_node->next; |
|||
} |
|||
event_node = event_node->next; |
|||
} |
|||
|
|||
/* Return */ |
|||
return(OK); |
|||
} |
|||
|
|||
|
|||
/* |
|||
EVTinit_info |
|||
|
|||
This function creates the ``info'' pointer tables used in the |
|||
event-driven circuit representation. These arrays allow faster |
|||
access to data associated with instances, nodes, ports, and |
|||
outputs than could be provided by having to scan the linked-list |
|||
representations created during parsing. |
|||
*/ |
|||
|
|||
|
|||
static int EVTinit_info( |
|||
CKTcircuit *ckt) /* the circuit structure */ |
|||
{ |
|||
|
|||
int i; |
|||
int j; |
|||
|
|||
int num_insts; |
|||
int num_nodes; |
|||
int num_ports; |
|||
int num_outputs; |
|||
|
|||
Evt_Inst_Info_t *inst; |
|||
Evt_Node_Info_t *node; |
|||
Evt_Port_Info_t *port; |
|||
Evt_Output_Info_t *output; |
|||
|
|||
Evt_Inst_Info_t **inst_table; |
|||
Evt_Node_Info_t **node_table; |
|||
Evt_Port_Info_t **port_table; |
|||
Evt_Output_Info_t **output_table; |
|||
|
|||
int *hybrid_index; |
|||
|
|||
int num_hybrids; |
|||
|
|||
|
|||
/* Allocate and initialize table of inst pointers */ |
|||
num_insts = ckt->evt->counts.num_insts; |
|||
CKALLOC(inst_table, num_insts, void *) |
|||
inst = ckt->evt->info.inst_list; |
|||
for(i = 0; i < num_insts; i++) { |
|||
inst_table[i] = inst; |
|||
inst = inst->next; |
|||
} |
|||
ckt->evt->info.inst_table = inst_table; |
|||
|
|||
/* Allocate and initialize table of node pointers */ |
|||
num_nodes = ckt->evt->counts.num_nodes; |
|||
CKALLOC(node_table, num_nodes, void *) |
|||
node = ckt->evt->info.node_list; |
|||
for(i = 0; i < num_nodes; i++) { |
|||
node_table[i] = node; |
|||
node = node->next; |
|||
} |
|||
ckt->evt->info.node_table = node_table; |
|||
|
|||
/* Allocate and initialize table of port pointers */ |
|||
num_ports = ckt->evt->counts.num_ports; |
|||
CKALLOC(port_table, num_ports, void *) |
|||
port = ckt->evt->info.port_list; |
|||
for(i = 0; i < num_ports; i++) { |
|||
port_table[i] = port; |
|||
port = port->next; |
|||
} |
|||
ckt->evt->info.port_table = port_table; |
|||
|
|||
/* Allocate and initialize table of output pointers */ |
|||
num_outputs = ckt->evt->counts.num_outputs; |
|||
CKALLOC(output_table, num_outputs, void *) |
|||
output = ckt->evt->info.output_list; |
|||
for(i = 0; i < num_outputs; i++) { |
|||
output_table[i] = output; |
|||
output = output->next; |
|||
} |
|||
ckt->evt->info.output_table = output_table; |
|||
|
|||
|
|||
/* Allocate and create table of indexes into inst_table for hybrids */ |
|||
num_hybrids = ckt->evt->counts.num_hybrids; |
|||
CKALLOC(hybrid_index, num_hybrids, int) |
|||
for(i = 0, j = 0; i < num_insts; i++) { |
|||
if(inst_table[i]->inst_ptr->analog) |
|||
hybrid_index[j++] = i; |
|||
} |
|||
ckt->evt->info.hybrid_index = hybrid_index; |
|||
|
|||
|
|||
/* Return */ |
|||
return(OK); |
|||
} |
|||
|
|||
|
|||
|
|||
/* |
|||
EVTinit_queue |
|||
|
|||
This function prepares the event-driven queues for simulation. |
|||
*/ |
|||
|
|||
|
|||
static int EVTinit_queue( |
|||
CKTcircuit *ckt) /* the circuit structure */ |
|||
{ |
|||
|
|||
int num_insts; |
|||
int num_nodes; |
|||
int num_outputs; |
|||
|
|||
Evt_Inst_Queue_t *inst_queue; |
|||
Evt_Node_Queue_t *node_queue; |
|||
Evt_Output_Queue_t *output_queue; |
|||
|
|||
|
|||
/* Allocate elements in the inst queue */ |
|||
|
|||
num_insts = ckt->evt->counts.num_insts; |
|||
inst_queue = &(ckt->evt->queue.inst); |
|||
|
|||
CKALLOC(inst_queue->head, num_insts, void *) |
|||
CKALLOC(inst_queue->current, num_insts, void *) |
|||
CKALLOC(inst_queue->last_step, num_insts, void *) |
|||
CKALLOC(inst_queue->free, num_insts, void *) |
|||
CKALLOC(inst_queue->modified_index, num_insts, int) |
|||
CKALLOC(inst_queue->modified, num_insts, Mif_Boolean_t) |
|||
CKALLOC(inst_queue->pending_index, num_insts, int) |
|||
CKALLOC(inst_queue->pending, num_insts, Mif_Boolean_t) |
|||
CKALLOC(inst_queue->to_call_index, num_insts, int) |
|||
CKALLOC(inst_queue->to_call, num_insts, Mif_Boolean_t) |
|||
|
|||
|
|||
/* Allocate elements in the node queue */ |
|||
|
|||
num_nodes = ckt->evt->counts.num_nodes; |
|||
node_queue = &(ckt->evt->queue.node); |
|||
|
|||
CKALLOC(node_queue->to_eval_index, num_nodes, int) |
|||
CKALLOC(node_queue->to_eval, num_nodes, Mif_Boolean_t) |
|||
CKALLOC(node_queue->changed_index, num_nodes, int) |
|||
CKALLOC(node_queue->changed, num_nodes, Mif_Boolean_t) |
|||
|
|||
|
|||
/* Allocate elements in the output queue */ |
|||
|
|||
num_outputs = ckt->evt->counts.num_outputs; |
|||
output_queue = &(ckt->evt->queue.output); |
|||
|
|||
CKALLOC(output_queue->head, num_outputs, void *) |
|||
CKALLOC(output_queue->current, num_outputs, void *) |
|||
CKALLOC(output_queue->last_step, num_outputs, void *) |
|||
CKALLOC(output_queue->free, num_outputs, void *) |
|||
CKALLOC(output_queue->modified_index, num_outputs, int) |
|||
CKALLOC(output_queue->modified, num_outputs, Mif_Boolean_t) |
|||
CKALLOC(output_queue->pending_index, num_outputs, int) |
|||
CKALLOC(output_queue->pending, num_outputs, Mif_Boolean_t) |
|||
CKALLOC(output_queue->changed_index, num_outputs, int) |
|||
CKALLOC(output_queue->changed, num_outputs, Mif_Boolean_t) |
|||
|
|||
|
|||
/* Return */ |
|||
return(OK); |
|||
} |
|||
|
|||
|
|||
|
|||
|
|||
/* |
|||
EVTinit_limits |
|||
|
|||
This function initializes the iteration limits applicable to the |
|||
event-driven algorithm. |
|||
*/ |
|||
|
|||
|
|||
static int EVTinit_limits( |
|||
CKTcircuit *ckt) /* the circuit structure */ |
|||
{ |
|||
|
|||
/* Set maximum number of event load calls within a single event iteration */ |
|||
/* to the number of event outputs. This should allow for the */ |
|||
/* maximum possible number of events that can trickle through any */ |
|||
/* circuit that does not contain loops. */ |
|||
|
|||
ckt->evt->limits.max_event_passes = ckt->evt->counts.num_outputs + 1; |
|||
|
|||
|
|||
/* Set maximum number of alternations between analog and event-driven */ |
|||
/* iterations to the number of event outputs on hybrids. */ |
|||
|
|||
ckt->evt->limits.max_op_alternations = ckt->evt->counts.num_hybrid_outputs + 1; |
|||
|
|||
|
|||
/* Return */ |
|||
return(OK); |
|||
} |
|||
@ -1,300 +0,0 @@ |
|||
/*============================================================================ |
|||
FILE EVTiter.c |
|||
|
|||
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 |
|||
|
|||
<date> <person name> <nature of modifications> |
|||
|
|||
SUMMARY |
|||
|
|||
This file contains function EVTiter which iterates through |
|||
event-driven outputs and instances until the outputs no longer change. |
|||
|
|||
|
|||
INTERFACES |
|||
|
|||
int EVTiter(CKTcircuit *ckt) |
|||
|
|||
REFERENCED FILES |
|||
|
|||
None. |
|||
|
|||
NON-STANDARD FEATURES |
|||
|
|||
None. |
|||
|
|||
============================================================================*/ |
|||
|
|||
#include <stdio.h> |
|||
#include <string.h> |
|||
|
|||
#include "ngspice.h" |
|||
//#include "misc.h" |
|||
#include "cktdefs.h" |
|||
//#include "util.h" |
|||
#include "sperror.h" |
|||
|
|||
#include "mif.h" |
|||
#include "evt.h" |
|||
#include "evtudn.h" |
|||
|
|||
#include "evtproto.h" |
|||
|
|||
|
|||
/* |
|||
EVTiter |
|||
|
|||
This function iterates through event-driven outputs and instances |
|||
until the outputs no longer change. The general algorithm used |
|||
is: |
|||
|
|||
Do: |
|||
|
|||
Scan list of changed outputs |
|||
Put items on the node queue 'to_eval' list for |
|||
each changed output. |
|||
|
|||
Scan list of changed nodes |
|||
Resolve nodes with multiple outputs posted. |
|||
Create inverted state for nodes with attached |
|||
inverted inputs. |
|||
Put items on the instance queue 'to_call' list |
|||
for each changed node. |
|||
If transient analysis, put state of the node |
|||
into the node data structure. |
|||
|
|||
Scan instance to_call list |
|||
Call EVTload for each instance on list. |
|||
|
|||
While there are changed outputs |
|||
|
|||
*/ |
|||
|
|||
|
|||
int EVTiter( |
|||
CKTcircuit *ckt) /* the circuit structure */ |
|||
{ |
|||
|
|||
int i; |
|||
int num_changed; |
|||
|
|||
int num_to_eval; |
|||
int num_to_call; |
|||
|
|||
int output_index; |
|||
/* int output_subindex;*/ |
|||
int inst_index; |
|||
int node_index; |
|||
int port_index; |
|||
|
|||
int num_outputs; |
|||
int udn_index; |
|||
|
|||
int passes; |
|||
|
|||
Evt_Ckt_Data_t *evt; |
|||
|
|||
Evt_Output_Queue_t *output_queue; |
|||
Evt_Node_Queue_t *node_queue; |
|||
Evt_Inst_Queue_t *inst_queue; |
|||
|
|||
Evt_Output_Info_t **output_table; |
|||
Evt_Node_Info_t **node_table; |
|||
Evt_Port_Info_t **port_table; |
|||
|
|||
Evt_Inst_Index_t *inst_list; |
|||
|
|||
Evt_Node_Data_t *node_data; |
|||
|
|||
Evt_Node_t *rhs; |
|||
Evt_Node_t *rhsold; |
|||
|
|||
Evt_Node_t *node; |
|||
|
|||
Mif_Boolean_t equal; |
|||
|
|||
char *err_msg; |
|||
|
|||
|
|||
/* Get temporary pointers for fast access */ |
|||
evt = ckt->evt; |
|||
|
|||
output_queue = &(evt->queue.output); |
|||
node_queue = &(evt->queue.node); |
|||
inst_queue = &(evt->queue.inst); |
|||
|
|||
output_table = evt->info.output_table; |
|||
node_table = evt->info.node_table; |
|||
port_table = evt->info.port_table; |
|||
|
|||
node_data = evt->data.node; |
|||
rhs = node_data->rhs; |
|||
rhsold = node_data->rhsold; |
|||
|
|||
|
|||
/* Loop until no more output change, or too many passes through loop */ |
|||
for(passes = 0; passes < evt->limits.max_event_passes; passes++) { |
|||
|
|||
|
|||
/* Create list of nodes to evaluate from list of changed outputs */ |
|||
num_changed = output_queue->num_changed; |
|||
for(i = 0; i < num_changed; i++) { |
|||
|
|||
/* Get index of node that output is connected to */ |
|||
output_index = output_queue->changed_index[i]; |
|||
node_index = output_table[output_index]->node_index; |
|||
|
|||
/* If not already on list of nodes to evaluate, add it */ |
|||
if(! node_queue->to_eval[node_index]) { |
|||
node_queue->to_eval[node_index] = MIF_TRUE; |
|||
node_queue->to_eval_index[(node_queue->num_to_eval)++] |
|||
= node_index; |
|||
} |
|||
|
|||
/* Reset the changed flag on the output queue */ |
|||
output_queue->changed[output_index] = MIF_FALSE; |
|||
|
|||
} |
|||
output_queue->num_changed = 0; |
|||
|
|||
|
|||
|
|||
/* Evaluate nodes and for any which have changed, enter */ |
|||
/* the instances that receive inputs from them on the list */ |
|||
/* of instances to call */ |
|||
|
|||
num_to_eval = node_queue->num_to_eval; |
|||
for(i = 0; i < num_to_eval; i++) { |
|||
|
|||
/* Get the node index, udn index and number of outputs */ |
|||
node_index = node_queue->to_eval_index[i]; |
|||
udn_index = node_table[node_index]->udn_index; |
|||
num_outputs = node_table[node_index]->num_outputs; |
|||
|
|||
/* Resolve the node value if multiple outputs on it */ |
|||
/* and test if new node value is different than old value */ |
|||
if(num_outputs > 1) { |
|||
(*(g_evt_udn_info[udn_index]->resolve)) |
|||
(num_outputs, |
|||
rhs[node_index].output_value, |
|||
rhs[node_index].node_value); |
|||
(*(g_evt_udn_info[udn_index]->compare)) |
|||
(rhs[node_index].node_value, |
|||
rhsold[node_index].node_value, |
|||
&equal); |
|||
if(! equal) { |
|||
(*(g_evt_udn_info[udn_index]->copy)) |
|||
(rhs[node_index].node_value, |
|||
rhsold[node_index].node_value); |
|||
} |
|||
} |
|||
/* Else, load function has already determined that they were */ |
|||
/* not equal */ |
|||
else |
|||
equal = MIF_FALSE; |
|||
|
|||
/* If not equal, make inverted copy in rhsold if */ |
|||
/* needed, and place indexes of instances with inputs connected */ |
|||
/* to the node in the to_call list of inst queue */ |
|||
if(! equal) { |
|||
if(node_table[node_index]->invert) { |
|||
(*(g_evt_udn_info[udn_index]->copy)) |
|||
(rhsold[node_index].node_value, |
|||
rhsold[node_index].inverted_value); |
|||
(*(g_evt_udn_info[udn_index]->invert)) |
|||
(rhsold[node_index].inverted_value); |
|||
} |
|||
inst_list = node_table[node_index]->inst_list; |
|||
while(inst_list) { |
|||
inst_index = inst_list->index; |
|||
if(! inst_queue->to_call[inst_index]) { |
|||
inst_queue->to_call[inst_index] = MIF_TRUE; |
|||
inst_queue->to_call_index[(inst_queue->num_to_call)++] |
|||
= inst_index; |
|||
} |
|||
inst_list = inst_list->next; |
|||
} /* end while instances with inputs on node */ |
|||
} /* end if not equal */ |
|||
|
|||
/* If transient analysis mode */ |
|||
/* Save the node data onto the node results list and mark */ |
|||
/* that it has been modified, even if the */ |
|||
/* resolved node value has not changed */ |
|||
if(g_mif_info.circuit.anal_type == MIF_TRAN) { |
|||
|
|||
node = *(node_data->tail[node_index]); |
|||
node_data->tail[node_index] = &(node->next); |
|||
EVTnode_copy(ckt, node_index, &(rhsold[node_index]), &(node->next)); |
|||
node->next->step = g_mif_info.circuit.evt_step; |
|||
|
|||
if(! node_data->modified[node_index]) { |
|||
node_data->modified[node_index] = MIF_TRUE; |
|||
node_data->modified_index[(node_data->num_modified)++] = node_index; |
|||
} |
|||
} |
|||
|
|||
/* Reset the to_eval flag on the node queue */ |
|||
node_queue->to_eval[node_index] = MIF_FALSE; |
|||
|
|||
} /* end for number of nodes to evaluate */ |
|||
node_queue->num_to_eval = 0; |
|||
|
|||
|
|||
|
|||
/* Call the instances with inputs on nodes that have changed */ |
|||
num_to_call = inst_queue->num_to_call; |
|||
for(i = 0; i < num_to_call; i++) { |
|||
inst_index = inst_queue->to_call_index[i]; |
|||
inst_queue->to_call[inst_index] = MIF_FALSE; |
|||
EVTload(ckt, inst_index); |
|||
} |
|||
inst_queue->num_to_call = 0; |
|||
|
|||
|
|||
/* Record statistics */ |
|||
if(g_mif_info.circuit.anal_type == MIF_DC) |
|||
(ckt->evt->data.statistics->op_event_passes)++; |
|||
|
|||
|
|||
/* If no outputs changed, iteration is over, so return with success! */ |
|||
if(output_queue->num_changed == 0) |
|||
return(0); |
|||
|
|||
} /* end for */ |
|||
|
|||
|
|||
/* Too many passes through loop, report problems and exit with error */ |
|||
|
|||
err_msg = MALLOC(10000); |
|||
for(i = 0; i < output_queue->num_changed; i++) { |
|||
output_index = output_queue->changed_index[i]; |
|||
port_index = output_table[output_index]->port_index; |
|||
sprintf(err_msg, "\n Instance: %s\n Connection: %s\n Port: %d", |
|||
port_table[port_index]->inst_name, |
|||
port_table[port_index]->conn_name, |
|||
port_table[port_index]->port_num); |
|||
ENHreport_conv_prob(ENH_EVENT_NODE, |
|||
port_table[port_index]->node_name, |
|||
err_msg); |
|||
} |
|||
FREE(err_msg); |
|||
|
|||
(*(SPfrontEnd->IFerror)) (ERR_WARNING, |
|||
"Too many iteration passes in event-driven circuits", |
|||
(IFuid *) NULL); |
|||
return(E_ITERLIM); |
|||
|
|||
} |
|||
@ -1,613 +0,0 @@ |
|||
/*============================================================================ |
|||
FILE EVTload.c |
|||
|
|||
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 |
|||
|
|||
<date> <person name> <nature of modifications> |
|||
|
|||
SUMMARY |
|||
|
|||
This file contains function EVTload which is used to call a |
|||
specified event-driven or hybrid code model during an event-driven |
|||
iteration. The 'CALL_TYPE' is set to 'EVENT_DRIVEN' when the |
|||
model is called from this function. |
|||
|
|||
INTERFACES |
|||
|
|||
int EVTload(CKTcircuit *ckt, int inst_index) |
|||
|
|||
REFERENCED FILES |
|||
|
|||
None. |
|||
|
|||
NON-STANDARD FEATURES |
|||
|
|||
None. |
|||
|
|||
============================================================================*/ |
|||
|
|||
#include <stdio.h> |
|||
|
|||
#include "ngspice.h" |
|||
#include "cktdefs.h" |
|||
//#include "util.h" |
|||
#include "devdefs.h" |
|||
#include "sperror.h" |
|||
|
|||
#include "mif.h" |
|||
#include "evt.h" |
|||
#include "evtudn.h" |
|||
|
|||
#include "mifproto.h" |
|||
#include "evtproto.h" |
|||
|
|||
|
|||
|
|||
|
|||
extern SPICEdev **DEVices; |
|||
|
|||
|
|||
|
|||
static void EVTcreate_state( |
|||
CKTcircuit *ckt, |
|||
int inst_index); |
|||
|
|||
static void EVTadd_msg( |
|||
CKTcircuit *ckt, |
|||
int port_index, |
|||
char *msg_text); |
|||
|
|||
static void EVTcreate_output_event( |
|||
CKTcircuit *ckt, |
|||
int node_index, |
|||
int output_index, |
|||
void **value_ptr); |
|||
|
|||
static void EVTprocess_output( |
|||
CKTcircuit *ckt, |
|||
Mif_Boolean_t changed, |
|||
int output_index, |
|||
Mif_Boolean_t invert, |
|||
double delay); |
|||
|
|||
|
|||
|
|||
/* |
|||
EVTload |
|||
|
|||
This function calls the code model function for the specified |
|||
instance with CALL_TYPE set to EVENT_DRIVEN. Event outputs, |
|||
messages, etc. are processed on return from the code model. |
|||
Analog outputs, partials, etc. should not be computed by the |
|||
code model when the call type is event-driven and are |
|||
ignored. |
|||
*/ |
|||
|
|||
int EVTload( |
|||
CKTcircuit *ckt, /* The circuit structure */ |
|||
int inst_index) /* The instance to call code model for */ |
|||
{ |
|||
|
|||
int i; |
|||
int j; |
|||
|
|||
int num_conn; |
|||
int num_port; |
|||
int mod_type; |
|||
|
|||
Mif_Conn_Data_t *conn; |
|||
Mif_Port_Data_t *port; |
|||
|
|||
Mif_Private_t cm_data; |
|||
|
|||
MIFinstance *inst; |
|||
|
|||
Evt_Node_Data_t *node_data; |
|||
|
|||
void *value_ptr; |
|||
|
|||
|
|||
/* ***************************** */ |
|||
/* Prepare the code model inputs */ |
|||
/* ***************************** */ |
|||
|
|||
/* Get pointer to instance data structure and other data */ |
|||
/* needed for fast access */ |
|||
inst = ckt->evt->info.inst_table[inst_index]->inst_ptr; |
|||
node_data = ckt->evt->data.node; |
|||
|
|||
/* Setup circuit data in struct to be passed to code model function */ |
|||
|
|||
if(inst->initialized) |
|||
cm_data.circuit.init = MIF_FALSE; |
|||
else |
|||
cm_data.circuit.init = MIF_TRUE; |
|||
|
|||
cm_data.circuit.anal_init = MIF_FALSE; |
|||
cm_data.circuit.anal_type = g_mif_info.circuit.anal_type; |
|||
|
|||
if(g_mif_info.circuit.anal_type == MIF_TRAN) |
|||
cm_data.circuit.time = g_mif_info.circuit.evt_step; |
|||
else |
|||
cm_data.circuit.time = 0.0; |
|||
|
|||
cm_data.circuit.call_type = MIF_EVENT_DRIVEN; |
|||
cm_data.circuit.temperature = ckt->CKTtemp - 273.15; |
|||
|
|||
|
|||
/* Setup data needed by cm_... functions */ |
|||
|
|||
g_mif_info.ckt = ckt; |
|||
g_mif_info.instance = inst; |
|||
g_mif_info.errmsg = ""; |
|||
g_mif_info.circuit.call_type = MIF_EVENT_DRIVEN; |
|||
|
|||
if(inst->initialized) |
|||
g_mif_info.circuit.init = MIF_FALSE; |
|||
else |
|||
g_mif_info.circuit.init = MIF_TRUE; |
|||
|
|||
|
|||
/* If after initialization and in transient analysis mode */ |
|||
/* create a new state for the instance */ |
|||
|
|||
if((g_mif_info.circuit.anal_type == MIF_TRAN) && inst->initialized) |
|||
EVTcreate_state(ckt, inst_index); |
|||
|
|||
|
|||
/* Loop through all connections on the instance and setup */ |
|||
/* load, total_load, and msg on all ports, and changed flag */ |
|||
/* and output pointer on all outputs */ |
|||
|
|||
num_conn = inst->num_conn; |
|||
for(i = 0; i < num_conn; i++) { |
|||
|
|||
conn = inst->conn[i]; |
|||
|
|||
/* if connection is null, continue to next */ |
|||
if(conn->is_null) |
|||
continue; |
|||
|
|||
/* Loop through each port on the connection */ |
|||
num_port = conn->size; |
|||
for(j = 0; j < num_port; j++) { |
|||
|
|||
port = conn->port[j]; |
|||
|
|||
/* Skip if port is null */ |
|||
if(port->is_null) |
|||
continue; |
|||
|
|||
/* If port type is Digital or User-Defined */ |
|||
if((port->type == MIF_DIGITAL) || (port->type == MIF_USER_DEFINED)) { |
|||
|
|||
/* Initialize the msg pointer on the port to NULL, */ |
|||
/* initialize the load value to zero, and get the total load */ |
|||
port->msg = NULL; |
|||
port->load = 0.0; |
|||
port->total_load = node_data->total_load[port->evt_data.node_index]; |
|||
|
|||
/* If connection is an output, initialize changed to true */ |
|||
/* and create a new output event object in the free list */ |
|||
/* if transient analysis mode */ |
|||
if(conn->is_output) { |
|||
port->changed = MIF_TRUE; |
|||
if(g_mif_info.circuit.anal_type == MIF_TRAN) { |
|||
EVTcreate_output_event(ckt, |
|||
port->evt_data.node_index, |
|||
port->evt_data.output_index, |
|||
&value_ptr); |
|||
port->output.pvalue = value_ptr; |
|||
} |
|||
} |
|||
} |
|||
else { |
|||
/* Get the analog input value. All we need to do is */ |
|||
/* set it to zero if mode is INITJCT. Otherwise, value */ |
|||
/* should still be around from last successful analog call */ |
|||
if(ckt->CKTmode & MODEINITJCT) |
|||
port->input.rvalue = 0.0; |
|||
} |
|||
|
|||
} /* end for number of ports */ |
|||
} /* end for number of connections */ |
|||
|
|||
|
|||
/* Prepare the structure to be passed to the code model */ |
|||
cm_data.num_conn = inst->num_conn; |
|||
cm_data.conn = inst->conn; |
|||
cm_data.num_param = inst->num_param; |
|||
cm_data.param = inst->param; |
|||
cm_data.num_inst_var = inst->num_inst_var; |
|||
cm_data.inst_var = inst->inst_var; |
|||
|
|||
|
|||
/* ******************* */ |
|||
/* Call the code model */ |
|||
/* ******************* */ |
|||
|
|||
mod_type = inst->MIFmodPtr->MIFmodType; |
|||
(*(DEVices[mod_type]->DEVpublic.cm_func)) (&cm_data); |
|||
|
|||
|
|||
/* ****************************** */ |
|||
/* Process the code model outputs */ |
|||
/* ****************************** */ |
|||
|
|||
/* Loop through all connections and ports and process the msgs */ |
|||
/* and event outputs */ |
|||
|
|||
num_conn = inst->num_conn; |
|||
for(i = 0; i < num_conn; i++) { |
|||
|
|||
conn = inst->conn[i]; |
|||
if(conn->is_null) |
|||
continue; |
|||
|
|||
/* Loop through each port on the connection */ |
|||
num_port = conn->size; |
|||
for(j = 0; j < num_port; j++) { |
|||
|
|||
port = conn->port[j]; |
|||
|
|||
/* Skip if port is null */ |
|||
if(port->is_null) |
|||
continue; |
|||
|
|||
/* Process the message if any */ |
|||
if(port->msg) |
|||
EVTadd_msg(ckt, port->evt_data.port_index, port->msg); |
|||
|
|||
/* If this is the initialization pass, process the load factor */ |
|||
if(! inst->initialized) { |
|||
node_data->total_load[port->evt_data.node_index] += |
|||
port->load; |
|||
} |
|||
|
|||
/* If connection is not an event output, continue to next port */ |
|||
if(! conn->is_output) |
|||
continue; |
|||
if((port->type != MIF_DIGITAL) && (port->type != MIF_USER_DEFINED)) |
|||
continue; |
|||
|
|||
/* If output changed, process it */ |
|||
EVTprocess_output(ckt, port->changed, |
|||
port->evt_data.output_index, |
|||
port->invert, port->delay); |
|||
|
|||
/* And prevent erroneous models from overwriting it during */ |
|||
/* analog iterations */ |
|||
if(g_mif_info.circuit.anal_type == MIF_TRAN) |
|||
port->output.pvalue = NULL; |
|||
|
|||
} /* end for number of ports */ |
|||
} /* end for number of connections */ |
|||
|
|||
|
|||
/* Record statistics */ |
|||
if(g_mif_info.circuit.anal_type == MIF_DC) |
|||
(ckt->evt->data.statistics->op_load_calls)++; |
|||
else if(g_mif_info.circuit.anal_type == MIF_TRAN) |
|||
(ckt->evt->data.statistics->tran_load_calls)++; |
|||
|
|||
/* Mark that the instance has been called once */ |
|||
inst->initialized = MIF_TRUE; |
|||
|
|||
return(OK); |
|||
} |
|||
|
|||
|
|||
|
|||
/* |
|||
EVTcreate_state |
|||
|
|||
This function creates a new state storage area for a particular instance |
|||
during an event-driven simulation. New states must be created so |
|||
that old states are saved and can be accessed by code models in the |
|||
future. The new state is initialized to the previous state value. |
|||
*/ |
|||
|
|||
|
|||
static void EVTcreate_state( |
|||
CKTcircuit *ckt, /* The circuit structure */ |
|||
int inst_index) /* The instance to create state for */ |
|||
{ |
|||
int i; |
|||
int total_size; |
|||
|
|||
Evt_State_Data_t *state_data; |
|||
|
|||
Evt_State_t *new_state; |
|||
Evt_State_t *prev_state; |
|||
|
|||
char *from; |
|||
char *to; |
|||
|
|||
|
|||
/* Get variables for fast access */ |
|||
state_data = ckt->evt->data.state; |
|||
|
|||
/* Exit immediately if no states on this instance */ |
|||
if(state_data->desc[inst_index] == NULL) |
|||
return; |
|||
|
|||
/* Get size of state block to be allocated */ |
|||
total_size = state_data->total_size[inst_index]; |
|||
|
|||
/* Allocate a new state for the instance */ |
|||
if(state_data->free[inst_index]) |
|||
{ |
|||
new_state = state_data->free[inst_index]; |
|||
state_data->free[inst_index] = new_state->next; |
|||
} |
|||
else |
|||
{ |
|||
|
|||
new_state = (void *) MALLOC(sizeof(Evt_State_t)); |
|||
new_state->block = (void *) MALLOC(total_size); |
|||
|
|||
} |
|||
|
|||
/* Splice the new state into the state data linked list */ |
|||
/* and update the tail pointer */ |
|||
prev_state = *(state_data->tail[inst_index]); |
|||
prev_state->next = new_state; |
|||
new_state->prev = prev_state; |
|||
state_data->tail[inst_index] = &(prev_state->next); |
|||
|
|||
/* Copy the old state to the new state and set the step */ |
|||
from = prev_state->block; |
|||
to = new_state->block; |
|||
for(i = 0; i < total_size; i++) |
|||
to[i] = from[i]; |
|||
new_state->step = g_mif_info.circuit.evt_step; |
|||
|
|||
/* Mark that the state data on the instance has been modified */ |
|||
if(! state_data->modified[inst_index]) { |
|||
state_data->modified[inst_index] = MIF_TRUE; |
|||
state_data->modified_index[(state_data->num_modified)++] = inst_index; |
|||
} |
|||
} |
|||
|
|||
|
|||
/* |
|||
EVTcreate_output_event |
|||
|
|||
This function creates a new output event. |
|||
*/ |
|||
|
|||
static void EVTcreate_output_event( |
|||
CKTcircuit *ckt, /* The circuit structure */ |
|||
int node_index, /* The node type port is on */ |
|||
int output_index, /* The output index for this port */ |
|||
void **value_ptr) /* The event created */ |
|||
{ |
|||
int udn_index; |
|||
Evt_Node_Info_t **node_table; |
|||
Evt_Output_Queue_t *output_queue; |
|||
Evt_Output_Event_t *event; |
|||
|
|||
|
|||
/* Check the output queue free list and use the structure */ |
|||
/* at the head of the list if non-null. Otherwise, create a new one. */ |
|||
output_queue = &(ckt->evt->queue.output); |
|||
if(output_queue->free[output_index]) { |
|||
*value_ptr = output_queue->free[output_index]->value; |
|||
} |
|||
else { |
|||
/* Create a new event */ |
|||
event = (void *) MALLOC(sizeof(Evt_Output_Event_t)); |
|||
event->next = NULL; |
|||
|
|||
/* Initialize the value */ |
|||
node_table = ckt->evt->info.node_table; |
|||
udn_index = node_table[node_index]->udn_index; |
|||
(*(g_evt_udn_info[udn_index]->create)) (&(event->value)); |
|||
|
|||
/* Put the event onto the free list and return the value pointer */ |
|||
output_queue->free[output_index] = event; |
|||
*value_ptr = event->value; |
|||
} |
|||
} |
|||
|
|||
|
|||
|
|||
/* |
|||
EVTadd_msg |
|||
|
|||
This function records a message output by a code model into the |
|||
message results data structure. |
|||
*/ |
|||
|
|||
|
|||
static void EVTadd_msg( |
|||
CKTcircuit *ckt, /* The circuit structure */ |
|||
int port_index, /* The port to add message to */ |
|||
char *msg_text) /* The message text */ |
|||
{ |
|||
|
|||
Evt_Msg_Data_t *msg_data; |
|||
|
|||
Evt_Msg_t **msg_ptr; |
|||
Evt_Msg_t *msg; |
|||
|
|||
|
|||
/* Get pointers for fast access */ |
|||
msg_data = ckt->evt->data.msg; |
|||
msg_ptr = msg_data->tail[port_index]; |
|||
|
|||
/* Set pointer to location at which to add, and update tail */ |
|||
if(*msg_ptr != NULL) { |
|||
msg_ptr = &((*msg_ptr)->next); |
|||
msg_data->tail[port_index] = msg_ptr; |
|||
} |
|||
|
|||
/* Add a new entry in the list of messages for this port */ |
|||
if(msg_data->free[port_index]) { |
|||
*msg_ptr = msg_data->free[port_index]; |
|||
msg_data->free[port_index] = msg_data->free[port_index]->next; |
|||
} |
|||
else { |
|||
*msg_ptr = (void *) MALLOC(sizeof(Evt_Msg_t)); |
|||
} |
|||
|
|||
/* Fill in the values */ |
|||
msg = *msg_ptr; |
|||
msg->next = NULL; |
|||
if((ckt->CKTmode & MODEDCOP) == MODEDCOP) |
|||
msg->op = MIF_TRUE; |
|||
else |
|||
msg->step = g_mif_info.circuit.evt_step; |
|||
msg->text = MIFcopy(msg_text); |
|||
|
|||
/* Update the modified indexes */ |
|||
if(g_mif_info.circuit.anal_type == MIF_TRAN) { |
|||
if(! msg_data->modified[port_index]) { |
|||
msg_data->modified[port_index] = MIF_TRUE; |
|||
msg_data->modified_index[(msg_data->num_modified)++] = port_index; |
|||
} |
|||
} |
|||
|
|||
} |
|||
|
|||
|
|||
/* |
|||
EVTprocess_output |
|||
|
|||
This function processes an event-driven output produced by a code |
|||
model. If transient analysis mode, the event is placed into the |
|||
output queue according to its (non-zero) delay. If DC analysis, |
|||
the event is processed immediately. |
|||
*/ |
|||
|
|||
|
|||
static void EVTprocess_output( |
|||
CKTcircuit *ckt, /* The circuit structure */ |
|||
Mif_Boolean_t changed, /* Has output changed? */ |
|||
int output_index, /* The output of interest */ |
|||
Mif_Boolean_t invert, /* Does output need to be inverted? */ |
|||
double delay) /* The output delay in transient analysis */ |
|||
{ |
|||
|
|||
int num_outputs; |
|||
int node_index; |
|||
int udn_index; |
|||
int output_subindex; |
|||
|
|||
Evt_Output_Info_t **output_table; |
|||
Evt_Node_Info_t **node_table; |
|||
|
|||
Evt_Node_t *rhs; |
|||
Evt_Node_t *rhsold; |
|||
|
|||
Evt_Output_Queue_t *output_queue; |
|||
Evt_Output_Event_t *output_event; |
|||
|
|||
Mif_Boolean_t equal; |
|||
|
|||
|
|||
output_queue = &(ckt->evt->queue.output); |
|||
output_table = ckt->evt->info.output_table; |
|||
node_table = ckt->evt->info.node_table; |
|||
|
|||
node_index = output_table[output_index]->node_index; |
|||
udn_index = node_table[node_index]->udn_index; |
|||
|
|||
|
|||
/* if transient analysis, just put the output event on the queue */ |
|||
/* to be processed at a later time */ |
|||
if(g_mif_info.circuit.anal_type == MIF_TRAN) { |
|||
/* If model signaled that output was not posted, */ |
|||
/* leave the event struct on the free list and return */ |
|||
if((! changed) || (delay <= 0.0)) { |
|||
if(changed && (delay <= 0.0)) |
|||
printf("\nERROR - Output delay <= 0 not allowed - output ignored!\n"); |
|||
return; |
|||
} |
|||
/* Remove the (now used) struct from the head of the free list */ |
|||
output_event = output_queue->free[output_index]; |
|||
output_queue->free[output_index] = output_event->next; |
|||
/* Invert the output value if necessary */ |
|||
if(invert) |
|||
(*(g_evt_udn_info[udn_index]->invert)) |
|||
(output_event->value); |
|||
/* Add it to the queue */ |
|||
EVTqueue_output(ckt, output_index, udn_index, output_event, |
|||
g_mif_info.circuit.evt_step, |
|||
g_mif_info.circuit.evt_step + delay); |
|||
return; |
|||
} |
|||
/* If not transient analysis, process immediately. */ |
|||
/* Determine if output has changed from rhsold value */ |
|||
/* and put entry in output queue changed list if so */ |
|||
else { |
|||
|
|||
/* If model signaled that output was not posted, */ |
|||
/* just return */ |
|||
if(! changed) |
|||
return; |
|||
/* |
|||
if(delay > 0.0) |
|||
printf("\nWARNING - Non-zero output delay not allowed in DCOP - delay ignored!\n"); |
|||
*/ |
|||
rhs = ckt->evt->data.node->rhs; |
|||
rhsold = ckt->evt->data.node->rhsold; |
|||
|
|||
/* Determine if changed */ |
|||
num_outputs = node_table[node_index]->num_outputs; |
|||
if(num_outputs > 1) { |
|||
output_subindex = output_table[output_index]->output_subindex; |
|||
if(invert) |
|||
(*(g_evt_udn_info[udn_index]->invert)) |
|||
(rhs[node_index].output_value[output_subindex]); |
|||
(*(g_evt_udn_info[udn_index]->compare)) |
|||
(rhs[node_index].output_value[output_subindex], |
|||
rhsold[node_index].output_value[output_subindex], |
|||
&equal); |
|||
if(! equal) { |
|||
(*(g_evt_udn_info[udn_index]->copy)) |
|||
(rhs[node_index].output_value[output_subindex], |
|||
rhsold[node_index].output_value[output_subindex]); |
|||
} |
|||
} |
|||
else { |
|||
if(invert) |
|||
(*(g_evt_udn_info[udn_index]->invert)) |
|||
(rhs[node_index].node_value); |
|||
(*(g_evt_udn_info[udn_index]->compare)) |
|||
(rhs[node_index].node_value, |
|||
rhsold[node_index].node_value, |
|||
&equal); |
|||
if(! equal) { |
|||
(*(g_evt_udn_info[udn_index]->copy)) |
|||
(rhs[node_index].node_value, |
|||
rhsold[node_index].node_value); |
|||
} |
|||
} |
|||
|
|||
/* If changed, put in changed list of output queue */ |
|||
if(! equal) { |
|||
if(! output_queue->changed[output_index]) { |
|||
output_queue->changed[output_index] = MIF_TRUE; |
|||
output_queue->changed_index[(output_queue->num_changed)++] = |
|||
output_index; |
|||
} |
|||
} |
|||
|
|||
return; |
|||
|
|||
} /* end else process immediately */ |
|||
} |
|||
@ -1,93 +0,0 @@ |
|||
/*============================================================================ |
|||
FILE EVTnext_time.c |
|||
|
|||
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 |
|||
|
|||
<date> <person name> <nature of modifications> |
|||
|
|||
SUMMARY |
|||
|
|||
This file contains function EVTnext_time which determines and |
|||
returns the time of the next scheduled event on the inst and output |
|||
queues. |
|||
|
|||
INTERFACES |
|||
|
|||
double EVTnext_time(CKTcircuit *ckt) |
|||
|
|||
REFERENCED FILES |
|||
|
|||
None. |
|||
|
|||
NON-STANDARD FEATURES |
|||
|
|||
None. |
|||
|
|||
============================================================================*/ |
|||
|
|||
#include <stdio.h> |
|||
|
|||
#include "ngspice.h" |
|||
#include "cktdefs.h" |
|||
//#include "util.h" |
|||
|
|||
#include "mif.h" |
|||
#include "evt.h" |
|||
|
|||
#include "evtproto.h" |
|||
|
|||
|
|||
|
|||
/* |
|||
EVTnext_time |
|||
|
|||
Get the next event time as the minimum of the next times |
|||
in the inst and output queues. If no next time in either, |
|||
return machine infinity. |
|||
*/ |
|||
|
|||
|
|||
double EVTnext_time( |
|||
CKTcircuit *ckt) /* The circuit structure */ |
|||
{ |
|||
|
|||
double next_time; |
|||
|
|||
Evt_Inst_Queue_t *inst_queue; |
|||
Evt_Output_Queue_t *output_queue; |
|||
|
|||
|
|||
/* Initialize next time to machine infinity */ |
|||
next_time = 1e30; |
|||
|
|||
/* Get pointers for fast access */ |
|||
inst_queue = &(ckt->evt->queue.inst); |
|||
output_queue = &(ckt->evt->queue.output); |
|||
|
|||
/* If anything pending in inst queue, set next time */ |
|||
/* to minimum of itself and the inst queue next time */ |
|||
if(inst_queue->num_pending) |
|||
if(inst_queue->next_time < next_time) |
|||
next_time = inst_queue->next_time; |
|||
|
|||
/* If anything pending in output queue, set next time */ |
|||
/* to minimum of itself and the output queue next time */ |
|||
if(output_queue->num_pending) |
|||
if(output_queue->next_time < next_time) |
|||
next_time = output_queue->next_time; |
|||
|
|||
return(next_time); |
|||
} |
|||
@ -1,159 +0,0 @@ |
|||
/*============================================================================ |
|||
FILE EVTnode_copy.c |
|||
|
|||
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 |
|||
|
|||
<date> <person name> <nature of modifications> |
|||
|
|||
SUMMARY |
|||
|
|||
This file contains function EVTnode_copy which copies the state |
|||
of a node structure. |
|||
|
|||
INTERFACES |
|||
|
|||
void EVTnode_copy(CKTcircuit *ckt, int node_index, Evt_Node_t *from, |
|||
Evt_Node_t **to) |
|||
|
|||
REFERENCED FILES |
|||
|
|||
None. |
|||
|
|||
NON-STANDARD FEATURES |
|||
|
|||
None. |
|||
|
|||
============================================================================*/ |
|||
|
|||
#include "ngspice.h" |
|||
#include "cktdefs.h" |
|||
//#include "util.h" |
|||
|
|||
#include "mif.h" |
|||
#include "evt.h" |
|||
#include "evtudn.h" |
|||
|
|||
#include "mifproto.h" |
|||
#include "evtproto.h" |
|||
#include "cm.h" |
|||
|
|||
/* |
|||
EVTnode_copy |
|||
|
|||
This function copies the state of a node structure. |
|||
|
|||
If the destination is NULL, it is allocated before the copy. This is the |
|||
case when EVTiter copies a node during a transient analysis to |
|||
save the state of an element of rhsold into the node data structure |
|||
lists. |
|||
|
|||
If the destination is non-NULL, only the internal elements of the node |
|||
structure are copied. This is the case when EVTbackup restores that state |
|||
of nodes that existed at a certain timestep back into rhs and rhsold. |
|||
*/ |
|||
|
|||
|
|||
void EVTnode_copy( |
|||
CKTcircuit *ckt, /* The circuit structure */ |
|||
int node_index, /* The node to copy */ |
|||
Evt_Node_t *from, /* Location to copy from */ |
|||
Evt_Node_t **to) /* Location to copy to */ |
|||
{ |
|||
|
|||
int i; |
|||
|
|||
int udn_index; |
|||
int num_outputs; |
|||
Mif_Boolean_t invert; |
|||
|
|||
Evt_Node_Data_t *node_data; |
|||
Evt_Node_Info_t **node_table; |
|||
|
|||
Evt_Node_t *here; |
|||
|
|||
/* Digital_t *dummy;*/ |
|||
|
|||
/* char buff[128];*/ |
|||
|
|||
/* Get data for fast access */ |
|||
node_data = ckt->evt->data.node; |
|||
node_table = ckt->evt->info.node_table; |
|||
|
|||
udn_index = node_table[node_index]->udn_index; |
|||
num_outputs = node_table[node_index]->num_outputs; |
|||
invert = node_table[node_index]->invert; |
|||
|
|||
|
|||
/* If destination is not allocated, allocate it */ |
|||
/* otherwise we just copy into the node struct */ |
|||
here = *to; |
|||
|
|||
if(here == NULL) |
|||
{ |
|||
/* Use allocated structure on free list if available */ |
|||
/* Otherwise, allocate a new one */ |
|||
here = node_data->free[node_index]; |
|||
if(here) |
|||
{ |
|||
*to = here; |
|||
node_data->free[node_index] = here->next; |
|||
here->next = NULL; |
|||
} |
|||
else |
|||
{ |
|||
here = (void *) MALLOC(sizeof(Evt_Node_t)); |
|||
*to = here; |
|||
/* Allocate/initialize the data in the new node struct */ |
|||
if(num_outputs > 1) |
|||
{ |
|||
here->output_value = (void *) MALLOC(num_outputs * sizeof(void *)); |
|||
|
|||
for(i = 0; i < num_outputs; i++) |
|||
{ |
|||
(*(g_evt_udn_info[udn_index]->create)) |
|||
( &(here->output_value[i]) ); |
|||
} |
|||
} |
|||
|
|||
here->node_value = NULL; |
|||
|
|||
(*(g_evt_udn_info[udn_index]->create)) ( &(here->node_value) ); |
|||
|
|||
if(invert) |
|||
(*(g_evt_udn_info[udn_index]->create)) ( &(here->inverted_value) ); |
|||
|
|||
|
|||
} |
|||
} |
|||
|
|||
/* Copy the node data */ |
|||
here->op = from->op; |
|||
here->step = from->step; |
|||
if(num_outputs > 1) |
|||
{ |
|||
for(i = 0; i < num_outputs; i++) |
|||
{ |
|||
(*(g_evt_udn_info[udn_index]->copy)) (from->output_value[i], |
|||
here->output_value[i]); |
|||
} |
|||
} |
|||
(*(g_evt_udn_info[udn_index]->copy)) (from->node_value, here->node_value); |
|||
if(invert) |
|||
{ |
|||
(*(g_evt_udn_info[udn_index]->copy)) (from->inverted_value, |
|||
here->inverted_value); |
|||
} |
|||
} |
|||
@ -1,321 +0,0 @@ |
|||
/*============================================================================ |
|||
FILE EVTop.c |
|||
|
|||
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 |
|||
|
|||
<date> <person name> <nature of modifications> |
|||
|
|||
SUMMARY |
|||
|
|||
This file contains function EVTop which is used to perform an |
|||
operating point analysis in place of CKTop when there are |
|||
event-driven instances in the circuit. It alternates between doing |
|||
event-driven iterations with EVTiter and doing analog iterations with |
|||
NIiter/CKTop until no more event-driven outputs change. |
|||
|
|||
INTERFACES |
|||
|
|||
EVTop() |
|||
|
|||
REFERENCED FILES |
|||
|
|||
None. |
|||
|
|||
NON-STANDARD FEATURES |
|||
|
|||
None. |
|||
|
|||
============================================================================*/ |
|||
|
|||
#include <stdio.h> |
|||
#include "ngspice.h" |
|||
#include "cktdefs.h" |
|||
//#include "util.h" |
|||
#include "sperror.h" |
|||
|
|||
#include "mif.h" |
|||
#include "evt.h" |
|||
#include "evtproto.h" |
|||
#include "evtudn.h" |
|||
|
|||
|
|||
static void EVTnode_compare( |
|||
CKTcircuit *ckt, |
|||
int node_index, |
|||
Evt_Node_t *node1, |
|||
Evt_Node_t *node2, |
|||
Mif_Boolean_t *equal); |
|||
|
|||
|
|||
|
|||
/* |
|||
EVTop |
|||
|
|||
This function is used to perform an operating point analysis |
|||
in place of CKTop when there are event-driven instances in the |
|||
circuit. It alternates between doing event-driven iterations |
|||
with EVTiter and doing analog iterations with NIiter/CKTop |
|||
until no more event-driven outputs change. |
|||
*/ |
|||
|
|||
|
|||
int EVTop( |
|||
CKTcircuit *ckt, /* The circuit structure */ |
|||
long firstmode, /* The SPICE 3C1 CKTop() firstmode parameter */ |
|||
long continuemode, /* The SPICE 3C1 CKTop() continuemode paramter */ |
|||
int max_iter, /* The SPICE 3C1 CKTop() max iteration parameter */ |
|||
Mif_Boolean_t first_call) /* Is this the first time through? */ |
|||
{ |
|||
|
|||
int i; |
|||
int num_insts; |
|||
int converged; |
|||
int output_index; |
|||
int port_index; |
|||
|
|||
char *err_msg; |
|||
|
|||
Mif_Boolean_t firstime; |
|||
|
|||
Evt_Inst_Queue_t *inst_queue; |
|||
Evt_Output_Queue_t *output_queue; |
|||
|
|||
Evt_Output_Info_t **output_table; |
|||
Evt_Port_Info_t **port_table; |
|||
|
|||
|
|||
/* get data to local storage for fast access */ |
|||
num_insts = ckt->evt->counts.num_insts; |
|||
inst_queue = &(ckt->evt->queue.inst); |
|||
|
|||
/* Initialize to_call entries in event inst queue */ |
|||
/* to force calling all event/hybrid instance the first */ |
|||
/* time through */ |
|||
|
|||
if(first_call) { |
|||
for(i = 0; i < num_insts; i++) { |
|||
inst_queue->to_call[i] = MIF_TRUE; |
|||
inst_queue->to_call_index[i] = i; |
|||
} |
|||
inst_queue->num_to_call = num_insts; |
|||
} |
|||
|
|||
|
|||
/* Alternate between event-driven and analog solutions until */ |
|||
/* there are no changed event-driven outputs */ |
|||
|
|||
firstime = MIF_TRUE; |
|||
for(;;) { |
|||
|
|||
/* Call EVTiter to establish initial outputs from */ |
|||
/* event/hybrid instances with states (e.g. flip-flops) */ |
|||
|
|||
ckt->CKTmode = firstmode; |
|||
converged = EVTiter(ckt); |
|||
if(converged != 0) |
|||
return(converged); |
|||
|
|||
/* Now do analog solution for current state of hybrid outputs */ |
|||
|
|||
/* If first analog solution, call CKTop */ |
|||
if(firstime) { |
|||
firstime = MIF_FALSE; |
|||
converged = CKTop(ckt, |
|||
firstmode, |
|||
continuemode, |
|||
max_iter); |
|||
if(converged != 0) |
|||
return(converged); |
|||
} |
|||
/* Otherwise attempt to converge with mode = continuemode */ |
|||
else { |
|||
ckt->CKTmode = continuemode; |
|||
converged = NIiter(ckt,max_iter); |
|||
if(converged != 0) { |
|||
converged = CKTop(ckt, |
|||
firstmode, |
|||
continuemode, |
|||
max_iter); |
|||
if(converged != 0) |
|||
return(converged); |
|||
} |
|||
} |
|||
|
|||
/* Call all hybrids to allow new event outputs to be posted */ |
|||
EVTcall_hybrids(ckt); |
|||
|
|||
/* Increment count of successful alternations */ |
|||
(ckt->evt->data.statistics->op_alternations)++; |
|||
|
|||
/* If .option card specified not to alternate solutions, exit */ |
|||
/* immediately with this first pass solution */ |
|||
if(! ckt->evt->options.op_alternate) |
|||
return(0); |
|||
|
|||
/* If no hybrid instances produced different event outputs, */ |
|||
/* alternation is completed, so exit */ |
|||
if(ckt->evt->queue.output.num_changed == 0) |
|||
return(0); |
|||
|
|||
/* If too many alternations, exit with error */ |
|||
if(ckt->evt->data.statistics->op_alternations >= |
|||
ckt->evt->limits.max_op_alternations) { |
|||
|
|||
(*(SPfrontEnd->IFerror)) (ERR_WARNING, |
|||
"Too many analog/event-driven solution alternations", |
|||
(IFuid *) NULL); |
|||
|
|||
err_msg = MALLOC(10000); |
|||
output_queue = &(ckt->evt->queue.output); |
|||
output_table = ckt->evt->info.output_table; |
|||
port_table = ckt->evt->info.port_table; |
|||
|
|||
for(i = 0; i < output_queue->num_changed; i++) { |
|||
output_index = output_queue->changed_index[i]; |
|||
port_index = output_table[output_index]->port_index; |
|||
sprintf(err_msg, "\n Instance: %s\n Connection: %s\n Port: %d", |
|||
port_table[port_index]->inst_name, |
|||
port_table[port_index]->conn_name, |
|||
port_table[port_index]->port_num); |
|||
ENHreport_conv_prob(ENH_EVENT_NODE, |
|||
port_table[port_index]->node_name, |
|||
err_msg); |
|||
} |
|||
FREE(err_msg); |
|||
|
|||
return(E_ITERLIM); |
|||
} |
|||
|
|||
} /* end forever */ |
|||
} |
|||
|
|||
|
|||
|
|||
/* |
|||
EVTop_save |
|||
|
|||
Save result from operating point iteration into the node data area. |
|||
*/ |
|||
|
|||
void EVTop_save( |
|||
CKTcircuit *ckt, /* The circuit structure */ |
|||
Mif_Boolean_t op, /* True if from a DCOP analysis, false if TRANOP, etc. */ |
|||
double step) |
|||
{ |
|||
|
|||
int i; |
|||
int num_nodes; |
|||
|
|||
Mif_Boolean_t equal; |
|||
|
|||
Evt_Node_Data_t *node_data; |
|||
|
|||
Evt_Node_t *rhsold; |
|||
Evt_Node_t **head; |
|||
Evt_Node_t **here; |
|||
|
|||
/* char buff[128];*/ |
|||
|
|||
|
|||
/* Get pointers for fast access */ |
|||
node_data = ckt->evt->data.node; |
|||
rhsold = node_data->rhsold; |
|||
head = node_data->head; |
|||
|
|||
/* For number of event nodes, copy rhsold to node data */ |
|||
/* and set the op member if appropriate */ |
|||
num_nodes = ckt->evt->counts.num_nodes; |
|||
|
|||
for(i = 0; i < num_nodes; i++) |
|||
{ |
|||
/* if head is null, just copy there */ |
|||
if(head[i] == NULL) |
|||
{ |
|||
EVTnode_copy(ckt, i, &(rhsold[i]), &(head[i])); |
|||
|
|||
head[i]->op = op; |
|||
head[i]->step = step; |
|||
|
|||
} |
|||
/* Otherwise, add to the end of the list */ |
|||
else |
|||
{ |
|||
/* Locate end of list */ |
|||
here = &(head[i]); |
|||
for(;;) |
|||
{ |
|||
if((*here)->next) |
|||
here = &((*here)->next); |
|||
else |
|||
break; |
|||
} |
|||
/* Compare entry at end of list to rhsold */ |
|||
|
|||
EVTnode_compare(ckt, i, &(rhsold[i]), *here, &equal); |
|||
|
|||
/* If new value in rhsold is different, add it to the list */ |
|||
if(!equal) |
|||
{ |
|||
here = &((*here)->next); |
|||
EVTnode_copy(ckt, i, &(rhsold[i]), here); |
|||
(*here)->op = op; |
|||
(*here)->step = step; |
|||
} |
|||
} /* end else add to end of list */ |
|||
} /* end for number of nodes */ |
|||
|
|||
} |
|||
|
|||
|
|||
|
|||
/* ************************************************************ */ |
|||
|
|||
|
|||
/* |
|||
EVTnode_compare |
|||
|
|||
This function compares the resolved values of the old and |
|||
new states on a node. The actual comparison is done by |
|||
calling the appropriate user-defined node compare function. |
|||
*/ |
|||
|
|||
|
|||
static void EVTnode_compare( |
|||
CKTcircuit *ckt, /* The circuit structure */ |
|||
int node_index, /* The index for the node in question */ |
|||
Evt_Node_t *node1, /* The first value */ |
|||
Evt_Node_t *node2, /* The second value */ |
|||
Mif_Boolean_t *equal) /* The computed result */ |
|||
{ |
|||
|
|||
Evt_Node_Data_t *node_data; |
|||
Evt_Node_Info_t **node_table; |
|||
|
|||
int udn_index; |
|||
|
|||
|
|||
/* Get data for fast access */ |
|||
node_data = ckt->evt->data.node; |
|||
node_table = ckt->evt->info.node_table; |
|||
udn_index = node_table[node_index]->udn_index; |
|||
|
|||
|
|||
/* Do compare based on changes in resolved node value only */ |
|||
(*(g_evt_udn_info[udn_index]->compare)) ( |
|||
node1->node_value, |
|||
node2->node_value, |
|||
equal); |
|||
} |
|||
@ -1,218 +0,0 @@ |
|||
/*============================================================================ |
|||
FILE EVTplot.c |
|||
|
|||
MEMBER OF process XSPICE |
|||
|
|||
Copyright 1992 |
|||
Georgia Tech Research Corporation |
|||
Atlanta, Georgia 30332 |
|||
All Rights Reserved |
|||
|
|||
PROJECT A-8503 |
|||
|
|||
AUTHORS |
|||
|
|||
5/7/92 Bill Kuhn |
|||
|
|||
MODIFICATIONS |
|||
|
|||
<date> <person name> <nature of modifications> |
|||
|
|||
SUMMARY |
|||
|
|||
This file contains function EVTplot which is used to provide basic |
|||
plotting of event driven nodes through SPICE3's 'plot' command. |
|||
|
|||
INTERFACES |
|||
|
|||
void EVTplot() |
|||
|
|||
REFERENCED FILES |
|||
|
|||
None. |
|||
|
|||
NON-STANDARD FEATURES |
|||
|
|||
None. |
|||
|
|||
============================================================================*/ |
|||
|
|||
#include <stdio.h> |
|||
#include <string.h> |
|||
|
|||
#include "ngspice.h" |
|||
//nclude "misc.h" |
|||
#include "evt.h" |
|||
#include "evtudn.h" |
|||
#include "evtproto.h" |
|||
#include "mif.h" |
|||
#include "mifproto.h" |
|||
|
|||
/*saj for output */ |
|||
#include "sim.h" |
|||
#include "dvec.h" |
|||
//#include "ftedata.h" |
|||
//#include "fteconstant.h" |
|||
//#include "util.h" |
|||
#include "cpstd.h" |
|||
|
|||
|
|||
/* |
|||
|
|||
EVTfindvec() |
|||
|
|||
This function is called from FTE/vectors.c:findvec() when a node specified |
|||
for plotting cannot be located in the analog plot data. It scans the |
|||
event driven data structures looking for the node, and if found, returns |
|||
a new 'dvec' structure holding the data to be plotted. The dvec struct |
|||
is created with it's own v_scale member holding the event time vector |
|||
for this node since the time vector is not aligned with the analog data |
|||
points or with other event vectors. |
|||
|
|||
The node name supplied as argument can either be a simple node name, or a |
|||
name of the form <node name>(<member>), where <member> is the member of |
|||
the event-driven structure to be plotted. These member names are defined |
|||
by the individual "user-defined node" plot_val routines for the node |
|||
type in question. If the simple node name form is used, the special |
|||
keyword "all" is supplied to the plot_val routine for the member name. |
|||
|
|||
*/ |
|||
|
|||
|
|||
struct dvec *EVTfindvec( |
|||
char *node) /* The node name (and optional member name) */ |
|||
{ |
|||
char *name; |
|||
char *member = "all"; |
|||
char *ptr; |
|||
|
|||
int i; |
|||
int len; |
|||
int num_nodes; |
|||
int udn_index; |
|||
int num_events; |
|||
|
|||
Mif_Boolean_t found; |
|||
Evt_Node_Info_t **node_table; |
|||
Evt_Node_t *head; |
|||
Evt_Node_t *event; |
|||
|
|||
double *anal_point_vec; |
|||
double *value_vec; |
|||
double value; |
|||
|
|||
struct dvec *d; |
|||
struct dvec *scale; |
|||
|
|||
/* Exit immediately if event-driven stuff not allocated yet, */ |
|||
/* or if number of event nodes is zero. */ |
|||
if(! g_mif_info.ckt) |
|||
return(NULL); |
|||
if(! g_mif_info.ckt->evt) |
|||
return(NULL); |
|||
if(g_mif_info.ckt->evt->counts.num_nodes == 0) |
|||
return(NULL); |
|||
|
|||
/* Make a copy of the node name. */ |
|||
/* Do not free this string. It is assigned into the dvec structure below. */ |
|||
name = MIFcopy(node); |
|||
|
|||
/* Convert to all lower case */ |
|||
len = strlen(name); |
|||
for(i = 0; i < len; i++) |
|||
if(isupper(name[i])) |
|||
name[i] = tolower(name[i]); |
|||
|
|||
/* Divide into the node name and member name */ |
|||
for(ptr = name; *ptr != '\0'; ptr++) |
|||
if(*ptr == '(') |
|||
break; |
|||
|
|||
if(*ptr == '(') { |
|||
*ptr = '\0'; |
|||
ptr++; |
|||
member = ptr; |
|||
for( ; *ptr != '\0'; ptr++) |
|||
if(*ptr == ')') |
|||
break; |
|||
*ptr = '\0'; |
|||
} |
|||
|
|||
/* Look for node name in the event-driven node list */ |
|||
num_nodes = g_mif_info.ckt->evt->counts.num_nodes; |
|||
node_table = g_mif_info.ckt->evt->info.node_table; |
|||
|
|||
for(i = 0, found = MIF_FALSE; i < num_nodes; i++) { |
|||
if(cieq(name, node_table[i]->name)) { |
|||
found = MIF_TRUE; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
if(! found) |
|||
return(NULL); |
|||
|
|||
/* Get the UDN type index */ |
|||
udn_index = node_table[i]->udn_index; |
|||
|
|||
/* Count the number of events */ |
|||
head = g_mif_info.ckt->evt->data.node->head[i]; |
|||
|
|||
for(event = head, num_events = 0; event; event = event->next) |
|||
num_events++; |
|||
|
|||
/* Allocate arrays to hold the analysis point and node value vectors */ |
|||
anal_point_vec = (double *) MALLOC(2 * (num_events + 2) * sizeof(double)); |
|||
value_vec = (double *) MALLOC(2 * (num_events + 2) * sizeof(double)); |
|||
|
|||
/* Iterate through the events and fill the arrays. */ |
|||
/* Note that we create vertical segments every time an event occurs. */ |
|||
/* Need to modify this in the future to complete the vector out to the */ |
|||
/* last analysis point... */ |
|||
for(i = 0, event = head; event; event = event->next) { |
|||
|
|||
/* If not first point, put the second value of the horizontal line in the vectors */ |
|||
if(i > 0) { |
|||
anal_point_vec[i] = event->step; |
|||
value_vec[i] = value; |
|||
i++; |
|||
} |
|||
|
|||
/* Get the next value by calling the appropriate UDN plot_val function */ |
|||
value = 0.0; |
|||
(*(g_evt_udn_info[udn_index]->plot_val)) (event->node_value, |
|||
member, |
|||
&value); |
|||
|
|||
/* Put the first value of the horizontal line in the vector */ |
|||
anal_point_vec[i] = event->step; |
|||
value_vec[i] = value; |
|||
i++; |
|||
|
|||
} |
|||
|
|||
/* Allocate dvec structures and assign the vectors into them. */ |
|||
/* See FTE/OUTinterface.c:plotInit() for initialization example. */ |
|||
|
|||
scale = (void *) MALLOC(sizeof(struct dvec)); |
|||
|
|||
scale->v_name = MIFcopy("step"); |
|||
scale->v_type = SV_TIME; |
|||
scale->v_flags = VF_REAL & ~VF_PERMANENT; |
|||
scale->v_length = i; |
|||
scale->v_realdata = anal_point_vec; |
|||
scale->v_scale = NULL; |
|||
|
|||
d = (void *) MALLOC(sizeof(struct dvec)); |
|||
|
|||
d->v_name = name; |
|||
d->v_type = SV_VOLTAGE; |
|||
d->v_flags = VF_REAL & ~VF_PERMANENT; |
|||
d->v_length = i; |
|||
d->v_realdata = value_vec; |
|||
d->v_scale = scale; |
|||
|
|||
|
|||
/* Return the dvec */ |
|||
return(d); |
|||
} |
|||
@ -1,369 +0,0 @@ |
|||
/*============================================================================ |
|||
FILE EVTprint.c |
|||
|
|||
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 |
|||
|
|||
<date> <person name> <nature of modifications> |
|||
|
|||
SUMMARY |
|||
|
|||
This file contains function EVTprint which is used to provide a simple |
|||
tabular output of event-driven node data. This printout is invoked |
|||
through a new nutmeg command called 'eprint' which takes event-driven |
|||
node names as argument. |
|||
|
|||
INTERFACES |
|||
|
|||
void EVTprint(wordlist *wl) |
|||
|
|||
REFERENCED FILES |
|||
|
|||
None. |
|||
|
|||
NON-STANDARD FEATURES |
|||
|
|||
None. |
|||
|
|||
============================================================================*/ |
|||
|
|||
#include <stdio.h> |
|||
#include <string.h> |
|||
|
|||
#include "ngspice.h" |
|||
//#include "misc.h" |
|||
|
|||
#include "cpstd.h" |
|||
|
|||
#include "mif.h" |
|||
#include "evt.h" |
|||
#include "evtudn.h" |
|||
|
|||
#include "evtproto.h" |
|||
|
|||
|
|||
|
|||
static int get_index(char *node_name); |
|||
|
|||
static void print_data( |
|||
Mif_Boolean_t dcop, |
|||
double step, |
|||
char **node_value, |
|||
int nargs); |
|||
|
|||
/* |
|||
EVTprint |
|||
|
|||
This function implements the 'eprint' command used to print |
|||
event-driven node values and messages from the latest simulation. |
|||
|
|||
This is a simple prototype implementation of the |
|||
eprint command for testing purposes. It is currently lacking |
|||
in the following areas: |
|||
|
|||
1) It accepts only up to 16 nodes. |
|||
|
|||
2) It does not support the selected printing of different |
|||
members of a user-defined data struct. |
|||
|
|||
3) It is dumb in its output formatting - just tries to print |
|||
everything on a line with 4 space separators. |
|||
|
|||
4) It works only for the latest simulation - i.e. it does not |
|||
use the evt jobs structure to find old results. |
|||
|
|||
5) It does not allow a range of timesteps to be selected. |
|||
|
|||
*/ |
|||
|
|||
|
|||
|
|||
#define EPRINT_MAXARGS 16 |
|||
|
|||
|
|||
void EVTprint( |
|||
wordlist *wl) /* The command line entered by user */ |
|||
{ |
|||
|
|||
int i; |
|||
int nargs; |
|||
int num_ports; |
|||
|
|||
wordlist *w; |
|||
|
|||
char *node_name[EPRINT_MAXARGS]; |
|||
int node_index[EPRINT_MAXARGS]; |
|||
int udn_index[EPRINT_MAXARGS]; |
|||
Evt_Node_t *node_data[EPRINT_MAXARGS]; |
|||
char *node_value[EPRINT_MAXARGS]; |
|||
|
|||
CKTcircuit *ckt; |
|||
|
|||
Evt_Node_Info_t **node_table; |
|||
Evt_Port_Info_t **port_table; |
|||
|
|||
Mif_Boolean_t more; |
|||
Mif_Boolean_t dcop; |
|||
|
|||
double step; |
|||
double next_step; |
|||
double this_step; |
|||
|
|||
char *value; |
|||
|
|||
Evt_Msg_t *msg_data; |
|||
Evt_Statistic_t *statistics; |
|||
|
|||
|
|||
/* Count the number of arguments to the command */ |
|||
nargs = 0; |
|||
w = wl; |
|||
while(w) { |
|||
nargs++; |
|||
w = w->wl_next; |
|||
} |
|||
|
|||
if(nargs < 1) { |
|||
printf("Usage: eprint <node1> <node2> ...\n"); |
|||
return; |
|||
} |
|||
if(nargs > EPRINT_MAXARGS) { |
|||
printf("ERROR - eprint currently limited to 16 arguments\n"); |
|||
return; |
|||
} |
|||
|
|||
/* Get needed pointers */ |
|||
ckt = g_mif_info.ckt; |
|||
node_table = ckt->evt->info.node_table; |
|||
|
|||
/* Get data for each argument */ |
|||
w = wl; |
|||
for(i = 0; i < nargs; i++) { |
|||
node_name[i] = w->wl_word; |
|||
node_index[i] = get_index(node_name[i]); |
|||
if(node_index[i] < 0) { |
|||
printf("ERROR - Node %s is not an event node.\n", node_name[i]); |
|||
return; |
|||
} |
|||
udn_index[i] = node_table[node_index[i]]->udn_index; |
|||
node_data[i] = ckt->evt->data.node->head[node_index[i]]; |
|||
node_value[i] = ""; |
|||
w = w->wl_next; |
|||
} |
|||
|
|||
|
|||
/* Print results data */ |
|||
printf("\n**** Results Data ****\n\n"); |
|||
|
|||
/* Print the column identifiers */ |
|||
printf("Time or Step\n"); |
|||
for(i = 0; i < nargs; i++) |
|||
printf("%s\n",node_name[i]); |
|||
printf("\n\n"); |
|||
|
|||
/* Scan the node data and determine if the first vector */ |
|||
/* is for a DCOP analysis or the first step in a swept DC */ |
|||
/* or transient analysis. Also, determine if there is */ |
|||
/* more data following it and if so, what the next step */ |
|||
/* is. */ |
|||
more = MIF_FALSE; |
|||
dcop = MIF_FALSE; |
|||
next_step = 1e30; |
|||
for(i = 0; i < nargs; i++) { |
|||
if(node_data[i]->op) |
|||
dcop = MIF_TRUE; |
|||
else |
|||
step = node_data[i]->step; |
|||
(*(g_evt_udn_info[udn_index[i]]->print_val)) |
|||
(node_data[i]->node_value, "all", &value); |
|||
node_value[i] = value; |
|||
node_data[i] = node_data[i]->next; |
|||
if(node_data[i]) { |
|||
more = MIF_TRUE; |
|||
if(node_data[i]->step < next_step) |
|||
next_step = node_data[i]->step; |
|||
} |
|||
} |
|||
|
|||
/* Print the data */ |
|||
print_data(dcop, step, node_value, nargs); |
|||
|
|||
/* While there is more data, get the next values and print */ |
|||
while(more) { |
|||
|
|||
more = MIF_FALSE; |
|||
this_step = next_step; |
|||
next_step = 1e30; |
|||
|
|||
for(i = 0; i < nargs; i++) { |
|||
|
|||
if(node_data[i]) { |
|||
if(node_data[i]->step == this_step) { |
|||
(*(g_evt_udn_info[udn_index[i]]->print_val)) |
|||
(node_data[i]->node_value, "all", &value); |
|||
node_value[i] = value; |
|||
node_data[i] = node_data[i]->next; |
|||
} |
|||
if(node_data[i]) { |
|||
more = MIF_TRUE; |
|||
if(node_data[i]->step < next_step) |
|||
next_step = node_data[i]->step; |
|||
} |
|||
|
|||
} /* end if node_data not NULL */ |
|||
|
|||
} /* end for number of args */ |
|||
|
|||
print_data(MIF_FALSE, this_step, node_value, nargs); |
|||
|
|||
} /* end while there is more data */ |
|||
printf("\n\n"); |
|||
|
|||
|
|||
/* Print messages for all ports */ |
|||
printf("\n**** Messages ****\n\n"); |
|||
|
|||
num_ports = ckt->evt->counts.num_ports; |
|||
port_table = ckt->evt->info.port_table; |
|||
|
|||
for(i = 0; i < num_ports; i++) { |
|||
|
|||
/* Get pointer to messages for this port */ |
|||
msg_data = ckt->evt->data.msg->head[i]; |
|||
|
|||
/* If no messages on this port, skip */ |
|||
if(! msg_data) |
|||
continue; |
|||
|
|||
/* Print the port description */ |
|||
printf("Node: %s Inst: %s Conn: %s Port: %d\n\n", |
|||
port_table[i]->node_name, |
|||
port_table[i]->inst_name, |
|||
port_table[i]->conn_name, |
|||
port_table[i]->port_num); |
|||
|
|||
/* Print the messages on this port */ |
|||
while(msg_data) { |
|||
if(msg_data->op) |
|||
printf("DCOP "); |
|||
else |
|||
printf("%-16.9e", msg_data->step); |
|||
printf("%s\n", msg_data->text); |
|||
msg_data = msg_data->next; |
|||
} |
|||
printf("\n\n"); |
|||
|
|||
} /* end for number of ports */ |
|||
|
|||
|
|||
/* Print statistics */ |
|||
printf("\n**** Statistics ****\n\n"); |
|||
|
|||
statistics = ckt->evt->data.statistics; |
|||
printf("Operating point analog/event alternations: %d\n", |
|||
statistics->op_alternations); |
|||
printf("Operating point load calls: %d\n", |
|||
statistics->op_load_calls); |
|||
printf("Operating point event passes: %d\n", |
|||
statistics->op_event_passes); |
|||
printf("Transient analysis load calls: %d\n", |
|||
statistics->tran_load_calls); |
|||
printf("Transient analysis timestep backups: %d\n", |
|||
statistics->tran_time_backups); |
|||
|
|||
printf("\n\n"); |
|||
} |
|||
|
|||
|
|||
|
|||
|
|||
/* |
|||
get_index |
|||
|
|||
This function determines the index of a specified event-driven node. |
|||
*/ |
|||
|
|||
|
|||
static int get_index( |
|||
char *node_name /* The name of the node to search for */ |
|||
) |
|||
{ |
|||
|
|||
/* Get the event-driven node index for the specified name */ |
|||
|
|||
int index; |
|||
|
|||
Mif_Boolean_t found; |
|||
Evt_Node_Info_t *node; |
|||
CKTcircuit *ckt; |
|||
|
|||
|
|||
/* Scan list of nodes in event structure to see if there */ |
|||
|
|||
found = MIF_FALSE; |
|||
index = 0; |
|||
|
|||
ckt = g_mif_info.ckt; |
|||
node = ckt->evt->info.node_list; |
|||
|
|||
while(node) { |
|||
if(strcmp(node_name, node->name) == 0) { |
|||
found = MIF_TRUE; |
|||
break; |
|||
} |
|||
else { |
|||
index++; |
|||
node = node->next; |
|||
} |
|||
} |
|||
|
|||
/* Return the index or -1 if not found */ |
|||
if(! found) |
|||
return(-1); |
|||
else |
|||
return(index); |
|||
} |
|||
|
|||
|
|||
|
|||
|
|||
/* |
|||
print_data |
|||
|
|||
This function prints the values of one or more nodes to |
|||
standard output. |
|||
*/ |
|||
|
|||
|
|||
static void print_data( |
|||
Mif_Boolean_t dcop, /* Is this the operating point data */ |
|||
double step, /* The analysis step if dcop */ |
|||
char **node_value, /* The array of values to be printed */ |
|||
int nargs) /* The size of the value array */ |
|||
{ |
|||
|
|||
int i; |
|||
char step_str[100]; |
|||
|
|||
if(dcop) |
|||
strcpy(step_str, "DCOP "); |
|||
else |
|||
sprintf(step_str, "%-16.9e", step); |
|||
|
|||
printf("%s", step_str); |
|||
for(i = 0; i < nargs; i++) |
|||
printf(" %s", node_value[i]); |
|||
printf("\n"); |
|||
} |
|||
@ -1,252 +0,0 @@ |
|||
/*============================================================================ |
|||
FILE EVTqueue.c |
|||
|
|||
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 |
|||
|
|||
<date> <person name> <nature of modifications> |
|||
|
|||
SUMMARY |
|||
|
|||
This file contains functions that place new events into the output and |
|||
instance queues. |
|||
|
|||
INTERFACES |
|||
|
|||
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) |
|||
|
|||
REFERENCED FILES |
|||
|
|||
None. |
|||
|
|||
NON-STANDARD FEATURES |
|||
|
|||
None. |
|||
|
|||
============================================================================*/ |
|||
|
|||
|
|||
#include <stdio.h> |
|||
|
|||
#include "ngspice.h" |
|||
#include "cktdefs.h" |
|||
//#include "util.h" |
|||
|
|||
#include "mif.h" |
|||
#include "evt.h" |
|||
#include "evtudn.h" |
|||
|
|||
#include "evtproto.h" |
|||
|
|||
|
|||
|
|||
/* |
|||
EVTqueue_output |
|||
|
|||
This function places the specified output event onto the output |
|||
queue. It is called by EVTload during a transient analysis. |
|||
|
|||
The linked list in the queue for the specified output is |
|||
searched beginning at the current head of the pending events |
|||
to find the location at which to insert the new event. The |
|||
events are ordered in the list by event_time. If the event |
|||
is placed before the end of the list, subsequent events are |
|||
removed from the list by marking them as 'removed' and |
|||
recording the time of removal. This allows efficient backup |
|||
of the state of the queue if a subsequent analog timestep |
|||
fails. |
|||
*/ |
|||
|
|||
|
|||
void EVTqueue_output( |
|||
CKTcircuit *ckt, /* The circuit structure */ |
|||
int output_index, /* The output in question */ |
|||
int udn_index, /* The associated user-defined node type */ |
|||
Evt_Output_Event_t *new_event, /* The event to queue */ |
|||
double posted_time, /* The current time */ |
|||
double event_time) /* The time the event should happen */ |
|||
{ |
|||
|
|||
Evt_Output_Queue_t *output_queue; |
|||
Evt_Output_Event_t **here; |
|||
Evt_Output_Event_t *next; |
|||
|
|||
Mif_Boolean_t splice; |
|||
|
|||
|
|||
/* Get pointers for fast access */ |
|||
output_queue = &(ckt->evt->queue.output); |
|||
|
|||
/* Put the times into the event struct */ |
|||
new_event->event_time = event_time; |
|||
new_event->posted_time = posted_time; |
|||
new_event->removed = MIF_FALSE; |
|||
|
|||
/* Update next_time in output queue */ |
|||
if((output_queue->num_pending <= 0) || |
|||
(event_time < output_queue->next_time)) |
|||
output_queue->next_time = event_time; |
|||
|
|||
/* Find location at which to insert event */ |
|||
splice = MIF_FALSE; |
|||
here = output_queue->current[output_index]; |
|||
while(*here) { |
|||
if(event_time <= (*here)->event_time) { |
|||
splice = MIF_TRUE; |
|||
break; |
|||
} |
|||
here = &((*here)->next); |
|||
} |
|||
|
|||
/* If needs to be spliced into middle of existing list */ |
|||
if(splice) { |
|||
/* splice it in */ |
|||
next = *here; |
|||
*here = new_event; |
|||
new_event->next = next; |
|||
/* mark later events as removed */ |
|||
while(next) { |
|||
if(! next->removed) { |
|||
next->removed = MIF_TRUE; |
|||
next->removed_time = posted_time; |
|||
} |
|||
next = next->next; |
|||
} |
|||
} |
|||
/* else, just put it at the end */ |
|||
else { |
|||
*here = new_event; |
|||
new_event->next = NULL; |
|||
} |
|||
|
|||
/* Add to the list of outputs modified since last accepted timestep */ |
|||
if(! output_queue->modified[output_index]) { |
|||
output_queue->modified[output_index] = MIF_TRUE; |
|||
output_queue->modified_index[(output_queue->num_modified)++] = |
|||
output_index; |
|||
} |
|||
|
|||
/* Add to the list of outputs with events pending */ |
|||
if(! output_queue->pending[output_index]) { |
|||
output_queue->pending[output_index] = MIF_TRUE; |
|||
output_queue->pending_index[(output_queue->num_pending)++] = |
|||
output_index; |
|||
} |
|||
} |
|||
|
|||
|
|||
|
|||
/* |
|||
EVTqueue_inst |
|||
|
|||
This function places the specified inst event onto the inst |
|||
queue. |
|||
|
|||
The linked list in the queue for the specified inst is |
|||
searched beginning at the current head of the pending events |
|||
to find the location at which to insert the new event. The |
|||
events are ordered in the list by event_time. |
|||
*/ |
|||
|
|||
|
|||
|
|||
|
|||
void EVTqueue_inst( |
|||
CKTcircuit *ckt, /* The circuit structure */ |
|||
int inst_index, /* The instance in question */ |
|||
double posted_time, /* The current time */ |
|||
double event_time) /* The time the event should happen */ |
|||
{ |
|||
|
|||
Evt_Inst_Queue_t *inst_queue; |
|||
Evt_Inst_Event_t **here; |
|||
Evt_Inst_Event_t *new_event; |
|||
Evt_Inst_Event_t *next; |
|||
|
|||
Mif_Boolean_t splice; |
|||
|
|||
|
|||
/* Get pointers for fast access */ |
|||
inst_queue = &(ckt->evt->queue.inst); |
|||
|
|||
/* Update next_time in inst queue */ |
|||
if((inst_queue->num_pending <= 0) || |
|||
(event_time < inst_queue->next_time)) |
|||
inst_queue->next_time = event_time; |
|||
|
|||
/* Create a new event or get one from the free list and copy in data */ |
|||
if(inst_queue->free[inst_index]) { |
|||
new_event = inst_queue->free[inst_index]; |
|||
inst_queue->free[inst_index] = new_event->next; |
|||
} |
|||
else { |
|||
new_event = (void *) MALLOC(sizeof(Evt_Inst_Event_t)); |
|||
} |
|||
new_event->event_time = event_time; |
|||
new_event->posted_time = posted_time; |
|||
|
|||
/* Find location at which to insert event */ |
|||
splice = MIF_FALSE; |
|||
here = inst_queue->current[inst_index]; |
|||
while(*here) { |
|||
/* If there's an event with the same time, don't duplicate it */ |
|||
if(event_time == (*here)->event_time) |
|||
return; |
|||
else if(event_time < (*here)->event_time) { |
|||
splice = MIF_TRUE; |
|||
break; |
|||
} |
|||
here = &((*here)->next); |
|||
} |
|||
|
|||
/* If needs to be spliced into middle of existing list */ |
|||
if(splice) { |
|||
/* splice it in */ |
|||
next = *here; |
|||
*here = new_event; |
|||
new_event->next = next; |
|||
} |
|||
/* else, just put it at the end */ |
|||
else { |
|||
*here = new_event; |
|||
new_event->next = NULL; |
|||
} |
|||
|
|||
/* Add to the list of insts modified since last accepted timestep */ |
|||
if(! inst_queue->modified[inst_index]) { |
|||
inst_queue->modified[inst_index] = MIF_TRUE; |
|||
inst_queue->modified_index[(inst_queue->num_modified)++] = |
|||
inst_index; |
|||
} |
|||
|
|||
/* Add to the list of insts with events pending */ |
|||
if(! inst_queue->pending[inst_index]) { |
|||
inst_queue->pending[inst_index] = MIF_TRUE; |
|||
inst_queue->pending_index[(inst_queue->num_pending)++] = |
|||
inst_index; |
|||
} |
|||
} |
|||
@ -1,578 +0,0 @@ |
|||
/*============================================================================ |
|||
FILE EVTsetup.c |
|||
|
|||
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 |
|||
|
|||
<date> <person name> <nature of modifications> |
|||
|
|||
SUMMARY |
|||
|
|||
This file contains function EVTsetup which clears/allocates the |
|||
event-driven queues and data structures immediately prior to a new |
|||
analysis. In addition, it places entries in the job list so that |
|||
results data from multiple analysis can be retrieved similar to |
|||
SPICE3C1 saving multiple 'plots'. |
|||
|
|||
INTERFACES |
|||
|
|||
int EVTsetup(CKTcircuit *ckt) |
|||
|
|||
REFERENCED FILES |
|||
|
|||
None. |
|||
|
|||
NON-STANDARD FEATURES |
|||
|
|||
None. |
|||
|
|||
============================================================================*/ |
|||
|
|||
#include <stdio.h> |
|||
#include <string.h> |
|||
|
|||
#include "ngspice.h" |
|||
//#include "misc.h" |
|||
|
|||
#include "cktdefs.h" |
|||
#include "sperror.h" |
|||
//#include "util.h" |
|||
|
|||
#include "mif.h" |
|||
#include "evt.h" |
|||
#include "evtudn.h" |
|||
#include "mifproto.h" |
|||
#include "evtproto.h" |
|||
|
|||
|
|||
|
|||
|
|||
static int EVTsetup_queues(CKTcircuit *ckt); |
|||
static int EVTsetup_data(CKTcircuit *ckt); |
|||
static int EVTsetup_jobs(CKTcircuit *ckt); |
|||
static int EVTsetup_load_ptrs(CKTcircuit *ckt); |
|||
|
|||
|
|||
|
|||
|
|||
/* Allocation macros with built-in check for out-of-memory */ |
|||
/* Adapted from SPICE 3C1 code in CKTsetup.c */ |
|||
|
|||
#define CKALLOC(var,size,type) \ |
|||
if(size) { \ |
|||
if(!(var = (void *) MALLOC((size) * sizeof(type)))) \ |
|||
return(E_NOMEM); \ |
|||
} |
|||
|
|||
#define CKREALLOC(var,size,type) \ |
|||
if((size) == 1) { \ |
|||
if(!(var = (void *) MALLOC((size) * sizeof(type)))) \ |
|||
return(E_NOMEM); \ |
|||
} else if((size) > 1) { \ |
|||
if(!(var = (void *) REALLOC((void *) (var), (size) * sizeof(type)))) \ |
|||
return(E_NOMEM); \ |
|||
} |
|||
|
|||
|
|||
/* |
|||
EVTsetup |
|||
|
|||
This function clears/allocates the event-driven queues and data structures |
|||
immediately prior to a new analysis. In addition, it places entries |
|||
in the job list so that results data from multiple analysis can be |
|||
retrieved similar to SPICE3C1 saving multiple 'plots'. |
|||
*/ |
|||
|
|||
|
|||
int EVTsetup( |
|||
CKTcircuit *ckt) /* The circuit structure */ |
|||
{ |
|||
|
|||
int err; |
|||
|
|||
|
|||
/* Exit immediately if no event-driven instances in circuit */ |
|||
if(ckt->evt->counts.num_insts == 0) |
|||
return(OK); |
|||
|
|||
/* Clear the inst, node, and output queues, and initialize the to_call */ |
|||
/* elements in the instance queue to call all event-driven instances */ |
|||
err = EVTsetup_queues(ckt); |
|||
if(err) |
|||
return(err); |
|||
|
|||
/* Allocate and initialize the node, state, message, and statistics data */ |
|||
err = EVTsetup_data(ckt); |
|||
if(err) |
|||
return(err); |
|||
|
|||
/* Set the job pointers to the allocated results, states, messages, */ |
|||
/* and statistics so that data will be accessable after run */ |
|||
err = EVTsetup_jobs(ckt); |
|||
if(err) |
|||
return(err); |
|||
|
|||
/* Setup the pointers in the MIFinstance structure for inputs, outputs, */ |
|||
/* and total loads */ |
|||
err = EVTsetup_load_ptrs(ckt); |
|||
if(err) |
|||
return(err); |
|||
|
|||
/* Initialize additional event data */ |
|||
g_mif_info.circuit.evt_step = 0.0; |
|||
|
|||
/* Return OK */ |
|||
return(OK); |
|||
} |
|||
|
|||
|
|||
|
|||
|
|||
/* |
|||
EVTsetup_queues |
|||
|
|||
This function clears the event-driven queues in preparation for |
|||
a new simulation. |
|||
*/ |
|||
|
|||
|
|||
static int EVTsetup_queues( |
|||
CKTcircuit *ckt) /* The circuit structure */ |
|||
{ |
|||
|
|||
int i; |
|||
int num_insts; |
|||
int num_nodes; |
|||
int num_outputs; |
|||
|
|||
Evt_Inst_Queue_t *inst_queue; |
|||
Evt_Node_Queue_t *node_queue; |
|||
Evt_Output_Queue_t *output_queue; |
|||
|
|||
Evt_Inst_Event_t *inst_event; |
|||
Evt_Output_Event_t *output_event; |
|||
|
|||
void *ptr; |
|||
|
|||
/* ************************ */ |
|||
/* Clear the instance queue */ |
|||
/* ************************ */ |
|||
|
|||
num_insts = ckt->evt->counts.num_insts; |
|||
inst_queue = &(ckt->evt->queue.inst); |
|||
|
|||
for(i = 0; i < num_insts; i++) { |
|||
inst_event = inst_queue->head[i]; |
|||
while(inst_event) { |
|||
ptr = inst_event; |
|||
inst_event = inst_event->next; |
|||
FREE(ptr); |
|||
} |
|||
inst_event = inst_queue->free[i]; |
|||
while(inst_event) { |
|||
ptr = inst_event; |
|||
inst_event = inst_event->next; |
|||
FREE(ptr); |
|||
} |
|||
inst_queue->head[i] = NULL; |
|||
inst_queue->current[i] = &(inst_queue->head[i]); |
|||
inst_queue->last_step[i] = &(inst_queue->head[i]); |
|||
inst_queue->free[i] = NULL; |
|||
} |
|||
|
|||
inst_queue->next_time = 0.0; |
|||
inst_queue->last_time = 0.0; |
|||
|
|||
inst_queue->num_modified = 0; |
|||
inst_queue->num_pending = 0; |
|||
inst_queue->num_to_call = 0; |
|||
|
|||
for(i = 0; i < num_insts; i++) { |
|||
inst_queue->modified[i] = MIF_FALSE; |
|||
inst_queue->pending[i] = MIF_FALSE; |
|||
inst_queue->to_call[i] = MIF_FALSE; |
|||
} |
|||
|
|||
|
|||
/* ******************** */ |
|||
/* Clear the node queue */ |
|||
/* ******************** */ |
|||
|
|||
num_nodes = ckt->evt->counts.num_nodes; |
|||
node_queue = &(ckt->evt->queue.node); |
|||
|
|||
node_queue->num_changed = 0; |
|||
node_queue->num_to_eval = 0; |
|||
|
|||
for(i = 0; i < num_nodes; i++) { |
|||
node_queue->changed[i] = MIF_FALSE; |
|||
node_queue->to_eval[i] = MIF_FALSE; |
|||
} |
|||
|
|||
/* ********************** */ |
|||
/* Clear the output queue */ |
|||
/* ********************** */ |
|||
|
|||
num_outputs = ckt->evt->counts.num_outputs; |
|||
output_queue = &(ckt->evt->queue.output); |
|||
|
|||
for(i = 0; i < num_outputs; i++) { |
|||
output_event = output_queue->head[i]; |
|||
while(output_event) { |
|||
ptr = output_event; |
|||
output_event = output_event->next; |
|||
FREE(ptr); |
|||
} |
|||
output_event = output_queue->free[i]; |
|||
while(output_event) { |
|||
ptr = output_event; |
|||
output_event = output_event->next; |
|||
FREE(ptr); |
|||
} |
|||
output_queue->head[i] = NULL; |
|||
output_queue->current[i] = &(output_queue->head[i]); |
|||
output_queue->last_step[i] = &(output_queue->head[i]); |
|||
output_queue->free[i] = NULL; |
|||
} |
|||
|
|||
output_queue->next_time = 0.0; |
|||
output_queue->last_time = 0.0; |
|||
|
|||
output_queue->num_modified = 0; |
|||
output_queue->num_pending = 0; |
|||
output_queue->num_changed = 0; |
|||
|
|||
for(i = 0; i < num_outputs; i++) { |
|||
output_queue->modified[i] = MIF_FALSE; |
|||
output_queue->pending[i] = MIF_FALSE; |
|||
output_queue->changed[i] = MIF_FALSE; |
|||
} |
|||
|
|||
return(OK); |
|||
} |
|||
|
|||
|
|||
|
|||
/* |
|||
EVTsetup_data |
|||
|
|||
This function sets up the event-driven node, state, and |
|||
message data runtime structures in preparation for |
|||
a new simulation. |
|||
*/ |
|||
|
|||
|
|||
static int EVTsetup_data( |
|||
CKTcircuit *ckt) /* The circuit structure */ |
|||
{ |
|||
|
|||
Evt_Data_t *data; |
|||
|
|||
int i; |
|||
int j; |
|||
|
|||
int num_insts; |
|||
int num_ports; |
|||
int num_nodes; |
|||
|
|||
int udn_index; |
|||
int num_outputs; |
|||
|
|||
Mif_Boolean_t invert; |
|||
|
|||
Evt_Node_Data_t *node_data; |
|||
Evt_State_Data_t *state_data; |
|||
Evt_Msg_Data_t *msg_data; |
|||
/* Evt_Statistic_t *statistics_data;*/ |
|||
|
|||
Evt_Node_t *rhs; |
|||
Evt_Node_t *rhsold; |
|||
|
|||
Evt_Node_Info_t *node_info; |
|||
|
|||
|
|||
/* Allocate main substructures of data */ |
|||
/* Note that we don't free any old structures */ |
|||
/* since they are pointed to by jobs and need */ |
|||
/* to be maintained so that results from multiple */ |
|||
/* jobs are kept around like SPICE does */ |
|||
|
|||
data = &(ckt->evt->data); |
|||
CKALLOC(data->node, 1, Evt_Node_Data_t) |
|||
CKALLOC(data->state, 1, Evt_State_Data_t) |
|||
CKALLOC(data->msg, 1, Evt_Msg_Data_t) |
|||
CKALLOC(data->statistics, 1, Evt_Statistic_t) |
|||
|
|||
/* Allocate node data */ |
|||
|
|||
num_nodes = ckt->evt->counts.num_nodes; |
|||
node_data = data->node; |
|||
|
|||
CKALLOC(node_data->head, num_nodes, void *) |
|||
CKALLOC(node_data->tail, num_nodes, void *) |
|||
CKALLOC(node_data->last_step, num_nodes, void *) |
|||
CKALLOC(node_data->free, num_nodes, void *) |
|||
CKALLOC(node_data->modified_index, num_nodes, int) |
|||
CKALLOC(node_data->modified, num_nodes, Mif_Boolean_t) |
|||
CKALLOC(node_data->rhs, num_nodes, Evt_Node_t) |
|||
CKALLOC(node_data->rhsold, num_nodes, Evt_Node_t) |
|||
CKALLOC(node_data->total_load, num_nodes, double) |
|||
|
|||
/* Initialize the node data */ |
|||
|
|||
for(i = 0; i < num_nodes; i++) { |
|||
node_data->tail[i] = &(node_data->head[i]); |
|||
node_data->last_step[i] = &(node_data->head[i]); |
|||
} |
|||
|
|||
for(i = 0; i < num_nodes; i++) { |
|||
|
|||
/* Get pointers to rhs & rhsold, the user-defined node type index, */ |
|||
/* the number of outputs on the node and the invert flag */ |
|||
rhs = &(node_data->rhs[i]); |
|||
rhsold = &(node_data->rhsold[i]); |
|||
node_info = ckt->evt->info.node_table[i]; |
|||
udn_index = node_info->udn_index; |
|||
num_outputs = node_info->num_outputs; |
|||
invert = node_info->invert; |
|||
|
|||
/* Initialize the elements within rhs and rhsold */ |
|||
rhs->step = 0.0; |
|||
rhsold->step = 0.0; |
|||
if(num_outputs > 1) { |
|||
CKALLOC(rhs->output_value, num_outputs, void *) |
|||
CKALLOC(rhsold->output_value, num_outputs, void *) |
|||
for(j = 0; j < num_outputs; j++) { |
|||
(*(g_evt_udn_info[udn_index]->create)) (&(rhs->output_value[j])); |
|||
(*(g_evt_udn_info[udn_index]->initialize)) (rhs->output_value[j]); |
|||
(*(g_evt_udn_info[udn_index]->create)) (&(rhsold->output_value[j])); |
|||
(*(g_evt_udn_info[udn_index]->initialize)) (rhsold->output_value[j]); |
|||
} |
|||
} |
|||
(*(g_evt_udn_info[udn_index]->create)) (&(rhs->node_value)); |
|||
(*(g_evt_udn_info[udn_index]->initialize)) (rhs->node_value); |
|||
(*(g_evt_udn_info[udn_index]->create)) (&(rhsold->node_value)); |
|||
(*(g_evt_udn_info[udn_index]->initialize)) (rhsold->node_value); |
|||
if(invert) { |
|||
(*(g_evt_udn_info[udn_index]->create)) (&(rhs->inverted_value)); |
|||
(*(g_evt_udn_info[udn_index]->initialize)) (rhs->inverted_value); |
|||
(*(g_evt_udn_info[udn_index]->create)) (&(rhsold->inverted_value)); |
|||
(*(g_evt_udn_info[udn_index]->initialize)) (rhsold->inverted_value); |
|||
} |
|||
|
|||
/* Initialize the total load value to zero */ |
|||
node_data->total_load[i] = 0.0; |
|||
} |
|||
|
|||
|
|||
/* Allocate and initialize state data */ |
|||
|
|||
num_insts = ckt->evt->counts.num_insts; |
|||
state_data = data->state; |
|||
|
|||
CKALLOC(state_data->head, num_insts, void *) |
|||
CKALLOC(state_data->tail, num_insts, void *) |
|||
CKALLOC(state_data->last_step, num_insts, void *) |
|||
CKALLOC(state_data->free, num_insts, void *) |
|||
CKALLOC(state_data->modified_index, num_insts, int) |
|||
CKALLOC(state_data->modified, num_insts, Mif_Boolean_t) |
|||
CKALLOC(state_data->total_size, num_insts, int) |
|||
CKALLOC(state_data->desc, num_insts, void *) |
|||
|
|||
for(i = 0; i < num_insts; i++) { |
|||
state_data->tail[i] = &(state_data->head[i]); |
|||
state_data->last_step[i] = &(state_data->head[i]); |
|||
} |
|||
|
|||
|
|||
/* Allocate and initialize msg data */ |
|||
|
|||
num_ports = ckt->evt->counts.num_ports; |
|||
msg_data = data->msg; |
|||
|
|||
CKALLOC(msg_data->head, num_ports, void *) |
|||
CKALLOC(msg_data->tail, num_ports, void *) |
|||
CKALLOC(msg_data->last_step, num_ports, void *) |
|||
CKALLOC(msg_data->free, num_ports, void *) |
|||
CKALLOC(msg_data->modified_index, num_ports, int) |
|||
CKALLOC(msg_data->modified, num_ports, Mif_Boolean_t) |
|||
|
|||
for(i = 0; i < num_ports; i++) { |
|||
msg_data->tail[i] = &(msg_data->head[i]); |
|||
msg_data->last_step[i] = &(msg_data->head[i]); |
|||
} |
|||
|
|||
/* Don't need to initialize statistics since they were */ |
|||
/* calloc'ed above */ |
|||
|
|||
return(OK); |
|||
} |
|||
|
|||
|
|||
|
|||
|
|||
/* |
|||
EVTsetup_jobs |
|||
|
|||
This function prepares the jobs data for a new simulation. |
|||
*/ |
|||
|
|||
|
|||
static int EVTsetup_jobs( |
|||
CKTcircuit *ckt) /* The circuit structure */ |
|||
{ |
|||
|
|||
int i; |
|||
int num_jobs; |
|||
|
|||
Evt_Job_t *jobs; |
|||
Evt_Data_t *data; |
|||
|
|||
|
|||
jobs = &(ckt->evt->jobs); |
|||
data = &(ckt->evt->data); |
|||
|
|||
/* Increment the number of jobs */ |
|||
num_jobs = ++(jobs->num_jobs); |
|||
|
|||
/* Allocate/reallocate necessary pointers */ |
|||
CKREALLOC(jobs->job_name, num_jobs, void *) |
|||
CKREALLOC(jobs->node_data, num_jobs, void *) |
|||
CKREALLOC(jobs->state_data, num_jobs, void *) |
|||
CKREALLOC(jobs->msg_data, num_jobs, void *) |
|||
CKREALLOC(jobs->statistics, num_jobs, void *) |
|||
|
|||
/* Fill in the pointers, etc. for this new job */ |
|||
i = num_jobs - 1; |
|||
jobs->job_name[i] = MIFcopy((char *) ckt->CKTcurJob->JOBname); |
|||
jobs->node_data[i] = data->node; |
|||
jobs->state_data[i] = data->state; |
|||
jobs->msg_data[i] = data->msg; |
|||
jobs->statistics[i] = data->statistics; |
|||
|
|||
return(OK); |
|||
} |
|||
|
|||
|
|||
|
|||
/* |
|||
EVTsetup_load_ptrs |
|||
|
|||
This function setups up the required data in the MIFinstance |
|||
structure of event-driven and hybrid instances. |
|||
*/ |
|||
|
|||
|
|||
static int EVTsetup_load_ptrs( |
|||
CKTcircuit *ckt) /* The circuit structure */ |
|||
{ |
|||
|
|||
int i; |
|||
int j; |
|||
int k; |
|||
|
|||
int num_insts; |
|||
int num_conn; |
|||
int num_port; |
|||
int num_outputs; |
|||
|
|||
int node_index; |
|||
int output_subindex; |
|||
|
|||
MIFinstance *fast; |
|||
|
|||
Mif_Conn_Data_t *conn; |
|||
|
|||
Mif_Port_Type_t type; |
|||
Mif_Port_Data_t *port; |
|||
|
|||
Evt_Node_Data_t *node_data; |
|||
|
|||
|
|||
/* This function setups up the required data in the MIFinstance */ |
|||
/* structure of event-driven and hybrid instances */ |
|||
|
|||
/* Loop through all event-driven and hybrid instances */ |
|||
num_insts = ckt->evt->counts.num_insts; |
|||
for(i = 0; i < num_insts; i++) { |
|||
|
|||
/* Get the MIFinstance pointer */ |
|||
fast = ckt->evt->info.inst_table[i]->inst_ptr; |
|||
|
|||
/* Loop through all connections */ |
|||
num_conn = fast->num_conn; |
|||
for(j = 0; j < num_conn; j++) { |
|||
|
|||
/* Skip if connection is null */ |
|||
if(fast->conn[j]->is_null) |
|||
continue; |
|||
|
|||
conn = fast->conn[j]; |
|||
|
|||
/* Loop through all ports */ |
|||
num_port = conn->size; |
|||
for(k = 0; k < num_port; k++) { |
|||
|
|||
/* Get port data pointer for quick access */ |
|||
port = conn->port[k]; |
|||
|
|||
if(port->is_null) |
|||
continue; |
|||
|
|||
/* Skip if port is not digital or user-defined type */ |
|||
type = port->type; |
|||
if((type != MIF_DIGITAL) && (type != MIF_USER_DEFINED)) |
|||
continue; |
|||
|
|||
/* Set input.pvalue to point to rhsold.node_value or to */ |
|||
/* rhsold.inverted_value as appropriate */ |
|||
node_index = port->evt_data.node_index; |
|||
node_data = ckt->evt->data.node; |
|||
if(conn->is_input) { |
|||
if(port->invert) { |
|||
port->input.pvalue = node_data->rhsold[node_index]. |
|||
inverted_value; |
|||
} |
|||
else { |
|||
port->input.pvalue = node_data->rhsold[node_index]. |
|||
node_value; |
|||
} |
|||
} |
|||
|
|||
/* Set output.pvalue to point to rhs.node_value or rhs.output_value[i] */ |
|||
/* where i is given by the output_subindex in output info */ |
|||
/* depending on whether more than one output is connected to the node. */ |
|||
/* Note that this is only for the DCOP analysis. During a transient */ |
|||
/* analysis, new structures will be created and the pointers will */ |
|||
/* be set by EVTload */ |
|||
if(conn->is_output) { |
|||
num_outputs = ckt->evt->info.node_table[node_index]->num_outputs; |
|||
if(num_outputs <= 1) { |
|||
port->output.pvalue = node_data->rhs[node_index]. |
|||
node_value; |
|||
} |
|||
else { |
|||
output_subindex = port->evt_data.output_subindex; |
|||
port->output.pvalue = node_data->rhs[node_index]. |
|||
output_value[output_subindex]; |
|||
} |
|||
} |
|||
|
|||
} /* end for number of ports */ |
|||
} /* end for number of connections */ |
|||
} /* end for number of insts */ |
|||
|
|||
return(OK); |
|||
} |
|||
@ -1,512 +0,0 @@ |
|||
/*============================================================================ |
|||
FILE EVTtermInsert.c |
|||
|
|||
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 |
|||
|
|||
<date> <person name> <nature of modifications> |
|||
|
|||
SUMMARY |
|||
|
|||
This file contains function EVTtermInsert which is called by |
|||
MIF_INP2A during the parsing of the input deck. EVTtermInsert is |
|||
similar to SPICE3's INPtermInsert except that it is used when the node |
|||
type is event-driven. Calls to this function build the info lists |
|||
for instances, nodes, outputs, and ports. The completion of the info |
|||
struct is carried out by EVTinit following the parsing of all |
|||
instances in the deck. |
|||
|
|||
INTERFACES |
|||
|
|||
void EVTtermInsert( |
|||
CKTcircuit *ckt, |
|||
MIFinstance *fast, |
|||
char *node_name, |
|||
char *type_name, |
|||
int conn_num, |
|||
int port_num, |
|||
char **err_msg) |
|||
|
|||
REFERENCED FILES |
|||
|
|||
None. |
|||
|
|||
NON-STANDARD FEATURES |
|||
|
|||
None. |
|||
|
|||
============================================================================*/ |
|||
|
|||
#include <stdio.h> |
|||
#include <strings.h> |
|||
|
|||
#include "ngspice.h" |
|||
//#include "misc.h" |
|||
|
|||
#include "cktdefs.h" |
|||
//#include "util.h" |
|||
|
|||
#include "mif.h" |
|||
#include "evt.h" |
|||
#include "evtudn.h" |
|||
|
|||
#include "mifproto.h" |
|||
#include "evtproto.h" |
|||
|
|||
|
|||
static void EVTinst_insert( |
|||
CKTcircuit *ckt, |
|||
MIFinstance *fast, |
|||
int *inst_index, |
|||
char **err_msg); |
|||
|
|||
static void EVTnode_insert( |
|||
CKTcircuit *ckt, |
|||
MIFinstance *fast, |
|||
int inst_index, |
|||
char *node_name, |
|||
char *type_name, |
|||
int conn_num, |
|||
int port_num, |
|||
int *node_index, |
|||
int *output_subindex, |
|||
char **err_msg); |
|||
|
|||
static void EVTport_insert( |
|||
CKTcircuit *ckt, |
|||
MIFinstance *fast, |
|||
int inst_index, |
|||
int node_index, |
|||
char *node_name, |
|||
int conn_num, |
|||
int port_num, |
|||
int *port_index, |
|||
char **err_msg); |
|||
|
|||
static void EVToutput_insert( |
|||
CKTcircuit *ckt, |
|||
MIFinstance *fast, |
|||
int inst_index, |
|||
int node_index, |
|||
int port_index, |
|||
int output_subindex, |
|||
int conn_num, |
|||
int port_num, |
|||
char **err_msg); |
|||
|
|||
|
|||
/* |
|||
EVTtermInsert |
|||
|
|||
This function is called by MIF_INP2A during the parsing of the input |
|||
deck. EVTtermInsert is similar to 3C1's INPtermInsert except that it is |
|||
used when the node type is event-driven. Calls to this function build |
|||
the info lists for instances, nodes, outputs, and ports. The |
|||
completion of the info struct is carried out by EVTinit following |
|||
the parsing of all instances in the deck. |
|||
*/ |
|||
|
|||
|
|||
void EVTtermInsert( |
|||
CKTcircuit *ckt, /* The circuit structure */ |
|||
MIFinstance *fast, /* The instance being parsed */ |
|||
char *node_name, /* The node name */ |
|||
char *type_name, /* The type of node */ |
|||
int conn_num, /* The port connection number */ |
|||
int port_num, /* The sub-port number - 0 for scalar ports */ |
|||
char **err_msg) /* Returned error message if any */ |
|||
{ |
|||
|
|||
int inst_index; |
|||
int node_index; |
|||
int port_index; |
|||
|
|||
int output_subindex; |
|||
|
|||
|
|||
/* Get the instance index and create new entry in inst */ |
|||
/* info list if this is a new instance. */ |
|||
EVTinst_insert(ckt, fast, &inst_index, err_msg); |
|||
if(*err_msg) |
|||
return; |
|||
|
|||
/* Get the node index and create new entry in node info */ |
|||
/* list if this is a new node */ |
|||
EVTnode_insert(ckt, fast, inst_index, node_name, type_name, |
|||
conn_num, port_num, &node_index, &output_subindex, |
|||
err_msg); |
|||
if(*err_msg) |
|||
return; |
|||
|
|||
/* Create new entry in port info list and return port index */ |
|||
EVTport_insert(ckt, fast, inst_index, node_index, node_name, conn_num, |
|||
port_num, &port_index, err_msg); |
|||
if(*err_msg) |
|||
return; |
|||
|
|||
/* Create new entry in output info list if appropriate */ |
|||
if(fast->conn[conn_num]->is_output) { |
|||
EVToutput_insert(ckt, fast, inst_index, node_index, port_index, |
|||
output_subindex, conn_num, port_num, err_msg); |
|||
if(*err_msg) |
|||
return; |
|||
} |
|||
} |
|||
|
|||
|
|||
|
|||
|
|||
/* |
|||
EVTinst_insert |
|||
|
|||
This function locates or creates a new entry for the specified |
|||
instance in the event-driven ``info'' structures during parsing. |
|||
*/ |
|||
|
|||
|
|||
static void EVTinst_insert( |
|||
CKTcircuit *ckt, /* The circuit structure */ |
|||
MIFinstance *fast, /* The instance being parsed */ |
|||
int *inst_index, /* The index found or added */ |
|||
char **err_msg) /* Error message if any */ |
|||
{ |
|||
|
|||
Mif_Boolean_t found; |
|||
int index; |
|||
|
|||
Evt_Inst_Info_t *inst; |
|||
Evt_Inst_Info_t **inst_ptr; |
|||
|
|||
|
|||
/* Scan list of instances in event structure to see if already there */ |
|||
/* and get the index */ |
|||
found = MIF_FALSE; |
|||
index = 0; |
|||
inst = ckt->evt->info.inst_list; |
|||
inst_ptr = &(ckt->evt->info.inst_list); |
|||
|
|||
while(inst) { |
|||
if(inst->inst_ptr == fast) { |
|||
found = MIF_TRUE; |
|||
break; |
|||
} |
|||
else { |
|||
index++; |
|||
inst_ptr = &(inst->next); |
|||
inst = inst->next; |
|||
} |
|||
} |
|||
|
|||
|
|||
/* If not found, create a new entry in list and increment the */ |
|||
/* instance count in the event structure */ |
|||
if(! found) { |
|||
*inst_ptr = (void *) MALLOC(sizeof(Evt_Inst_Info_t)); |
|||
inst = *inst_ptr; |
|||
inst->next = NULL; |
|||
inst->inst_ptr = fast; |
|||
index = ckt->evt->counts.num_insts; |
|||
(ckt->evt->counts.num_insts)++; |
|||
} |
|||
|
|||
/* Record the inst index in the MIFinstance structure and return it */ |
|||
fast->inst_index = index; |
|||
*inst_index = index; |
|||
} |
|||
|
|||
|
|||
|
|||
/* |
|||
EVTnode_insert |
|||
|
|||
This function locates or creates a new entry for the specified |
|||
node in the event-driven ``info'' structures during parsing. |
|||
*/ |
|||
|
|||
|
|||
static void EVTnode_insert( |
|||
CKTcircuit *ckt, /* The circuit structure */ |
|||
MIFinstance *fast, /* The instance being parsed */ |
|||
int inst_index, /* The index of inst in evt structures */ |
|||
char *node_name, /* The node name */ |
|||
char *type_name, /* The node type specified */ |
|||
int conn_num, /* The port connection number */ |
|||
int port_num, /* The sub-port number - 0 if scalar port */ |
|||
int *node_index, /* The node index found or added */ |
|||
int *output_subindex, /* The output number on this node */ |
|||
char **err_msg) /* Error message text if any */ |
|||
{ |
|||
|
|||
int i; |
|||
int udn_index=0; |
|||
Mif_Boolean_t found; |
|||
|
|||
int index; |
|||
|
|||
Evt_Node_Info_t *node; |
|||
Evt_Node_Info_t **node_ptr; |
|||
|
|||
Evt_Inst_Index_t *inst; |
|||
Evt_Inst_Index_t **inst_ptr; |
|||
|
|||
|
|||
/* *************************************** */ |
|||
/* Get and check the node type information */ |
|||
/* *************************************** */ |
|||
|
|||
/* Scan the list of user-defined node types and get the index */ |
|||
found = MIF_FALSE; |
|||
for(i = 0; i < g_evt_num_udn_types; i++) { |
|||
if(strcmp(type_name, g_evt_udn_info[i]->name) == 0) { |
|||
udn_index = i; |
|||
found = MIF_TRUE; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
/* Report error if not recognized */ |
|||
if(! found) { |
|||
*err_msg = "Unrecognized connection type"; |
|||
return; |
|||
} |
|||
|
|||
/* If inverted, check to be sure invert function exists for type */ |
|||
if(fast->conn[conn_num]->port[port_num]->invert) { |
|||
if(g_evt_udn_info[udn_index]->invert == NULL) { |
|||
*err_msg = "Connection type cannot be inverted"; |
|||
return; |
|||
} |
|||
} |
|||
|
|||
|
|||
/* ******************************************* */ |
|||
/* Find/create entry in event-driven node list */ |
|||
/* ******************************************* */ |
|||
|
|||
/* Scan list of nodes in event structure to see if already there */ |
|||
/* and get the index */ |
|||
found = MIF_FALSE; |
|||
index = 0; |
|||
node = ckt->evt->info.node_list; |
|||
node_ptr = &(ckt->evt->info.node_list); |
|||
|
|||
while(node) { |
|||
if(strcmp(node_name, node->name) == 0) { |
|||
found = MIF_TRUE; |
|||
break; |
|||
} |
|||
else { |
|||
index++; |
|||
node_ptr = &(node->next); |
|||
node = node->next; |
|||
} |
|||
} |
|||
|
|||
|
|||
/* If found, verify that connection type is same as type of node */ |
|||
if(found) { |
|||
if(udn_index != node->udn_index) { |
|||
*err_msg = "Node cannot have two different types"; |
|||
return; |
|||
} |
|||
} |
|||
|
|||
/* If not found, create a new entry in list and increment the */ |
|||
/* node count in the event structure */ |
|||
if(! found) { |
|||
*node_ptr = (void *) MALLOC(sizeof(Evt_Node_Info_t)); |
|||
node = *node_ptr; |
|||
node->next = NULL; |
|||
node->name = MIFcopy(node_name); |
|||
node->udn_index = udn_index; |
|||
index = ckt->evt->counts.num_nodes; |
|||
(ckt->evt->counts.num_nodes)++; |
|||
} |
|||
|
|||
|
|||
/* ******************************************* */ |
|||
/* Update remaining items in node list struct */ |
|||
/* ******************************************* */ |
|||
|
|||
/* Update flag on node that indicates if inversion is used by any */ |
|||
/* instance inputs */ |
|||
if(fast->conn[conn_num]->is_input) |
|||
if(! node->invert) |
|||
node->invert = fast->conn[conn_num]->port[port_num]->invert; |
|||
|
|||
/* Increment counts of ports, outputs connected to node */ |
|||
(node->num_ports)++; |
|||
if(fast->conn[conn_num]->is_output) |
|||
(node->num_outputs)++; |
|||
|
|||
/* If this is an input, add instance to list if not already there */ |
|||
if(fast->conn[conn_num]->is_input) { |
|||
|
|||
found = MIF_FALSE; |
|||
inst = node->inst_list; |
|||
inst_ptr = &(node->inst_list); |
|||
|
|||
while(inst) { |
|||
if(inst_index == inst->index) { |
|||
found = MIF_TRUE; |
|||
break; |
|||
} |
|||
else { |
|||
inst_ptr = &(inst->next); |
|||
inst = inst->next; |
|||
} |
|||
} |
|||
|
|||
if(! found) { |
|||
(node->num_insts)++; |
|||
*inst_ptr = (void *) MALLOC(sizeof(Evt_Inst_Index_t)); |
|||
inst = *inst_ptr; |
|||
inst->next = NULL; |
|||
inst->index = inst_index; |
|||
} |
|||
} |
|||
|
|||
/* Record the node index in the MIFinstance structure */ |
|||
fast->conn[conn_num]->port[port_num]->evt_data.node_index = index; |
|||
|
|||
/* Return the node index */ |
|||
*node_index = index; |
|||
if(fast->conn[conn_num]->is_output) |
|||
*output_subindex = node->num_outputs - 1; |
|||
else |
|||
*output_subindex = 0; /* just for safety - shouldn't need this */ |
|||
} |
|||
|
|||
|
|||
|
|||
/* |
|||
EVTport_insert |
|||
|
|||
This function locates or creates a new entry for the specified |
|||
port in the event-driven ``info'' structures during parsing. |
|||
*/ |
|||
|
|||
|
|||
static void EVTport_insert( |
|||
CKTcircuit *ckt, /* The circuit structure */ |
|||
MIFinstance *fast, /* The instance being parsed */ |
|||
int inst_index, /* The index of inst in evt structures */ |
|||
int node_index, /* The index of the node in evt structures */ |
|||
char *node_name, /* The node name */ |
|||
int conn_num, /* The port connection number */ |
|||
int port_num, /* The sub-port number - 0 if scalar port */ |
|||
int *port_index, /* The port index found or added */ |
|||
char **err_msg) /* Error message text if any */ |
|||
{ |
|||
|
|||
Evt_Port_Info_t *port; |
|||
Evt_Port_Info_t **port_ptr; |
|||
|
|||
int index; |
|||
|
|||
/* Find the end of the port info list */ |
|||
port = ckt->evt->info.port_list; |
|||
port_ptr = &(ckt->evt->info.port_list); |
|||
|
|||
index = 0; |
|||
while(port) { |
|||
port_ptr = &(port->next); |
|||
port = port->next; |
|||
index++; |
|||
} |
|||
|
|||
|
|||
/* Update the port count and create a new entry in the list */ |
|||
|
|||
(ckt->evt->counts.num_ports)++; |
|||
|
|||
*port_ptr = (void *) MALLOC(sizeof(Evt_Port_Info_t)); |
|||
port = *port_ptr; |
|||
|
|||
/* Fill in the elements */ |
|||
port->next = NULL; |
|||
port->inst_index = inst_index; |
|||
port->node_index = node_index; |
|||
port->node_name = MIFcopy(node_name); |
|||
port->inst_name = MIFcopy((char *) fast->MIFname); |
|||
port->conn_name = MIFcopy((char *) fast->conn[conn_num]->name); |
|||
port->port_num = port_num; |
|||
|
|||
/* Record the port index in the MIFinstance structure */ |
|||
fast->conn[conn_num]->port[port_num]->evt_data.port_index = index; |
|||
|
|||
/* Return the port index */ |
|||
*port_index = index; |
|||
} |
|||
|
|||
|
|||
|
|||
|
|||
/* |
|||
EVToutput_insert |
|||
|
|||
This function locates or creates a new entry for the specified |
|||
output in the event-driven ``info'' structures during parsing. |
|||
*/ |
|||
|
|||
|
|||
static void EVToutput_insert( |
|||
CKTcircuit *ckt, /* The circuit structure */ |
|||
MIFinstance *fast, /* The instance being parsed */ |
|||
int inst_index, /* The index of inst in evt structures */ |
|||
int node_index, /* The index of the node in evt structures */ |
|||
int port_index, /* The index of the port in the evt structures */ |
|||
int output_subindex, /* The output on this node */ |
|||
int conn_num, /* The port connection number */ |
|||
int port_num, /* The sub-port number - 0 if scalar port */ |
|||
char **err_msg) /* Error message text if any */ |
|||
{ |
|||
Evt_Output_Info_t *output; |
|||
Evt_Output_Info_t **output_ptr; |
|||
|
|||
int index; |
|||
|
|||
/* Find the end of the port info list */ |
|||
output = ckt->evt->info.output_list; |
|||
output_ptr = &(ckt->evt->info.output_list); |
|||
|
|||
index = 0; |
|||
while(output) { |
|||
output_ptr = &(output->next); |
|||
output = output->next; |
|||
index++; |
|||
} |
|||
|
|||
|
|||
/* Update the port count and create a new entry in the list */ |
|||
|
|||
(ckt->evt->counts.num_outputs)++; |
|||
|
|||
*output_ptr = (void *) MALLOC(sizeof(Evt_Output_Info_t)); |
|||
output = *output_ptr; |
|||
|
|||
/* Fill in the elements */ |
|||
output->next = NULL; |
|||
output->inst_index = inst_index; |
|||
output->node_index = node_index; |
|||
output->port_index = port_index; |
|||
output->output_subindex = output_subindex; |
|||
|
|||
/* Record the output index and subindex in the MIFinstance structure */ |
|||
fast->conn[conn_num]->port[port_num]->evt_data.output_index = index; |
|||
fast->conn[conn_num]->port[port_num]->evt_data.output_subindex |
|||
= output_subindex; |
|||
|
|||
} |
|||
@ -1,67 +0,0 @@ |
|||
Code Model Test - AC: gain, summer, mult, divide, pwl |
|||
* |
|||
* |
|||
*** analysis type *** |
|||
.ac dec 10 10 1000 |
|||
* |
|||
*** input sources *** |
|||
* |
|||
v1 1 0 1.0 AC 1.0 0.0 |
|||
* |
|||
v2 2 0 1.0 AC 1.0 0.0 |
|||
* |
|||
v3 3 0 DC 2.0 |
|||
* |
|||
v4 4 0 0.5 AC 0.5 0.0 |
|||
* |
|||
*** gain block *** |
|||
a1 1 10 gain1 |
|||
.model gain1 gain (in_offset=0.0 gain=2.0 out_offset=0.0) |
|||
* |
|||
* |
|||
*** summer block *** |
|||
a2 [1 2] 20 summer1 |
|||
.model summer1 summer (in_offset=[0.0 0.0] in_gain=[1.0 1.0] |
|||
+ out_gain=1.0 out_offset=0.0) |
|||
* |
|||
* |
|||
*** mult block *** |
|||
a3 [1 3] 30 mult1 |
|||
.model mult1 mult (in_offset=[0.0 0.0] in_gain=[1.0 1.0] |
|||
+ out_gain=1.0 out_offset=0.0) |
|||
* |
|||
* |
|||
*** divider block *** |
|||
a4 1 3 40 divide1 |
|||
.model divide1 divide (num_offset=0.0 num_gain=1.0 den_offset=0.0 den_gain=1.0 |
|||
+ den_lower_limit=1.0e-10 den_domain=1.0e-16 |
|||
+ fraction=false out_gain=1.0 out_offset=0.0) |
|||
* |
|||
* |
|||
*** pwl block *** |
|||
a5 4 50 pwl1 |
|||
.model pwl1 pwl (x_array=[-1.0 0.0 1.0 2.0 3.0 4.0 5.0] |
|||
+ y_array=[-1.0 0.0 1.0 4.0 4.5 5.0 5.0] |
|||
+ input_domain=0.01 fraction=TRUE) |
|||
* |
|||
* |
|||
*** resistors to ground *** |
|||
r1 1 0 1k |
|||
r2 2 0 1k |
|||
r3 3 0 1k |
|||
r4 4 0 1k |
|||
* |
|||
r10 10 0 1k |
|||
r20 20 0 1k |
|||
r30 30 0 1k |
|||
r40 40 0 1k |
|||
r50 50 0 1k |
|||
* |
|||
* |
|||
.end |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
@ -1,61 +0,0 @@ |
|||
Code Model Test - DC: gain, summer, mult, divide, pwl |
|||
* |
|||
* |
|||
*** analysis type *** |
|||
.op |
|||
* |
|||
*** input sources *** |
|||
v1 1 0 DC 2 |
|||
* |
|||
v2 2 0 DC 2 |
|||
* |
|||
*** gain block *** |
|||
a1 1 10 gain1 |
|||
.model gain1 gain (in_offset=0.0 gain=2.0 out_offset=0.0) |
|||
* |
|||
* |
|||
*** summer block *** |
|||
a2 [1 2] 20 summer1 |
|||
.model summer1 summer (in_offset=[0.0 0.0] in_gain=[1.0 1.0] |
|||
+ out_gain=1.0 out_offset=0.0) |
|||
* |
|||
* |
|||
*** mult block *** |
|||
a3 [1 1] 30 mult1 |
|||
.model mult1 mult (in_offset=[0.0 0.0] in_gain=[1.0 1.0] |
|||
+ out_gain=0.1 out_offset=0.0) |
|||
* |
|||
* |
|||
*** divider block *** |
|||
a4 2 1 40 divide1 |
|||
.model divide1 divide (num_offset=0.0 num_gain=1.0 den_offset=0.0 den_gain=1.0 |
|||
+ den_lower_limit=1.0e-10 den_domain=1.0e-16 |
|||
+ fraction=false out_gain=1.0 out_offset=0.0) |
|||
* |
|||
* |
|||
*** pwl block *** |
|||
a5 1 50 pwl1 |
|||
.model pwl1 pwl (x_array=[-1.0 0.0 1.0 2.0 3.0 4.0 5.0] |
|||
+ y_array=[ 0.0 0.0 1.0 4.0 4.5 5.0 5.0] |
|||
+ input_domain=0.01 fraction=TRUE) |
|||
* |
|||
* |
|||
*** resistors to ground *** |
|||
r1 1 0 1k |
|||
r2 2 0 1k |
|||
r3 3 0 1k |
|||
* |
|||
r10 10 0 1k |
|||
r20 20 0 1k |
|||
r30 30 0 1k |
|||
r40 40 0 1k |
|||
r50 50 0 1k |
|||
* |
|||
* |
|||
.end |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
@ -1,61 +0,0 @@ |
|||
Code Model Test - Swept DC: gain, summer, mult, divide, pwl |
|||
* |
|||
* |
|||
*** analysis type *** |
|||
.dc v1 .1 10 .1 |
|||
* |
|||
*** input sources *** |
|||
v1 1 0 DC 2 |
|||
* |
|||
v2 2 0 DC 2 |
|||
* |
|||
*** gain block *** |
|||
a1 1 10 gain1 |
|||
.model gain1 gain (in_offset=0.0 gain=2.0 out_offset=0.0) |
|||
* |
|||
* |
|||
*** summer block *** |
|||
a2 [1 2] 20 summer1 |
|||
.model summer1 summer (in_offset=[0.0 0.0] in_gain=[1.0 1.0] |
|||
+ out_gain=1.0 out_offset=0.0) |
|||
* |
|||
* |
|||
*** mult block *** |
|||
a3 [1 1] 30 mult1 |
|||
.model mult1 mult (in_offset=[0.0 0.0] in_gain=[1.0 1.0] |
|||
+ out_gain=0.1 out_offset=0.0) |
|||
* |
|||
* |
|||
*** divider block *** |
|||
a4 2 1 40 divide1 |
|||
.model divide1 divide (num_offset=0.0 num_gain=1.0 den_offset=0.0 den_gain=1.0 |
|||
+ den_lower_limit=1.0e-10 den_domain=1.0e-16 |
|||
+ fraction=false out_gain=1.0 out_offset=0.0) |
|||
* |
|||
* |
|||
*** pwl block *** |
|||
a5 1 50 pwl1 |
|||
.model pwl1 pwl (x_array=[-1.0 0.0 1.0 2.0 3.0 4.0 5.0] |
|||
+ y_array=[ 0.0 0.0 1.0 4.0 4.5 5.0 5.0] |
|||
+ input_domain=0.01 fraction=TRUE) |
|||
* |
|||
* |
|||
*** resistors to ground *** |
|||
r1 1 0 1k |
|||
r2 2 0 1k |
|||
r3 3 0 1k |
|||
* |
|||
r10 10 0 1k |
|||
r20 20 0 1k |
|||
r30 30 0 1k |
|||
r40 40 0 1k |
|||
r50 50 0 1k |
|||
* |
|||
* |
|||
.end |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
@ -1,62 +0,0 @@ |
|||
Code Model Test - Transient: gain, summer, mult, divide, pwl |
|||
* |
|||
* |
|||
*** analysis type *** |
|||
.tran .1s 10s |
|||
* |
|||
*** input sources *** |
|||
* |
|||
v1 1 0 DC PWL(0 0 10 10) |
|||
* |
|||
v2 2 0 DC 2 |
|||
* |
|||
*** gain block *** |
|||
a1 1 10 gain1 |
|||
.model gain1 gain (in_offset=0.0 gain=2.0 out_offset=0.0) |
|||
* |
|||
* |
|||
*** summer block *** |
|||
a2 [1 2] 20 summer1 |
|||
.model summer1 summer (in_offset=[0.0 0.0] in_gain=[1.0 1.0] |
|||
+ out_gain=1.0 out_offset=0.0) |
|||
* |
|||
* |
|||
*** mult block *** |
|||
a3 [1 1] 30 mult1 |
|||
.model mult1 mult (in_offset=[0.0 0.0] in_gain=[1.0 1.0] |
|||
+ out_gain=0.1 out_offset=0.0) |
|||
* |
|||
* |
|||
*** divider block *** |
|||
a4 2 1 40 divide1 |
|||
.model divide1 divide (num_offset=0.0 num_gain=1.0 den_offset=0.0 den_gain=1.0 |
|||
+ den_lower_limit=0.1 den_domain=1.0e-16 |
|||
+ fraction=false out_gain=1.0 out_offset=0.0) |
|||
* |
|||
* |
|||
*** pwl block *** |
|||
a5 1 50 pwl1 |
|||
.model pwl1 pwl (x_array=[-1.0 0.0 1.0 2.0 3.0 4.0 5.0] |
|||
+ y_array=[ 0.0 0.0 1.0 4.0 4.5 5.0 5.0] |
|||
+ input_domain=0.01 fraction=TRUE) |
|||
* |
|||
* |
|||
*** resistors to ground *** |
|||
r1 1 0 1k |
|||
r2 2 0 1k |
|||
r3 3 0 1k |
|||
* |
|||
r10 10 0 1k |
|||
r20 20 0 1k |
|||
r30 30 0 1k |
|||
r40 40 0 1k |
|||
r50 50 0 1k |
|||
* |
|||
* |
|||
.end |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
@ -1,66 +0,0 @@ |
|||
Code Model Test - Swept DC: int, d_dt, s_xfer, core, lcouple |
|||
* |
|||
* |
|||
*** analysis type *** |
|||
.ac dec 10 10 1000 |
|||
* |
|||
* |
|||
*** input sources *** |
|||
* |
|||
v1 1 0 1.0 AC 1.0 0.0 |
|||
* |
|||
* |
|||
*** integrator block *** |
|||
a1 1 10 int1 |
|||
.model int1 int (in_offset=0.0 gain=2.0 out_lower_limit=-1.0e6 |
|||
+ out_upper_limit=1.0e6 limit_range=1.0e-6 out_ic=0.0) |
|||
* |
|||
* |
|||
*** differentiator block *** |
|||
a2 1 20 d_dt1 |
|||
.model d_dt1 d_dt (out_offset=0.0 gain=1.0 out_lower_limit=-1.0e6 |
|||
+ out_upper_limit=1.0e6 limit_range=1.0e-6) |
|||
* |
|||
* |
|||
*** s_xfer block *** |
|||
a3 1 30 filter1 |
|||
.model filter1 s_xfer (in_offset=0.0 gain=1.0 num_coeff=[1.0] |
|||
+ den_coeff=[1.0 1.414214 1.0] int_ic=[0.0 0.0] |
|||
+ denormalized_freq=628.0) |
|||
* |
|||
* |
|||
* |
|||
*** magnetic core & inductive coupling *** |
|||
v40 45 46 0.0 |
|||
a4 40 45 core1 |
|||
.model core1 core (H_array=[-2.0 -1.0 1.0 2.0] |
|||
+ B_array=[-2.0 -1.0 1.0 2.0] |
|||
+ area=1.0 length=1.0 input_domain=1.0e-6 |
|||
+ fraction=TRUE mode=1 |
|||
+ in_low=-1.0 in_high=1.0 hyst=0.5 |
|||
+ out_lower_limit=-1.0 out_upper_limit=1.0) |
|||
* |
|||
* |
|||
r5 1 50 100.0 |
|||
a5 (50 0) (40 46) inductor1 |
|||
.model inductor1 lcouple (num_turns=10) |
|||
* |
|||
* |
|||
*** resistors to ground *** |
|||
r1 1 0 1k |
|||
* |
|||
r10 10 0 1e12 |
|||
r20 20 0 1e12 |
|||
r30 30 0 1e12 |
|||
r40 40 0 1e12 |
|||
r45 45 0 1e12 |
|||
r50 50 0 1e12 |
|||
* |
|||
* |
|||
.end |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
@ -1,63 +0,0 @@ |
|||
Code Model Test - DC: int, d_dt, s_xfer, core, lcouple |
|||
* |
|||
* |
|||
*** analysis type *** |
|||
.op |
|||
* |
|||
*** input sources *** |
|||
v1 1 0 DC 1.0 |
|||
* |
|||
* |
|||
* |
|||
* |
|||
*** integrator block *** |
|||
a1 1 10 int1 |
|||
.model int1 int (in_offset=0.0 gain=2.0 out_lower_limit=-1.0e6 |
|||
+ out_upper_limit=1.0e6 limit_range=1.0e-6 out_ic=0.0) |
|||
* |
|||
* |
|||
*** differentiator block *** |
|||
a2 1 20 d_dt1 |
|||
.model d_dt1 d_dt (out_offset=0.0 gain=1.0 out_lower_limit=-1.0e6 |
|||
+ out_upper_limit=1.0e6 limit_range=1.0e-6) |
|||
* |
|||
* |
|||
*** s_xfer block *** |
|||
a3 1 30 filter1 |
|||
.model filter1 s_xfer (in_offset=0.0 gain=1.0 num_coeff=[1.0] |
|||
+ den_coeff=[1.0 1.425625 1.516203] int_ic=[0.0 0.0] |
|||
+ denormalized_freq=6283.2) |
|||
* |
|||
* |
|||
*** magnetic core & inductive coupling *** |
|||
a4 40 45 core1 |
|||
.model core1 core (H_array=[-2.0 -1.0 1.0 2.0] |
|||
+ B_array=[-2.0 -1.0 1.0 2.0] |
|||
+ area=1.0 length=1.0 input_domain=1.0e-6 |
|||
+ fraction=TRUE mode=1 |
|||
+ in_low=-1.0 in_high=1.0 hyst=0.5 |
|||
+ out_lower_limit=-1.0 out_upper_limit=1.0) |
|||
* |
|||
* |
|||
r5 1 50 100.0 |
|||
a5 (50 0) (40 45) inductor1 |
|||
.model inductor1 lcouple (num_turns=10) |
|||
* |
|||
* |
|||
*** resistors to ground *** |
|||
r1 1 0 1k |
|||
* |
|||
r10 10 0 1k |
|||
r20 20 0 1k |
|||
r30 30 0 1k |
|||
r40 40 0 1k |
|||
r50 50 0 1k |
|||
* |
|||
* |
|||
.end |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
@ -1,64 +0,0 @@ |
|||
Code Model Test - Swept DC: int, d_dt, s_xfer, core, lcouple |
|||
* |
|||
* |
|||
*** analysis type *** |
|||
.dc v1 .1 10 .5 |
|||
* |
|||
*** input sources *** |
|||
v1 1 0 DC 2 |
|||
* |
|||
* |
|||
*** integrator block *** |
|||
a1 1 10 int1 |
|||
.model int1 int (in_offset=0.0 gain=2.0 out_lower_limit=-1.0e6 |
|||
+ out_upper_limit=1.0e6 limit_range=1.0e-6 out_ic=0.0) |
|||
* |
|||
* |
|||
*** differentiator block *** |
|||
a2 1 20 d_dt1 |
|||
.model d_dt1 d_dt (out_offset=0.0 gain=1.0 out_lower_limit=-1.0e6 |
|||
+ out_upper_limit=1.0e6 limit_range=1.0e-6) |
|||
* |
|||
* |
|||
*** s_xfer block *** |
|||
a3 1 30 filter1 |
|||
.model filter1 s_xfer (in_offset=0.0 gain=1.0 num_coeff=[1.0] |
|||
+ den_coeff=[1.0 1.414214 1.0] int_ic=[0.0 0.0] |
|||
+ denormalized_freq=1.0) |
|||
* |
|||
* |
|||
* |
|||
*** magnetic core & inductive coupling *** |
|||
v40 45 46 0.0 |
|||
a4 40 45 core1 |
|||
.model core1 core (H_array=[-2.0 -1.0 1.0 2.0] |
|||
+ B_array=[-2.0 -1.0 1.0 2.0] |
|||
+ area=1.0 length=1.0 input_domain=1.0e-6 |
|||
+ fraction=TRUE mode=1 |
|||
+ in_low=-1.0 in_high=1.0 hyst=0.5 |
|||
+ out_lower_limit=-1.0 out_upper_limit=1.0) |
|||
* |
|||
* |
|||
r5 1 50 100.0 |
|||
a5 (50 0) (40 46) inductor1 |
|||
.model inductor1 lcouple (num_turns=10) |
|||
* |
|||
* |
|||
*** resistors to ground *** |
|||
r1 1 0 1k |
|||
* |
|||
r10 10 0 1e12 |
|||
r20 20 0 1e12 |
|||
r30 30 0 1e12 |
|||
r40 40 0 1e12 |
|||
r45 45 0 1e12 |
|||
r50 50 0 1e12 |
|||
* |
|||
* |
|||
.end |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
@ -1,67 +0,0 @@ |
|||
Code Model Test - Transient: int, d_dt, s_xfer, core, lcouple |
|||
* |
|||
* |
|||
*** analysis type *** |
|||
.tran .1s 10s |
|||
* |
|||
*** input sources *** |
|||
* |
|||
v1 1 0 DC PWL(0 0 10 10) |
|||
* |
|||
v2 2 0 DC PWL(0 0 0.1 0.1 0.2 0.9 0.3 1.0 10 1.0) |
|||
* |
|||
* |
|||
* |
|||
*** integrator block *** |
|||
a1 1 10 int1 |
|||
.model int1 int (in_offset=0.0 gain=2.0 out_lower_limit=-1.0e6 |
|||
+ out_upper_limit=1.0e6 limit_range=1.0e-6 out_ic=0.0) |
|||
* |
|||
* |
|||
*** differentiator block *** |
|||
a2 1 20 d_dt1 |
|||
.model d_dt1 d_dt (out_offset=0.0 gain=1.0 out_lower_limit=-1.0e6 |
|||
+ out_upper_limit=1.0e6 limit_range=1.0e-6) |
|||
* |
|||
* |
|||
*** s_xfer block *** |
|||
a3 2 30 filter1 |
|||
.model filter1 s_xfer (in_offset=0.0 gain=1.0 num_coeff=[1.0] |
|||
+ den_coeff=[1.0 1.414214 1.0] int_ic=[0.0 0.0] |
|||
+ denormalized_freq=1.0) |
|||
* |
|||
* |
|||
* |
|||
*** magnetic core & inductive coupling *** |
|||
a4 40 45 core1 |
|||
.model core1 core (H_array=[-2.0 -1.0 1.0 2.0] |
|||
+ B_array=[-2.0 -1.0 1.0 2.0] |
|||
+ area=1.0 length=1.0 input_domain=1.0e-6 |
|||
+ fraction=TRUE mode=1 |
|||
+ in_low=-1.0 in_high=1.0 hyst=0.5 |
|||
+ out_lower_limit=-1.0 out_upper_limit=1.0) |
|||
* |
|||
* |
|||
r5 1 50 100.0 |
|||
a5 (50 0) (40 45) inductor1 |
|||
.model inductor1 lcouple (num_turns=10) |
|||
* |
|||
* |
|||
*** resistors to ground *** |
|||
r1 1 0 1k |
|||
r2 2 0 1k |
|||
* |
|||
r10 10 0 1k |
|||
r20 20 0 1k |
|||
r30 30 0 1k |
|||
r40 40 0 1k |
|||
r50 50 0 1k |
|||
* |
|||
* |
|||
.end |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
@ -1,81 +0,0 @@ |
|||
Code Model Test - AC: hyst, limit, ilimit, climit, cmeter, lmeter |
|||
* |
|||
* |
|||
*** analysis type *** |
|||
.ac dec 10 10 1000 |
|||
* |
|||
* |
|||
*** input sources *** |
|||
* |
|||
v1 1 0 1.0 AC 1.0 0.0 |
|||
* |
|||
v2 2 0 DC 10.0 |
|||
* |
|||
v3 3 0 DC -10.0 |
|||
* |
|||
* |
|||
* |
|||
*** hyst block *** |
|||
a1 1 10 hyst1 |
|||
.model hyst1 hyst (in_low=0.0 in_high=1.0 hyst=0.1 out_lower_limit=0.0 |
|||
+ out_upper_limit=1.0 input_domain=0.01 fraction=TRUE) |
|||
* |
|||
* |
|||
*** limit block *** |
|||
a2 1 20 limit1 |
|||
.model limit1 limit (in_offset=0.0 gain=1.0 out_lower_limit=-1.0e6 |
|||
+ out_upper_limit=1.0e6 limit_range=1.0e-6 fraction=FALSE) |
|||
* |
|||
* |
|||
*** ilimit block *** |
|||
a3 1 2 3 30 ilimit1 |
|||
.model ilimit1 ilimit (in_offset=0.0 gain=1.0 r_out_source=1.0 |
|||
+ r_out_sink=1.0 i_limit_source=1.0 |
|||
+ i_limit_sink=1.0 v_pwr_range=1.0e-3 |
|||
+ i_source_range=1.0e-6 i_sink_range=1.0e-6 |
|||
+ r_out_domain=1.0e-6) |
|||
* |
|||
* |
|||
*** climit block *** |
|||
a4 1 2 3 40 climit1 |
|||
.model climit1 climit (in_offset=0.0 gain=1.0 upper_delta=0.0 |
|||
+ lower_delta=0.0 limit_range=1.0e-6 |
|||
+ fraction=FALSE) |
|||
* |
|||
* |
|||
*** cmeter block *** |
|||
c5 51 0 1.0e-6 |
|||
a5 51 50 cmeter1 |
|||
.model cmeter1 cmeter (gain=1.0) |
|||
* |
|||
* |
|||
* |
|||
*** lmeter block *** |
|||
l6 61 0 1.0e-6 |
|||
a6 61 60 lmeter1 |
|||
.model lmeter1 lmeter (gain=1.0) |
|||
* |
|||
* |
|||
* |
|||
*** resistors to ground *** |
|||
r1 1 0 10k |
|||
r2 2 0 10k |
|||
r3 3 0 10k |
|||
* |
|||
r10 10 0 10k |
|||
r20 20 0 10k |
|||
r30 30 0 10k |
|||
r40 40 0 10k |
|||
r50 50 0 10k |
|||
r51 51 0 10k |
|||
r60 60 0 10k |
|||
r61 61 0 10k |
|||
* |
|||
* |
|||
.end |
|||
|
|||
|
|||
|
|||
|
|||
|
|||
|
|||
Some files were not shown because too many files changed in this diff
Write
Preview
Loading…
Cancel
Save
Reference in new issue