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