Jspice3
dioload.c
Go to the documentation of this file.
1 /***************************************************************************
2 JSPICE3 adaptation of Spice3f2 - Copyright (c) Stephen R. Whiteley 1992
3 Copyright 1990 Regents of the University of California. All rights reserved.
4 Authors: 1985 Thomas L. Quarles
5  1992 Stephen R. Whiteley
6 ****************************************************************************/
7 
8 #include "spice.h"
9 #include <stdio.h>
10 #include "diodefs.h"
11 #include "const.h"
12 #include "util.h"
13 #include "sperror.h"
14 #include "niext.h"
15 
16 
17 #ifdef __STDC__
20 static int dio_pnjlim(double*,double,double,double);
21 static void dio_iv(CKTcircuit*,DIOmodel*,DIOinstance*);
22 static void dio_cap(CKTcircuit*,DIOmodel*,DIOinstance*);
23 static void dio_load(CKTcircuit*,DIOmodel*,DIOinstance*);
24 #else
25 static int dio_bypass();
26 static int dio_limiting();
27 static void dio_iv();
28 static void dio_cap();
29 static void dio_load();
30 #endif
31 
32 
33 int
34 DIOload(inModel,ckt)
35 
36 /* actually load the current stamp into the
37  * sparse matrix previously provided
38  */
39 GENmodel *inModel;
40 CKTcircuit *ckt;
41 {
42  DIOmodel *model = (DIOmodel*)inModel;
43  DIOinstance *here;
44  double ceq;
45  double geq;
46  int error;
47 
48  if (ckt->CKTmode & MODEINITFLOAT) {
49 
50  /* loop through all the diode models */
51  for ( ; model != NULL; model = model->DIOnextModel) {
52 
53  /* loop through all the instances of the model */
54  for (here = model->DIOinstances; here != NULL;
55  here = here->DIOnextInstance) {
56 
57  here->DIOvd = *(ckt->CKTrhsOld + here->DIOposPrimeNode) -
58  *(ckt->CKTrhsOld + here->DIOnegNode);
59 
60  /*
61  * bypass if solution has not changed
62  */
63  if (ckt->CKTbypass && dio_bypass(ckt,model,here))
64  continue;
65 
66  (void)dio_limiting(ckt,model,here);
67 
68  dio_iv(ckt,model,here);
69 
70  if (ckt->CKTmode & MODETRAN) {
71  dio_cap(ckt,model,here);
72  /*
73  * transient analysis
74  */
75  NI_INTEG(ckt,geq,ceq,here->DIOcap,here->DIOcapCharge);
76  here->DIOgd += geq;
77  here->DIOcd += *(ckt->CKTstate0 + here->DIOcapCurrent);
78  }
79  dio_load(ckt,model,here);
80  }
81  }
82  return (OK);
83  }
84 
85  if (ckt->CKTmode & MODEINITPRED) {
86  double xf1;
87  double xf2;
88 
89  xf2 = -ckt->CKTdelta/ckt->CKTdeltaOld[1];
90  xf1 = 1 - xf2;
91 
92  /* loop through all the diode models */
93  for ( ; model != NULL; model = model->DIOnextModel) {
94 
95  /* loop through all the instances of the model */
96  for (here = model->DIOinstances; here != NULL;
97  here = here->DIOnextInstance) {
98 
99  here->DIOvd = xf1* *(ckt->CKTstate1 + here->DIOvoltage)
100  + xf2* *(ckt->CKTstate2 + here->DIOvoltage);
101 
102  *(ckt->CKTstate0 + here->DIOvoltage) =
103  *(ckt->CKTstate1 + here->DIOvoltage);
104 
105  (void)dio_limiting(ckt,model,here);
106  dio_iv(ckt,model,here);
107  if (ckt->CKTmode & MODETRAN) {
108  dio_cap(ckt,model,here);
109  NI_INTEG(ckt,geq,ceq,here->DIOcap,here->DIOcapCharge);
110  here->DIOgd += geq;
111  here->DIOcd += *(ckt->CKTstate0 + here->DIOcapCurrent);
112  }
113  dio_load(ckt,model,here);
114  }
115  }
116  return (OK);
117  }
118 
119  if (ckt->CKTmode & MODEINITFIX) {
120 
121  /* loop through all the diode models */
122  for ( ; model != NULL; model = model->DIOnextModel) {
123 
124  /* loop through all the instances of the model */
125  for (here = model->DIOinstances; here != NULL;
126  here = here->DIOnextInstance) {
127 
128  if (here->DIOoff)
129  here->DIOvd = 0;
130  else {
131  here->DIOvd = *(ckt->CKTrhsOld + here->DIOposPrimeNode) -
132  *(ckt->CKTrhsOld + here->DIOnegNode);
133 
134  if (dio_limiting(ckt,model,here))
135  ckt->CKTnoncon++;
136  }
137  dio_iv(ckt,model,here);
138  dio_load(ckt,model,here);
139  }
140  }
141  return (OK);
142  }
143 
144  if (ckt->CKTmode & MODEINITTRAN) {
145 
146  /* loop through all the diode models */
147  for ( ; model != NULL; model = model->DIOnextModel) {
148 
149  /* loop through all the instances of the model */
150  for (here = model->DIOinstances; here != NULL;
151  here = here->DIOnextInstance) {
152 
153  here->DIOvd = *(ckt->CKTstate1 + here->DIOvoltage);
154 
155  dio_iv(ckt,model,here);
156  dio_cap(ckt,model,here);
157  *(ckt->CKTstate1 + here->DIOcapCharge) =
158  *(ckt->CKTstate0 + here->DIOcapCharge);
159  NI_INTEG(ckt,geq,ceq,here->DIOcap,here->DIOcapCharge);
160  here->DIOgd += geq;
161  here->DIOcd += *(ckt->CKTstate0 + here->DIOcapCurrent);
162  dio_load(ckt,model,here);
163  }
164  }
165  return (OK);
166  }
167 
168  if (ckt->CKTmode & MODEINITSMSIG) {
169 
170  /* loop through all the diode models */
171  for ( ; model != NULL; model = model->DIOnextModel) {
172 
173  /* loop through all the instances of the model */
174  for (here = model->DIOinstances; here != NULL;
175  here = here->DIOnextInstance) {
176 
177  here->DIOvd = *(ckt->CKTstate0 + here->DIOvoltage);
178  dio_iv(ckt,model,here);
179  dio_cap(ckt,model,here);
180  }
181  }
182  return (OK);
183  }
184 
185  if ((ckt->CKTmode & MODEINITJCT) &&
186  (ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC)) {
187 
188  /* loop through all the diode models */
189  for ( ; model != NULL; model = model->DIOnextModel) {
190 
191  /* loop through all the instances of the model */
192  for (here = model->DIOinstances; here != NULL;
193  here = here->DIOnextInstance) {
194 
195  *(ckt->CKTstate0 + here->DIOvoltage) = here->DIOinitCond;
196  }
197  }
198  return (OK);
199  }
200 
201  if (ckt->CKTmode & MODEINITJCT) {
202 
203  /* loop through all the diode models */
204  for ( ; model != NULL; model = model->DIOnextModel) {
205 
206  /* loop through all the instances of the model */
207  for (here = model->DIOinstances; here != NULL;
208  here = here->DIOnextInstance) {
209 
210  if (here->DIOoff)
211  here->DIOvd = 0;
212  else
213  here->DIOvd = here->DIOtVcrit;
214  dio_iv(ckt,model,here);
215  dio_load(ckt,model,here);
216  }
217  }
218  }
219  return (OK);
220 }
221 
222 
223 static int
224 dio_bypass(ckt,model,here)
225 
226 CKTcircuit *ckt;
227 DIOmodel *model;
228 DIOinstance *here;
229 {
230  double delvd, cdhat, tol, A1, A2;
231 
232  delvd = here->DIOvd - *(ckt->CKTstate0 + here->DIOvoltage);
233 
234  A1 = FABS(here->DIOvd);
235  A2 = FABS(*(ckt->CKTstate0 + here->DIOvoltage));
236  tol = ckt->CKTvoltTol + ckt->CKTreltol*MAX(A1,A2);
237 
238  if (FABS(delvd) < tol) {
239  cdhat = here->DIOcd + here->DIOgd*delvd;
240  A1 = FABS(cdhat);
241  A2 = FABS(here->DIOcd);
242  tol = ckt->CKTabstol + ckt->CKTreltol*MAX(A1,A2);
243  A1 = cdhat - here->DIOcd;
244  if (FABS(A1) < tol) {
245  here->DIOvd = *(ckt->CKTstate0 + here->DIOvoltage);
246  dio_load(ckt,model,here);
247  return (1);
248  }
249  }
250  return (0);
251 }
252 
253 
254 static int
256 
257 CKTcircuit *ckt;
258 DIOmodel *model;
259 DIOinstance *here;
260 {
261  double temp;
262  int rt;
263 
264  if (model->DIObreakdownVoltageGiven) {
265  temp = 10*here->DIOvte - here->DIOtBrkdwnV;
266  if (here->DIOvd < MIN(0,temp)) {
267 
268  temp = -(here->DIOvd + here->DIOtBrkdwnV);
269  rt = dio_pnjlim(&temp,
270  -(*(ckt->CKTstate0 + here->DIOvoltage) + here->DIOtBrkdwnV),
271  here->DIOvte,here->DIOtVcrit);
272  here->DIOvd = -(temp + here->DIOtBrkdwnV);
273  return (rt);
274  }
275  }
276  return (dio_pnjlim(&here->DIOvd,*(ckt->CKTstate0 + here->DIOvoltage),
277  here->DIOvte,here->DIOtVcrit));
278 
279 }
280 
281 
282 static int
283 dio_pnjlim(vnew,vold,vt,vcrit)
284 
285 /*
286  * limit the per-iteration change of PN junction voltages
287  */
288 double *vnew;
289 double vold;
290 double vt;
291 double vcrit;
292 {
293  double arg;
294  double vn;
295 
296  vn = *vnew;
297  if ((vn > vcrit) && (FABS(vn - vold) > (vt + vt))) {
298  if (vold > 0) {
299  arg = 1 + (vn - vold)/vt;
300  if (arg > 0) {
301  *vnew = vold + vt*log(arg);
302  }
303  else {
304  *vnew = vcrit;
305  }
306  }
307  else {
308  *vnew = vt*log(vn/vt);
309  }
310  return (1);
311  }
312  return (0);
313 }
314 
315 
316 static void
317 dio_iv(ckt,model,here)
318 
319 /*
320  * compute dc current and derivitives
321  */
322 CKTcircuit *ckt;
323 DIOmodel *model;
324 DIOinstance *here;
325 {
326  double arg;
327  double vte;
328  double vd;
329  double csat;
330 
331  vte = here->DIOvte;
332  csat = here->DIOtSatCur;
333  vd = here->DIOvd;
334 
335  if (vd >= -3*vte) {
336  arg = exp(vd/vte);
337  here->DIOcd = csat*(arg-1) + ckt->CKTgmin*vd;
338  here->DIOgd = csat*arg/vte + ckt->CKTgmin;
339  }
340  else if ((!(here->DIOtBrkdwnV)) || vd >= -here->DIOtBrkdwnV) {
341  arg = 3*vte/(vd*CONSTe);
342  arg = arg * arg * arg;
343  here->DIOcd = -csat*(1+arg) + ckt->CKTgmin*vd;
344  here->DIOgd = csat*3*arg/vd + ckt->CKTgmin;
345  }
346  else {
347  arg = exp(-(here->DIOtBrkdwnV + vd)/vte);
348  here->DIOcd = -csat*arg + ckt->CKTgmin*vd;
349  here->DIOgd = csat*arg/vte + ckt->CKTgmin;
350  }
351 }
352 
353 
354 static void
355 dio_cap(ckt,model,here)
356 
357 /*
358  * charge storage elements
359  */
360 CKTcircuit *ckt;
361 DIOmodel *model;
362 DIOinstance *here;
363 {
364  double czero;
365  double czof2;
366  double arg;
367  double sarg;
368  double vd;
369 
370  vd = here->DIOvd;
371  czero = here->DIOtJctCap*here->DIOarea;
372 
373  if (vd < here->DIOtDepCap) {
374  arg = 1 - vd/model->DIOjunctionPot;
375 
376  if (model->DIOgradingCoeff == .5)
377  sarg = 1/sqrt(arg);
378  else
379  sarg = exp(-model->DIOgradingCoeff*log(arg));
380 
381  *(ckt->CKTstate0 + here->DIOcapCharge) =
382  model->DIOtransitTime*here->DIOcd +
383  model->DIOjunctionPot*czero*(1 - arg*sarg)/
384  (1 - model->DIOgradingCoeff);
385  here->DIOcap =
386  model->DIOtransitTime*here->DIOgd + czero*sarg;
387  }
388  else {
389  czof2 = czero/model->DIOf2;
390  *(ckt->CKTstate0 + here->DIOcapCharge) =
391  model->DIOtransitTime*here->DIOcd + czero*here->DIOtF1 +
392  czof2*(model->DIOf3*(vd - here->DIOtDepCap) +
393  (model->DIOgradingCoeff/
394  (model->DIOjunctionPot + model->DIOjunctionPot))*
395  (vd*vd - here->DIOtDepCap*here->DIOtDepCap));
396  here->DIOcap =
397  model->DIOtransitTime*here->DIOgd +
398  czof2*(model->DIOf3 +
399  model->DIOgradingCoeff*vd/model->DIOjunctionPot);
400  }
401 }
402 
403 
404 static void
405 dio_load(ckt,model,here)
406 
407 /*
408  * load matrix, rhs, and state
409  */
410 CKTcircuit *ckt;
411 DIOmodel *model;
412 DIOinstance *here;
413 {
414  double gspr;
415  double cdeq;
416  double gd;
417 
418  gd = here->DIOgd;
419 
420  *(ckt->CKTstate0 + here->DIOvoltage) = here->DIOvd;
421 
422  gspr = model->DIOconductance*here->DIOarea;
423  cdeq = here->DIOcd - gd*here->DIOvd;
424 
425  *(ckt->CKTrhs + here->DIOnegNode) += cdeq;
426  *(ckt->CKTrhs + here->DIOposPrimeNode) -= cdeq;
427 
428  *(here->DIOposPosPtr) += gspr;
429  *(here->DIOnegNegPtr) += gd;
430  *(here->DIOposPrimePosPrimePtr) += gd + gspr;
431  *(here->DIOposPosPrimePtr) -= gspr;
432  *(here->DIOnegPosPrimePtr) -= gd;
433  *(here->DIOposPrimePosPtr) -= gspr;
434  *(here->DIOposPrimeNegPtr) -= gd;
435 }
double DIOtDepCap
Definition: diodefs.h:53
double DIOgd
Definition: diodefs.h:61
#define MODEINITPRED
Definition: cktdefs.h:161
#define MODETRAN
Definition: cktdefs.h:145
double DIOtBrkdwnV
Definition: diodefs.h:58
#define MAX(a, b)
Definition: spdefs.h:135
double CKTdelta
Definition: cktdefs.h:78
#define MIN(a, b)
Definition: spdefs.h:136
unsigned DIObreakdownVoltageGiven
Definition: diodefs.h:135
#define MODEINITFLOAT
Definition: cktdefs.h:156
double DIOvd
Definition: diodefs.h:63
#define MODEINITTRAN
Definition: cktdefs.h:160
struct sDIOinstance * DIOnextInstance
Definition: diodefs.h:20
static void dio_iv()
double DIOcd
Definition: diodefs.h:60
double * DIOposPosPtr
Definition: diodefs.h:35
static int dio_limiting()
double * DIOposPosPrimePtr
Definition: diodefs.h:27
double * DIOposPrimePosPrimePtr
Definition: diodefs.h:39
double DIOtransitTime
Definition: diodefs.h:145
double DIOtSatCur
Definition: diodefs.h:55
double * DIOposPrimePosPtr
Definition: diodefs.h:31
#define OK
Definition: iferrmsg.h:17
double DIOconductance
Definition: diodefs.h:143
double * CKTrhsOld
Definition: cktdefs.h:98
double * DIOnegPosPrimePtr
Definition: diodefs.h:29
double CONSTe
Definition: main.c:916
int DIOload(GENmodel *inModel, CKTcircuit *ckt)
Definition: dioload.c:34
DIOinstance * DIOinstances
Definition: diodefs.h:121
unsigned DIOoff
Definition: diodefs.h:42
static int dio_bypass()
#define NULL
Definition: spdefs.h:121
double * DIOposPrimeNegPtr
Definition: diodefs.h:33
double * DIOnegNegPtr
Definition: diodefs.h:37
int DIOposPrimeNode
Definition: diodefs.h:26
double DIOtF1
Definition: diodefs.h:57
#define MODEINITSMSIG
Definition: cktdefs.h:159
#define NI_INTEG(ckt, geq, ceq, cap, qcap)
Definition: devdefs.h:141
struct sDIOmodel * DIOnextModel
Definition: diodefs.h:119
#define MODETRANOP
Definition: cktdefs.h:151
static int dio_pnjlim(double *vnew, double vold, double vt, double vcrit)
Definition: dioload.c:283
double DIOtVcrit
Definition: diodefs.h:56
static char model[32]
Definition: subckt.c:76
#define MODEINITFIX
Definition: cktdefs.h:158
double DIOcap
Definition: diodefs.h:62
double DIOvte
Definition: diodefs.h:59
int CKTbypass
Definition: cktdefs.h:169
#define FABS(a)
Definition: util.h:41
double DIOf2
Definition: diodefs.h:154
static void dio_cap()
int DIOnegNode
Definition: diodefs.h:25
double DIOjunctionPot
Definition: diodefs.h:147
double DIOarea
Definition: diodefs.h:48
double CKTdeltaOld[7]
Definition: cktdefs.h:79
int CKTnoncon
Definition: cktdefs.h:203
static void dio_load()
double DIOtJctCap
Definition: diodefs.h:52
long CKTmode
Definition: cktdefs.h:139
#define MODEINITJCT
Definition: cktdefs.h:157
#define MODEUIC
Definition: cktdefs.h:166
double DIOgradingCoeff
Definition: diodefs.h:148
double DIOinitCond
Definition: diodefs.h:49
double DIOf3
Definition: diodefs.h:155