Branch data Line data Source code
1 : : /*
2 : : * fa1b.core.cpp - device implementations for fa1b module
3 : : *
4 : : * This is free software; you can redistribute it and/or modify
5 : : * it under the terms of the GNU General Public License as published by
6 : : * the Free Software Foundation; either version 2, or (at your option)
7 : : * any later version.
8 : : *
9 : : */
10 : :
11 : : #if HAVE_CONFIG_H
12 : : #include <config.h>
13 : : #endif
14 : :
15 : : #include "fa1b.analogfunction.h"
16 : : #include "component.h"
17 : : #include "device.h"
18 : : #include "fa1b.core.h"
19 : :
20 : : #ifndef CIR_fa1b
21 : : #define CIR_fa1b -1
22 : : #endif
23 : :
24 : : // external nodes
25 : : #define A 0
26 : : #define B 1
27 : : #define CI 2
28 : : #define CO 3
29 : : #define S 4
30 : : // internal nodes
31 : : #define Sn1 5
32 : : #define Sn2 6
33 : : #define COn1 7
34 : : #define COn2 8
35 : :
36 : : // useful macro definitions
37 : : #define NP(node) real (getV (node))
38 : : #define BP(pnode,nnode) (NP(pnode) - NP(nnode))
39 : : #define _load_static_residual2(pnode,nnode,current)\
40 : : _rhs[pnode] -= current;\
41 : : _rhs[nnode] += current;
42 : : #define _load_static_augmented_residual2(pnode,nnode,current)\
43 : : _rhs[pnode] -= current;\
44 : : _rhs[nnode] += current;
45 : : #define _load_static_residual1(node,current)\
46 : : _rhs[node] -= current;
47 : : #define _load_static_augmented_residual1(node,current)\
48 : : _rhs[node] -= current;
49 : : #define _load_static_jacobian4(pnode,nnode,vpnode,vnnode,conductance)\
50 : : _jstat[pnode][vpnode] += conductance;\
51 : : _jstat[nnode][vnnode] += conductance;\
52 : : _jstat[pnode][vnnode] -= conductance;\
53 : : _jstat[nnode][vpnode] -= conductance;\
54 : : if (doHB) {\
55 : : _ghs[pnode] += conductance * BP(vpnode,vnnode);\
56 : : _ghs[nnode] -= conductance * BP(vpnode,vnnode);\
57 : : } else {\
58 : : _rhs[pnode] += conductance * BP(vpnode,vnnode);\
59 : : _rhs[nnode] -= conductance * BP(vpnode,vnnode);\
60 : : }
61 : : #define _load_static_jacobian2p(node,vpnode,vnnode,conductance)\
62 : : _jstat[node][vpnode] += conductance;\
63 : : _jstat[node][vnnode] -= conductance;\
64 : : if (doHB) {\
65 : : _ghs[node] += conductance * BP(vpnode,vnnode);\
66 : : } else {\
67 : : _rhs[node] += conductance * BP(vpnode,vnnode);\
68 : : }
69 : : #define _load_static_jacobian2s(pnode,nnode,node,conductance)\
70 : : _jstat[pnode][node] += conductance;\
71 : : _jstat[nnode][node] -= conductance;\
72 : : if (doHB) {\
73 : : _ghs[pnode] += conductance * NP(node);\
74 : : _ghs[nnode] -= conductance * NP(node);\
75 : : } else {\
76 : : _rhs[pnode] += conductance * NP(node);\
77 : : _rhs[nnode] -= conductance * NP(node);\
78 : : }
79 : : #define _load_static_jacobian1(node,vnode,conductance)\
80 : : _jstat[node][vnode] += conductance;\
81 : : if (doHB) {\
82 : : _ghs[node] += conductance * NP(vnode);\
83 : : } else {\
84 : : _rhs[node] += conductance * NP(vnode);\
85 : : }
86 : : #define _load_dynamic_residual2(pnode,nnode,charge)\
87 : : if (doTR) _charges[pnode][nnode] += charge;\
88 : : if (doHB) {\
89 : : _qhs[pnode] -= charge;\
90 : : _qhs[nnode] += charge;\
91 : : }
92 : : #define _load_dynamic_residual1(node,charge)\
93 : : if (doTR) _charges[node][node] += charge;\
94 : : if (doHB) {\
95 : : _qhs[node] -= charge;\
96 : : }
97 : : #define _load_dynamic_jacobian4(pnode,nnode,vpnode,vnnode,capacitance)\
98 : : if (doAC) {\
99 : : _jdyna[pnode][vpnode] += capacitance;\
100 : : _jdyna[nnode][vnnode] += capacitance;\
101 : : _jdyna[pnode][vnnode] -= capacitance;\
102 : : _jdyna[nnode][vpnode] -= capacitance;\
103 : : }\
104 : : if (doTR) {\
105 : : _caps[pnode][nnode][vpnode][vnnode] += capacitance;\
106 : : }\
107 : : if (doHB) {\
108 : : _chs[pnode] += capacitance * BP(vpnode,vnnode);\
109 : : _chs[nnode] -= capacitance * BP(vpnode,vnnode);\
110 : : }
111 : : #define _load_dynamic_jacobian2s(pnode,nnode,vnode,capacitance)\
112 : : if (doAC) {\
113 : : _jdyna[pnode][vnode] += capacitance;\
114 : : _jdyna[nnode][vnode] -= capacitance;\
115 : : }\
116 : : if (doTR) {\
117 : : _caps[pnode][nnode][vnode][vnode] += capacitance;\
118 : : }\
119 : : if (doHB) {\
120 : : _chs[pnode] += capacitance * NP(vnode);\
121 : : _chs[nnode] -= capacitance * NP(vnode);\
122 : : }
123 : : #define _load_dynamic_jacobian2p(node,vpnode,vnnode,capacitance)\
124 : : if (doAC) {\
125 : : _jdyna[node][vpnode] += capacitance;\
126 : : _jdyna[node][vnnode] -= capacitance;\
127 : : }\
128 : : if (doTR) {\
129 : : _caps[node][node][vpnode][vnnode] += capacitance;\
130 : : }\
131 : : if (doHB) {\
132 : : _chs[node] += capacitance * BP(vpnode,vnnode);\
133 : : }
134 : : #define _load_dynamic_jacobian1(node,vnode,capacitance)\
135 : : if (doAC) {\
136 : : _jdyna[node][vnode] += capacitance;\
137 : : }\
138 : : if (doTR) {\
139 : : _caps[node][node][vnode][vnode] += capacitance;\
140 : : }\
141 : : if (doHB) {\
142 : : _chs[node] += capacitance * NP(vnode);\
143 : : }
144 : :
145 : : #define _save_whitenoise1(n1,pwr,type)\
146 : : _white_pwr[n1][n1] += pwr;
147 : : #define _save_whitenoise2(n1,n2,pwr,type)\
148 : : _white_pwr[n1][n2] += pwr;
149 : : #define _save_flickernoise1(n1,pwr,exp,type)\
150 : : _flicker_pwr[n1][n1] += pwr;\
151 : : _flicker_exp[n1][n1] += exp;
152 : : #define _save_flickernoise2(n1,n2,pwr,exp,type)\
153 : : _flicker_pwr[n1][n2] += pwr;\
154 : : _flicker_exp[n1][n2] += exp;
155 : : #define _load_whitenoise2(n1,n2,pwr)\
156 : : cy (n1,n2) -= pwr/kB/T0; cy (n2,n1) -= pwr/kB/T0;\
157 : : cy (n1,n1) += pwr/kB/T0; cy (n2,n2) += pwr/kB/T0;
158 : : #define _load_whitenoise1(n1,pwr)\
159 : : cy (n1,n1) += pwr/kB/T0;
160 : : #define _load_flickernoise2(n1,n2,pwr,exp)\
161 : : cy (n1,n2) -= pwr*pow(_freq,-exp)/kB/T0;\
162 : : cy (n2,n1) -= pwr*pow(_freq,-exp)/kB/T0;\
163 : : cy (n1,n1) += pwr*pow(_freq,-exp)/kB/T0;\
164 : : cy (n2,n2) += pwr*pow(_freq,-exp)/kB/T0;
165 : : #define _load_flickernoise1(n1,pwr,exp)\
166 : : cy (n1,n1) += pwr*pow(_freq,-exp)/kB/T0;
167 : :
168 : : // derivative helper macros
169 : : // transcendental LRM p. 59
170 : : #define m00_cos(v00,x) v00 = cos(x);
171 : : #define m10_cos(v10,v00,x) v10 = (-sin(x));
172 : : #define m00_sin(v00,x) v00 = sin(x);
173 : : #define m10_sin(v10,v00,x) v10 = (cos(x));
174 : : #define m00_tan(v00,x) v00 = tan(x);
175 : : #define m10_tan(v10,v00,x) v10 = (1.0/cos(x)/cos(x));
176 : : #define m00_cosh(v00,x) v00 = cosh(x);
177 : : #define m10_cosh(v10,v00,x) v10 = (sinh(x));
178 : : #define m00_sinh(v00,x) v00 = sinh(x);
179 : : #define m10_sinh(v10,v00,x) v10 = (cosh(x));
180 : : #define m00_tanh(v00,x) v00 = tanh(x);
181 : : #define m10_tanh(v10,v00,x) v10 = (1.0/cosh(x)/cosh(x));
182 : : #define m00_acos(v00,x) v00 = acos(x);
183 : : #define m10_acos(v10,v00,x) v10 = (-1.0/sqrt(1-x*x));
184 : : #define m00_asin(v00,x) v00 = asin(x);
185 : : #define m10_asin(v10,v00,x) v10 = (+1.0/sqrt(1-x*x));
186 : : #define m00_atan(v00,x) v00 = atan(x);
187 : : #define m10_atan(v10,v00,x) v10 = (+1.0/(1+x*x));
188 : : #define m00_hypot(v00,x,y) v00 = sqrt((x)*(x)+(y)*(y));
189 : : #define m10_hypot(v10,v00,x,y) v10 = (x)/(v00);
190 : : #define m11_hypot(v11,v00,x,y) v11 = (y)/(v00);
191 : : #define m00_atan2(v00,x,y) v00 = atan2(x,y);
192 : : // TODO atan2 derivatives ?
193 : : #define m00_acosh(v00,x) v00 = acosh(x);
194 : : #define m10_acosh(v10,v00,x) v10 = (1.0/(sqrt(x-1)*sqrt(x+1)));
195 : : #define m00_asinh(v00,x) v00 = asinh(x);
196 : : #define m10_asinh(v10,v00,x) v10 = (1.0/(sqrt(x*x+1)));
197 : : #define m00_atanh(v00,x) v00 = atanh(x);
198 : : #define m10_atanh(v10,v00,x) v10 = (1.0/(1-x*x));
199 : :
200 : :
201 : : // standard functions LRM p.58
202 : : #define m00_logE(v00,x) v00 = log(x);
203 : : #define m10_logE(v10,v00,x) v10 = (1.0/x);
204 : : #define m00_log10(v00,x) v00 = log10(x);
205 : : #define m10_log10(v10,v00,x) v10 = (1.0/x/M_LN10);
206 : : #define m00_exp(v00,x) v00 = exp(x);
207 : : #define m10_exp(v10,v00,x) v10 = v00;
208 : : #define m00_sqrt(v00,x) v00 = sqrt(x);
209 : : #define m10_sqrt(v10,v00,x) v10 = (0.5/v00);
210 : : #define m00_min(v00,x,y) v00 = ((x)<(y))?(x):(y);
211 : : #define m10_min(v10,v00,x,y) v10 = ((x)<(y))?1.0:0.0;
212 : : #define m11_min(v11,v00,x,y) v11 = ((x)<(y))?0.0:1.0;
213 : : #define m00_max(v00,x,y) v00 = ((x)>(y))?(x):(y);
214 : : #define m10_max(v10,v00,x,y) v10 = ((x)>(y))?1.0:0.0;
215 : : #define m11_max(v11,v00,x,y) v11 = ((x)>(y))?0.0:1.0;
216 : : #define m00_pow(v00,x,y) v00 = pow(x,y);
217 : : #define m10_pow(v10,v00,x,y) v10 = (x==0.0)?0.0:(v00)*(y)/(x);
218 : : #define m11_pow(v11,v00,x,y) v11 = (x==0.0)?0.0:(log(x)*(v00));
219 : : #define m00_abs(v00,x) v00 = ((x)<(0)?(-(x)):(x));
220 : : #define m10_abs(v10,v00,x) v10 = (((x)>=0)?(+1.0):(-1.0));
221 : : #define m00_floor(v00,x) v00 = floor(x);
222 : : #define m10_floor(v10,v00,x) v10 = 1.0;
223 : :
224 : : #define m00_ceil(v00,x) v00 = ceil(x);
225 : : // TODO ceil derivative, needed?
226 : :
227 : : // analog operator, LRM p.61
228 : : #define m00_limexp(v00,x) v00 = ((x)<80.0?exp(x):exp(80.0)*(x-79.0));
229 : : #define m10_limexp(v10,v00,x) v10 = ((x)<80.0?(v00):exp(80.0));
230 : :
231 : : // analog kernel parameter system functions, LRM p.215
232 : : #define m00_vt(x) (kBoverQ*(x))
233 : : #define m10_vt(x) (kBoverQ)
234 : :
235 : : // extra functions (?)
236 : : #define m00_div(v00,v10,x,y) double v10=1/(y); double v00=(x)*v10;
237 : : #define m10_div(v10,v00,vv,x,y)
238 : : #define m11_div(v11,v00,vv,x,y) double v11 = -v00*vv;
239 : : #define m00_mult(v00,v10,v11,x,y) double v10=(x); double v11=(y); double v00=v10*v11;
240 : : #define m00_add(v00,x,y) double v00=(x)+(y);
241 : :
242 : : // second derivatives
243 : : #define m20_logE(v00) (-1.0/v00/v00)
244 : : #define m20_exp(v00) exp(v00)
245 : : #define m20_limexp(v00) ((v00)<80.0?exp(v00):0.0)
246 : : #define m20_sqrt(v00) (-0.25/(v00)/sqrt(v00))
247 : : #define m20_abs(v00) 0.0
248 : : #define m20_pow(x,y) ((y)*((y)-1.0)*pow(x,y)/(x)/(x))
249 : :
250 : :
251 : : // simulator specific definitions
252 : : #define _modelname "fa1b"
253 : : #define _instancename getName()
254 : : #define _circuit_temp (getPropertyDouble("Temp")+273.15)
255 : : #define _param_given(p) (isPropertyGiven(p)?1:0)
256 : :
257 : :
258 : : // $vt and $vt() functions
259 : : #define _vt_nom (kBoverQ*_circuit_temp)
260 : :
261 : : using namespace qucs::device;
262 : : using qucs::matrix;
263 : :
264 : : /* Device constructor. */
265 : 0 : fa1b::fa1b() : circuit (9)
266 : : {
267 : 0 : type = CIR_fa1b;
268 : 0 : }
269 : :
270 : : /* Initialization of model. */
271 : 0 : void fa1b::initModel (void)
272 : : {
273 : : // create internal nodes
274 : 0 : setInternalNode (Sn1, "Sn1");
275 : 0 : setInternalNode (Sn2, "Sn2");
276 : 0 : setInternalNode (COn1, "COn1");
277 : 0 : setInternalNode (COn2, "COn2");
278 : :
279 : : // get device model parameters
280 : 0 : loadVariables ();
281 : : // evaluate global model equations
282 : 0 : initializeModel ();
283 : : // evaluate initial step equations
284 : 0 : initialStep ();
285 : : // evaluate global instance equations
286 : 0 : initializeInstance ();
287 : 0 : }
288 : :
289 : : /* Initialization of DC analysis. */
290 : 0 : void fa1b::initDC (void)
291 : : {
292 : 0 : allocMatrixMNA ();
293 : 0 : initModel ();
294 : 0 : pol = 1;
295 : 0 : restartDC ();
296 : 0 : doAC = 1;
297 : 0 : doTR = 0;
298 : 0 : doHB = 0;
299 : 0 : }
300 : :
301 : : /* Run when DC is restarted (fallback algorithms). */
302 : 0 : void fa1b::restartDC (void)
303 : : {
304 : 0 : }
305 : :
306 : : /* Initialize Verilog-AMS code. */
307 : 0 : void fa1b::initVerilog (void)
308 : : {
309 : : // initialization of noise variables
310 : :
311 : : int i1, i2, i3, i4;
312 : :
313 : : // zero charges
314 [ # # ]: 0 : for (i1 = 0; i1 < 9; i1++) {
315 [ # # ]: 0 : for (i2 = 0; i2 < 9; i2++) {
316 : 0 : _charges[i1][i2] = 0.0;
317 : : } }
318 : :
319 : : // zero capacitances
320 [ # # ]: 0 : for (i1 = 0; i1 < 9; i1++) {
321 [ # # ]: 0 : for (i2 = 0; i2 < 9; i2++) {
322 [ # # ]: 0 : for (i3 = 0; i3 < 9; i3++) {
323 [ # # ]: 0 : for (i4 = 0; i4 < 9; i4++) {
324 : 0 : _caps[i1][i2][i3][i4] = 0.0;
325 : : } } } }
326 : :
327 : : // zero right hand side, static and dynamic jacobian
328 [ # # ]: 0 : for (i1 = 0; i1 < 9; i1++) {
329 : 0 : _rhs[i1] = 0.0;
330 : 0 : _qhs[i1] = 0.0;
331 : 0 : _chs[i1] = 0.0;
332 : 0 : _ghs[i1] = 0.0;
333 [ # # ]: 0 : for (i2 = 0; i2 < 9; i2++) {
334 : 0 : _jstat[i1][i2] = 0.0;
335 : 0 : _jdyna[i1][i2] = 0.0;
336 : : }
337 : : }
338 : 0 : }
339 : :
340 : : /* Load device model input parameters. */
341 : 0 : void fa1b::loadVariables (void)
342 : : {
343 : 0 : TR = getPropertyDouble ("TR");
344 : 0 : Delay = getPropertyDouble ("Delay");
345 : 0 : }
346 : :
347 : : /* #define's for translated code */
348 : : #undef _DDT
349 : : #define _DDT(q) q
350 : : #define _DYNAMIC
351 : : #define _DERIVATE
352 : : #define _DDX
353 : : #define _DERIVATEFORDDX
354 : :
355 : : /* Evaluate Verilog-AMS equations in model initialization. */
356 : 0 : void fa1b::initializeModel (void)
357 : : {
358 : : #if defined(_DYNAMIC)
359 : : #endif
360 : : {
361 : 0 : Rd=1e3;
362 : : #if defined(_DYNAMIC)
363 : 0 : Cd=((Delay*1.43)/Rd);
364 : : #endif
365 : : }
366 : 0 : }
367 : :
368 : : /* Evaluate Verilog-AMS equations in instance initialization. */
369 : 0 : void fa1b::initializeInstance (void)
370 : : {
371 : 0 : }
372 : :
373 : : /* Evaluate Verilog-AMS equations in initial step. */
374 : 0 : void fa1b::initialStep (void)
375 : : {
376 : 0 : }
377 : :
378 : : /* Evaluate Verilog-AMS equations in final step. */
379 : 0 : void fa1b::finalStep (void)
380 : : {
381 : 0 : }
382 : :
383 : : /* Evaluate Verilog-AMS equations in analog block. */
384 : 0 : void fa1b::calcVerilog (void)
385 : : {
386 : :
387 : : /* ----------------- evaluate verilog analog equations -------------------- */
388 : : double IS;
389 : : #if defined(_DERIVATE)
390 : : double IS_VCI_GND;
391 : : double IS_VA_GND;
392 : : double IS_VB_GND;
393 : : #endif
394 : : double ICO;
395 : : #if defined(_DERIVATE)
396 : : double ICO_VA_GND;
397 : : double ICO_VB_GND;
398 : : double ICO_VCI_GND;
399 : : #endif
400 : : double HCO;
401 : : #if defined(_DERIVATE)
402 : : double HCO_VA_GND;
403 : : double HCO_VB_GND;
404 : : #endif
405 : : double KS;
406 : : #if defined(_DERIVATE)
407 : : double KS_VA_GND;
408 : : double KS_VB_GND;
409 : : #endif
410 : : #if defined(_DERIVATE)
411 : 0 : KS_VA_GND=(NP(B));
412 : 0 : KS_VB_GND=(NP(A));
413 : : #endif
414 [ # # ]: 0 : KS=(NP(A)*NP(B));
415 : : #if defined(_DERIVATE)
416 [ # # ]: 0 : HCO_VA_GND=(((1-NP(B)))+(-1.0)*NP(B));
417 [ # # ]: 0 : HCO_VB_GND=((NP(A)*(-1.0))+((1-NP(A))));
418 : : #endif
419 [ # # ][ # # ]: 0 : HCO=((NP(A)*(1-NP(B)))+((1-NP(A))*NP(B)));
[ # # ]
420 : : #if defined(_DERIVATE)
421 : 0 : ICO_VA_GND=(KS_VA_GND+(NP(CI)*HCO_VA_GND));
422 : 0 : ICO_VB_GND=(KS_VB_GND+(NP(CI)*HCO_VB_GND));
423 : 0 : ICO_VCI_GND=(HCO);
424 : : #endif
425 : 0 : ICO=(KS+(NP(CI)*HCO));
426 : : #if defined(_DERIVATE)
427 : 0 : IS_VCI_GND=(((1-HCO))+(-1.0)*HCO);
428 [ # # ]: 0 : IS_VA_GND=((NP(CI)*(-HCO_VA_GND))+((1-NP(CI))*HCO_VA_GND));
429 [ # # ]: 0 : IS_VB_GND=((NP(CI)*(-HCO_VB_GND))+((1-NP(CI))*HCO_VB_GND));
430 : : #endif
431 [ # # ]: 0 : IS=((NP(CI)*(1-HCO))+((1-NP(CI))*HCO));
432 [ # # ]: 0 : if
433 : : (ICO>=0.5)
434 : : {
435 : : #if defined(_DERIVATE)
436 : 0 : ICO_VA_GND=0.0;
437 : 0 : ICO_VB_GND=0.0;
438 : 0 : ICO_VCI_GND=0.0;
439 : : #endif
440 : 0 : ICO=1;
441 : : }
442 : : else
443 : : {
444 : : #if defined(_DERIVATE)
445 : 0 : ICO_VA_GND=0.0;
446 : 0 : ICO_VB_GND=0.0;
447 : 0 : ICO_VCI_GND=0.0;
448 : : #endif
449 : 0 : ICO=0;
450 : : }
451 [ # # ]: 0 : if
452 : : (IS>=0.5)
453 : : {
454 : : #if defined(_DERIVATE)
455 : 0 : IS_VCI_GND=0.0;
456 : 0 : IS_VA_GND=0.0;
457 : 0 : IS_VB_GND=0.0;
458 : : #endif
459 : 0 : IS=1;
460 : : }
461 : : else
462 : : {
463 : : #if defined(_DERIVATE)
464 : 0 : IS_VCI_GND=0.0;
465 : 0 : IS_VA_GND=0.0;
466 : 0 : IS_VB_GND=0.0;
467 : : #endif
468 : 0 : IS=0;
469 : : }
470 : : {
471 : 0 : double m00_tanh(d00_tanh0,(TR*(IS-0.5)))
472 : : #if defined(_DERIVATE)
473 : 0 : double m10_tanh(d10_tanh0,d00_tanh0,(TR*(IS-0.5)))
474 : : #endif
475 : 0 : _load_static_residual1(Sn1,((-0.5)*(1+d00_tanh0)));
476 : : #if defined(_DERIVATE)
477 [ # # ]: 0 : _load_static_jacobian1(Sn1,B,((-0.5)*(TR*IS_VB_GND)*d10_tanh0));
478 [ # # ]: 0 : _load_static_jacobian1(Sn1,A,((-0.5)*(TR*IS_VA_GND)*d10_tanh0));
479 [ # # ]: 0 : _load_static_jacobian1(Sn1,CI,((-0.5)*(TR*IS_VCI_GND)*d10_tanh0));
480 : : #endif
481 : : }
482 : 0 : _load_static_residual1(Sn1,NP(Sn1));
483 : : #if defined(_DERIVATE)
484 [ # # ]: 0 : _load_static_jacobian1(Sn1,Sn1,1.0);
485 : : #endif
486 [ # # ][ # # ]: 0 : _load_static_residual2(Sn1,Sn2,(BP(Sn1,Sn2)/Rd));
487 : : #if defined(_DERIVATE)
488 [ # # ][ # # ]: 0 : _load_static_jacobian4(Sn1,Sn2,Sn1,Sn2,(1/Rd));
[ # # ][ # # ]
[ # # ]
489 : : #endif
490 : : #if defined(_DYNAMIC)
491 [ # # ][ # # ]: 0 : _load_dynamic_residual1(Sn2,_DDT((Cd*NP(Sn2))));
492 : : #if defined(_DERIVATE)
493 [ # # ][ # # ]: 0 : _load_dynamic_jacobian1(Sn2,Sn2,(Cd));
[ # # ]
494 : : #endif
495 : : #endif
496 : 0 : _load_static_residual1(S,(-NP(Sn2)));
497 : : #if defined(_DERIVATE)
498 [ # # ]: 0 : _load_static_jacobian1(S,Sn2,(-1.0));
499 : : #endif
500 : 0 : _load_static_residual1(S,NP(S));
501 : : #if defined(_DERIVATE)
502 [ # # ]: 0 : _load_static_jacobian1(S,S,1.0);
503 : : #endif
504 : : {
505 : 0 : double m00_tanh(d00_tanh0,(TR*(ICO-0.5)))
506 : : #if defined(_DERIVATE)
507 : 0 : double m10_tanh(d10_tanh0,d00_tanh0,(TR*(ICO-0.5)))
508 : : #endif
509 : 0 : _load_static_residual1(COn1,((-0.5)*(1+d00_tanh0)));
510 : : #if defined(_DERIVATE)
511 [ # # ]: 0 : _load_static_jacobian1(COn1,CI,((-0.5)*(TR*ICO_VCI_GND)*d10_tanh0));
512 [ # # ]: 0 : _load_static_jacobian1(COn1,B,((-0.5)*(TR*ICO_VB_GND)*d10_tanh0));
513 [ # # ]: 0 : _load_static_jacobian1(COn1,A,((-0.5)*(TR*ICO_VA_GND)*d10_tanh0));
514 : : #endif
515 : : }
516 : 0 : _load_static_residual1(COn1,NP(COn1));
517 : : #if defined(_DERIVATE)
518 [ # # ]: 0 : _load_static_jacobian1(COn1,COn1,1.0);
519 : : #endif
520 [ # # ][ # # ]: 0 : _load_static_residual2(COn1,COn2,(BP(COn1,COn2)/Rd));
521 : : #if defined(_DERIVATE)
522 [ # # ][ # # ]: 0 : _load_static_jacobian4(COn1,COn2,COn1,COn2,(1/Rd));
[ # # ][ # # ]
[ # # ]
523 : : #endif
524 : : #if defined(_DYNAMIC)
525 [ # # ][ # # ]: 0 : _load_dynamic_residual1(COn2,_DDT((Cd*NP(COn2))));
526 : : #if defined(_DERIVATE)
527 [ # # ][ # # ]: 0 : _load_dynamic_jacobian1(COn2,COn2,(Cd));
[ # # ]
528 : : #endif
529 : : #endif
530 : 0 : _load_static_residual1(CO,(-NP(COn2)));
531 : : #if defined(_DERIVATE)
532 [ # # ]: 0 : _load_static_jacobian1(CO,COn2,(-1.0));
533 : : #endif
534 : 0 : _load_static_residual1(CO,NP(CO));
535 : : #if defined(_DERIVATE)
536 [ # # ]: 0 : _load_static_jacobian1(CO,CO,1.0);
537 : : #endif
538 : :
539 : : /* ------------------ end of verilog analog equations --------------------- */
540 : :
541 : : /* ------------------ evaluate verilog noise equations -------------------- */
542 : :
543 : : /* ------------------- end of verilog noise equations --------------------- */
544 : 0 : }
545 : :
546 : : /* Perform DC iteration. */
547 : 0 : void fa1b::calcDC (void)
548 : : {
549 : : // evaluate Verilog code
550 : 0 : initVerilog ();
551 : 0 : calcVerilog ();
552 : :
553 : : // fill right hand side and static jacobian
554 [ # # ]: 0 : for (int i1 = 0; i1 < 9; i1++) {
555 [ # # ]: 0 : setI (i1, _rhs[i1]);
556 [ # # ]: 0 : for (int i2 = 0; i2 < 9; i2++) {
557 [ # # ]: 0 : setY (i1, i2, _jstat[i1][i2]);
558 : : }
559 : : }
560 : 0 : }
561 : :
562 : : /* Save operating points. */
563 : 0 : void fa1b::saveOperatingPoints (void)
564 : : {
565 : : // save global instance operating points
566 : 0 : }
567 : :
568 : : /* Load operating points. */
569 : 0 : void fa1b::loadOperatingPoints (void)
570 : : {
571 : 0 : }
572 : :
573 : : /* Calculate operating points. */
574 : 0 : void fa1b::calcOperatingPoints (void)
575 : : {
576 : 0 : }
577 : :
578 : : /* Initialization of AC analysis. */
579 : 0 : void fa1b::initAC (void)
580 : : {
581 : 0 : allocMatrixMNA ();
582 : 0 : }
583 : :
584 : : /* Perform AC calculations. */
585 : 0 : void fa1b::calcAC (nr_double_t frequency)
586 : : {
587 [ # # ]: 0 : setMatrixY (calcMatrixY (frequency));
588 : 0 : }
589 : :
590 : : /* Compute Y-matrix for AC analysis. */
591 : 0 : matrix fa1b::calcMatrixY (nr_double_t frequency)
592 : : {
593 : 0 : _freq = frequency;
594 : 0 : saveOperatingPoints ();
595 : 0 : matrix y (9);
596 : :
597 [ # # ]: 0 : for (int i1 = 0; i1 < 9; i1++) {
598 [ # # ]: 0 : for (int i2 = 0; i2 < 9; i2++) {
599 : 0 : y (i1,i2) = nr_complex_t (_jstat[i1][i2], _jdyna[i1][i2] * 2 * M_PI * _freq);
600 : : }
601 : : }
602 : :
603 : 0 : return y;
604 : : }
605 : :
606 : : /* Initialization of S-parameter analysis. */
607 : 0 : void fa1b::initSP (void)
608 : : {
609 : 0 : allocMatrixS ();
610 : 0 : }
611 : :
612 : : /* Perform S-parameter calculations. */
613 : 0 : void fa1b::calcSP (nr_double_t frequency)
614 : : {
615 [ # # ][ # # ]: 0 : setMatrixS (ytos (calcMatrixY (frequency)));
[ # # ][ # # ]
[ # # ]
616 : 0 : }
617 : :
618 : : /* Initialization of transient analysis. */
619 : 0 : void fa1b::initTR (void)
620 : : {
621 : 0 : setStates (2 * 9 * 9);
622 : 0 : initDC ();
623 : 0 : }
624 : :
625 : : /* Perform transient analysis iteration step. */
626 : 0 : void fa1b::calcTR (nr_double_t)
627 : : {
628 : 0 : doHB = 0;
629 : 0 : doAC = 1;
630 : 0 : doTR = 1;
631 : 0 : calcDC ();
632 : :
633 : : int i1, i2, i3, i4, state;
634 : :
635 : : // 2-node charge integrations
636 [ # # ]: 0 : for (i1 = 0; i1 < 9; i1++) {
637 [ # # ]: 0 : for (i2 = 0; i2 < 9; i2++) {
638 : 0 : state = 2 * (i2 + 9 * i1);
639 [ # # ]: 0 : if (i1 != i2)
640 [ # # ]: 0 : if (_charges[i1][i2] != 0.0)
641 : 0 : transientCapacitanceQ (state, i1, i2, _charges[i1][i2]);
642 : : } }
643 : :
644 : : // 1-node charge integrations
645 [ # # ]: 0 : for (i1 = 0; i1 < 9; i1++) {
646 : 0 : state = 2 * (i1 + 9 * i1);
647 [ # # ]: 0 : if (_charges[i1][i1] != 0.0)
648 : 0 : transientCapacitanceQ (state, i1, _charges[i1][i1]);
649 : : }
650 : :
651 : : // charge: 2-node, voltage: 2-node
652 [ # # ]: 0 : for (i1 = 0; i1 < 9; i1++) {
653 [ # # ]: 0 : for (i2 = 0; i2 < 9; i2++) {
654 [ # # ]: 0 : if (i1 != i2)
655 [ # # ]: 0 : for (i3 = 0; i3 < 9; i3++) {
656 [ # # ]: 0 : for (i4 = 0; i4 < 9; i4++) {
657 [ # # ]: 0 : if (i3 != i4)
658 [ # # ]: 0 : if (_caps[i1][i2][i3][i4] != 0.0)
659 [ # # ][ # # ]: 0 : transientCapacitanceC (i1, i2, i3, i4, _caps[i1][i2][i3][i4], BP(i3,i4));
660 : : } } } }
661 : :
662 : : // charge: 2-node, voltage: 1-node
663 [ # # ]: 0 : for (i1 = 0; i1 < 9; i1++) {
664 [ # # ]: 0 : for (i2 = 0; i2 < 9; i2++) {
665 [ # # ]: 0 : if (i1 != i2)
666 [ # # ]: 0 : for (i3 = 0; i3 < 9; i3++) {
667 [ # # ]: 0 : if (_caps[i1][i2][i3][i3] != 0.0)
668 [ # # ]: 0 : transientCapacitanceC2Q (i1, i2, i3, _caps[i1][i2][i3][i3], NP(i3));
669 : : } } }
670 : :
671 : : // charge: 1-node, voltage: 2-node
672 [ # # ]: 0 : for (i1 = 0; i1 < 9; i1++) {
673 [ # # ]: 0 : for (i3 = 0; i3 < 9; i3++) {
674 [ # # ]: 0 : for (i4 = 0; i4 < 9; i4++) {
675 [ # # ]: 0 : if (i3 != i4)
676 [ # # ]: 0 : if (_caps[i1][i1][i3][i4] != 0.0)
677 [ # # ][ # # ]: 0 : transientCapacitanceC2V (i1, i3, i4, _caps[i1][i1][i3][i4], BP(i3,i4));
678 : : } } }
679 : :
680 : : // charge: 1-node, voltage: 1-node
681 [ # # ]: 0 : for (i1 = 0; i1 < 9; i1++) {
682 [ # # ]: 0 : for (i3 = 0; i3 < 9; i3++) {
683 [ # # ]: 0 : if (_caps[i1][i1][i3][i3] != 0.0)
684 [ # # ]: 0 : transientCapacitanceC (i1, i3, _caps[i1][i1][i3][i3], NP(i3));
685 : : } }
686 : 0 : }
687 : :
688 : : /* Compute Cy-matrix for AC noise analysis. */
689 : 0 : matrix fa1b::calcMatrixCy (nr_double_t frequency)
690 : : {
691 : 0 : _freq = frequency;
692 : 0 : matrix cy (9);
693 : :
694 : :
695 : 0 : return cy;
696 : : }
697 : :
698 : : /* Perform AC noise computations. */
699 : 0 : void fa1b::calcNoiseAC (nr_double_t frequency)
700 : : {
701 [ # # ]: 0 : setMatrixN (calcMatrixCy (frequency));
702 : 0 : }
703 : :
704 : : /* Perform S-parameter noise computations. */
705 : 0 : void fa1b::calcNoiseSP (nr_double_t frequency)
706 : : {
707 [ # # ][ # # ]: 0 : setMatrixN (cytocs (calcMatrixCy (frequency) * z0, getMatrixS ()));
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
708 : 0 : }
709 : :
710 : : /* Initialization of HB analysis. */
711 : 0 : void fa1b::initHB (int)
712 : : {
713 : 0 : initDC ();
714 : 0 : allocMatrixHB ();
715 : 0 : }
716 : :
717 : : /* Perform HB analysis. */
718 : 0 : void fa1b::calcHB (int)
719 : : {
720 : 0 : doHB = 1;
721 : 0 : doAC = 1;
722 : 0 : doTR = 0;
723 : :
724 : : // jacobian dI/dV and currents get filled
725 : 0 : calcDC ();
726 : 0 : saveOperatingPoints ();
727 : :
728 : : // fill in HB matrices
729 [ # # ]: 0 : for (int i1 = 0; i1 < 9; i1++) {
730 [ # # ]: 0 : setQ (i1, _qhs[i1]); // charges
731 [ # # ]: 0 : setCV (i1, _chs[i1]); // jacobian dQ/dV * V
732 [ # # ]: 0 : setGV (i1, _ghs[i1]); // jacobian dI/dV * V
733 [ # # ]: 0 : for (int i2 = 0; i2 < 9; i2++) {
734 [ # # ]: 0 : setQV (i1, i2, _jdyna[i1][i2]); // jacobian dQ/dV
735 : : }
736 : : }
737 : 0 : }
738 : :
739 : : #include "fa1b.defs.h"
740 : :
|