basic_circuit.cc revision 10152:52c552138ba1
1/*****************************************************************************
2 *                                McPAT/CACTI
3 *                      SOFTWARE LICENSE AGREEMENT
4 *            Copyright 2012 Hewlett-Packard Development Company, L.P.
5 *                          All Rights Reserved
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
9 * met: redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer;
11 * redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution;
14 * neither the name of the copyright holders nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.”
29 *
30 ***************************************************************************/
31
32
33
34
35#include <cassert>
36#include <cmath>
37#include <iostream>
38
39#include "basic_circuit.h"
40#include "parameter.h"
41
42uint32_t _log2(uint64_t num)
43{
44  uint32_t log2 = 0;
45
46  if (num == 0)
47  {
48    std::cerr << "log0?" << std::endl;
49    exit(1);
50  }
51
52  while (num > 1)
53  {
54    num = (num >> 1);
55    log2++;
56  }
57
58  return log2;
59}
60
61
62bool is_pow2(int64_t val)
63{
64  if (val <= 0)
65  {
66    return false;
67  }
68  else if (val == 1)
69  {
70    return true;
71  }
72  else
73  {
74    return (_log2(val) != _log2(val-1));
75  }
76}
77
78
79int powers (int base, int n)
80{
81  int i, p;
82
83  p = 1;
84  for (i = 1; i <= n; ++i)
85    p *= base;
86  return p;
87}
88
89/*----------------------------------------------------------------------*/
90
91double logtwo (double x)
92{
93  assert(x > 0);
94  return ((double) (log (x) / log (2.0)));
95}
96
97/*----------------------------------------------------------------------*/
98
99
100double gate_C(
101    double width,
102    double wirelength,
103    bool   _is_dram,
104    bool   _is_cell,
105    bool   _is_wl_tr)
106{
107  const TechnologyParameter::DeviceType * dt;
108
109  if (_is_dram && _is_cell)
110  {
111    dt = &g_tp.dram_acc;   //DRAM cell access transistor
112  }
113  else if (_is_dram && _is_wl_tr)
114  {
115    dt = &g_tp.dram_wl;    //DRAM wordline transistor
116  }
117  else if (!_is_dram && _is_cell)
118  {
119    dt = &g_tp.sram_cell;  // SRAM cell access transistor
120  }
121  else
122  {
123    dt = &g_tp.peri_global;
124  }
125
126  return (dt->C_g_ideal + dt->C_overlap + 3*dt->C_fringe)*width + dt->l_phy*Cpolywire;
127}
128
129
130// returns gate capacitance in Farads
131// actually this function is the same as gate_C() now
132double gate_C_pass(
133    double width,       // gate width in um (length is Lphy_periph_global)
134    double wirelength,  // poly wire length going to gate in lambda
135    bool   _is_dram,
136    bool   _is_cell,
137    bool   _is_wl_tr)
138{
139  // v5.0
140  const TechnologyParameter::DeviceType * dt;
141
142  if ((_is_dram) && (_is_cell))
143  {
144    dt = &g_tp.dram_acc;   //DRAM cell access transistor
145  }
146  else if ((_is_dram) && (_is_wl_tr))
147  {
148    dt = &g_tp.dram_wl;    //DRAM wordline transistor
149  }
150  else if ((!_is_dram) && _is_cell)
151  {
152    dt = &g_tp.sram_cell;  // SRAM cell access transistor
153  }
154  else
155  {
156    dt = &g_tp.peri_global;
157  }
158
159  return (dt->C_g_ideal + dt->C_overlap + 3*dt->C_fringe)*width + dt->l_phy*Cpolywire;
160}
161
162
163
164double drain_C_(
165    double width,
166    int nchannel,
167    int stack,
168    int next_arg_thresh_folding_width_or_height_cell,
169    double fold_dimension,
170    bool _is_dram,
171    bool _is_cell,
172    bool _is_wl_tr)
173{
174  double w_folded_tr;
175  const  TechnologyParameter::DeviceType * dt;
176
177  if ((_is_dram) && (_is_cell))
178  {
179    dt = &g_tp.dram_acc;   // DRAM cell access transistor
180  }
181  else if ((_is_dram) && (_is_wl_tr))
182  {
183    dt = &g_tp.dram_wl;    // DRAM wordline transistor
184  }
185  else if ((!_is_dram) && _is_cell)
186  {
187    dt = &g_tp.sram_cell;  // SRAM cell access transistor
188  }
189  else
190  {
191    dt = &g_tp.peri_global;
192  }
193
194  double c_junc_area = dt->C_junc;
195  double c_junc_sidewall = dt->C_junc_sidewall;
196  double c_fringe    = 2*dt->C_fringe;
197  double c_overlap   = 2*dt->C_overlap;
198  double drain_C_metal_connecting_folded_tr = 0;
199
200  // determine the width of the transistor after folding (if it is getting folded)
201  if (next_arg_thresh_folding_width_or_height_cell == 0)
202  { // interpret fold_dimension as the the folding width threshold
203    // i.e. the value of transistor width above which the transistor gets folded
204    w_folded_tr = fold_dimension;
205  }
206  else
207  { // interpret fold_dimension as the height of the cell that this transistor is part of.
208    double h_tr_region  = fold_dimension - 2 * g_tp.HPOWERRAIL;
209    // TODO : w_folded_tr must come from Component::compute_gate_area()
210    double ratio_p_to_n = 2.0 / (2.0 + 1.0);
211    if (nchannel)
212    {
213      w_folded_tr = (1 - ratio_p_to_n) * (h_tr_region - g_tp.MIN_GAP_BET_P_AND_N_DIFFS);
214    }
215    else
216    {
217      w_folded_tr = ratio_p_to_n * (h_tr_region - g_tp.MIN_GAP_BET_P_AND_N_DIFFS);
218    }
219  }
220  int num_folded_tr = (int) (ceil(width / w_folded_tr));
221
222  if (num_folded_tr < 2)
223  {
224    w_folded_tr = width;
225  }
226
227  double total_drain_w = (g_tp.w_poly_contact + 2 * g_tp.spacing_poly_to_contact) +  // only for drain
228                         (stack - 1) * g_tp.spacing_poly_to_poly;
229  double drain_h_for_sidewall = w_folded_tr;
230  double total_drain_height_for_cap_wrt_gate = w_folded_tr + 2 * w_folded_tr * (stack - 1);
231  if (num_folded_tr > 1)
232  {
233    total_drain_w += (num_folded_tr - 2) * (g_tp.w_poly_contact + 2 * g_tp.spacing_poly_to_contact) +
234                     (num_folded_tr - 1) * ((stack - 1) * g_tp.spacing_poly_to_poly);
235
236    if (num_folded_tr%2 == 0)
237    {
238      drain_h_for_sidewall = 0;
239    }
240    total_drain_height_for_cap_wrt_gate *= num_folded_tr;
241    drain_C_metal_connecting_folded_tr   = g_tp.wire_local.C_per_um * total_drain_w;
242  }
243
244  double drain_C_area     = c_junc_area * total_drain_w * w_folded_tr;
245  double drain_C_sidewall = c_junc_sidewall * (drain_h_for_sidewall + 2 * total_drain_w);
246  double drain_C_wrt_gate = (c_fringe + c_overlap) * total_drain_height_for_cap_wrt_gate;
247
248  return (drain_C_area + drain_C_sidewall + drain_C_wrt_gate + drain_C_metal_connecting_folded_tr);
249}
250
251
252double tr_R_on(
253    double width,
254    int nchannel,
255    int stack,
256    bool _is_dram,
257    bool _is_cell,
258    bool _is_wl_tr)
259{
260  const TechnologyParameter::DeviceType * dt;
261
262  if ((_is_dram) && (_is_cell))
263  {
264    dt = &g_tp.dram_acc;   //DRAM cell access transistor
265  }
266  else if ((_is_dram) && (_is_wl_tr))
267  {
268    dt = &g_tp.dram_wl;    //DRAM wordline transistor
269  }
270  else if ((!_is_dram) && _is_cell)
271  {
272    dt = &g_tp.sram_cell;  // SRAM cell access transistor
273  }
274  else
275  {
276    dt = &g_tp.peri_global;
277  }
278
279  double restrans = (nchannel) ? dt->R_nch_on : dt->R_pch_on;
280  return (stack * restrans / width);
281}
282
283
284/* This routine operates in reverse: given a resistance, it finds
285 * the transistor width that would have this R.  It is used in the
286 * data wordline to estimate the wordline driver size. */
287
288// returns width in um
289double R_to_w(
290    double res,
291    int   nchannel,
292    bool _is_dram,
293    bool _is_cell,
294    bool _is_wl_tr)
295{
296  const TechnologyParameter::DeviceType * dt;
297
298  if ((_is_dram) && (_is_cell))
299  {
300    dt = &g_tp.dram_acc;   //DRAM cell access transistor
301  }
302  else if ((_is_dram) && (_is_wl_tr))
303  {
304    dt = &g_tp.dram_wl;    //DRAM wordline transistor
305  }
306  else if ((!_is_dram) && (_is_cell))
307  {
308    dt = &g_tp.sram_cell;  // SRAM cell access transistor
309  }
310  else
311  {
312    dt = &g_tp.peri_global;
313  }
314
315  double restrans = (nchannel) ? dt->R_nch_on : dt->R_pch_on;
316  return (restrans / res);
317}
318
319
320double pmos_to_nmos_sz_ratio(
321    bool _is_dram,
322    bool _is_wl_tr)
323{
324  double p_to_n_sizing_ratio;
325  if ((_is_dram) && (_is_wl_tr))
326  { //DRAM wordline transistor
327    p_to_n_sizing_ratio = g_tp.dram_wl.n_to_p_eff_curr_drv_ratio;
328  }
329  else
330  { //DRAM or SRAM all other transistors
331    p_to_n_sizing_ratio = g_tp.peri_global.n_to_p_eff_curr_drv_ratio;
332  }
333  return p_to_n_sizing_ratio;
334}
335
336
337// "Timing Models for MOS Circuits" by Mark Horowitz, 1984
338double horowitz(
339    double inputramptime, // input rise time
340    double tf,            // time constant of gate
341    double vs1,           // threshold voltage
342    double vs2,           // threshold voltage
343    int    rise)          // whether input rises or fall
344{
345  if (inputramptime == 0 && vs1 == vs2)
346  {
347    return tf * (vs1 < 1 ? -log(vs1) : log(vs1));
348  }
349  double a, b, td;
350
351  a = inputramptime / tf;
352  if (rise == RISE)
353  {
354    b = 0.5;
355    td = tf * sqrt(log(vs1)*log(vs1) + 2*a*b*(1.0 - vs1)) + tf*(log(vs1) - log(vs2));
356  }
357  else
358  {
359    b = 0.4;
360    td = tf * sqrt(log(1.0 - vs1)*log(1.0 - vs1) + 2*a*b*(vs1)) + tf*(log(1.0 - vs1) - log(1.0 - vs2));
361  }
362  return (td);
363}
364
365double cmos_Ileak(
366    double nWidth,
367    double pWidth,
368    bool _is_dram,
369    bool _is_cell,
370    bool _is_wl_tr)
371{
372  TechnologyParameter::DeviceType * dt;
373
374  if ((!_is_dram)&&(_is_cell))
375  { //SRAM cell access transistor
376    dt = &(g_tp.sram_cell);
377  }
378  else if ((_is_dram)&&(_is_wl_tr))
379  { //DRAM wordline transistor
380    dt = &(g_tp.dram_wl);
381  }
382  else
383  { //DRAM or SRAM all other transistors
384    dt = &(g_tp.peri_global);
385  }
386  return nWidth*dt->I_off_n + pWidth*dt->I_off_p;
387}
388
389
390double simplified_nmos_leakage(
391    double nwidth,
392    bool _is_dram,
393    bool _is_cell,
394    bool _is_wl_tr)
395{
396  TechnologyParameter::DeviceType * dt;
397
398  if ((!_is_dram)&&(_is_cell))
399  { //SRAM cell access transistor
400    dt = &(g_tp.sram_cell);
401  }
402  else if ((_is_dram)&&(_is_wl_tr))
403  { //DRAM wordline transistor
404    dt = &(g_tp.dram_wl);
405  }
406  else
407  { //DRAM or SRAM all other transistors
408    dt = &(g_tp.peri_global);
409  }
410  return nwidth * dt->I_off_n;
411}
412
413int factorial(int n, int m)
414{
415        int fa = m, i;
416        for (i=m+1; i<=n; i++)
417                fa *=i;
418        return fa;
419}
420
421int combination(int n, int m)
422{
423  int ret;
424  ret = factorial(n, m+1) / factorial(n - m);
425  return ret;
426}
427
428double simplified_pmos_leakage(
429    double pwidth,
430    bool _is_dram,
431    bool _is_cell,
432    bool _is_wl_tr)
433{
434  TechnologyParameter::DeviceType * dt;
435
436  if ((!_is_dram)&&(_is_cell))
437  { //SRAM cell access transistor
438    dt = &(g_tp.sram_cell);
439  }
440  else if ((_is_dram)&&(_is_wl_tr))
441  { //DRAM wordline transistor
442    dt = &(g_tp.dram_wl);
443  }
444  else
445  { //DRAM or SRAM all other transistors
446    dt = &(g_tp.peri_global);
447  }
448  return pwidth * dt->I_off_p;
449}
450
451double cmos_Ig_n(
452    double nWidth,
453    bool _is_dram,
454    bool _is_cell,
455    bool _is_wl_tr)
456{
457  TechnologyParameter::DeviceType * dt;
458
459  if ((!_is_dram)&&(_is_cell))
460  { //SRAM cell access transistor
461    dt = &(g_tp.sram_cell);
462  }
463  else if ((_is_dram)&&(_is_wl_tr))
464  { //DRAM wordline transistor
465    dt = &(g_tp.dram_wl);
466  }
467  else
468  { //DRAM or SRAM all other transistors
469    dt = &(g_tp.peri_global);
470  }
471  return nWidth*dt->I_g_on_n;
472}
473
474double cmos_Ig_p(
475    double pWidth,
476    bool _is_dram,
477    bool _is_cell,
478    bool _is_wl_tr)
479{
480  TechnologyParameter::DeviceType * dt;
481
482  if ((!_is_dram)&&(_is_cell))
483  { //SRAM cell access transistor
484    dt = &(g_tp.sram_cell);
485  }
486  else if ((_is_dram)&&(_is_wl_tr))
487  { //DRAM wordline transistor
488    dt = &(g_tp.dram_wl);
489  }
490  else
491  { //DRAM or SRAM all other transistors
492    dt = &(g_tp.peri_global);
493  }
494  return pWidth*dt->I_g_on_p;
495}
496
497double cmos_Isub_leakage(
498    double nWidth,
499    double pWidth,
500    int    fanin,
501    enum Gate_type g_type,
502    bool _is_dram,
503    bool _is_cell,
504    bool _is_wl_tr,
505    enum Half_net_topology topo)
506{
507        assert (fanin>=1);
508        double nmos_leak = simplified_nmos_leakage(nWidth, _is_dram, _is_cell, _is_wl_tr);
509        double pmos_leak = simplified_pmos_leakage(pWidth, _is_dram, _is_cell, _is_wl_tr);
510    double Isub=0;
511    int    num_states;
512    int    num_off_tx;
513
514    num_states = int(pow(2.0, fanin));
515
516    switch (g_type)
517    {
518    case nmos:
519        if (fanin==1)
520        {
521                Isub = nmos_leak/num_states;
522        }
523        else
524        {
525                if (topo==parallel)
526                {
527                        Isub=nmos_leak*fanin/num_states; //only when all tx are off, leakage power is non-zero. The possibility of this state is 1/num_states
528                }
529                else
530                {
531                        for (num_off_tx=1; num_off_tx<=fanin; num_off_tx++) //when num_off_tx ==0 there is no leakage power
532                        {
533                                //Isub += nmos_leak*pow(UNI_LEAK_STACK_FACTOR,(num_off_tx-1))*(factorial(fanin)/(factorial(fanin, num_off_tx)*factorial(num_off_tx)));
534                                Isub += nmos_leak*pow(UNI_LEAK_STACK_FACTOR,(num_off_tx-1))*combination(fanin, num_off_tx);
535                        }
536                        Isub /=num_states;
537                }
538
539        }
540        break;
541    case pmos:
542        if (fanin==1)
543        {
544                Isub = pmos_leak/num_states;
545        }
546        else
547        {
548                if (topo==parallel)
549                {
550                        Isub=pmos_leak*fanin/num_states; //only when all tx are off, leakage power is non-zero. The possibility of this state is 1/num_states
551                }
552                else
553                {
554                        for (num_off_tx=1; num_off_tx<=fanin; num_off_tx++) //when num_off_tx ==0 there is no leakage power
555                        {
556                                //Isub += pmos_leak*pow(UNI_LEAK_STACK_FACTOR,(num_off_tx-1))*(factorial(fanin)/(factorial(fanin, num_off_tx)*factorial(num_off_tx)));
557                                Isub += pmos_leak*pow(UNI_LEAK_STACK_FACTOR,(num_off_tx-1))*combination(fanin, num_off_tx);
558                        }
559                        Isub /=num_states;
560                }
561
562        }
563        break;
564    case inv:
565        Isub = (nmos_leak + pmos_leak)/2;
566        break;
567    case nand:
568        Isub += fanin*pmos_leak;//the pullup network
569        for (num_off_tx=1; num_off_tx<=fanin; num_off_tx++) // the pulldown network
570        {
571                //Isub += nmos_leak*pow(UNI_LEAK_STACK_FACTOR,(num_off_tx-1))*(factorial(fanin)/(factorial(fanin, num_off_tx)*factorial(num_off_tx)));
572            Isub += nmos_leak*pow(UNI_LEAK_STACK_FACTOR,(num_off_tx-1))*combination(fanin, num_off_tx);
573        }
574        Isub /=num_states;
575        break;
576    case nor:
577        for (num_off_tx=1; num_off_tx<=fanin; num_off_tx++) // the pullup network
578        {
579                //Isub += pmos_leak*pow(UNI_LEAK_STACK_FACTOR,(num_off_tx-1))*(factorial(fanin)/(factorial(fanin, num_off_tx)*factorial(num_off_tx)));
580                Isub += pmos_leak*pow(UNI_LEAK_STACK_FACTOR,(num_off_tx-1))*combination(fanin, num_off_tx);
581        }
582        Isub += fanin*nmos_leak;//the pulldown network
583        Isub /=num_states;
584        break;
585    case tri:
586        Isub += (nmos_leak + pmos_leak)/2;//enabled
587        Isub += nmos_leak*UNI_LEAK_STACK_FACTOR; //disabled upper bound of leakage power
588        Isub /=2;
589        break;
590    case tg:
591        Isub = (nmos_leak + pmos_leak)/2;
592        break;
593    default:
594        assert(0);
595        break;
596          }
597
598    return Isub;
599}
600
601
602double cmos_Ig_leakage(
603    double nWidth,
604    double pWidth,
605    int    fanin,
606    enum Gate_type g_type,
607    bool _is_dram,
608    bool _is_cell,
609    bool _is_wl_tr,
610    enum Half_net_topology topo)
611{
612        assert (fanin>=1);
613                double nmos_leak = cmos_Ig_n(nWidth, _is_dram, _is_cell, _is_wl_tr);
614                double pmos_leak = cmos_Ig_p(pWidth, _is_dram, _is_cell, _is_wl_tr);
615            double Ig_on=0;
616            int    num_states;
617            int    num_on_tx;
618
619            num_states = int(pow(2.0, fanin));
620
621            switch (g_type)
622            {
623            case nmos:
624                if (fanin==1)
625                {
626                        Ig_on = nmos_leak/num_states;
627                }
628                else
629                {
630                        if (topo==parallel)
631                        {
632                        for (num_on_tx=1; num_on_tx<=fanin; num_on_tx++)
633                        {
634                                Ig_on += nmos_leak*combination(fanin, num_on_tx)*num_on_tx;
635                        }
636                        }
637                        else
638                        {
639                                Ig_on += nmos_leak * fanin;//pull down network when all TXs are on.
640                            //num_on_tx is the number of on tx
641                                for (num_on_tx=1; num_on_tx<fanin; num_on_tx++)//when num_on_tx=[1,n-1]
642                                {
643                                        Ig_on += nmos_leak*combination(fanin, num_on_tx)*num_on_tx/2;//TODO: this is a approximation now, a precise computation will be very complicated.
644                                }
645                                Ig_on /=num_states;
646                        }
647                }
648                break;
649            case pmos:
650                if (fanin==1)
651                {
652                        Ig_on = pmos_leak/num_states;
653                }
654                else
655                {
656                        if (topo==parallel)
657                    {
658                  for (num_on_tx=1; num_on_tx<=fanin; num_on_tx++)
659                  {
660                          Ig_on += pmos_leak*combination(fanin, num_on_tx)*num_on_tx;
661                  }
662                    }
663                    else
664                    {
665                          Ig_on += pmos_leak * fanin;//pull down network when all TXs are on.
666                      //num_on_tx is the number of on tx
667                          for (num_on_tx=1; num_on_tx<fanin; num_on_tx++)//when num_on_tx=[1,n-1]
668                          {
669                                  Ig_on += pmos_leak*combination(fanin, num_on_tx)*num_on_tx/2;//TODO: this is a approximation now, a precise computation will be very complicated.
670                          }
671                          Ig_on /=num_states;
672                    }
673                }
674                break;
675
676            case inv:
677                Ig_on = (nmos_leak + pmos_leak)/2;
678                break;
679            case nand:
680                //pull up network
681                for (num_on_tx=1; num_on_tx<=fanin; num_on_tx++)//when num_on_tx=[1,n]
682                {
683                        Ig_on += pmos_leak*combination(fanin, num_on_tx)*num_on_tx;
684                }
685
686                //pull down network
687                Ig_on += nmos_leak * fanin;//pull down network when all TXs are on.
688                //num_on_tx is the number of on tx
689                for (num_on_tx=1; num_on_tx<fanin; num_on_tx++)//when num_on_tx=[1,n-1]
690                {
691                        Ig_on += nmos_leak*combination(fanin, num_on_tx)*num_on_tx/2;//TODO: this is a approximation now, a precise computation will be very complicated.
692                }
693                Ig_on /=num_states;
694                break;
695            case nor:
696                // num_on_tx is the number of on tx in pull up network
697                Ig_on += pmos_leak * fanin;//pull up network when all TXs are on.
698                for (num_on_tx=1; num_on_tx<fanin; num_on_tx++)
699                {
700                        Ig_on += pmos_leak*combination(fanin, num_on_tx)*num_on_tx/2;
701
702                }
703                //pull down network
704                for (num_on_tx=1; num_on_tx<=fanin; num_on_tx++)//when num_on_tx=[1,n]
705                {
706                        Ig_on += nmos_leak*combination(fanin, num_on_tx)*num_on_tx;
707                }
708                Ig_on /=num_states;
709                break;
710            case tri:
711                Ig_on += (2*nmos_leak + 2*pmos_leak)/2;//enabled
712                Ig_on += (nmos_leak + pmos_leak)/2; //disabled upper bound of leakage power
713                Ig_on /=2;
714                break;
715            case tg:
716                Ig_on = (nmos_leak + pmos_leak)/2;
717                break;
718            default:
719                assert(0);
720                break;
721                  }
722
723            return Ig_on;
724}
725
726double shortcircuit_simple(
727    double vt,
728    double velocity_index,
729    double c_in,
730    double c_out,
731    double w_nmos,
732    double w_pmos,
733    double i_on_n,
734    double i_on_p,
735    double i_on_n_in,
736    double i_on_p_in,
737    double vdd)
738{
739
740        double p_short_circuit, p_short_circuit_discharge, p_short_circuit_charge, p_short_circuit_discharge_low, p_short_circuit_discharge_high, p_short_circuit_charge_low, p_short_circuit_charge_high; //this is actually energy
741        double fo_n, fo_p, fanout, beta_ratio, vt_to_vdd_ratio;
742
743        fo_n	= i_on_n/i_on_n_in;
744        fo_p	= i_on_p/i_on_p_in;
745        fanout	= c_out/c_in;
746        beta_ratio = i_on_p/i_on_n;
747        vt_to_vdd_ratio = vt/vdd;
748
749        //p_short_circuit_discharge_low 	= 10/3*(pow(0.5-vt_to_vdd_ratio,3.0)/pow(velocity_index,2.0)/pow(2.0,3*vt_to_vdd_ratio*vt_to_vdd_ratio))*c_in*vdd*vdd*fo_p*fo_p/fanout/beta_ratio;
750        p_short_circuit_discharge_low 	= 10/3*(pow(((vdd-vt)-vt_to_vdd_ratio),3.0)/pow(velocity_index,2.0)/pow(2.0,3*vt_to_vdd_ratio*vt_to_vdd_ratio))*c_in*vdd*vdd*fo_p*fo_p/fanout/beta_ratio;
751        p_short_circuit_charge_low 		= 10/3*(pow(((vdd-vt)-vt_to_vdd_ratio),3.0)/pow(velocity_index,2.0)/pow(2.0,3*vt_to_vdd_ratio*vt_to_vdd_ratio))*c_in*vdd*vdd*fo_n*fo_n/fanout*beta_ratio;
752//	double t1, t2, t3, t4, t5;
753//	t1=pow(((vdd-vt)-vt_to_vdd_ratio),3);
754//	t2=pow(velocity_index,2.0);
755//	t3=pow(2.0,3*vt_to_vdd_ratio*vt_to_vdd_ratio);
756//	t4=t1/t2/t3;
757//	cout <<t1<<"t1\n"<<t2<<"t2\n"<<t3<<"t3\n"<<t4<<"t4\n"<<fanout<<endl;
758
759        p_short_circuit_discharge_high 	= pow(((vdd-vt)-vt_to_vdd_ratio),1.5)*c_in*vdd*vdd*fo_p/10/pow(2, 3*vt_to_vdd_ratio+2*velocity_index);
760        p_short_circuit_charge_high 	= pow(((vdd-vt)-vt_to_vdd_ratio),1.5)*c_in*vdd*vdd*fo_n/10/pow(2, 3*vt_to_vdd_ratio+2*velocity_index);
761
762//	t1=pow(((vdd-vt)-vt_to_vdd_ratio),1.5);
763//	t2=pow(2, 3*vt_to_vdd_ratio+2*velocity_index);
764//	t3=t1/t2;
765//	cout <<t1<<"t1\n"<<t2<<"t2\n"<<t3<<"t3\n"<<t4<<"t4\n"<<fanout<<endl;
766//	p_short_circuit_discharge = 1.0/(1.0/p_short_circuit_discharge_low + 1.0/p_short_circuit_discharge_high);
767//	p_short_circuit_charge = 1/(1/p_short_circuit_charge_low + 1/p_short_circuit_charge_high); //harmmoic mean cannot be applied simple formulas.
768
769        p_short_circuit_discharge = p_short_circuit_discharge_low;
770        p_short_circuit_charge = p_short_circuit_charge_low;
771        p_short_circuit = (p_short_circuit_discharge + p_short_circuit_charge)/2;
772
773  return (p_short_circuit);
774}
775
776double shortcircuit(
777    double vt,
778    double velocity_index,
779    double c_in,
780    double c_out,
781    double w_nmos,
782    double w_pmos,
783    double i_on_n,
784    double i_on_p,
785    double i_on_n_in,
786    double i_on_p_in,
787    double vdd)
788{
789
790        double p_short_circuit=0, p_short_circuit_discharge;//, p_short_circuit_charge, p_short_circuit_discharge_low, p_short_circuit_discharge_high, p_short_circuit_charge_low, p_short_circuit_charge_high; //this is actually energy
791        double fo_n, fo_p, fanout, beta_ratio, vt_to_vdd_ratio;
792        double f_alpha, k_v, e, g_v_alpha, h_v_alpha;
793
794        fo_n		= i_on_n/i_on_n_in;
795        fo_p		= i_on_p/i_on_p_in;
796        fanout		= 1;
797        beta_ratio 	= i_on_p/i_on_n;
798        vt_to_vdd_ratio = vt/vdd;
799        e 			= 	2.71828;
800        f_alpha		=	1/(velocity_index+2) -velocity_index/(2*(velocity_index+3)) +velocity_index/(velocity_index+4)*(velocity_index/2-1);
801        k_v			=	0.9/0.8+(vdd-vt)/0.8*log(10*(vdd-vt)/e);
802        g_v_alpha	=	(velocity_index + 1)*pow((1-velocity_index),velocity_index)*pow((1-velocity_index),velocity_index/2)/f_alpha/pow((1-velocity_index-velocity_index),(velocity_index/2+velocity_index+2));
803        h_v_alpha	=   pow(2, velocity_index)*(velocity_index+1)*pow((1-velocity_index),velocity_index)/pow((1-velocity_index-velocity_index),(velocity_index+1));
804
805        //p_short_circuit_discharge_low 	= 10/3*(pow(0.5-vt_to_vdd_ratio,3.0)/pow(velocity_index,2.0)/pow(2.0,3*vt_to_vdd_ratio*vt_to_vdd_ratio))*c_in*vdd*vdd*fo_p*fo_p/fanout/beta_ratio;
806//	p_short_circuit_discharge_low 	= 10/3*(pow(((vdd-vt)-vt_to_vdd_ratio),3.0)/pow(velocity_index,2.0)/pow(2.0,3*vt_to_vdd_ratio*vt_to_vdd_ratio))*c_in*vdd*vdd*fo_p*fo_p/fanout/beta_ratio;
807//	p_short_circuit_charge_low 		= 10/3*(pow(((vdd-vt)-vt_to_vdd_ratio),3.0)/pow(velocity_index,2.0)/pow(2.0,3*vt_to_vdd_ratio*vt_to_vdd_ratio))*c_in*vdd*vdd*fo_n*fo_n/fanout*beta_ratio;
808//	double t1, t2, t3, t4, t5;
809//	t1=pow(((vdd-vt)-vt_to_vdd_ratio),3);
810//	t2=pow(velocity_index,2.0);
811//	t3=pow(2.0,3*vt_to_vdd_ratio*vt_to_vdd_ratio);
812//	t4=t1/t2/t3;
813//
814//	cout <<t1<<"t1\n"<<t2<<"t2\n"<<t3<<"t3\n"<<t4<<"t4\n"<<fanout<<endl;
815//
816//
817//	p_short_circuit_discharge_high 	= pow(((vdd-vt)-vt_to_vdd_ratio),1.5)*c_in*vdd*vdd*fo_p/10/pow(2, 3*vt_to_vdd_ratio+2*velocity_index);
818//	p_short_circuit_charge_high 	= pow(((vdd-vt)-vt_to_vdd_ratio),1.5)*c_in*vdd*vdd*fo_n/10/pow(2, 3*vt_to_vdd_ratio+2*velocity_index);
819//
820//	p_short_circuit_discharge = 1.0/(1.0/p_short_circuit_discharge_low + 1.0/p_short_circuit_discharge_high);
821//	p_short_circuit_charge = 1/(1/p_short_circuit_charge_low + 1/p_short_circuit_charge_high);
822//
823//	p_short_circuit = (p_short_circuit_discharge + p_short_circuit_charge)/2;
824//
825//	p_short_circuit = p_short_circuit_discharge;
826
827        p_short_circuit_discharge = k_v*vdd*vdd*c_in*fo_p*fo_p/((vdd-vt)*g_v_alpha*fanout*beta_ratio/2/k_v + h_v_alpha*fo_p);
828  return (p_short_circuit);
829}
830