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