My Project  0.0.16
QUCS Mapping
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
mux2to1.core.cpp
Go to the documentation of this file.
1 /*
2  * mux2to1.core.cpp - device implementations for mux2to1 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 "mux2to1.analogfunction.h"
16 #include "component.h"
17 #include "device.h"
18 #include "mux2to1.core.h"
19 
20 #ifndef CIR_mux2to1
21 #define CIR_mux2to1 -1
22 #endif
23 
24 // external nodes
25 #define EN 0
26 #define A 1
27 #define D0 2
28 #define D1 3
29 #define Y 4
30 // internal nodes
31 #define n1 5
32 #define n2 6
33 
34 // useful macro definitions
35 #define NP(node) real (getV (node))
36 #define BP(pnode,nnode) (NP(pnode) - NP(nnode))
37 #define _load_static_residual2(pnode,nnode,current)\
38  _rhs[pnode] -= current;\
39  _rhs[nnode] += current;
40 #define _load_static_augmented_residual2(pnode,nnode,current)\
41  _rhs[pnode] -= current;\
42  _rhs[nnode] += current;
43 #define _load_static_residual1(node,current)\
44  _rhs[node] -= current;
45 #define _load_static_augmented_residual1(node,current)\
46  _rhs[node] -= current;
47 #define _load_static_jacobian4(pnode,nnode,vpnode,vnnode,conductance)\
48  _jstat[pnode][vpnode] += conductance;\
49  _jstat[nnode][vnnode] += conductance;\
50  _jstat[pnode][vnnode] -= conductance;\
51  _jstat[nnode][vpnode] -= conductance;\
52  if (doHB) {\
53  _ghs[pnode] += conductance * BP(vpnode,vnnode);\
54  _ghs[nnode] -= conductance * BP(vpnode,vnnode);\
55  } else {\
56  _rhs[pnode] += conductance * BP(vpnode,vnnode);\
57  _rhs[nnode] -= conductance * BP(vpnode,vnnode);\
58  }
59 #define _load_static_jacobian2p(node,vpnode,vnnode,conductance)\
60  _jstat[node][vpnode] += conductance;\
61  _jstat[node][vnnode] -= conductance;\
62  if (doHB) {\
63  _ghs[node] += conductance * BP(vpnode,vnnode);\
64  } else {\
65  _rhs[node] += conductance * BP(vpnode,vnnode);\
66  }
67 #define _load_static_jacobian2s(pnode,nnode,node,conductance)\
68  _jstat[pnode][node] += conductance;\
69  _jstat[nnode][node] -= conductance;\
70  if (doHB) {\
71  _ghs[pnode] += conductance * NP(node);\
72  _ghs[nnode] -= conductance * NP(node);\
73  } else {\
74  _rhs[pnode] += conductance * NP(node);\
75  _rhs[nnode] -= conductance * NP(node);\
76  }
77 #define _load_static_jacobian1(node,vnode,conductance)\
78  _jstat[node][vnode] += conductance;\
79  if (doHB) {\
80  _ghs[node] += conductance * NP(vnode);\
81  } else {\
82  _rhs[node] += conductance * NP(vnode);\
83  }
84 #define _load_dynamic_residual2(pnode,nnode,charge)\
85  if (doTR) _charges[pnode][nnode] += charge;\
86  if (doHB) {\
87  _qhs[pnode] -= charge;\
88  _qhs[nnode] += charge;\
89  }
90 #define _load_dynamic_residual1(node,charge)\
91  if (doTR) _charges[node][node] += charge;\
92  if (doHB) {\
93  _qhs[node] -= charge;\
94  }
95 #define _load_dynamic_jacobian4(pnode,nnode,vpnode,vnnode,capacitance)\
96  if (doAC) {\
97  _jdyna[pnode][vpnode] += capacitance;\
98  _jdyna[nnode][vnnode] += capacitance;\
99  _jdyna[pnode][vnnode] -= capacitance;\
100  _jdyna[nnode][vpnode] -= capacitance;\
101  }\
102  if (doTR) {\
103  _caps[pnode][nnode][vpnode][vnnode] += capacitance;\
104  }\
105  if (doHB) {\
106  _chs[pnode] += capacitance * BP(vpnode,vnnode);\
107  _chs[nnode] -= capacitance * BP(vpnode,vnnode);\
108  }
109 #define _load_dynamic_jacobian2s(pnode,nnode,vnode,capacitance)\
110  if (doAC) {\
111  _jdyna[pnode][vnode] += capacitance;\
112  _jdyna[nnode][vnode] -= capacitance;\
113  }\
114  if (doTR) {\
115  _caps[pnode][nnode][vnode][vnode] += capacitance;\
116  }\
117  if (doHB) {\
118  _chs[pnode] += capacitance * NP(vnode);\
119  _chs[nnode] -= capacitance * NP(vnode);\
120  }
121 #define _load_dynamic_jacobian2p(node,vpnode,vnnode,capacitance)\
122  if (doAC) {\
123  _jdyna[node][vpnode] += capacitance;\
124  _jdyna[node][vnnode] -= capacitance;\
125  }\
126  if (doTR) {\
127  _caps[node][node][vpnode][vnnode] += capacitance;\
128  }\
129  if (doHB) {\
130  _chs[node] += capacitance * BP(vpnode,vnnode);\
131  }
132 #define _load_dynamic_jacobian1(node,vnode,capacitance)\
133  if (doAC) {\
134  _jdyna[node][vnode] += capacitance;\
135  }\
136  if (doTR) {\
137  _caps[node][node][vnode][vnode] += capacitance;\
138  }\
139  if (doHB) {\
140  _chs[node] += capacitance * NP(vnode);\
141  }
142 
143 #define _save_whitenoise1(n1,pwr,type)\
144  _white_pwr[n1][n1] += pwr;
145 #define _save_whitenoise2(n1,n2,pwr,type)\
146  _white_pwr[n1][n2] += pwr;
147 #define _save_flickernoise1(n1,pwr,exp,type)\
148  _flicker_pwr[n1][n1] += pwr;\
149  _flicker_exp[n1][n1] += exp;
150 #define _save_flickernoise2(n1,n2,pwr,exp,type)\
151  _flicker_pwr[n1][n2] += pwr;\
152  _flicker_exp[n1][n2] += exp;
153 #define _load_whitenoise2(n1,n2,pwr)\
154  cy (n1,n2) -= pwr/kB/T0; cy (n2,n1) -= pwr/kB/T0;\
155  cy (n1,n1) += pwr/kB/T0; cy (n2,n2) += pwr/kB/T0;
156 #define _load_whitenoise1(n1,pwr)\
157  cy (n1,n1) += pwr/kB/T0;
158 #define _load_flickernoise2(n1,n2,pwr,exp)\
159  cy (n1,n2) -= pwr*pow(_freq,-exp)/kB/T0;\
160  cy (n2,n1) -= pwr*pow(_freq,-exp)/kB/T0;\
161  cy (n1,n1) += pwr*pow(_freq,-exp)/kB/T0;\
162  cy (n2,n2) += pwr*pow(_freq,-exp)/kB/T0;
163 #define _load_flickernoise1(n1,pwr,exp)\
164  cy (n1,n1) += pwr*pow(_freq,-exp)/kB/T0;
165 
166 // derivative helper macros
167 #define m00_hypot(v00,x,y) v00 = xhypot(x,y);
168 #define m10_hypot(v10,v00,x,y) v10 = (x)/(v00);
169 #define m11_hypot(v11,v00,x,y) v11 = (y)/(v00);
170 #define m00_max(v00,x,y) v00 = ((x)>(y))?(x):(y);
171 #define m10_max(v10,v00,x,y) v10 = ((x)>(y))?1.0:0.0;
172 #define m11_max(v11,v00,x,y) v11 = ((x)>(y))?0.0:1.0;
173 #define m00_min(v00,x,y) v00 = ((x)<(y))?(x):(y);
174 #define m10_min(v10,v00,x,y) v10 = ((x)<(y))?1.0:0.0;
175 #define m11_min(v11,v00,x,y) v11 = ((x)<(y))?0.0:1.0;
176 #define m00_pow(v00,x,y) v00 = pow(x,y);
177 #define m10_pow(v10,v00,x,y) v10 = (x==0.0)?0.0:(v00)*(y)/(x);
178 #define m11_pow(v11,v00,x,y) v11 = (x==0.0)?0.0:(log(x)*(v00));
179 
180 #define m00_div(v00,v10,x,y) double v10=1/(y); double v00=(x)*v10;
181 #define m10_div(v10,v00,vv,x,y)
182 #define m11_div(v11,v00,vv,x,y) double v11 = -v00*vv;
183 
184 #define m00_mult(v00,v10,v11,x,y) double v10=(x); double v11=(y); double v00=v10*v11;
185 #define m00_add(v00,x,y) double v00=(x)+(y);
186 
187 #define m00_cos(v00,x) v00 = cos(x);
188 #define m10_cos(v10,v00,x) v10 = (-sin(x));
189 #define m00_sin(v00,x) v00 = sin(x);
190 #define m10_sin(v10,v00,x) v10 = (cos(x));
191 #define m00_tan(v00,x) v00 = tan(x);
192 #define m10_tan(v10,v00,x) v10 = (1.0/cos(x)/cos(x));
193 #define m00_cosh(v00,x) v00 = cosh(x);
194 #define m10_cosh(v10,v00,x) v10 = (sinh(x));
195 #define m00_sinh(v00,x) v00 = sinh(x);
196 #define m10_sinh(v10,v00,x) v10 = (cosh(x));
197 #define m00_tanh(v00,x) v00 = tanh(x);
198 #define m10_tanh(v10,v00,x) v10 = (1.0/cosh(x)/cosh(x));
199 #define m00_acos(v00,x) v00 = acos(x);
200 #define m10_acos(v10,v00,x) v10 = (-1.0/sqrt(1-x*x));
201 #define m00_asin(v00,x) v00 = asin(x);
202 #define m10_asin(v10,v00,x) v10 = (+1.0/sqrt(1-x*x));
203 #define m00_atan(v00,x) v00 = atan(x);
204 #define m10_atan(v10,v00,x) v10 = (+1.0/(1+x*x));
205 #define m00_atanh(v00,x) v00 = atanh(x);
206 #define m10_atanh(v10,v00,x) v10 = (+1.0/(1-x*x));
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_sqrt(v00,x) v00 = sqrt(x);
212 #define m10_sqrt(v10,v00,x) v10 = (0.5/v00);
213 #define m00_fabs(v00,x) v00 = fabs(x);
214 #define m10_fabs(v10,v00,x) v10 = (((x)>=0)?(+1.0):(-1.0));
215 
216 #define m00_exp(v00,x) v00 = exp(x);
217 #define m10_exp(v10,v00,x) v10 = v00;
218 
219 #define m00_abs(v00) ((v00)<(0)?(-(v00)):(v00))
220 #define m00_floor(v00,x) v00 = floor(x);
221 #define m00_limexp(v00,x) v00 = ((x)<80.0?exp(x):exp(80.0)*(x-79.0));
222 #define m10_limexp(v10,v00,x) v10 = ((x)<80.0?(v00):exp(80.0));
223 
224 #define m20_logE(v00) (-1.0/v00/v00)
225 #define m20_exp(v00) exp(v00)
226 #define m20_limexp(v00) ((v00)<80.0?exp(v00):0.0)
227 #define m20_sqrt(v00) (-0.25/(v00)/sqrt(v00))
228 #define m20_fabs(v00) 0.0
229 #define m20_pow(x,y) ((y)*((y)-1.0)*pow(x,y)/(x)/(x))
230 #define m00_vt(x) (kBoverQ*(x))
231 #define m10_vt(x) (kBoverQ)
232 
233 // simulator specific definitions
234 #define _modelname "mux2to1"
235 #define _instancename getName()
236 #define _circuit_temp (getPropertyDouble("Temp")+273.15)
237 #define _param_given(p) (isPropertyGiven(p)?1:0)
238 
239 
240 // $vt and $vt() functions
241 #define _vt_nom (kBoverQ*_circuit_temp)
242 
243 using namespace device;
244 
245 /* Device constructor. */
247 {
248  type = CIR_mux2to1;
249 }
250 
251 /* Initialization of model. */
252 void mux2to1::initModel (void)
253 {
254  // create internal nodes
255  setInternalNode (n1, "n1");
256  setInternalNode (n2, "n2");
257 
258  // get device model parameters
259  loadVariables ();
260  // evaluate global model equations
261  initializeModel ();
262  // evaluate initial step equations
263  initialStep ();
264  // evaluate global instance equations
265  initializeInstance ();
266 }
267 
268 /* Initialization of DC analysis. */
269 void mux2to1::initDC (void)
270 {
271  allocMatrixMNA ();
272  initModel ();
273  pol = 1;
274  restartDC ();
275  doAC = 1;
276  doTR = 0;
277  doHB = 0;
278 }
279 
280 /* Run when DC is restarted (fallback algorithms). */
282 {
283 }
284 
285 /* Initialize Verilog-AMS code. */
286 void mux2to1::initVerilog (void)
287 {
288  // initialization of noise variables
289 
290  int i1, i2, i3, i4;
291 
292  // zero charges
293  for (i1 = 0; i1 < 7; i1++) {
294  for (i2 = 0; i2 < 7; i2++) {
295  _charges[i1][i2] = 0.0;
296  } }
297 
298  // zero capacitances
299  for (i1 = 0; i1 < 7; i1++) {
300  for (i2 = 0; i2 < 7; i2++) {
301  for (i3 = 0; i3 < 7; i3++) {
302  for (i4 = 0; i4 < 7; i4++) {
303  _caps[i1][i2][i3][i4] = 0.0;
304  } } } }
305 
306  // zero right hand side, static and dynamic jacobian
307  for (i1 = 0; i1 < 7; i1++) {
308  _rhs[i1] = 0.0;
309  _qhs[i1] = 0.0;
310  _chs[i1] = 0.0;
311  _ghs[i1] = 0.0;
312  for (i2 = 0; i2 < 7; i2++) {
313  _jstat[i1][i2] = 0.0;
314  _jdyna[i1][i2] = 0.0;
315  }
316  }
317 }
318 
319 /* Load device model input parameters. */
320 void mux2to1::loadVariables (void)
321 {
322  TR = getPropertyDouble ("TR");
323  Delay = getPropertyDouble ("Delay");
324 }
325 
326 /* #define's for translated code */
327 #undef _DDT
328 #define _DDT(q) q
329 #define _DYNAMIC
330 #define _DERIVATE
331 #define _DDX
332 #define _DERIVATEFORDDX
333 
334 /* Evaluate Verilog-AMS equations in model initialization. */
335 void mux2to1::initializeModel (void)
336 {
337 #if defined(_DYNAMIC)
338 #endif
339 {
340 Rd=1e3;
341 #if defined(_DYNAMIC)
342 Ccc=((Delay*1.43)/Rd);
343 #endif
344 }
345 }
346 
347 /* Evaluate Verilog-AMS equations in instance initialization. */
348 void mux2to1::initializeInstance (void)
349 {
350 }
351 
352 /* Evaluate Verilog-AMS equations in initial step. */
353 void mux2to1::initialStep (void)
354 {
355 }
356 
357 /* Evaluate Verilog-AMS equations in final step. */
358 void mux2to1::finalStep (void)
359 {
360 }
361 
362 /* Evaluate Verilog-AMS equations in analog block. */
363 void mux2to1::calcVerilog (void)
364 {
365 
366 /* ----------------- evaluate verilog analog equations -------------------- */
367 double In1;
368 #if defined(_DERIVATE)
369 double In1_VEN_GND;
370 double In1_VD1_GND;
371 double In1_VA_GND;
372 double In1_VD0_GND;
373 #endif
374 #if defined(_DERIVATE)
375 In1_VEN_GND=(-1.0)*((NP(D1)*NP(A))+(NP(D0)*(1-NP(A))));
376 In1_VD1_GND=((1-NP(EN))*(NP(A)));
377 In1_VA_GND=((1-NP(EN))*((NP(D1))+(NP(D0)*(-1.0))));
378 In1_VD0_GND=((1-NP(EN))*((1-NP(A))));
379 #endif
380 In1=((1-NP(EN))*((NP(D1)*NP(A))+(NP(D0)*(1-NP(A)))));
381 {
382 double m00_tanh(d00_tanh0,(TR*(In1-0.5)))
383 #if defined(_DERIVATE)
384 double m10_tanh(d10_tanh0,d00_tanh0,(TR*(In1-0.5)))
385 #endif
386 _load_static_residual1(n1,((-0.5)*(1+d00_tanh0)));
387 #if defined(_DERIVATE)
388 _load_static_jacobian1(n1,D0,((-0.5)*(TR*In1_VD0_GND)*d10_tanh0));
389 _load_static_jacobian1(n1,A,((-0.5)*(TR*In1_VA_GND)*d10_tanh0));
390 _load_static_jacobian1(n1,D1,((-0.5)*(TR*In1_VD1_GND)*d10_tanh0));
391 _load_static_jacobian1(n1,EN,((-0.5)*(TR*In1_VEN_GND)*d10_tanh0));
392 #endif
393 }
395 #if defined(_DERIVATE)
397 #endif
399 #if defined(_DERIVATE)
401 #endif
402 #if defined(_DYNAMIC)
404 #if defined(_DERIVATE)
406 #endif
407 #endif
409 #if defined(_DERIVATE)
410 _load_static_jacobian1(Y,n2,(-1.0));
411 #endif
413 #if defined(_DERIVATE)
415 #endif
416 
417 /* ------------------ end of verilog analog equations --------------------- */
418 
419 /* ------------------ evaluate verilog noise equations -------------------- */
420 
421 /* ------------------- end of verilog noise equations --------------------- */
422 }
423 
424 /* Perform DC iteration. */
425 void mux2to1::calcDC (void)
426 {
427  // evaluate Verilog code
428  initVerilog ();
429  calcVerilog ();
430 
431  // fill right hand side and static jacobian
432  for (int i1 = 0; i1 < 7; i1++) {
433  setI (i1, _rhs[i1]);
434  for (int i2 = 0; i2 < 7; i2++) {
435  setY (i1, i2, _jstat[i1][i2]);
436  }
437  }
438 }
439 
440 /* Save operating points. */
442 {
443  // save global instance operating points
444 }
445 
446 /* Load operating points. */
448 {
449 }
450 
451 /* Calculate operating points. */
453 {
454 }
455 
456 /* Initialization of AC analysis. */
457 void mux2to1::initAC (void)
458 {
459  allocMatrixMNA ();
460 }
461 
462 /* Perform AC calculations. */
463 void mux2to1::calcAC (nr_double_t frequency)
464 {
465  setMatrixY (calcMatrixY (frequency));
466 }
467 
468 /* Compute Y-matrix for AC analysis. */
469 matrix mux2to1::calcMatrixY (nr_double_t frequency)
470 {
471  _freq = frequency;
473  matrix y (7);
474 
475  for (int i1 = 0; i1 < 7; i1++) {
476  for (int i2 = 0; i2 < 7; i2++) {
477  y (i1,i2) = rect (_jstat[i1][i2], _jdyna[i1][i2] * 2 * M_PI * _freq);
478  }
479  }
480 
481  return y;
482 }
483 
484 /* Initialization of S-parameter analysis. */
485 void mux2to1::initSP (void)
486 {
487  allocMatrixS ();
488 }
489 
490 /* Perform S-parameter calculations. */
491 void mux2to1::calcSP (nr_double_t frequency)
492 {
493  setMatrixS (ytos (calcMatrixY (frequency)));
494 }
495 
496 /* Initialization of transient analysis. */
497 void mux2to1::initTR (void)
498 {
499  setStates (2 * 7 * 7);
500  initDC ();
501 }
502 
503 /* Perform transient analysis iteration step. */
504 void mux2to1::calcTR (nr_double_t)
505 {
506  doHB = 0;
507  doAC = 1;
508  doTR = 1;
509  calcDC ();
510 
511  int i1, i2, i3, i4, state;
512 
513  // 2-node charge integrations
514  for (i1 = 0; i1 < 7; i1++) {
515  for (i2 = 0; i2 < 7; i2++) {
516  state = 2 * (i2 + 7 * i1);
517  if (i1 != i2)
518  if (_charges[i1][i2] != 0.0)
519  transientCapacitanceQ (state, i1, i2, _charges[i1][i2]);
520  } }
521 
522  // 1-node charge integrations
523  for (i1 = 0; i1 < 7; i1++) {
524  state = 2 * (i1 + 7 * i1);
525  if (_charges[i1][i1] != 0.0)
526  transientCapacitanceQ (state, i1, _charges[i1][i1]);
527  }
528 
529  // charge: 2-node, voltage: 2-node
530  for (i1 = 0; i1 < 7; i1++) {
531  for (i2 = 0; i2 < 7; i2++) {
532  if (i1 != i2)
533  for (i3 = 0; i3 < 7; i3++) {
534  for (i4 = 0; i4 < 7; i4++) {
535  if (i3 != i4)
536  if (_caps[i1][i2][i3][i4] != 0.0)
537  transientCapacitanceC (i1, i2, i3, i4, _caps[i1][i2][i3][i4], BP(i3,i4));
538  } } } }
539 
540  // charge: 2-node, voltage: 1-node
541  for (i1 = 0; i1 < 7; i1++) {
542  for (i2 = 0; i2 < 7; i2++) {
543  if (i1 != i2)
544  for (i3 = 0; i3 < 7; i3++) {
545  if (_caps[i1][i2][i3][i3] != 0.0)
546  transientCapacitanceC2Q (i1, i2, i3, _caps[i1][i2][i3][i3], NP(i3));
547  } } }
548 
549  // charge: 1-node, voltage: 2-node
550  for (i1 = 0; i1 < 7; i1++) {
551  for (i3 = 0; i3 < 7; i3++) {
552  for (i4 = 0; i4 < 7; i4++) {
553  if (i3 != i4)
554  if (_caps[i1][i1][i3][i4] != 0.0)
555  transientCapacitanceC2V (i1, i3, i4, _caps[i1][i1][i3][i4], BP(i3,i4));
556  } } }
557 
558  // charge: 1-node, voltage: 1-node
559  for (i1 = 0; i1 < 7; i1++) {
560  for (i3 = 0; i3 < 7; i3++) {
561  if (_caps[i1][i1][i3][i3] != 0.0)
562  transientCapacitanceC (i1, i3, _caps[i1][i1][i3][i3], NP(i3));
563  } }
564 }
565 
566 /* Compute Cy-matrix for AC noise analysis. */
567 matrix mux2to1::calcMatrixCy (nr_double_t frequency)
568 {
569  _freq = frequency;
570  matrix cy (7);
571 
572 
573  return cy;
574 }
575 
576 /* Perform AC noise computations. */
577 void mux2to1::calcNoiseAC (nr_double_t frequency)
578 {
579  setMatrixN (calcMatrixCy (frequency));
580 }
581 
582 /* Perform S-parameter noise computations. */
583 void mux2to1::calcNoiseSP (nr_double_t frequency)
584 {
585  setMatrixN (cytocs (calcMatrixCy (frequency) * z0, getMatrixS ()));
586 }
587 
588 /* Initialization of HB analysis. */
589 void mux2to1::initHB (int)
590 {
591  initDC ();
592  allocMatrixHB ();
593 }
594 
595 /* Perform HB analysis. */
596 void mux2to1::calcHB (int)
597 {
598  doHB = 1;
599  doAC = 1;
600  doTR = 0;
601 
602  // jacobian dI/dV and currents get filled
603  calcDC ();
605 
606  // fill in HB matrices
607  for (int i1 = 0; i1 < 7; i1++) {
608  setQ (i1, _qhs[i1]); // charges
609  setCV (i1, _chs[i1]); // jacobian dQ/dV * V
610  setGV (i1, _ghs[i1]); // jacobian dI/dV * V
611  for (int i2 = 0; i2 < 7; i2++) {
612  setQV (i1, i2, _jdyna[i1][i2]); // jacobian dQ/dV
613  }
614  }
615 }
616 
617 #include "mux2to1.defs.h"