Jspice3
devsup.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: 1987 Thomas L. Quarles
5  1993 Stephen R. Whiteley
6 ****************************************************************************/
7 
8 
9  /* support routines for device models */
10 
11 #include "spice.h"
12 #include "devdefs.h"
13 #include "optdefs.h"
14 #include <math.h>
15 #include "util.h"
16 #include "cktext.h"
17 
18 
19 
20 double
21 DEVlimvds(vnew,vold)
22 
23 /* DEVlimvds(vnew,vold)
24  * limit the per-iteration change of VDS
25  */
26 double vnew;
27 double vold;
28 {
29 
30  if (vold >= 3.5) {
31  if(vnew > vold) {
32  vnew = MIN(vnew,(3 * vold) +2);
33  }
34  else {
35  if (vnew < 3.5) {
36  vnew = MAX(vnew,2);
37  }
38  }
39  }
40  else {
41  if(vnew > vold) {
42  vnew = MIN(vnew,4);
43  }
44  else {
45  vnew = MAX(vnew,-.5);
46  }
47  }
48  return (vnew);
49 }
50 
51 
52 double
53 DEVpnjlim(vnew,vold,vt,vcrit,icheck)
54 
55 /* DEVpnjlim(vnew,vold,vt,vcrit,icheck)
56  * limit the per-iteration change of PN junction voltages
57  */
58 double vnew;
59 double vold;
60 double vt;
61 double vcrit;
62 int *icheck;
63 {
64  double arg;
65 
66  if ((vnew > vcrit) && (FABS(vnew - vold) > (vt + vt))) {
67  if(vold > 0) {
68  arg = 1 + (vnew - vold) / vt;
69  if(arg > 0) {
70  vnew = vold + vt * log(arg);
71  }
72  else {
73  vnew = vcrit;
74  }
75  }
76  else {
77  vnew = vt *log(vnew/vt);
78  }
79  *icheck = 1;
80  }
81  else {
82  *icheck = 0;
83  }
84  return (vnew);
85 }
86 
87 
88 double
89 DEVfetlim(vnew,vold,vto)
90 
91 /*
92  * DEVfetlim(vnew,vold.vto)
93  *
94  * limit the per-iteration change of FET voltages
95  */
96 double vnew;
97 double vold;
98 double vto;
99 {
100  double vtsthi;
101  double vtstlo;
102  double vtox;
103  double delv;
104  double vtemp;
105 
106  vtsthi = FABS(2*(vold-vto))+2;
107  vtstlo = vtsthi/2 +2;
108  vtox = vto + 3.5;
109  delv = vnew-vold;
110 
111  if (vold >= vto) {
112  if (vold >= vtox) {
113  if (delv <= 0) {
114  /* going off */
115  if (vnew >= vtox) {
116  if (-delv >vtstlo) {
117  vnew = vold - vtstlo;
118  }
119  }
120  else {
121  vnew = MAX(vnew,vto+2);
122  }
123  }
124  else {
125  /* staying on */
126  if (delv >= vtsthi) {
127  vnew = vold + vtsthi;
128  }
129  }
130  }
131  else {
132  /* middle region */
133  if (delv <= 0) {
134  /* decreasing */
135  vnew = MAX(vnew,vto-.5);
136  }
137  else {
138  /* increasing */
139  vnew = MIN(vnew,vto+4);
140  }
141  }
142  }
143  else {
144  /* off */
145  if (delv <= 0) {
146  if (-delv >vtsthi) {
147  vnew = vold - vtsthi;
148  }
149  }
150  else {
151  vtemp = vto + .5;
152  if (vnew <= vtemp) {
153  if (delv >vtstlo) {
154  vnew = vold + vtstlo;
155  }
156  }
157  else {
158  vnew = vtemp;
159  }
160  }
161  }
162  return (vnew);
163 }
164 
165 
166 void
167 DEVqmeyer(vgs,vgd,von,vdsat,capgs,capgd,capgb,phi,cox)
168 
169 /*
170  * DEVqmeyer(vgs,vgd,vgb,von,vdsat,capgs,capgd,capgb,phi,cox)
171  *
172  * Compute the MOS overlap capacitances as functions of the
173  * device terminal voltages
174  */
175 double vgs; /* initial voltage gate-source */
176 double vgd; /* initial voltage gate-drain */
177 double von;
178 double vdsat;
179 double *capgs; /* non-constant portion of g-s overlap capacitance */
180 double *capgd; /* non-constant portion of g-d overlap capacitance */
181 double *capgb; /* non-constant portion of g-b overlap capacitance */
182 double phi;
183 double cox; /* oxide capactiance */
184 {
185  double vds;
186  double vddif;
187  double vddif1;
188  double vddif2;
189  double vgst;
190 
191  vgst = vgs-von;
192  if (vgst <= -phi) {
193  *capgb = cox/2;
194  *capgs = 0;
195  *capgd = 0;
196  }
197  else if (vgst <= -phi/2) {
198  *capgb = -vgst*cox/(2*phi);
199  *capgs = 0;
200  *capgd = 0;
201  }
202  else if (vgst <= 0) {
203  *capgb = -vgst*cox/(2*phi);
204  *capgs = vgst*cox/(1.5*phi)+cox/3;
205  *capgd = 0;
206  }
207  else {
208  vds = vgs-vgd;
209  if (vdsat <= vds) {
210  *capgs = cox/3;
211  *capgd = 0;
212  *capgb = 0;
213  }
214  else {
215  vddif = 2.0*vdsat-vds;
216  vddif1 = vdsat-vds/*-1.0e-12*/;
217  vddif2 = vddif*vddif;
218  *capgd = cox*(1.0-vdsat*vdsat/vddif2)/3;
219  *capgs = cox*(1.0-vddif1*vddif1/vddif2)/3;
220  *capgb = 0;
221  }
222  }
223 }
224 
225 
226 double DEVpred(ckt,loct)
227 
228 /* predict a value for the capacitor at loct by
229  * extrapolating from previous values
230  */
231 CKTcircuit *ckt;
232 int loct;
233 {
234 
235 #ifndef NEWTRUNC
236  double xfact;
237  xfact = ckt->CKTdelta/ckt->CKTdeltaOld[1];
238  return( ( (1+xfact) * *(ckt->CKTstate1+loct) ) -
239  ( xfact * *(ckt->CKTstate2+loct) ) );
240 #endif /*NEWTRUNC*/
241 
242 }
243 
244 /************************************************************************
245  * Routine added by S. R. Whiteley.
246  ************************************************************************/
247 
248 struct sCKTtable **
250 
251 GENERIC *ckt;
252 {
253  return (&((CKTcircuit*)ckt)->CKTtableHead);
254 }
255 
256 
257 double *
259 
260 /* Compute the Lagrange factors for extrapolation to new time point.
261  * Sets ckt->CKTpred[4] and returns pointer: diff = DEVpredNew(ckt).
262  * Use: predicted = diff[0]*state1 + diff[1]*state2 + diff[2]*state3
263  * + dif[3]*state0.
264  */
265 
266 CKTcircuit *ckt;
267 {
268  double *diff;
269  double d1,d2,d3,d4,c;
270  STATistics *stat = (STATistics*)ckt->CKTstat;
271 
272  if (ckt == NULL)
273  return (NULL);
274 
275  diff = ckt->CKTpred; /* double CKTpred[4] */
276  d1 = ckt->CKTdelta;
277 
278  if (stat->STATaccepted >= 4) {
279 
280  /* third order extrapolation factors */
281 
282  double c1,c2,c3,c12,c23,c123,dd1,dd2;
283 
284  d1 = 1/d1;
285  c1 = ckt->CKTdeltaOld[1]*d1;
286  c2 = ckt->CKTdeltaOld[2]*d1;
287  c3 = ckt->CKTdeltaOld[3]*d1;
288  c12 = c1 + c2;
289  c23 = c2 + c3;
290  c123 = c12 + c3;
291 
292  d2 = 1 + c1;
293  d3 = 1 + c12;
294  d4 = 1 + c123;
295 
296  c = c1*c2*c3*c12*c23*c123;
297  c = 1/c;
298 
299  dd1 = d3*d4*c*c3;
300  dd2 = d2*c*c1;
301 
302  diff[0] = dd1 * d2 * c2 * c23;
303  diff[1] = -dd1 * c12 * c123;
304  diff[2] = dd2 * d4 * c23 * c123;
305  diff[3] = -dd2 * d3 * c2 * c12;
306 
307  /***************************************
308  * i486 cpu cycles: * 16, / 73, +- 10. *
309  * *
310  * expr (1): 24 *, 2 /, 6 + (above) *
311  * total: 590 *
312  * expr (2): 16 *, 5 /, 6 + *
313  * total: 681 *
314  * expr (3): 15 *, 4 /, 12 + *
315  * total: 652 *
316  * *
317  * Note that 1,2 better conditioned. *
318  ***************************************/
319 
320  /* expr (2)
321  diff[0] = d2*d3*d4/(( c1 )*( c12 )*( c123));
322  diff[1] = -d3*d4 /(( c1 )*( c2 )*( c23 ));
323  diff[2] = d2*d4 /(( c12 )*( c2 )*( c3 ));
324  diff[3] = -d2*d3 /(( c123)*( c23 )*( c3 ));
325  */
326 
327  /* expr (3)
328  d2 = d1 + ckt->CKTdeltaOld[1];
329  d3 = d2 + ckt->CKTdeltaOld[2];
330  d4 = d3 + ckt->CKTdeltaOld[3];
331 
332  c = -d1*d2*d3*d4;
333  diff[0] = c/((d1-d2)*(d1-d3)*(d1-d4)*d1);
334  diff[1] = c/((d2-d1)*(d2-d3)*(d2-d4)*d2);
335  diff[2] = c/((d3-d1)*(d3-d2)*(d3-d4)*d3);
336  diff[3] = c/((d4-d1)*(d4-d2)*(d4-d3)*d4);
337  */
338 
339  }
340  else
341  if (stat->STATaccepted >= 3) {
342 
343  /* second order extrapolation factors */
344  d2 = d1 + ckt->CKTdeltaOld[1];
345  d3 = d2 + ckt->CKTdeltaOld[2];
346 
347  diff[0] = d2*d3/((d1-d2)*(d1-d3));
348  diff[1] = d1*d3/((d2-d1)*(d2-d3));
349  diff[2] = d1*d2/((d3-d1)*(d3-d2));
350  diff[3] = 0;
351  }
352 
353  else {
354  /* first order extrapolation factors */
355  diff[1] = -d1/ckt->CKTdeltaOld[1];
356  diff[0] = 1 - diff[1];
357  diff[2] = diff[3] = 0;
358 
359  }
360  return (diff);
361 }
double phi()
double DEVpred(CKTcircuit *ckt, int loct)
Definition: devsup.c:226
#define MAX(a, b)
Definition: spdefs.h:135
double CKTdelta
Definition: cktdefs.h:78
#define MIN(a, b)
Definition: spdefs.h:136
if(TDesc==NULL)
Definition: cd.c:1326
double DEVpnjlim(double vnew, double vold, double vt, double vcrit, int *icheck)
Definition: devsup.c:53
double DEVlimvds(double vnew, double vold)
Definition: devsup.c:21
int STATaccepted
Definition: optdefs.h:21
double DEVfetlim(double vnew, double vold, double vto)
Definition: devsup.c:89
struct sCKTtable ** DEVtableHead(GENERIC *ckt)
Definition: devsup.c:249
#define NULL
Definition: spdefs.h:121
static double c
Definition: vectors.c:16
#define FABS(a)
Definition: util.h:41
double * DEVpredNew(CKTcircuit *ckt)
Definition: devsup.c:258
void DEVqmeyer(double vgs, double vgd, double von, double vdsat, double *capgs, double *capgd, double *capgb, double phi, double cox)
Definition: devsup.c:167
char GENERIC
Definition: ifsim.h:27