1 /**********
2 Copyright 1990 Regents of the University of California.  All rights reserved.
3 Author: 1985 Thomas L. Quarlesù
4 Modified: 2000 AlansFixes
5 **********/
6 
7 #include "ngspice/ngspice.h"
8 #include "ngspice/smpdefs.h"
9 #include "ngspice/cktdefs.h"
10 #include "mos3defs.h"
11 #include "ngspice/const.h"
12 #include "ngspice/sperror.h"
13 #include "ngspice/suffix.h"
14 
15 /* assuming silicon - make definition for epsilon of silicon */
16 #define EPSSIL (11.7 * 8.854214871e-12)
17 
18 int
MOS3setup(SMPmatrix * matrix,GENmodel * inModel,CKTcircuit * ckt,int * states)19 MOS3setup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states)
20         /* load the MOS3 device structure with those pointers needed later
21          * for fast matrix loading
22          */
23 
24 {
25     MOS3model *model = (MOS3model *)inModel;
26     MOS3instance *here;
27     int error;
28     CKTnode *tmp;
29 
30     /*  loop through all the MOS3 device models */
31     for( ; model != NULL; model = MOS3nextModel(model)) {
32 
33         /* perform model defaulting */
34         if(!model->MOS3typeGiven) {
35             model->MOS3type = NMOS;
36         }
37         if(!model->MOS3latDiffGiven) {
38             model->MOS3latDiff = 0;
39         }
40         if(!model->MOS3lengthAdjustGiven) {
41             model->MOS3lengthAdjust = 0;
42         }
43         if(!model->MOS3widthNarrowGiven) {
44             model->MOS3widthNarrow = 0;
45         }
46         if(!model->MOS3widthAdjustGiven) {
47             model->MOS3widthAdjust = 0;
48         }
49         if(!model->MOS3delvt0Given) {
50             model->MOS3delvt0 = 0;
51         }
52         if(!model->MOS3jctSatCurDensityGiven) {
53             model->MOS3jctSatCurDensity = 0;
54         }
55         if(!model->MOS3jctSatCurGiven) {
56             model->MOS3jctSatCur = 1e-14;
57         }
58         if(!model->MOS3drainResistanceGiven) {
59             model->MOS3drainResistance = 0;
60         }
61         if(!model->MOS3sourceResistanceGiven) {
62             model->MOS3sourceResistance = 0;
63         }
64         if(!model->MOS3sheetResistanceGiven) {
65             model->MOS3sheetResistance = 0;
66         }
67         if(!model->MOS3transconductanceGiven) {
68             model->MOS3transconductance = 2e-5;
69         }
70         if(!model->MOS3gateSourceOverlapCapFactorGiven) {
71             model->MOS3gateSourceOverlapCapFactor = 0;
72         }
73         if(!model->MOS3gateDrainOverlapCapFactorGiven) {
74             model->MOS3gateDrainOverlapCapFactor = 0;
75         }
76         if(!model->MOS3gateBulkOverlapCapFactorGiven) {
77             model->MOS3gateBulkOverlapCapFactor = 0;
78         }
79         if(!model->MOS3vt0Given) {
80             model->MOS3vt0 = 0;
81         }
82         if(!model->MOS3capBDGiven) {
83             model->MOS3capBD = 0;
84         }
85         if(!model->MOS3capBSGiven) {
86             model->MOS3capBS = 0;
87         }
88         if(!model->MOS3bulkCapFactorGiven) {
89             model->MOS3bulkCapFactor = 0;
90         }
91         if(!model->MOS3sideWallCapFactorGiven) {
92             model->MOS3sideWallCapFactor = 0;
93         }
94         if(!model->MOS3bulkJctPotentialGiven) {
95             model->MOS3bulkJctPotential = .8;
96         }
97         if(!model->MOS3bulkJctBotGradingCoeffGiven) {
98             model->MOS3bulkJctBotGradingCoeff = .5;
99         }
100         if(!model->MOS3bulkJctSideGradingCoeffGiven) {
101             model->MOS3bulkJctSideGradingCoeff = .33;
102         }
103         if(!model->MOS3fwdCapDepCoeffGiven) {
104             model->MOS3fwdCapDepCoeff = .5;
105         }
106         if(!model->MOS3phiGiven) {
107             model->MOS3phi = .6;
108         }
109         if(!model->MOS3gammaGiven) {
110             model->MOS3gamma = 0;
111         }
112         if(!model->MOS3deltaGiven) {
113             model->MOS3delta = 0;
114         }
115         if(!model->MOS3maxDriftVelGiven) {
116             model->MOS3maxDriftVel = 0;
117         }
118         if(!model->MOS3junctionDepthGiven) {
119             model->MOS3junctionDepth = 0;
120         }
121         if(!model->MOS3fastSurfaceStateDensityGiven) {
122             model->MOS3fastSurfaceStateDensity = 0;
123         }
124         if(!model->MOS3etaGiven) {
125             model->MOS3eta = 0;
126         }
127         if(!model->MOS3thetaGiven) {
128             model->MOS3theta = 0;
129         }
130         if(!model->MOS3kappaGiven) {
131             model->MOS3kappa = .2;
132         }
133         if(!model->MOS3oxideThicknessGiven) {
134             model->MOS3oxideThickness = 1e-7;
135         }
136 	if(!model->MOS3fNcoefGiven) {
137 	    model->MOS3fNcoef = 0;
138 	}
139 	if(!model->MOS3fNexpGiven) {
140 	    model->MOS3fNexp = 1;
141 	}
142 
143         /* loop through all the instances of the model */
144         for (here = MOS3instances(model); here != NULL ;
145                 here=MOS3nextInstance(here)) {
146 
147          CKTnode *tmpNode;
148          IFuid tmpName;
149 
150             /* allocate a chunk of the state vector */
151             here->MOS3states = *states;
152             *states += MOS3NUMSTATES;
153 
154             if(!here->MOS3drainAreaGiven) {
155                 here->MOS3drainArea = ckt->CKTdefaultMosAD;
156             }
157             if(!here->MOS3drainPerimiterGiven) {
158                 here->MOS3drainPerimiter = 0;
159             }
160             if(!here->MOS3drainSquaresGiven) {
161                 here->MOS3drainSquares = 1;
162             }
163             if(!here->MOS3icVBSGiven) {
164                 here->MOS3icVBS = 0;
165             }
166             if(!here->MOS3icVDSGiven) {
167                 here->MOS3icVDS = 0;
168             }
169             if(!here->MOS3icVGSGiven) {
170                 here->MOS3icVGS = 0;
171             }
172             if(!here->MOS3sourcePerimiterGiven) {
173                 here->MOS3sourcePerimiter = 0;
174             }
175             if(!here->MOS3sourceSquaresGiven) {
176                 here->MOS3sourceSquares = 1;
177             }
178             if(!here->MOS3vdsatGiven) {
179                 here->MOS3vdsat = 0;
180             }
181             if(!here->MOS3vonGiven) {
182                 here->MOS3von = 0;
183             }
184             if(!here->MOS3modeGiven) {
185                 here->MOS3mode = 1;
186             }
187 
188             if((model->MOS3drainResistance != 0 ||
189                     (model->MOS3sheetResistance != 0 &&
190                      here->MOS3drainSquares != 0      ) )) {
191                 if (here->MOS3dNodePrime == 0) {
192                 error = CKTmkVolt(ckt,&tmp,here->MOS3name,"internal#drain");
193                 if(error) return(error);
194                 here->MOS3dNodePrime = tmp->number;
195                 if (ckt->CKTcopyNodesets) {
196                   if (CKTinst2Node(ckt,here,1,&tmpNode,&tmpName)==OK) {
197                      if (tmpNode->nsGiven) {
198                        tmp->nodeset=tmpNode->nodeset;
199                        tmp->nsGiven=tmpNode->nsGiven;
200                      }
201                   }
202                 }
203                 }
204             } else {
205                 here->MOS3dNodePrime = here->MOS3dNode;
206             }
207 
208             if((model->MOS3sourceResistance != 0 ||
209                     (model->MOS3sheetResistance != 0 &&
210                      here->MOS3sourceSquares != 0     ) )) {
211                 if (here->MOS3sNodePrime == 0) {
212                 error = CKTmkVolt(ckt,&tmp,here->MOS3name,"internal#source");
213                 if(error) return(error);
214                 here->MOS3sNodePrime = tmp->number;
215                 if (ckt->CKTcopyNodesets) {
216                   if (CKTinst2Node(ckt,here,3,&tmpNode,&tmpName)==OK) {
217                      if (tmpNode->nsGiven) {
218                        tmp->nodeset=tmpNode->nodeset;
219                        tmp->nsGiven=tmpNode->nsGiven;
220                      }
221                   }
222                 }
223                 }
224             } else {
225                 here->MOS3sNodePrime = here->MOS3sNode;
226             }
227 
228 /* macro to make elements with built in test for out of memory */
229 #define TSTALLOC(ptr,first,second) \
230 do { if((here->ptr = SMPmakeElt(matrix, here->first, here->second)) == NULL){\
231     return(E_NOMEM);\
232 } } while(0)
233 
234             TSTALLOC(MOS3DdPtr, MOS3dNode, MOS3dNode);
235             TSTALLOC(MOS3GgPtr, MOS3gNode, MOS3gNode);
236             TSTALLOC(MOS3SsPtr, MOS3sNode, MOS3sNode);
237             TSTALLOC(MOS3BbPtr, MOS3bNode, MOS3bNode);
238             TSTALLOC(MOS3DPdpPtr, MOS3dNodePrime, MOS3dNodePrime);
239             TSTALLOC(MOS3SPspPtr, MOS3sNodePrime, MOS3sNodePrime);
240             TSTALLOC(MOS3DdpPtr, MOS3dNode, MOS3dNodePrime);
241             TSTALLOC(MOS3GbPtr, MOS3gNode, MOS3bNode);
242             TSTALLOC(MOS3GdpPtr, MOS3gNode, MOS3dNodePrime);
243             TSTALLOC(MOS3GspPtr, MOS3gNode, MOS3sNodePrime);
244             TSTALLOC(MOS3SspPtr, MOS3sNode, MOS3sNodePrime);
245             TSTALLOC(MOS3BdpPtr, MOS3bNode, MOS3dNodePrime);
246             TSTALLOC(MOS3BspPtr, MOS3bNode, MOS3sNodePrime);
247             TSTALLOC(MOS3DPspPtr, MOS3dNodePrime, MOS3sNodePrime);
248             TSTALLOC(MOS3DPdPtr, MOS3dNodePrime, MOS3dNode);
249             TSTALLOC(MOS3BgPtr, MOS3bNode, MOS3gNode);
250             TSTALLOC(MOS3DPgPtr, MOS3dNodePrime, MOS3gNode);
251             TSTALLOC(MOS3SPgPtr, MOS3sNodePrime, MOS3gNode);
252             TSTALLOC(MOS3SPsPtr, MOS3sNodePrime, MOS3sNode);
253             TSTALLOC(MOS3DPbPtr, MOS3dNodePrime, MOS3bNode);
254             TSTALLOC(MOS3SPbPtr, MOS3sNodePrime, MOS3bNode);
255             TSTALLOC(MOS3SPdpPtr, MOS3sNodePrime, MOS3dNodePrime);
256 
257         }
258     }
259     return(OK);
260 }
261 
262 int
MOS3unsetup(GENmodel * inModel,CKTcircuit * ckt)263 MOS3unsetup(GENmodel *inModel, CKTcircuit *ckt)
264 {
265     MOS3model *model;
266     MOS3instance *here;
267 
268     for (model = (MOS3model *)inModel; model != NULL;
269 	    model = MOS3nextModel(model))
270     {
271         for (here = MOS3instances(model); here != NULL;
272                 here=MOS3nextInstance(here))
273 	{
274 	    if (here->MOS3sNodePrime > 0
275 		    && here->MOS3sNodePrime != here->MOS3sNode)
276 		CKTdltNNum(ckt, here->MOS3sNodePrime);
277             here->MOS3sNodePrime= 0;
278 
279 	    if (here->MOS3dNodePrime > 0
280 		    && here->MOS3dNodePrime != here->MOS3dNode)
281 		CKTdltNNum(ckt, here->MOS3dNodePrime);
282             here->MOS3dNodePrime= 0;
283 	}
284     }
285     return OK;
286 }
287