1 /**********
2 Copyright 2013 Dietmar Warning. All rights reserved.
3 Author: 2013 Dietmar Warning
4 **********/
5
6 #include "ngspice/ngspice.h"
7 #include "ngspice/cktdefs.h"
8 #include "bsim4v7def.h"
9 #include "ngspice/trandefs.h"
10 #include "ngspice/sperror.h"
11 #include "ngspice/suffix.h"
12 #include "ngspice/cpdefs.h"
13
14
15 int
BSIM4v7soaCheck(CKTcircuit * ckt,GENmodel * inModel)16 BSIM4v7soaCheck(CKTcircuit *ckt, GENmodel *inModel)
17 {
18 BSIM4v7model *model = (BSIM4v7model *) inModel;
19 BSIM4v7instance *here;
20 double vgs, vgd, vgb, vds, vbs, vbd; /* actual mos voltages */
21 int maxwarns;
22 static int warns_vgs = 0, warns_vgd = 0, warns_vgb = 0, warns_vds = 0, warns_vbs = 0, warns_vbd = 0;
23
24 if (!ckt) {
25 warns_vgs = 0;
26 warns_vgd = 0;
27 warns_vgb = 0;
28 warns_vds = 0;
29 warns_vbs = 0;
30 warns_vbd = 0;
31 return OK;
32 }
33
34 maxwarns = ckt->CKTsoaMaxWarns;
35
36 for (; model; model = BSIM4v7nextModel(model)) {
37
38 for (here = BSIM4v7instances(model); here; here = BSIM4v7nextInstance(here)) {
39
40 vgs = ckt->CKTrhsOld [here->BSIM4v7gNodePrime] -
41 ckt->CKTrhsOld [here->BSIM4v7sNodePrime];
42
43 vgd = ckt->CKTrhsOld [here->BSIM4v7gNodePrime] -
44 ckt->CKTrhsOld [here->BSIM4v7dNodePrime];
45
46 vgb = ckt->CKTrhsOld [here->BSIM4v7gNodePrime] -
47 ckt->CKTrhsOld [here->BSIM4v7bNodePrime];
48
49 vds = ckt->CKTrhsOld [here->BSIM4v7dNodePrime] -
50 ckt->CKTrhsOld [here->BSIM4v7sNodePrime];
51
52 vbs = ckt->CKTrhsOld [here->BSIM4v7bNodePrime] -
53 ckt->CKTrhsOld [here->BSIM4v7sNodePrime];
54
55 vbd = ckt->CKTrhsOld [here->BSIM4v7bNodePrime] -
56 ckt->CKTrhsOld [here->BSIM4v7dNodePrime];
57
58 if (!model->BSIM4v7vgsrMaxGiven) {
59 if (fabs(vgs) > model->BSIM4v7vgsMax)
60 if (warns_vgs < maxwarns) {
61 soa_printf(ckt, (GENinstance*) here,
62 "Vgs=%g has exceeded Vgs_max=%g\n",
63 vgs, model->BSIM4v7vgsMax);
64 warns_vgs++;
65 }
66 if (!model->BSIM4v7vgbMaxGiven) {
67 if (fabs(vgb) > model->BSIM4v7vgsMax)
68 if (warns_vgb < maxwarns) {
69 soa_printf(ckt, (GENinstance*) here,
70 "Vgb=%g has exceeded Vgs_max=%g\n",
71 vgb, model->BSIM4v7vgsMax);
72 warns_vgb++;
73 }
74 } else {
75 if (fabs(vgb) > model->BSIM4v7vgbMax)
76 if (warns_vgb < maxwarns) {
77 soa_printf(ckt, (GENinstance*) here,
78 "Vgb=%g has exceeded Vgb_max=%g\n",
79 vgb, model->BSIM4v7vgbMax);
80 warns_vgb++;
81 }
82 }
83 } else {
84 if (model->BSIM4v7type > 0) {
85 if (vgs > model->BSIM4v7vgsMax)
86 if (warns_vgs < maxwarns) {
87 soa_printf(ckt, (GENinstance*) here,
88 "Vgs=%g has exceeded Vgs_max=%g\n",
89 vgs, model->BSIM4v7vgsMax);
90 warns_vgs++;
91 }
92 if (-1*vgs > model->BSIM4v7vgsrMax)
93 if (warns_vgs < maxwarns) {
94 soa_printf(ckt, (GENinstance*) here,
95 "Vgs=%g has exceeded Vgsr_max=%g\n",
96 vgs, model->BSIM4v7vgsrMax);
97 warns_vgs++;
98 }
99 } else {
100 if (vgs > model->BSIM4v7vgsrMax)
101 if (warns_vgs < maxwarns) {
102 soa_printf(ckt, (GENinstance*) here,
103 "Vgs=%g has exceeded Vgsr_max=%g\n",
104 vgs, model->BSIM4v7vgsrMax);
105 warns_vgs++;
106 }
107 if (-1*vgs > model->BSIM4v7vgsMax)
108 if (warns_vgs < maxwarns) {
109 soa_printf(ckt, (GENinstance*) here,
110 "Vgs=%g has exceeded Vgs_max=%g\n",
111 vgs, model->BSIM4v7vgsMax);
112 warns_vgs++;
113 }
114 }
115 }
116
117 if (!model->BSIM4v7vgdrMaxGiven) {
118 if (fabs(vgd) > model->BSIM4v7vgdMax)
119 if (warns_vgd < maxwarns) {
120 soa_printf(ckt, (GENinstance*) here,
121 "Vgd=%g has exceeded Vgd_max=%g\n",
122 vgd, model->BSIM4v7vgdMax);
123 warns_vgd++;
124 }
125 } else {
126 if (model->BSIM4v7type > 0) {
127 if (vgd > model->BSIM4v7vgdMax)
128 if (warns_vgd < maxwarns) {
129 soa_printf(ckt, (GENinstance*) here,
130 "Vgd=%g has exceeded Vgd_max=%g\n",
131 vgd, model->BSIM4v7vgdMax);
132 warns_vgd++;
133 }
134 if (-1*vgd > model->BSIM4v7vgdrMax)
135 if (warns_vgd < maxwarns) {
136 soa_printf(ckt, (GENinstance*) here,
137 "Vgd=%g has exceeded Vgdr_max=%g\n",
138 vgd, model->BSIM4v7vgdrMax);
139 warns_vgd++;
140 }
141 } else {
142 if (vgd > model->BSIM4v7vgdrMax)
143 if (warns_vgd < maxwarns) {
144 soa_printf(ckt, (GENinstance*) here,
145 "Vgd=%g has exceeded Vgdr_max=%g\n",
146 vgd, model->BSIM4v7vgdrMax);
147 warns_vgd++;
148 }
149 if (-1*vgd > model->BSIM4v7vgdMax)
150 if (warns_vgd < maxwarns) {
151 soa_printf(ckt, (GENinstance*) here,
152 "Vgd=%g has exceeded Vgd_max=%g\n",
153 vgd, model->BSIM4v7vgdMax);
154 warns_vgd++;
155 }
156 }
157 }
158
159 if (fabs(vds) > model->BSIM4v7vdsMax)
160 if (warns_vds < maxwarns) {
161 soa_printf(ckt, (GENinstance*) here,
162 "Vds=%g has exceeded Vds_max=%g\n",
163 vds, model->BSIM4v7vdsMax);
164 warns_vds++;
165 }
166
167 if (!model->BSIM4v7vgbrMaxGiven) {
168 if (fabs(vgb) > model->BSIM4v7vgbMax)
169 if (warns_vgb < maxwarns) {
170 soa_printf(ckt, (GENinstance*) here,
171 "Vgb=%g has exceeded Vgb_max=%g\n",
172 vgb, model->BSIM4v7vgbMax);
173 warns_vgb++;
174 }
175 } else {
176 if (model->BSIM4v7type > 0) {
177 if (vgb > model->BSIM4v7vgbMax)
178 if (warns_vgb < maxwarns) {
179 soa_printf(ckt, (GENinstance*) here,
180 "Vgb=%g has exceeded Vgb_max=%g\n",
181 vgb, model->BSIM4v7vgbMax);
182 warns_vgb++;
183 }
184 if (-1*vgb > model->BSIM4v7vgbrMax)
185 if (warns_vgb < maxwarns) {
186 soa_printf(ckt, (GENinstance*) here,
187 "Vgb=%g has exceeded Vgbr_max=%g\n",
188 vgb, model->BSIM4v7vgbrMax);
189 warns_vgb++;
190 }
191 } else {
192 if (vgb > model->BSIM4v7vgbrMax)
193 if (warns_vgb < maxwarns) {
194 soa_printf(ckt, (GENinstance*) here,
195 "Vgb=%g has exceeded Vgbr_max=%g\n",
196 vgb, model->BSIM4v7vgbrMax);
197 warns_vgb++;
198 }
199 if (-1*vgb > model->BSIM4v7vgbMax)
200 if (warns_vgb < maxwarns) {
201 soa_printf(ckt, (GENinstance*) here,
202 "Vgb=%g has exceeded Vgb_max=%g\n",
203 vgb, model->BSIM4v7vgbMax);
204 warns_vgb++;
205 }
206 }
207 }
208
209 if (!model->BSIM4v7vbsrMaxGiven) {
210 if (!model->BSIM4v7vbsMaxGiven) {
211 if (fabs(vbs) > model->BSIM4v7vbdMax)
212 if (warns_vbs < maxwarns) {
213 soa_printf(ckt, (GENinstance*) here,
214 "Vbs=%g has exceeded Vbd_max=%g\n",
215 vbs, model->BSIM4v7vbdMax);
216 warns_vbs++;
217 }
218 } else {
219 if (fabs(vbs) > model->BSIM4v7vbsMax)
220 if (warns_vbs < maxwarns) {
221 soa_printf(ckt, (GENinstance*) here,
222 "Vbs=%g has exceeded Vbs_max=%g\n",
223 vbs, model->BSIM4v7vbsMax);
224 warns_vbs++;
225 }
226 }
227 } else {
228 if (!model->BSIM4v7vbsMaxGiven) {
229 if (model->BSIM4v7type > 0) {
230 if (vbs > model->BSIM4v7vbdMax)
231 if (warns_vbs < maxwarns) {
232 soa_printf(ckt, (GENinstance*) here,
233 "Vbs=%g has exceeded Vbd_max=%g\n",
234 vbs, model->BSIM4v7vbdMax);
235 warns_vbs++;
236 }
237 if (-1*vbs > model->BSIM4v7vbsrMax)
238 if (warns_vbs < maxwarns) {
239 soa_printf(ckt, (GENinstance*) here,
240 "Vbs=%g has exceeded Vbsr_max=%g\n",
241 vbs, model->BSIM4v7vbsrMax);
242 warns_vbs++;
243 }
244 } else {
245 if (vbs > model->BSIM4v7vbsrMax)
246 if (warns_vbs < maxwarns) {
247 soa_printf(ckt, (GENinstance*) here,
248 "Vbs=%g has exceeded Vbsr_max=%g\n",
249 vbs, model->BSIM4v7vbsrMax);
250 warns_vbs++;
251 }
252 if (-1*vbs > model->BSIM4v7vbdMax)
253 if (warns_vbs < maxwarns) {
254 soa_printf(ckt, (GENinstance*) here,
255 "Vbs=%g has exceeded Vbd_max=%g\n",
256 vbs, model->BSIM4v7vbdMax);
257 warns_vbs++;
258 }
259 }
260 } else {
261 if (model->BSIM4v7type > 0) {
262 if (vbs > model->BSIM4v7vbsMax)
263 if (warns_vbs < maxwarns) {
264 soa_printf(ckt, (GENinstance*) here,
265 "Vbs=%g has exceeded Vbs_max=%g\n",
266 vbs, model->BSIM4v7vbsMax);
267 warns_vbs++;
268 }
269 if (-1*vbs > model->BSIM4v7vbsrMax)
270 if (warns_vbs < maxwarns) {
271 soa_printf(ckt, (GENinstance*) here,
272 "Vbs=%g has exceeded Vbsr_max=%g\n",
273 vbs, model->BSIM4v7vbsrMax);
274 warns_vbs++;
275 }
276 } else {
277 if (vbs > model->BSIM4v7vbsrMax)
278 if (warns_vbs < maxwarns) {
279 soa_printf(ckt, (GENinstance*) here,
280 "Vbs=%g has exceeded Vbsr_max=%g\n",
281 vbs, model->BSIM4v7vbsrMax);
282 warns_vbs++;
283 }
284 if (-1*vbs > model->BSIM4v7vbsMax)
285 if (warns_vbs < maxwarns) {
286 soa_printf(ckt, (GENinstance*) here,
287 "Vbs=%g has exceeded Vbs_max=%g\n",
288 vbs, model->BSIM4v7vbsMax);
289 warns_vbs++;
290 }
291 }
292 }
293 }
294
295 if (!model->BSIM4v7vbdrMaxGiven) {
296 if (fabs(vbd) > model->BSIM4v7vbdMax)
297 if (warns_vbd < maxwarns) {
298 soa_printf(ckt, (GENinstance*) here,
299 "Vbd=%g has exceeded Vbd_max=%g\n",
300 vbd, model->BSIM4v7vbdMax);
301 warns_vbd++;
302 }
303 } else {
304 if (model->BSIM4v7type > 0) {
305 if (vbd > model->BSIM4v7vbdMax)
306 if (warns_vbd < maxwarns) {
307 soa_printf(ckt, (GENinstance*) here,
308 "Vbd=%g has exceeded Vbd_max=%g\n",
309 vbd, model->BSIM4v7vbdMax);
310 warns_vbd++;
311 }
312 if (-1*vbd > model->BSIM4v7vbdrMax)
313 if (warns_vbd < maxwarns) {
314 soa_printf(ckt, (GENinstance*) here,
315 "Vbd=%g has exceeded Vbdr_max=%g\n",
316 vbd, model->BSIM4v7vbdrMax);
317 warns_vbd++;
318 }
319 } else {
320 if (vbd > model->BSIM4v7vbdrMax)
321 if (warns_vbd < maxwarns) {
322 soa_printf(ckt, (GENinstance*) here,
323 "Vbd=%g has exceeded Vbdr_max=%g\n",
324 vbd, model->BSIM4v7vbdrMax);
325 warns_vbd++;
326 }
327 if (-1*vbd > model->BSIM4v7vbdMax)
328 if (warns_vbd < maxwarns) {
329 soa_printf(ckt, (GENinstance*) here,
330 "Vbd=%g has exceeded Vbd_max=%g\n",
331 vbd, model->BSIM4v7vbdMax);
332 warns_vbd++;
333 }
334 }
335 }
336
337 }
338 }
339
340 return OK;
341 }
342