spice21/comps/bsim4/
tran.rs1use super::{Bsim4, Bsim4OpPoint};
2use crate::analysis::TranState;
3
4impl Bsim4 {
5 pub(crate) fn tran_op(&self, newop: &mut Bsim4OpPoint, tran_state: &TranState) {
12 let nqs_scaling_factor = 1.0e-9; let mut ceqqjd = 0.0;
18 let mut ceqqjs = 0.0;
19 let mut cqcheq = 0.0;
20 let mut cqdef = 0.0;
21
22 let mut gcdgb = 0.0;
23 let mut gcddb = 0.0;
24 let mut gcdsb = 0.0;
25 let mut gcdbb = 0.0;
26 let mut gcsgb = 0.0;
27 let mut gcsdb = 0.0;
28 let mut gcssb = 0.0;
29 let mut gcsbb = 0.0;
30 let mut gcggb = 0.0;
31 let mut gcgdb = 0.0;
32 let mut gcgsb = 0.0;
33 let mut gcgbb = 0.0;
34 let mut gcbdb = 0.0;
35 let mut gcbgb = 0.0;
36 let mut gcbsb = 0.0;
37 let mut gcbbb = 0.0;
38
39 let mut gcgmgmb = 0.0;
40 let mut gcgmdb = 0.0;
41 let mut gcgmsb = 0.0;
42 let mut gcgmbb = 0.0;
43 let mut gcdgmb = 0.0;
44 let mut gcsgmb = 0.0;
45 let mut gcbgmb = 0.0;
46 let mut gcdbdb = 0.0;
47 let mut gcsbsb = 0.0;
48
49 let mut gqdef = 0.0;
50 let mut gcqgb = 0.0;
51 let mut gcqdb = 0.0;
52 let mut gcqsb = 0.0;
53 let mut gcqbb = 0.0;
54 let mut ggtg = 0.0;
55 let mut ggtd = 0.0;
56 let mut ggtb = 0.0;
57 let mut ggts = 0.0;
58 let mut dxpart = if newop.mode > 0 { 0.4 } else { 0.6 };
59 let mut sxpart = 1.0 - dxpart;
60 let mut ddxpart_dVd = 0.0;
61 let mut ddxpart_dVg = 0.0;
62 let mut ddxpart_dVb = 0.0;
63 let mut ddxpart_dVs = 0.0;
64 let mut dsxpart_dVd = 0.0;
65 let mut dsxpart_dVg = 0.0;
66 let mut dsxpart_dVb = 0.0;
67 let mut dsxpart_dVs = 0.0;
68
69 let Bsim4OpPoint { qdrn, qgdo, qgso, qdef, .. } = *newop;
70 let Bsim4OpPoint { cgdo, cgso, .. } = *newop;
71 let Bsim4OpPoint {
72 vbs,
73 vbd,
74 vgb,
75 vgmb,
76 vbs_jct,
77 vbd_jct,
78 ..
79 } = *newop;
80
81 let ag0 = 1.0 / tran_state.dt;
87 if newop.mode > 0 {
88 if self.model.trnqsmod == 0 {
89 if self.model.rgatemod == 3 {
90 gcgmgmb = (cgdo + cgso + self.size_params.cgbo) * ag0;
91 gcgmdb = -cgdo * ag0;
92 gcgmsb = -cgso * ag0;
93 gcgmbb = -self.size_params.cgbo * ag0;
94
95 gcdgmb = gcgmdb;
96 gcsgmb = gcgmsb;
97 gcbgmb = gcgmbb;
98
99 gcggb = newop.cggb * ag0;
100 gcgdb = newop.cgdb * ag0;
101 gcgsb = newop.cgsb * ag0;
102 gcgbb = -(gcggb + gcgdb + gcgsb);
103
104 gcdgb = newop.cdgb * ag0;
105 gcsgb = -(newop.cggb + newop.cbgb + newop.cdgb) * ag0;
106 gcbgb = newop.cbgb * ag0;
107 } else {
108 gcggb = (newop.cggb + cgdo + cgso + self.size_params.cgbo) * ag0;
110 gcgdb = (newop.cgdb - cgdo) * ag0;
111 gcgsb = (newop.cgsb - cgso) * ag0;
112 gcgbb = -(gcggb + gcgdb + gcgsb);
113
114 gcdgb = (newop.cdgb - cgdo) * ag0;
115 gcsgb = -(newop.cggb + newop.cbgb + newop.cdgb + cgso) * ag0;
116 gcbgb = (newop.cbgb - self.size_params.cgbo) * ag0;
117
118 gcdgmb = 0.0;
119 gcsgmb = 0.0;
120 gcbgmb = 0.0;
121 }
122 gcddb = (newop.cddb + newop.capbd + cgdo) * ag0;
123 gcdsb = newop.cdsb * ag0;
124
125 gcsdb = -(newop.cgdb + newop.cbdb + newop.cddb) * ag0;
126 gcssb = (newop.capbs + cgso - (newop.cgsb + newop.cbsb + newop.cdsb)) * ag0;
127
128 if self.model.rbodymod == 0 {
129 gcdbb = -(gcdgb + gcddb + gcdsb + gcdgmb);
131 gcsbb = -(gcsgb + gcsdb + gcssb + gcsgmb);
132 gcbdb = (newop.cbdb - newop.capbd) * ag0;
133 gcbsb = (newop.cbsb - newop.capbs) * ag0;
134 gcdbdb = 0.0;
135 gcsbsb = 0.0;
136 } else {
137 gcdbb = -(newop.cddb + newop.cdgb + newop.cdsb) * ag0;
138 gcsbb = -(gcsgb + gcsdb + gcssb + gcsgmb) + newop.capbs * ag0;
139 gcbdb = newop.cbdb * ag0;
140 gcbsb = newop.cbsb * ag0;
141
142 gcdbdb = -newop.capbd * ag0;
143 gcsbsb = -newop.capbs * ag0;
144 }
145 gcbbb = -(gcbdb + gcbgb + gcbsb + gcbgmb);
146
147 ggtg = 0.0;
148 ggtd = 0.0;
149 ggtb = 0.0;
150 ggts = 0.0;
151 sxpart = 0.6;
152 dxpart = 0.4;
153 ddxpart_dVd = 0.0;
154 ddxpart_dVg = 0.0;
155 ddxpart_dVb = 0.0;
156 ddxpart_dVs = 0.0;
157 dsxpart_dVd = 0.0;
158 dsxpart_dVg = 0.0;
159 dsxpart_dVb = 0.0;
160 dsxpart_dVs = 0.0;
161 } else {
162 let qcheq = newop.qchqs;
163 let CoxWL = self.model_derived.coxe * self.size_params.weffCV * self.intp.nf * self.size_params.leffCV;
164 let T0 = qdef * nqs_scaling_factor / CoxWL;
165
166 ggtg = T0 * newop.gcrgg;
167 newop.gtg = ggtg;
168 ggtd = T0 * newop.gcrgd;
169 newop.gtd = ggtd;
170 ggts = T0 * newop.gcrgs;
171 newop.gts = ggts;
172 ggtb = T0 * newop.gcrgb;
173 newop.gtb = ggtb;
174 gqdef = nqs_scaling_factor * ag0;
175
176 gcqgb = newop.cqgb * ag0;
177 gcqdb = newop.cqdb * ag0;
178 gcqsb = newop.cqsb * ag0;
179 gcqbb = newop.cqbb * ag0;
180
181 if qcheq.abs() <= 1.0e-5 * CoxWL {
182 if self.model.xpart < 0.5 {
183 dxpart = 0.4;
184 } else if self.model.xpart > 0.5 {
185 dxpart = 0.0;
186 } else {
187 dxpart = 0.5;
188 }
189 ddxpart_dVd = 0.0;
190 ddxpart_dVg = 0.0;
191 ddxpart_dVb = 0.0;
192 ddxpart_dVs = 0.0;
193 } else {
194 dxpart = qdrn / qcheq;
195 let Cdd = newop.cddb;
196 let Csd = -(newop.cgdb + newop.cddb + newop.cbdb);
197 ddxpart_dVd = (Cdd - dxpart * (Cdd + Csd)) / qcheq;
198 let Cdg = newop.cdgb;
199 let Csg = -(newop.cggb + newop.cdgb + newop.cbgb);
200 ddxpart_dVg = (Cdg - dxpart * (Cdg + Csg)) / qcheq;
201
202 let Cds = newop.cdsb;
203 let Css = -(newop.cgsb + newop.cdsb + newop.cbsb);
204 ddxpart_dVs = (Cds - dxpart * (Cds + Css)) / qcheq;
205
206 ddxpart_dVb = -(ddxpart_dVd + ddxpart_dVg + ddxpart_dVs);
207 }
208 sxpart = 1.0 - dxpart;
209 dsxpart_dVd = -ddxpart_dVd;
210 dsxpart_dVg = -ddxpart_dVg;
211 dsxpart_dVs = -ddxpart_dVs;
212 dsxpart_dVb = -(dsxpart_dVd + dsxpart_dVg + dsxpart_dVs);
213
214 if self.model.rgatemod == 3 {
215 gcgmgmb = (cgdo + cgso + self.size_params.cgbo) * ag0;
216 gcgmdb = -cgdo * ag0;
217 gcgmsb = -cgso * ag0;
218 gcgmbb = -self.size_params.cgbo * ag0;
219
220 gcdgmb = gcgmdb;
221 gcsgmb = gcgmsb;
222 gcbgmb = gcgmbb;
223
224 gcdgb = 0.0;
225 gcsgb = 0.0;
226 gcbgb = 0.0;
227 gcggb = 0.0;
228 gcgdb = 0.0;
229 gcgsb = 0.0;
230 gcgbb = 0.0;
231 } else {
232 gcggb = (cgdo + cgso + self.size_params.cgbo) * ag0;
233 gcgdb = -cgdo * ag0;
234 gcgsb = -cgso * ag0;
235 gcgbb = -self.size_params.cgbo * ag0;
236
237 gcdgb = gcgdb;
238 gcsgb = gcgsb;
239 gcbgb = gcgbb;
240 gcdgmb = 0.0;
241 gcsgmb = 0.0;
242 gcbgmb = 0.0;
243 }
244
245 gcddb = (newop.capbd + cgdo) * ag0;
246 gcdsb = 0.0;
247 gcsdb = 0.0;
248 gcssb = (newop.capbs + cgso) * ag0;
249
250 if self.model.rbodymod == 0 {
251 gcdbb = -(gcdgb + gcddb + gcdgmb);
252 gcsbb = -(gcsgb + gcssb + gcsgmb);
253 gcbdb = -newop.capbd * ag0;
254 gcbsb = -newop.capbs * ag0;
255 gcdbdb = 0.0;
256 gcsbsb = 0.0;
257 } else {
258 gcdbb = 0.0;
259 gcsbb = 0.0;
260 gcbdb = 0.0;
261 gcbsb = 0.0;
262 gcdbdb = -newop.capbd * ag0;
263 gcsbsb = -newop.capbs * ag0;
264 }
265 gcbbb = -(gcbdb + gcbgb + gcbsb + gcbgmb);
266 }
267 } else {
268 if self.model.trnqsmod == 0 {
269 if self.model.rgatemod == 3 {
270 gcgmgmb = (cgdo + cgso + self.size_params.cgbo) * ag0;
271 gcgmdb = -cgdo * ag0;
272 gcgmsb = -cgso * ag0;
273 gcgmbb = -self.size_params.cgbo * ag0;
274
275 gcdgmb = gcgmdb;
276 gcsgmb = gcgmsb;
277 gcbgmb = gcgmbb;
278
279 gcggb = newop.cggb * ag0;
280 gcgdb = newop.cgsb * ag0;
281 gcgsb = newop.cgdb * ag0;
282 gcgbb = -(gcggb + gcgdb + gcgsb);
283
284 gcdgb = -(newop.cggb + newop.cbgb + newop.cdgb) * ag0;
285 gcsgb = newop.cdgb * ag0;
286 gcbgb = newop.cbgb * ag0;
287 } else {
288 gcggb = (newop.cggb + cgdo + cgso + self.size_params.cgbo) * ag0;
289 gcgdb = (newop.cgsb - cgdo) * ag0;
290 gcgsb = (newop.cgdb - cgso) * ag0;
291 gcgbb = -(gcggb + gcgdb + gcgsb);
292
293 gcdgb = -(newop.cggb + newop.cbgb + newop.cdgb + cgdo) * ag0;
294 gcsgb = (newop.cdgb - cgso) * ag0;
295 gcbgb = (newop.cbgb - self.size_params.cgbo) * ag0;
296
297 gcdgmb = 0.0;
298 gcsgmb = 0.0;
299 gcbgmb = 0.0;
300 }
301 gcddb = (newop.capbd + cgdo - (newop.cgsb + newop.cbsb + newop.cdsb)) * ag0;
302 gcdsb = -(newop.cgdb + newop.cbdb + newop.cddb) * ag0;
303
304 gcsdb = newop.cdsb * ag0;
305 gcssb = (newop.cddb + newop.capbs + cgso) * ag0;
306
307 if self.model.rbodymod == 0 {
308 gcdbb = -(gcdgb + gcddb + gcdsb + gcdgmb);
309 gcsbb = -(gcsgb + gcsdb + gcssb + gcsgmb);
310 gcbdb = (newop.cbsb - newop.capbd) * ag0;
311 gcbsb = (newop.cbdb - newop.capbs) * ag0;
312 gcdbdb = 0.0;
313 gcsbsb = 0.0;
314 } else {
315 gcdbb = -(gcdgb + gcddb + gcdsb + gcdgmb) + newop.capbd * ag0;
316 gcsbb = -(newop.cddb + newop.cdgb + newop.cdsb) * ag0;
317 gcbdb = newop.cbsb * ag0;
318 gcbsb = newop.cbdb * ag0;
319 gcdbdb = -newop.capbd * ag0;
320 gcsbsb = -newop.capbs * ag0;
321 }
322 gcbbb = -(gcbgb + gcbdb + gcbsb + gcbgmb);
323
324 ggtg = 0.0;
325 ggtd = 0.0;
326 ggtb = 0.0;
327 ggts = 0.0;
328 sxpart = 0.4;
329 dxpart = 0.6;
330 ddxpart_dVd = 0.0;
331 ddxpart_dVg = 0.0;
332 ddxpart_dVb = 0.0;
333 ddxpart_dVs = 0.0;
334 dsxpart_dVd = 0.0;
335 dsxpart_dVg = 0.0;
336 dsxpart_dVb = 0.0;
337 dsxpart_dVs = 0.0;
338 } else {
339 let qcheq = newop.qchqs;
340 let CoxWL = self.model_derived.coxe * self.size_params.weffCV * self.intp.nf * self.size_params.leffCV;
341 let T0 = qdef * nqs_scaling_factor / CoxWL;
342 ggtg = T0 * newop.gcrgg;
343 newop.gtg = ggtg;
344 ggts = T0 * newop.gcrgd;
345 newop.gts = ggts;
346 ggtd = T0 * newop.gcrgs;
347 newop.gtd = ggtd;
348 ggtb = T0 * newop.gcrgb;
349 newop.gtb = ggtb;
350 gqdef = nqs_scaling_factor * ag0;
351
352 gcqgb = newop.cqgb * ag0;
353 gcqdb = newop.cqsb * ag0;
354 gcqsb = newop.cqdb * ag0;
355 gcqbb = newop.cqbb * ag0;
356
357 if qcheq.abs() <= 1.0e-5 * CoxWL {
358 if self.model.xpart < 0.5 {
359 sxpart = 0.4;
360 } else if self.model.xpart > 0.5 {
361 sxpart = 0.0;
362 } else {
363 sxpart = 0.5;
364 }
365 dsxpart_dVd = 0.0;
366 dsxpart_dVg = 0.0;
367 dsxpart_dVb = 0.0;
368 dsxpart_dVs = 0.0;
369 } else {
370 sxpart = qdrn / qcheq;
371 let Css = newop.cddb;
372 let Cds = -(newop.cgdb + newop.cddb + newop.cbdb);
373 dsxpart_dVs = (Css - sxpart * (Css + Cds)) / qcheq;
374 let Csg = newop.cdgb;
375 let Cdg = -(newop.cggb + newop.cdgb + newop.cbgb);
376 dsxpart_dVg = (Csg - sxpart * (Csg + Cdg)) / qcheq;
377
378 let Csd = newop.cdsb;
379 let Cdd = -(newop.cgsb + newop.cdsb + newop.cbs);
380 dsxpart_dVd = (Csd - sxpart * (Csd + Cdd)) / qcheq;
381
382 dsxpart_dVb = -(dsxpart_dVd + dsxpart_dVg + dsxpart_dVs);
383 }
384 dxpart = 1.0 - sxpart;
385 ddxpart_dVd = -dsxpart_dVd;
386 ddxpart_dVg = -dsxpart_dVg;
387 ddxpart_dVs = -dsxpart_dVs;
388 ddxpart_dVb = -(ddxpart_dVd + ddxpart_dVg + ddxpart_dVs);
389
390 if self.model.rgatemod == 3 {
391 gcgmgmb = (cgdo + cgso + self.size_params.cgbo) * ag0;
392 gcgmdb = -cgdo * ag0;
393 gcgmsb = -cgso * ag0;
394 gcgmbb = -self.size_params.cgbo * ag0;
395
396 gcdgmb = gcgmdb;
397 gcsgmb = gcgmsb;
398 gcbgmb = gcgmbb;
399
400 gcdgb = 0.0;
401 gcsgb = 0.0;
402 gcbgb = 0.0;
403 gcggb = 0.0;
404 gcgdb = 0.0;
405 gcgsb = 0.0;
406 gcgbb = 0.0;
407 } else {
408 gcggb = (cgdo + cgso + self.size_params.cgbo) * ag0;
409 gcgdb = -cgdo * ag0;
410 gcgsb = -cgso * ag0;
411 gcgbb = -self.size_params.cgbo * ag0;
412
413 gcdgb = gcgdb;
414 gcsgb = gcgsb;
415 gcbgb = gcgbb;
416 gcdgmb = 0.0;
417 gcsgmb = 0.0;
418 gcbgmb = 0.0;
419 }
420
421 gcddb = (newop.capbd + cgdo) * ag0;
422 gcdsb = 0.0;
423 gcsdb = 0.0;
424 gcssb = (newop.capbs + cgso) * ag0;
425 if self.model.rbodymod == 0 {
426 gcdbb = -(gcdgb + gcddb + gcdgmb);
427 gcsbb = -(gcsgb + gcssb + gcsgmb);
428 gcbdb = -newop.capbd * ag0;
429 gcbsb = -newop.capbs * ag0;
430 gcdbdb = 0.0;
431 gcsbsb = 0.0;
432 } else {
433 gcdbb = 0.0;
434 gcsbb = 0.0;
435 gcbdb = 0.0;
436 gcbsb = 0.0;
437 gcdbdb = -newop.capbd * ag0;
438 gcsbsb = -newop.capbs * ag0;
439 }
440 gcbbb = -(gcbdb + gcbgb + gcbsb + gcbgmb);
441 }
442 }
443
444 let (_g, i, _r) = tran_state.integrate(newop.qb - self.op.qb, 0.0, 0.0, self.op.cqb);
448 newop.cqb = i;
449 let (_g, i, _r) = tran_state.integrate(newop.qg - self.op.qg, 0.0, 0.0, self.op.cqg);
450 newop.cqg = i;
451 let (_g, i, _r) = tran_state.integrate(newop.qd - self.op.qd, 0.0, 0.0, self.op.cqd);
452 newop.cqd = i;
453 if self.model.trnqsmod != 0 {
454 newop.qcdump = qdef * nqs_scaling_factor;
455 let (_g, i, _r) = tran_state.integrate(newop.qcdump - self.op.qcdump, 0.0, 0.0, self.op.cqcdump);
456 newop.cqcdump = i;
457 }
458 if self.model.rgatemod == 3 {
459 let (_g, i, _r) = tran_state.integrate(newop.qgmid - self.op.qgmid, 0.0, 0.0, self.op.cqgmid);
460 newop.cqgmid = i;
461 }
462 if self.model.rbodymod != 0 {
463 let (_g, i, _r) = tran_state.integrate(newop.qbs - self.op.qbs, 0.0, 0.0, self.op.cqbs);
464 newop.cqbs = i;
465 let (_g, i, _r) = tran_state.integrate(newop.qbd - self.op.qbd, 0.0, 0.0, self.op.cqbd);
466 newop.cqbd = i;
467 }
468
469 let cqgate = newop.cqg;
471 let cqbody = newop.cqb;
472 let cqdrn = newop.cqd;
473
474 let mut ceqqg = cqgate - gcggb * vgb + gcgdb * vbd + gcgsb * vbs;
475 let mut ceqqd = cqdrn - gcdgb * vgb - gcdgmb * vgmb + (gcddb + gcdbdb) * vbd - gcdbdb * vbd_jct + gcdsb * vbs;
476 let mut ceqqb = cqbody - gcbgb * vgb - gcbgmb * vgmb + gcbdb * vbd + gcbsb * vbs;
477
478 if self.model.rgatemod == 3 {
479 newop.ceqqgmid = newop.cqgmid + gcgmdb * vbd + gcgmsb * vbs - gcgmgmb * vgmb;
480 }
481 if self.model.rbodymod != 0 {
482 newop.ceqqjs = newop.cqbs + gcsbsb * vbs_jct;
483 newop.ceqqjd = newop.cqbd + gcdbdb * vbd_jct;
484 }
485
486 if self.model.trnqsmod != 0 {
487 let (_g, i, _r) = tran_state.integrate(newop.qcheq - self.op.qcheq, 0.0, 0.0, self.op.cqcheq);
488 newop.cqcheq = i;
489
490 let T0 = ggtg * vgb - ggtd * vbd - ggts * vbs;
491 ceqqg += T0;
492 let T1 = qdef * newop.gtau;
493 ceqqd -= dxpart * T0 + T1 * (ddxpart_dVg * vgb - ddxpart_dVd * vbd - ddxpart_dVs * vbs);
494 cqdef = newop.cqcdump - gqdef * qdef;
495 cqcheq = newop.cqcheq - (gcqgb * vgb - gcqdb * vbd - gcqsb * vbs) + T0;
496 }
497
498 newop.gqdef = gqdef;
499 newop.ggtg = ggtg;
500 newop.ggtd = ggtd;
501 newop.ggts = ggts;
502 newop.ggtb = ggtb;
503 newop.gcsbsb = gcsbsb;
504 newop.gcsbsb = gcsbsb;
505 newop.gcqsb = gcqsb;
506 newop.gcqdb = gcqdb;
507 newop.gcqgb = gcqgb;
508 newop.cqcheq = cqcheq;
509 newop.cqdef = cqdef;
510 newop.gcqbb = gcqbb;
511 newop.ceqqg = ceqqg;
512 newop.ceqqd = ceqqd;
513 newop.ceqqb = ceqqb;
514 newop.gcgbb = gcgbb;
515 newop.gcsbb = gcsbb;
516 newop.gcssb = gcssb;
517 newop.gcsgb = gcsgb;
518 newop.gcsdb = gcsdb;
519 newop.gcdbb = gcdbb;
520 newop.gcggb = gcggb;
521 newop.gcgdb = gcgdb;
522 newop.gcgsb = gcgsb;
523 newop.gcgsb = gcgsb;
524 newop.gcgmgmb = gcgmgmb;
525 newop.gcgmsb = gcgmsb;
526 newop.gcgmdb = gcgmdb;
527 newop.gcgmbb = gcgmbb;
528 newop.gcdgmb = gcdgmb;
529 newop.gcsgmb = gcsgmb;
530 newop.ddxpart_dVd = ddxpart_dVd;
531 newop.ddxpart_dVs = ddxpart_dVs;
532 newop.ddxpart_dVb = ddxpart_dVb;
533 newop.dsxpart_dVb = dsxpart_dVb;
534 newop.dsxpart_dVs = dsxpart_dVs;
535 newop.dsxpart_dVg = dsxpart_dVg;
536 newop.dsxpart_dVd = dsxpart_dVd;
537 newop.ddxpart_dVg = ddxpart_dVg;
538 newop.gcgmdb = gcgmdb;
539 newop.gcbgmb = gcbgmb;
540 newop.gcddb = gcddb;
541 newop.gcdgb = gcdgb;
542 newop.gcdsb = gcdsb;
543 newop.gcbdb = gcbdb;
544 newop.gcbgb = gcbgb;
545 newop.gcbsb = gcbsb;
546 newop.gcbbb = gcbbb;
547 newop.dxpart = dxpart;
548 newop.sxpart = sxpart;
549 }
550}