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