Jspice3
mesdset.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: 1988 Jaijeet S Roychowdhury
5  1993 Stephen R. Whiteley
6 ****************************************************************************/
7 
8 #include "spice.h"
9 #include <stdio.h>
10 #include "mesdefs.h"
11 #include "distodef.h"
12 #include "const.h"
13 #include "sperror.h"
14 #include "util.h"
15 #include "distoext.h"
16 
17 int
18 MESdSetup(inModel,ckt)
19  GENmodel *inModel;
20  CKTcircuit *ckt;
21  /* actually load the current resistance value into the
22  * sparse matrix previously provided
23  */
24 {
25  register MESmodel *model = (MESmodel*)inModel;
26  register MESinstance *here;
27  double afact;
28  double beta;
29  double betap;
30  double cdrain;
31  double cg;
32  double cgd;
33  double csat;
34  double czgd;
35  double czgs;
36  double denom;
37  double evgd;
38  double evgs;
39  double gdpr;
40  double gspr;
41  double invdenom;
42  double lfact;
43  double phib;
44  double prod;
45  double vcap;
46  double vcrit;
47  double vds;
48  double vgd;
49  double vgs;
50  double vgst;
51  double vto;
52  double lggd1;
53  double lggd2;
54  double lggd3;
55  double lggs1;
56  double lggs2;
57  double lggs3;
58  Dderivs d_cdrain, d_qgs, d_qgd;
59  Dderivs d_p, d_q, d_r, d_zero;
60 
61  /* loop through all the models */
62  for( ; model != NULL; model = model->MESnextModel ) {
63 
64  /* loop through all the instances of the model */
65  for (here = model->MESinstances; here != NULL ;
66  here=here->MESnextInstance) {
67 
68  /*
69  * dc model parameters
70  */
71  beta = model->MESbeta * here->MESarea;
72  gdpr = model->MESdrainConduct * here->MESarea;
73  gspr = model->MESsourceConduct * here->MESarea;
74  csat = model->MESgateSatCurrent * here->MESarea;
75  vcrit = model->MESvcrit;
76  vto = model->MESthreshold;
77  /*
78  * initialization
79  */
80  /*
81  * compute new nonlinear branch voltages
82  */
83  vgs = model->MEStype*
84  (*(ckt->CKTrhsOld+ here->MESgateNode)-
85  *(ckt->CKTrhsOld+
86  here->MESsourcePrimeNode));
87  vgd = model->MEStype*
88  (*(ckt->CKTrhsOld+here->MESgateNode)-
89  *(ckt->CKTrhsOld+
90  here->MESdrainPrimeNode));
91 
92  /*
93  * determine dc current and derivatives
94  */
95  vds = vgs-vgd;
96  if (vgs <= -5*CONSTvt0) {
97  lggs1 = -csat/vgs+ckt->CKTgmin;
98  lggs2=lggs3=0;
99  cg = lggs1*vgs;
100  } else {
101  evgs = exp(vgs/CONSTvt0);
102  lggs1 = csat*evgs/CONSTvt0+ckt->CKTgmin;
103  lggs2 = (lggs1-ckt->CKTgmin)/(CONSTvt0*2);
104  lggs3 = lggs2/(3*CONSTvt0);
105  cg = csat*(evgs-1)+ckt->CKTgmin*vgs;
106  }
107  if (vgd <= -5*CONSTvt0) {
108  lggd1 = -csat/vgd+ckt->CKTgmin;
109  lggd2=lggd3=0;
110  cgd = lggd1*vgd;
111  } else {
112  evgd = exp(vgd/CONSTvt0);
113  lggd1 = csat*evgd/CONSTvt0+ckt->CKTgmin;
114  lggd2 = (lggd1-ckt->CKTgmin)/(CONSTvt0*2);
115  lggd3 = lggd2/(3*CONSTvt0);
116  cgd = csat*(evgd-1)+ckt->CKTgmin*vgd;
117  }
118  cg = cg+cgd;
119  /*
120  * compute drain current and derivitives for normal mode
121  */
122  /* until now, we were using the real vgs, vgd, and vds */
123  {
124  /* converting (temporarily) to local vgs, vgd, and vds */
125  double vgsreal=vgs;
126  double vgdreal=vgd;
127  double vdsreal=vds;
128  Dderivs d_afact, d_lfact;
129  Dderivs d_betap, d_denom, d_invdenom;
130  Dderivs d_prod;
131  Dderivs d_vgst;
132 
133  if (vdsreal < 0.0) {
134  vgs = vgdreal;
135  vgd = vgsreal;
136  vds = -vdsreal;
137  here->MESmode = -1;
138 
139  /* source-drain interchange */
140 
141  }
142  else
143  here->MESmode = 1;
144 d_p.value = 0.0;
145 d_p.d1_p = 1.0;
146 d_p.d1_q = 0.0;
147 d_p.d1_r = 0.0;
148 d_p.d2_p2 = 0.0;
149 d_p.d2_q2 = 0.0;
150 d_p.d2_r2 = 0.0;
151 d_p.d2_pq = 0.0;
152 d_p.d2_qr = 0.0;
153 d_p.d2_pr = 0.0;
154 d_p.d3_p3 = 0.0;
155 d_p.d3_q3 = 0.0;
156 d_p.d3_r3 = 0.0;
157 d_p.d3_p2r = 0.0;
158 d_p.d3_p2q = 0.0;
159 d_p.d3_q2r = 0.0;
160 d_p.d3_pq2 = 0.0;
161 d_p.d3_pr2 = 0.0;
162 d_p.d3_qr2 = 0.0;
163 d_p.d3_pqr = 0.0;
164  EqualDeriv(&d_q,&d_p);
165  EqualDeriv(&d_r,&d_p);
166  EqualDeriv(&d_zero,&d_p);
167  d_q.d1_p = d_r.d1_p = d_zero.d1_p = 0.0;
168  d_q.d1_q = d_r.d1_r = 1.0;
169  d_p.value = vgs; d_r.value = vds;
170 
171  /* p =vgs; q= nothing in particular ; r = vds */
172 
173  vgst = vgs-model->MESthreshold;
174  EqualDeriv(&d_vgst,&d_p);
175  d_vgst.value = vgst;
176  /*
177  * normal mode, cutoff region
178  */
179  if (vgst <= 0) {
180  cdrain = 0;
181  EqualDeriv(&d_cdrain,&d_zero);
182  } else {
183  prod = 1 + model->MESlModulation * vds;
184  TimesDeriv(&d_prod,&d_r,model->MESlModulation);
185  d_prod.value = prod;
186  betap = beta * prod;
187  TimesDeriv(&d_betap,&d_prod,beta);
188  denom = 1 + model->MESb * vgst;
189  TimesDeriv(&d_denom,&d_vgst,model->MESb);
190  d_denom.value = denom;
191  invdenom = 1 / denom;
192  InvDeriv(&d_invdenom,&d_denom);
193  /*
194  * normal mode, saturation region
195  */
196  cdrain = betap * vgst * vgst * invdenom;
197  MultDeriv(&d_cdrain,&d_betap,&d_vgst);
198  MultDeriv(&d_cdrain,&d_cdrain,&d_vgst);
199  MultDeriv(&d_cdrain,&d_cdrain,&d_invdenom);
200 
201  if (vds < ( 3 / model->MESalpha ) ) {
202  /*
203  * normal mode, linear region
204  */
205  afact = 1 - model->MESalpha * vds / 3;
206  TimesDeriv(&d_afact,&d_r,-model->MESalpha/3.0);
207  d_afact.value = afact;
208  lfact = 1 - afact * afact * afact;
209  CubeDeriv(&d_lfact,&d_afact);
210  TimesDeriv(&d_lfact,&d_lfact,-1.0);
211  d_lfact.value += 1.0;
212  cdrain = betap*vgst*vgst*invdenom*lfact;
213  MultDeriv(&d_cdrain,&d_betap,&d_vgst);
214  MultDeriv(&d_cdrain,&d_cdrain,&d_vgst);
215  MultDeriv(&d_cdrain,&d_cdrain,&d_invdenom);
216  MultDeriv(&d_cdrain,&d_cdrain,&d_lfact);
217  }
218  }
219 
220  /* converting back to real vgs, vgd, vds */
221 
222  if (here->MESmode == -1) {
223  vgs = vgsreal;
224  vgd = vgdreal;
225  vds = vdsreal;
226  }
227  }
228  /*
229  * charge storage elements
230  */
231 { /* code block */
232 czgs = model->MEScapGS * here->MESarea;
233 czgd = model->MEScapGD * here->MESarea;
234 phib = model->MESgatePotential;
235 vcap = 1 / model->MESalpha;
236 
237 /*
238  * qgga = qggnew(vgs,vgd,phib,vcap,vto,czgs,czgd,&cgsna,&cgdna);
239  */
240 /* function qggnew - private, used by MESload*/
241 {
242  double veroot,veff1,veff2,del,vnroot,vnew1,vnew3,vmax,ext;
243  double qroot,par1,cfact,cplus,cminus;
244  Dderivs d_vnroot;
245  Dderivs d_cgsnew, d_cgdnew, d_dummy, d_dummy2;
246  Dderivs d_ext, d_qroot, d_par1, d_cfact, d_cplus, d_cminus;
247  Dderivs d_veroot, d_veff1, d_veff2, d_vnew1, d_vnew3;
248 
249 /* now p=vgs, q=vgd, r= nothing */
250 
251  d_q.value = vgd; d_p.value = vgs;
252  veroot = sqrt( (vgs - vgd) * (vgs - vgd) + vcap*vcap );
253  TimesDeriv(&d_veroot,&d_q,-1.0);
254  PlusDeriv(&d_veroot,&d_veroot,&d_p);
255  MultDeriv(&d_veroot,&d_veroot,&d_veroot);
256  d_veroot.value += vcap*vcap;
257  SqrtDeriv(&d_veroot,&d_veroot);
258  veff1 = 0.5 * (vgs + vgd + veroot);
259  PlusDeriv(&d_veff1,&d_veroot,&d_p);
260  PlusDeriv(&d_veff1,&d_veff1,&d_q);
261  TimesDeriv(&d_veff1,&d_veff1,0.5);
262  veff2 = veff1 - veroot;
263  TimesDeriv(&d_veff2,&d_veroot,-1.0);
264  PlusDeriv(&d_veff2,&d_veff2,&d_veff1);
265 
266  del = 0.2;/*const*/
267  vnroot = sqrt( (veff1 - vto)*(veff1 - vto) + del * del );
268  EqualDeriv(&d_vnroot,&d_veff1);
269  d_vnroot.value -= vto;
270  MultDeriv(&d_vnroot,&d_vnroot,&d_vnroot);
271  d_vnroot.value += del*del;
272  SqrtDeriv(&d_vnroot,&d_vnroot);
273  vnew1 = 0.5 * (veff1 + vto + vnroot);
274  PlusDeriv(&d_vnew1,&d_veff1,&d_vnroot);
275  d_vnew1.value += vto;
276  TimesDeriv(&d_vnew1,&d_vnew1,0.5);
277  vnew3 = vnew1;
278  EqualDeriv(&d_vnew3,&d_vnew1);
279  vmax = 0.5;/*const*/
280  if ( vnew1 < vmax ) {
281  ext=0;
282  EqualDeriv(&d_ext,&d_zero);
283  } else {
284  vnew1 = vmax;
285  EqualDeriv(&d_vnew1,&d_zero);
286  d_vnew1.value = vmax;
287  ext = (vnew3 - vmax)/sqrt(1 - vmax/phib);
288  EqualDeriv(&d_ext,&d_vnew3);
289  d_ext.value -= vmax;
290  TimesDeriv(&d_ext,&d_ext,1/sqrt(1 - vmax/phib));
291  }
292 
293  qroot = sqrt(1 - vnew1/phib);
294  TimesDeriv(&d_qroot,&d_vnew1,-1/phib);
295  d_qroot.value += 1.0;
296  SqrtDeriv(&d_qroot,&d_qroot);
297  /*
298  * qggval = czgs * (2*phib*(1-qroot) + ext) + czgd*veff2;
299  */
300  par1 = 0.5 * ( 1 + (veff1-vto)/vnroot);
301  EqualDeriv(&d_par1,&d_veff1);
302  d_par1.value -= vto;
303  DivDeriv(&d_par1,&d_par1,&d_vnroot);
304  d_par1.value += 1.0;
305  TimesDeriv(&d_par1,&d_par1,0.5);
306  cfact = (vgs- vgd)/veroot;
307  TimesDeriv(&d_cfact,&d_q,-1.0);
308  PlusDeriv(&d_cfact,&d_cfact,&d_p);
309  DivDeriv(&d_cfact,&d_cfact,&d_veroot);
310  cplus = 0.5 * (1 + cfact);
311  TimesDeriv(&d_cplus,&d_cfact,0.5);
312  d_cplus.value += 0.5;
313  cminus = cplus - cfact;
314  TimesDeriv(&d_cminus,&d_cfact,-0.5);
315  d_cminus.value += 0.5;
316  /*
317  *cgsnew = czgs/qroot*par1*cplus + czgd*cminus;
318  *cgdnew = czgs/qroot*par1*cminus + czgd*cplus;
319  *
320  * assuming qgs = vgs*cgsnew
321  * and qgd = vgd*cgsnew
322  *
323  * This is probably wrong but then so is the a.c. analysis
324  * routine and everything else
325  *
326  */
327 
328  MultDeriv(&d_dummy,&d_qroot,&d_par1);
329  InvDeriv(&d_dummy,&d_dummy);
330  TimesDeriv(&d_dummy,&d_dummy,czgs);
331 
332  TimesDeriv(&d_cgsnew,&d_cminus,czgd);
333  MultDeriv(&d_dummy2,&d_dummy,&d_cplus);
334  PlusDeriv(&d_cgsnew,&d_cgsnew,&d_dummy2);
335 
336  TimesDeriv(&d_cgdnew,&d_cplus,czgd);
337  MultDeriv(&d_dummy2,&d_dummy,&d_cminus);
338  PlusDeriv(&d_cgdnew,&d_cgdnew,&d_dummy2);
339 
340  MultDeriv(&d_qgs,&d_cgsnew,&d_p);
341  MultDeriv(&d_qgd,&d_cgdnew,&d_q);
342 }
343 }
344 
345 
346  if (here->MESmode == 1)
347  {
348  /* normal mode - no source-drain interchange */
349 here->cdr_x = d_cdrain.d1_p;
350 here->cdr_z = d_cdrain.d1_r;
351 here->cdr_x2 = d_cdrain.d2_p2;
352 here->cdr_z2 = d_cdrain.d2_r2;
353 here->cdr_xz = d_cdrain.d2_pr;
354 here->cdr_x3 = d_cdrain.d3_p3;
355 here->cdr_z3 = d_cdrain.d3_r3;;
356 here->cdr_x2z = d_cdrain.d3_p2r;
357 here->cdr_xz2 = d_cdrain.d3_pr2;
358 
359 } else {
360  /*
361  * inverse mode - source and drain interchanged
362  */
363 
364 
365 here->cdr_x = -d_cdrain.d1_p;
366 here->cdr_z = d_cdrain.d1_p + d_cdrain.d1_r;
367 here->cdr_x2 = -d_cdrain.d2_p2;
368 here->cdr_z2 = -(d_cdrain.d2_p2 + d_cdrain.d2_r2 + 2*d_cdrain.d2_pr);
369 here->cdr_xz = d_cdrain.d2_p2 + d_cdrain.d2_pr;
370 here->cdr_x3 = -d_cdrain.d3_p3;
371 here->cdr_z3 = d_cdrain.d3_p3 + d_cdrain.d3_r3 + 3*(d_cdrain.d3_p2r + d_cdrain.d3_pr2 ) ;
372 here->cdr_x2z = d_cdrain.d3_p3 + d_cdrain.d3_p2r;
373 here->cdr_xz2 = -(d_cdrain.d3_p3 + 2*d_cdrain.d3_p2r + d_cdrain.d3_pr2);
374 
375 }
376 
377 /* now to adjust for type and multiply by factors to convert to Taylor coeffs. */
378 
379 here->cdr_x2 = 0.5*model->MEStype*here->cdr_x2;
380 here->cdr_z2 = 0.5*model->MEStype*here->cdr_z2;
381 here->cdr_xz = model->MEStype*here->cdr_xz;
382 here->cdr_x3 = here->cdr_x3/6.;
383 here->cdr_z3 = here->cdr_z3/6.;
384 here->cdr_x2z = 0.5*here->cdr_x2z;
385 here->cdr_xz2 = 0.5*here->cdr_xz2;
386 
387 
388 here->ggs3 = lggs3;
389 here->ggd3 = lggd3;
390 here->ggs2 = model->MEStype*lggs2;
391 here->ggd2 = model->MEStype*lggd2;
392 
393 here->qgs_x2 = 0.5*model->MEStype*d_qgs.d2_p2;
394 here->qgs_y2 = 0.5*model->MEStype*d_qgs.d2_q2;
395 here->qgs_xy = model->MEStype*d_qgs.d2_pq;
396 here->qgs_x3 = d_qgs.d3_p3/6.;
397 here->qgs_y3 = d_qgs.d3_q3/6.;
398 here->qgs_x2y = 0.5*d_qgs.d3_p2q;
399 here->qgs_xy2 = 0.5*d_qgs.d3_pq2;
400 
401 here->qgd_x2 = 0.5*model->MEStype*d_qgd.d2_p2;
402 here->qgd_y2 = 0.5*model->MEStype*d_qgd.d2_q2;
403 here->qgd_xy = model->MEStype*d_qgd.d2_pq;
404 here->qgd_x3 = d_qgd.d3_p3/6.;
405 here->qgd_y3 = d_qgd.d3_q3/6.;
406 here->qgd_x2y = 0.5*d_qgd.d3_p2q;
407 here->qgd_xy2 = 0.5*d_qgd.d3_pq2;
408  }
409  }
410  return(OK);
411 }
double d2_pr
Definition: distodef.h:75
double d3_pr2
Definition: distodef.h:83
int MEStype
Definition: mesdefs.h:166
double d3_pq2
Definition: distodef.h:81
double d3_p3
Definition: distodef.h:76
double d1_q
Definition: distodef.h:68
double d2_pq
Definition: distodef.h:73
double MESlModulation
Definition: mesdefs.h:171
int MESmode
Definition: mesdefs.h:71
void PlusDeriv(Dderivs *new, Dderivs *old1, Dderivs *old2)
Definition: plusder.c:19
MESinstance * MESinstances
Definition: mesdefs.h:163
double d3_pqr
Definition: distodef.h:85
double d2_r2
Definition: distodef.h:72
double MESdrainConduct
Definition: mesdefs.h:183
struct sMESmodel * MESnextModel
Definition: mesdefs.h:161
double MEScapGS
Definition: mesdefs.h:175
double MESalpha
Definition: mesdefs.h:169
void SqrtDeriv(Dderivs *new, Dderivs *old)
Definition: sqrtder.c:19
void MultDeriv(Dderivs *new, Dderivs *old1, Dderivs *old2)
Definition: multder.c:19
double MESsourceConduct
Definition: mesdefs.h:184
struct sMESinstance * MESnextInstance
Definition: mesdefs.h:22
#define OK
Definition: iferrmsg.h:17
double * CKTrhsOld
Definition: cktdefs.h:98
int MESgateNode
Definition: mesdefs.h:28
double d3_p2r
Definition: distodef.h:80
double d2_qr
Definition: distodef.h:74
#define NULL
Definition: spdefs.h:121
double d1_r
Definition: distodef.h:69
double d1_p
Definition: distodef.h:67
double d3_qr2
Definition: distodef.h:84
int MESdrainPrimeNode
Definition: mesdefs.h:30
double d3_q3
Definition: distodef.h:77
double MESgatePotential
Definition: mesdefs.h:177
void DivDeriv(Dderivs *new, Dderivs *old1, Dderivs *old2)
Definition: divderiv.c:19
double MESarea
Definition: mesdefs.h:32
int MESdSetup(GENmodel *inModel, CKTcircuit *ckt)
Definition: mesdset.c:18
double MESb
Definition: mesdefs.h:172
void TimesDeriv(Dderivs *new, Dderivs *old, double k)
Definition: timesder.c:19
double MESthreshold
Definition: mesdefs.h:168
static char model[32]
Definition: subckt.c:76
double d3_q2r
Definition: distodef.h:82
void CubeDeriv(Dderivs *new, Dderivs *old)
Definition: cubeder.c:19
double MEScapGD
Definition: mesdefs.h:176
double CONSTvt0
Definition: main.c:914
double MESvcrit
Definition: mesdefs.h:189
double value
Definition: distodef.h:66
double CKTgmin
Definition: cktdefs.h:190
double d3_r3
Definition: distodef.h:78
double d3_p2q
Definition: distodef.h:79
double d2_q2
Definition: distodef.h:71
void InvDeriv(Dderivs *new, Dderivs *old)
Definition: invderiv.c:19
int MESsourcePrimeNode
Definition: mesdefs.h:31
double MESbeta
Definition: mesdefs.h:170
double d2_p2
Definition: distodef.h:70
double MESgateSatCurrent
Definition: mesdefs.h:178
void EqualDeriv(Dderivs *new, Dderivs *old)
Definition: equalder.c:17