110152Satgutier@umich.edu/*****************************************************************************
210152Satgutier@umich.edu *                                McPAT/CACTI
310152Satgutier@umich.edu *                      SOFTWARE LICENSE AGREEMENT
410152Satgutier@umich.edu *            Copyright 2012 Hewlett-Packard Development Company, L.P.
510234Syasuko.eckert@amd.com *            Copyright (c) 2010-2013 Advanced Micro Devices, Inc.
610152Satgutier@umich.edu *                          All Rights Reserved
710152Satgutier@umich.edu *
810152Satgutier@umich.edu * Redistribution and use in source and binary forms, with or without
910152Satgutier@umich.edu * modification, are permitted provided that the following conditions are
1010152Satgutier@umich.edu * met: redistributions of source code must retain the above copyright
1110152Satgutier@umich.edu * notice, this list of conditions and the following disclaimer;
1210152Satgutier@umich.edu * redistributions in binary form must reproduce the above copyright
1310152Satgutier@umich.edu * notice, this list of conditions and the following disclaimer in the
1410152Satgutier@umich.edu * documentation and/or other materials provided with the distribution;
1510152Satgutier@umich.edu * neither the name of the copyright holders nor the names of its
1610152Satgutier@umich.edu * contributors may be used to endorse or promote products derived from
1710152Satgutier@umich.edu * this software without specific prior written permission.
1810152Satgutier@umich.edu
1910152Satgutier@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2010152Satgutier@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2110152Satgutier@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2210152Satgutier@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2310152Satgutier@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2410152Satgutier@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2510152Satgutier@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2610152Satgutier@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2710152Satgutier@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2810152Satgutier@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2910234Syasuko.eckert@amd.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3010152Satgutier@umich.edu *
3110152Satgutier@umich.edu ***************************************************************************/
3210152Satgutier@umich.edu
3310152Satgutier@umich.edu
3410152Satgutier@umich.edu
3510152Satgutier@umich.edu
3610152Satgutier@umich.edu#include <cassert>
3710152Satgutier@umich.edu#include <cmath>
3810152Satgutier@umich.edu#include <iostream>
3910152Satgutier@umich.edu
4010152Satgutier@umich.edu#include "basic_circuit.h"
4110152Satgutier@umich.edu#include "parameter.h"
4210152Satgutier@umich.edu
4310234Syasuko.eckert@amd.comuint32_t _log2(uint64_t num) {
4410234Syasuko.eckert@amd.com    uint32_t log2 = 0;
4510152Satgutier@umich.edu
4610234Syasuko.eckert@amd.com    if (num == 0) {
4710234Syasuko.eckert@amd.com        std::cerr << "log0?" << std::endl;
4810234Syasuko.eckert@amd.com        exit(1);
4910234Syasuko.eckert@amd.com    }
5010152Satgutier@umich.edu
5110234Syasuko.eckert@amd.com    while (num > 1) {
5210234Syasuko.eckert@amd.com        num = (num >> 1);
5310234Syasuko.eckert@amd.com        log2++;
5410234Syasuko.eckert@amd.com    }
5510152Satgutier@umich.edu
5610234Syasuko.eckert@amd.com    return log2;
5710152Satgutier@umich.edu}
5810152Satgutier@umich.edu
5910152Satgutier@umich.edu
6010234Syasuko.eckert@amd.combool is_pow2(int64_t val) {
6110234Syasuko.eckert@amd.com    if (val <= 0) {
6210234Syasuko.eckert@amd.com        return false;
6310234Syasuko.eckert@amd.com    } else if (val == 1) {
6410234Syasuko.eckert@amd.com        return true;
6510234Syasuko.eckert@amd.com    } else {
6610234Syasuko.eckert@amd.com        return (_log2(val) != _log2(val - 1));
6710234Syasuko.eckert@amd.com    }
6810152Satgutier@umich.edu}
6910152Satgutier@umich.edu
7010152Satgutier@umich.edu
7110234Syasuko.eckert@amd.comint powers (int base, int n) {
7210234Syasuko.eckert@amd.com    int i, p;
7310152Satgutier@umich.edu
7410234Syasuko.eckert@amd.com    p = 1;
7510234Syasuko.eckert@amd.com    for (i = 1; i <= n; ++i)
7610234Syasuko.eckert@amd.com        p *= base;
7710234Syasuko.eckert@amd.com    return p;
7810152Satgutier@umich.edu}
7910152Satgutier@umich.edu
8010152Satgutier@umich.edu/*----------------------------------------------------------------------*/
8110152Satgutier@umich.edu
8210234Syasuko.eckert@amd.comdouble logtwo (double x) {
8310234Syasuko.eckert@amd.com    assert(x > 0);
8410234Syasuko.eckert@amd.com    return ((double) (log (x) / log (2.0)));
8510152Satgutier@umich.edu}
8610152Satgutier@umich.edu
8710152Satgutier@umich.edu/*----------------------------------------------------------------------*/
8810152Satgutier@umich.edu
8910152Satgutier@umich.edu
9010152Satgutier@umich.edudouble gate_C(
9110152Satgutier@umich.edu    double width,
9210152Satgutier@umich.edu    double wirelength,
9310152Satgutier@umich.edu    bool   _is_dram,
9410152Satgutier@umich.edu    bool   _is_cell,
9510234Syasuko.eckert@amd.com    bool   _is_wl_tr) {
9610234Syasuko.eckert@amd.com    const TechnologyParameter::DeviceType * dt;
9710152Satgutier@umich.edu
9810234Syasuko.eckert@amd.com    if (_is_dram && _is_cell) {
9910234Syasuko.eckert@amd.com        dt = &g_tp.dram_acc;   //DRAM cell access transistor
10010234Syasuko.eckert@amd.com    } else if (_is_dram && _is_wl_tr) {
10110234Syasuko.eckert@amd.com        dt = &g_tp.dram_wl;    //DRAM wordline transistor
10210234Syasuko.eckert@amd.com    } else if (!_is_dram && _is_cell) {
10310234Syasuko.eckert@amd.com        dt = &g_tp.sram_cell;  // SRAM cell access transistor
10410234Syasuko.eckert@amd.com    } else {
10510234Syasuko.eckert@amd.com        dt = &g_tp.peri_global;
10610234Syasuko.eckert@amd.com    }
10710152Satgutier@umich.edu
10810234Syasuko.eckert@amd.com    return (dt->C_g_ideal + dt->C_overlap + 3*dt->C_fringe)*width + dt->l_phy*Cpolywire;
10910152Satgutier@umich.edu}
11010152Satgutier@umich.edu
11110152Satgutier@umich.edu
11210152Satgutier@umich.edu// returns gate capacitance in Farads
11310152Satgutier@umich.edu// actually this function is the same as gate_C() now
11410152Satgutier@umich.edudouble gate_C_pass(
11510152Satgutier@umich.edu    double width,       // gate width in um (length is Lphy_periph_global)
11610152Satgutier@umich.edu    double wirelength,  // poly wire length going to gate in lambda
11710152Satgutier@umich.edu    bool   _is_dram,
11810152Satgutier@umich.edu    bool   _is_cell,
11910234Syasuko.eckert@amd.com    bool   _is_wl_tr) {
12010234Syasuko.eckert@amd.com    // v5.0
12110234Syasuko.eckert@amd.com    const TechnologyParameter::DeviceType * dt;
12210152Satgutier@umich.edu
12310234Syasuko.eckert@amd.com    if ((_is_dram) && (_is_cell)) {
12410234Syasuko.eckert@amd.com        dt = &g_tp.dram_acc;   //DRAM cell access transistor
12510234Syasuko.eckert@amd.com    } else if ((_is_dram) && (_is_wl_tr)) {
12610234Syasuko.eckert@amd.com        dt = &g_tp.dram_wl;    //DRAM wordline transistor
12710234Syasuko.eckert@amd.com    } else if ((!_is_dram) && _is_cell) {
12810234Syasuko.eckert@amd.com        dt = &g_tp.sram_cell;  // SRAM cell access transistor
12910234Syasuko.eckert@amd.com    } else {
13010234Syasuko.eckert@amd.com        dt = &g_tp.peri_global;
13110234Syasuko.eckert@amd.com    }
13210152Satgutier@umich.edu
13310234Syasuko.eckert@amd.com    return (dt->C_g_ideal + dt->C_overlap + 3*dt->C_fringe)*width + dt->l_phy*Cpolywire;
13410152Satgutier@umich.edu}
13510152Satgutier@umich.edu
13610152Satgutier@umich.edu
13710152Satgutier@umich.edu
13810152Satgutier@umich.edudouble drain_C_(
13910152Satgutier@umich.edu    double width,
14010152Satgutier@umich.edu    int nchannel,
14110152Satgutier@umich.edu    int stack,
14210152Satgutier@umich.edu    int next_arg_thresh_folding_width_or_height_cell,
14310152Satgutier@umich.edu    double fold_dimension,
14410152Satgutier@umich.edu    bool _is_dram,
14510152Satgutier@umich.edu    bool _is_cell,
14610234Syasuko.eckert@amd.com    bool _is_wl_tr) {
14710234Syasuko.eckert@amd.com    double w_folded_tr;
14810234Syasuko.eckert@amd.com    const  TechnologyParameter::DeviceType * dt;
14910152Satgutier@umich.edu
15010234Syasuko.eckert@amd.com    if ((_is_dram) && (_is_cell)) {
15110234Syasuko.eckert@amd.com        dt = &g_tp.dram_acc;   // DRAM cell access transistor
15210234Syasuko.eckert@amd.com    } else if ((_is_dram) && (_is_wl_tr)) {
15310234Syasuko.eckert@amd.com        dt = &g_tp.dram_wl;    // DRAM wordline transistor
15410234Syasuko.eckert@amd.com    } else if ((!_is_dram) && _is_cell) {
15510234Syasuko.eckert@amd.com        dt = &g_tp.sram_cell;  // SRAM cell access transistor
15610234Syasuko.eckert@amd.com    } else {
15710234Syasuko.eckert@amd.com        dt = &g_tp.peri_global;
15810234Syasuko.eckert@amd.com    }
15910152Satgutier@umich.edu
16010234Syasuko.eckert@amd.com    double c_junc_area = dt->C_junc;
16110234Syasuko.eckert@amd.com    double c_junc_sidewall = dt->C_junc_sidewall;
16210234Syasuko.eckert@amd.com    double c_fringe    = 2 * dt->C_fringe;
16310234Syasuko.eckert@amd.com    double c_overlap   = 2 * dt->C_overlap;
16410234Syasuko.eckert@amd.com    double drain_C_metal_connecting_folded_tr = 0;
16510152Satgutier@umich.edu
16610234Syasuko.eckert@amd.com    // determine the width of the transistor after folding (if it is getting folded)
16710234Syasuko.eckert@amd.com    if (next_arg_thresh_folding_width_or_height_cell == 0) {
16810234Syasuko.eckert@amd.com        // interpret fold_dimension as the the folding width threshold
16910234Syasuko.eckert@amd.com        // i.e. the value of transistor width above which the transistor gets folded
17010234Syasuko.eckert@amd.com        w_folded_tr = fold_dimension;
17110234Syasuko.eckert@amd.com    } else { // interpret fold_dimension as the height of the cell that this transistor is part of.
17210234Syasuko.eckert@amd.com        double h_tr_region  = fold_dimension - 2 * g_tp.HPOWERRAIL;
17310234Syasuko.eckert@amd.com        // TODO : w_folded_tr must come from Component::compute_gate_area()
17410234Syasuko.eckert@amd.com        double ratio_p_to_n = 2.0 / (2.0 + 1.0);
17510234Syasuko.eckert@amd.com        if (nchannel) {
17610234Syasuko.eckert@amd.com            w_folded_tr = (1 - ratio_p_to_n) * (h_tr_region - g_tp.MIN_GAP_BET_P_AND_N_DIFFS);
17710234Syasuko.eckert@amd.com        } else {
17810234Syasuko.eckert@amd.com            w_folded_tr = ratio_p_to_n * (h_tr_region - g_tp.MIN_GAP_BET_P_AND_N_DIFFS);
17910234Syasuko.eckert@amd.com        }
18010152Satgutier@umich.edu    }
18110234Syasuko.eckert@amd.com    int num_folded_tr = (int) (ceil(width / w_folded_tr));
18210234Syasuko.eckert@amd.com
18310234Syasuko.eckert@amd.com    if (num_folded_tr < 2) {
18410234Syasuko.eckert@amd.com        w_folded_tr = width;
18510152Satgutier@umich.edu    }
18610152Satgutier@umich.edu
18710234Syasuko.eckert@amd.com    double total_drain_w = (g_tp.w_poly_contact + 2 * g_tp.spacing_poly_to_contact) +  // only for drain
18810234Syasuko.eckert@amd.com                           (stack - 1) * g_tp.spacing_poly_to_poly;
18910234Syasuko.eckert@amd.com    double drain_h_for_sidewall = w_folded_tr;
19010234Syasuko.eckert@amd.com    double total_drain_height_for_cap_wrt_gate = w_folded_tr + 2 * w_folded_tr * (stack - 1);
19110234Syasuko.eckert@amd.com    if (num_folded_tr > 1) {
19210234Syasuko.eckert@amd.com        total_drain_w += (num_folded_tr - 2) * (g_tp.w_poly_contact + 2 * g_tp.spacing_poly_to_contact) +
19310234Syasuko.eckert@amd.com                         (num_folded_tr - 1) * ((stack - 1) * g_tp.spacing_poly_to_poly);
19410152Satgutier@umich.edu
19510234Syasuko.eckert@amd.com        if (num_folded_tr % 2 == 0) {
19610234Syasuko.eckert@amd.com            drain_h_for_sidewall = 0;
19710234Syasuko.eckert@amd.com        }
19810234Syasuko.eckert@amd.com        total_drain_height_for_cap_wrt_gate *= num_folded_tr;
19910234Syasuko.eckert@amd.com        drain_C_metal_connecting_folded_tr   = g_tp.wire_local.C_per_um * total_drain_w;
20010234Syasuko.eckert@amd.com    }
20110152Satgutier@umich.edu
20210234Syasuko.eckert@amd.com    double drain_C_area     = c_junc_area * total_drain_w * w_folded_tr;
20310234Syasuko.eckert@amd.com    double drain_C_sidewall = c_junc_sidewall * (drain_h_for_sidewall + 2 * total_drain_w);
20410234Syasuko.eckert@amd.com    double drain_C_wrt_gate = (c_fringe + c_overlap) * total_drain_height_for_cap_wrt_gate;
20510152Satgutier@umich.edu
20610234Syasuko.eckert@amd.com    return (drain_C_area + drain_C_sidewall + drain_C_wrt_gate + drain_C_metal_connecting_folded_tr);
20710152Satgutier@umich.edu}
20810152Satgutier@umich.edu
20910152Satgutier@umich.edu
21010152Satgutier@umich.edudouble tr_R_on(
21110152Satgutier@umich.edu    double width,
21210152Satgutier@umich.edu    int nchannel,
21310152Satgutier@umich.edu    int stack,
21410152Satgutier@umich.edu    bool _is_dram,
21510152Satgutier@umich.edu    bool _is_cell,
21610234Syasuko.eckert@amd.com    bool _is_wl_tr) {
21710234Syasuko.eckert@amd.com    const TechnologyParameter::DeviceType * dt;
21810152Satgutier@umich.edu
21910234Syasuko.eckert@amd.com    if ((_is_dram) && (_is_cell)) {
22010234Syasuko.eckert@amd.com        dt = &g_tp.dram_acc;   //DRAM cell access transistor
22110234Syasuko.eckert@amd.com    } else if ((_is_dram) && (_is_wl_tr)) {
22210234Syasuko.eckert@amd.com        dt = &g_tp.dram_wl;    //DRAM wordline transistor
22310234Syasuko.eckert@amd.com    } else if ((!_is_dram) && _is_cell) {
22410234Syasuko.eckert@amd.com        dt = &g_tp.sram_cell;  // SRAM cell access transistor
22510234Syasuko.eckert@amd.com    } else {
22610234Syasuko.eckert@amd.com        dt = &g_tp.peri_global;
22710234Syasuko.eckert@amd.com    }
22810152Satgutier@umich.edu
22910234Syasuko.eckert@amd.com    double restrans = (nchannel) ? dt->R_nch_on : dt->R_pch_on;
23010234Syasuko.eckert@amd.com    return (stack * restrans / width);
23110152Satgutier@umich.edu}
23210152Satgutier@umich.edu
23310152Satgutier@umich.edu
23410152Satgutier@umich.edu/* This routine operates in reverse: given a resistance, it finds
23510152Satgutier@umich.edu * the transistor width that would have this R.  It is used in the
23610152Satgutier@umich.edu * data wordline to estimate the wordline driver size. */
23710152Satgutier@umich.edu
23810152Satgutier@umich.edu// returns width in um
23910152Satgutier@umich.edudouble R_to_w(
24010152Satgutier@umich.edu    double res,
24110152Satgutier@umich.edu    int   nchannel,
24210152Satgutier@umich.edu    bool _is_dram,
24310152Satgutier@umich.edu    bool _is_cell,
24410234Syasuko.eckert@amd.com    bool _is_wl_tr) {
24510234Syasuko.eckert@amd.com    const TechnologyParameter::DeviceType * dt;
24610152Satgutier@umich.edu
24710234Syasuko.eckert@amd.com    if ((_is_dram) && (_is_cell)) {
24810234Syasuko.eckert@amd.com        dt = &g_tp.dram_acc;   //DRAM cell access transistor
24910234Syasuko.eckert@amd.com    } else if ((_is_dram) && (_is_wl_tr)) {
25010234Syasuko.eckert@amd.com        dt = &g_tp.dram_wl;    //DRAM wordline transistor
25110234Syasuko.eckert@amd.com    } else if ((!_is_dram) && (_is_cell)) {
25210234Syasuko.eckert@amd.com        dt = &g_tp.sram_cell;  // SRAM cell access transistor
25310234Syasuko.eckert@amd.com    } else {
25410234Syasuko.eckert@amd.com        dt = &g_tp.peri_global;
25510234Syasuko.eckert@amd.com    }
25610152Satgutier@umich.edu
25710234Syasuko.eckert@amd.com    double restrans = (nchannel) ? dt->R_nch_on : dt->R_pch_on;
25810234Syasuko.eckert@amd.com    return (restrans / res);
25910152Satgutier@umich.edu}
26010152Satgutier@umich.edu
26110152Satgutier@umich.edu
26210152Satgutier@umich.edudouble pmos_to_nmos_sz_ratio(
26310152Satgutier@umich.edu    bool _is_dram,
26410234Syasuko.eckert@amd.com    bool _is_wl_tr) {
26510234Syasuko.eckert@amd.com    double p_to_n_sizing_ratio;
26610234Syasuko.eckert@amd.com    if ((_is_dram) && (_is_wl_tr)) { //DRAM wordline transistor
26710234Syasuko.eckert@amd.com        p_to_n_sizing_ratio = g_tp.dram_wl.n_to_p_eff_curr_drv_ratio;
26810234Syasuko.eckert@amd.com    } else { //DRAM or SRAM all other transistors
26910234Syasuko.eckert@amd.com        p_to_n_sizing_ratio = g_tp.peri_global.n_to_p_eff_curr_drv_ratio;
27010234Syasuko.eckert@amd.com    }
27110234Syasuko.eckert@amd.com    return p_to_n_sizing_ratio;
27210152Satgutier@umich.edu}
27310152Satgutier@umich.edu
27410152Satgutier@umich.edu
27510152Satgutier@umich.edu// "Timing Models for MOS Circuits" by Mark Horowitz, 1984
27610152Satgutier@umich.edudouble horowitz(
27710152Satgutier@umich.edu    double inputramptime, // input rise time
27810152Satgutier@umich.edu    double tf,            // time constant of gate
27910152Satgutier@umich.edu    double vs1,           // threshold voltage
28010152Satgutier@umich.edu    double vs2,           // threshold voltage
28110234Syasuko.eckert@amd.com    int    rise) {        // whether input rises or fall
28210234Syasuko.eckert@amd.com    if (inputramptime == 0 && vs1 == vs2) {
28310234Syasuko.eckert@amd.com        return tf * (vs1 < 1 ? -log(vs1) : log(vs1));
28410234Syasuko.eckert@amd.com    }
28510234Syasuko.eckert@amd.com    double a, b, td;
28610152Satgutier@umich.edu
28710234Syasuko.eckert@amd.com    a = inputramptime / tf;
28810234Syasuko.eckert@amd.com    if (rise == RISE) {
28910234Syasuko.eckert@amd.com        b = 0.5;
29010234Syasuko.eckert@amd.com        td = tf * sqrt(log(vs1) * log(vs1) + 2 * a * b * (1.0 - vs1)) +
29110234Syasuko.eckert@amd.com            tf * (log(vs1) - log(vs2));
29210234Syasuko.eckert@amd.com    } else {
29310234Syasuko.eckert@amd.com        b = 0.4;
29410234Syasuko.eckert@amd.com        td = tf * sqrt(log(1.0 - vs1) * log(1.0 - vs1) + 2 * a * b * (vs1)) +
29510234Syasuko.eckert@amd.com            tf * (log(1.0 - vs1) - log(1.0 - vs2));
29610234Syasuko.eckert@amd.com    }
29710234Syasuko.eckert@amd.com    return (td);
29810152Satgutier@umich.edu}
29910152Satgutier@umich.edu
30010152Satgutier@umich.edudouble cmos_Ileak(
30110152Satgutier@umich.edu    double nWidth,
30210152Satgutier@umich.edu    double pWidth,
30310152Satgutier@umich.edu    bool _is_dram,
30410152Satgutier@umich.edu    bool _is_cell,
30510234Syasuko.eckert@amd.com    bool _is_wl_tr) {
30610234Syasuko.eckert@amd.com    TechnologyParameter::DeviceType * dt;
30710152Satgutier@umich.edu
30810234Syasuko.eckert@amd.com    if ((!_is_dram) && (_is_cell)) { //SRAM cell access transistor
30910234Syasuko.eckert@amd.com        dt = &(g_tp.sram_cell);
31010234Syasuko.eckert@amd.com    } else if ((_is_dram) && (_is_wl_tr)) { //DRAM wordline transistor
31110234Syasuko.eckert@amd.com        dt = &(g_tp.dram_wl);
31210234Syasuko.eckert@amd.com    } else { //DRAM or SRAM all other transistors
31310234Syasuko.eckert@amd.com        dt = &(g_tp.peri_global);
31410234Syasuko.eckert@amd.com    }
31510234Syasuko.eckert@amd.com    return nWidth*dt->I_off_n + pWidth*dt->I_off_p;
31610152Satgutier@umich.edu}
31710152Satgutier@umich.edu
31810152Satgutier@umich.edu
31910152Satgutier@umich.edudouble simplified_nmos_leakage(
32010152Satgutier@umich.edu    double nwidth,
32110152Satgutier@umich.edu    bool _is_dram,
32210152Satgutier@umich.edu    bool _is_cell,
32310234Syasuko.eckert@amd.com    bool _is_wl_tr) {
32410234Syasuko.eckert@amd.com    TechnologyParameter::DeviceType * dt;
32510152Satgutier@umich.edu
32610234Syasuko.eckert@amd.com    if ((!_is_dram) && (_is_cell)) { //SRAM cell access transistor
32710234Syasuko.eckert@amd.com        dt = &(g_tp.sram_cell);
32810234Syasuko.eckert@amd.com    } else if ((_is_dram) && (_is_wl_tr)) { //DRAM wordline transistor
32910234Syasuko.eckert@amd.com        dt = &(g_tp.dram_wl);
33010234Syasuko.eckert@amd.com    } else { //DRAM or SRAM all other transistors
33110234Syasuko.eckert@amd.com        dt = &(g_tp.peri_global);
33210234Syasuko.eckert@amd.com    }
33310234Syasuko.eckert@amd.com    return nwidth * dt->I_off_n;
33410152Satgutier@umich.edu}
33510152Satgutier@umich.edu
33610234Syasuko.eckert@amd.comint factorial(int n, int m) {
33710234Syasuko.eckert@amd.com    int fa = m, i;
33810234Syasuko.eckert@amd.com    for (i = m + 1; i <= n; i++)
33910234Syasuko.eckert@amd.com        fa *= i;
34010234Syasuko.eckert@amd.com    return fa;
34110152Satgutier@umich.edu}
34210152Satgutier@umich.edu
34310234Syasuko.eckert@amd.comint combination(int n, int m) {
34410234Syasuko.eckert@amd.com    int ret;
34510234Syasuko.eckert@amd.com    ret = factorial(n, m + 1) / factorial(n - m);
34610234Syasuko.eckert@amd.com    return ret;
34710152Satgutier@umich.edu}
34810152Satgutier@umich.edu
34910152Satgutier@umich.edudouble simplified_pmos_leakage(
35010152Satgutier@umich.edu    double pwidth,
35110152Satgutier@umich.edu    bool _is_dram,
35210152Satgutier@umich.edu    bool _is_cell,
35310234Syasuko.eckert@amd.com    bool _is_wl_tr) {
35410234Syasuko.eckert@amd.com    TechnologyParameter::DeviceType * dt;
35510152Satgutier@umich.edu
35610234Syasuko.eckert@amd.com    if ((!_is_dram) && (_is_cell)) { //SRAM cell access transistor
35710234Syasuko.eckert@amd.com        dt = &(g_tp.sram_cell);
35810234Syasuko.eckert@amd.com    } else if ((_is_dram) && (_is_wl_tr)) { //DRAM wordline transistor
35910234Syasuko.eckert@amd.com        dt = &(g_tp.dram_wl);
36010234Syasuko.eckert@amd.com    } else { //DRAM or SRAM all other transistors
36110234Syasuko.eckert@amd.com        dt = &(g_tp.peri_global);
36210234Syasuko.eckert@amd.com    }
36310234Syasuko.eckert@amd.com    return pwidth * dt->I_off_p;
36410152Satgutier@umich.edu}
36510152Satgutier@umich.edu
36610152Satgutier@umich.edudouble cmos_Ig_n(
36710152Satgutier@umich.edu    double nWidth,
36810152Satgutier@umich.edu    bool _is_dram,
36910152Satgutier@umich.edu    bool _is_cell,
37010234Syasuko.eckert@amd.com    bool _is_wl_tr) {
37110234Syasuko.eckert@amd.com    TechnologyParameter::DeviceType * dt;
37210152Satgutier@umich.edu
37310234Syasuko.eckert@amd.com    if ((!_is_dram) && (_is_cell)) { //SRAM cell access transistor
37410234Syasuko.eckert@amd.com        dt = &(g_tp.sram_cell);
37510234Syasuko.eckert@amd.com    } else if ((_is_dram) && (_is_wl_tr)) { //DRAM wordline transistor
37610234Syasuko.eckert@amd.com        dt = &(g_tp.dram_wl);
37710234Syasuko.eckert@amd.com    } else { //DRAM or SRAM all other transistors
37810234Syasuko.eckert@amd.com        dt = &(g_tp.peri_global);
37910234Syasuko.eckert@amd.com    }
38010234Syasuko.eckert@amd.com    return nWidth*dt->I_g_on_n;
38110152Satgutier@umich.edu}
38210152Satgutier@umich.edu
38310152Satgutier@umich.edudouble cmos_Ig_p(
38410152Satgutier@umich.edu    double pWidth,
38510152Satgutier@umich.edu    bool _is_dram,
38610152Satgutier@umich.edu    bool _is_cell,
38710234Syasuko.eckert@amd.com    bool _is_wl_tr) {
38810234Syasuko.eckert@amd.com    TechnologyParameter::DeviceType * dt;
38910152Satgutier@umich.edu
39010234Syasuko.eckert@amd.com    if ((!_is_dram) && (_is_cell)) { //SRAM cell access transistor
39110234Syasuko.eckert@amd.com        dt = &(g_tp.sram_cell);
39210234Syasuko.eckert@amd.com    } else if ((_is_dram) && (_is_wl_tr)) { //DRAM wordline transistor
39310234Syasuko.eckert@amd.com        dt = &(g_tp.dram_wl);
39410234Syasuko.eckert@amd.com    } else { //DRAM or SRAM all other transistors
39510234Syasuko.eckert@amd.com        dt = &(g_tp.peri_global);
39610234Syasuko.eckert@amd.com    }
39710234Syasuko.eckert@amd.com    return pWidth*dt->I_g_on_p;
39810152Satgutier@umich.edu}
39910152Satgutier@umich.edu
40010152Satgutier@umich.edudouble cmos_Isub_leakage(
40110152Satgutier@umich.edu    double nWidth,
40210152Satgutier@umich.edu    double pWidth,
40310152Satgutier@umich.edu    int    fanin,
40410152Satgutier@umich.edu    enum Gate_type g_type,
40510152Satgutier@umich.edu    bool _is_dram,
40610152Satgutier@umich.edu    bool _is_cell,
40710152Satgutier@umich.edu    bool _is_wl_tr,
40810234Syasuko.eckert@amd.com    enum Half_net_topology topo) {
40910234Syasuko.eckert@amd.com    assert (fanin >= 1);
41010234Syasuko.eckert@amd.com    double nmos_leak = simplified_nmos_leakage(nWidth, _is_dram, _is_cell, _is_wl_tr);
41110234Syasuko.eckert@amd.com    double pmos_leak = simplified_pmos_leakage(pWidth, _is_dram, _is_cell, _is_wl_tr);
41210234Syasuko.eckert@amd.com    double Isub = 0;
41310152Satgutier@umich.edu    int    num_states;
41410152Satgutier@umich.edu    int    num_off_tx;
41510152Satgutier@umich.edu
41610152Satgutier@umich.edu    num_states = int(pow(2.0, fanin));
41710152Satgutier@umich.edu
41810234Syasuko.eckert@amd.com    switch (g_type) {
41910152Satgutier@umich.edu    case nmos:
42010234Syasuko.eckert@amd.com        if (fanin == 1) {
42110234Syasuko.eckert@amd.com            Isub = nmos_leak / num_states;
42210234Syasuko.eckert@amd.com        } else {
42310234Syasuko.eckert@amd.com            if (topo == parallel) {
42410234Syasuko.eckert@amd.com                //only when all tx are off, leakage power is non-zero.
42510234Syasuko.eckert@amd.com                //The possibility of this state is 1/num_states
42610234Syasuko.eckert@amd.com                Isub = nmos_leak * fanin / num_states;
42710234Syasuko.eckert@amd.com            } else {
42810234Syasuko.eckert@amd.com                for (num_off_tx = 1; num_off_tx <= fanin; num_off_tx++) {
42910234Syasuko.eckert@amd.com                    //when num_off_tx ==0 there is no leakage power
43010234Syasuko.eckert@amd.com                    Isub += nmos_leak * pow(UNI_LEAK_STACK_FACTOR,
43110234Syasuko.eckert@amd.com                                            (num_off_tx - 1)) *
43210234Syasuko.eckert@amd.com                        combination(fanin, num_off_tx);
43310152Satgutier@umich.edu                }
43410234Syasuko.eckert@amd.com                Isub /= num_states;
43510234Syasuko.eckert@amd.com            }
43610152Satgutier@umich.edu
43710152Satgutier@umich.edu        }
43810152Satgutier@umich.edu        break;
43910152Satgutier@umich.edu    case pmos:
44010234Syasuko.eckert@amd.com        if (fanin == 1) {
44110234Syasuko.eckert@amd.com            Isub = pmos_leak / num_states;
44210234Syasuko.eckert@amd.com        } else {
44310234Syasuko.eckert@amd.com            if (topo == parallel) {
44410234Syasuko.eckert@amd.com                //only when all tx are off, leakage power is non-zero.
44510234Syasuko.eckert@amd.com                //The possibility of this state is 1/num_states
44610234Syasuko.eckert@amd.com                Isub = pmos_leak * fanin / num_states;
44710234Syasuko.eckert@amd.com            } else {
44810234Syasuko.eckert@amd.com                for (num_off_tx = 1; num_off_tx <= fanin; num_off_tx++) {
44910234Syasuko.eckert@amd.com                    //when num_off_tx ==0 there is no leakage power
45010234Syasuko.eckert@amd.com                    Isub += pmos_leak * pow(UNI_LEAK_STACK_FACTOR,
45110234Syasuko.eckert@amd.com                                            (num_off_tx - 1)) *
45210234Syasuko.eckert@amd.com                        combination(fanin, num_off_tx);
45310152Satgutier@umich.edu                }
45410234Syasuko.eckert@amd.com                Isub /= num_states;
45510234Syasuko.eckert@amd.com            }
45610152Satgutier@umich.edu
45710152Satgutier@umich.edu        }
45810152Satgutier@umich.edu        break;
45910152Satgutier@umich.edu    case inv:
46010234Syasuko.eckert@amd.com        Isub = (nmos_leak + pmos_leak) / 2;
46110152Satgutier@umich.edu        break;
46210152Satgutier@umich.edu    case nand:
46310234Syasuko.eckert@amd.com        Isub += fanin * pmos_leak;//the pullup network
46410234Syasuko.eckert@amd.com        for (num_off_tx = 1; num_off_tx <= fanin; num_off_tx++) {
46510234Syasuko.eckert@amd.com            // the pulldown network
46610234Syasuko.eckert@amd.com            Isub += nmos_leak * pow(UNI_LEAK_STACK_FACTOR,
46710234Syasuko.eckert@amd.com                                    (num_off_tx - 1)) *
46810234Syasuko.eckert@amd.com                combination(fanin, num_off_tx);
46910152Satgutier@umich.edu        }
47010234Syasuko.eckert@amd.com        Isub /= num_states;
47110152Satgutier@umich.edu        break;
47210152Satgutier@umich.edu    case nor:
47310234Syasuko.eckert@amd.com        for (num_off_tx = 1; num_off_tx <= fanin; num_off_tx++) {
47410234Syasuko.eckert@amd.com             // the pullup network
47510234Syasuko.eckert@amd.com            Isub += pmos_leak * pow(UNI_LEAK_STACK_FACTOR,
47610234Syasuko.eckert@amd.com                                    (num_off_tx - 1)) *
47710234Syasuko.eckert@amd.com                combination(fanin, num_off_tx);
47810152Satgutier@umich.edu        }
47910234Syasuko.eckert@amd.com        Isub += fanin * nmos_leak;//the pulldown network
48010234Syasuko.eckert@amd.com        Isub /= num_states;
48110152Satgutier@umich.edu        break;
48210152Satgutier@umich.edu    case tri:
48310234Syasuko.eckert@amd.com        Isub += (nmos_leak + pmos_leak) / 2;//enabled
48410234Syasuko.eckert@amd.com        //disabled upper bound of leakage power
48510234Syasuko.eckert@amd.com        Isub += nmos_leak * UNI_LEAK_STACK_FACTOR;
48610234Syasuko.eckert@amd.com        Isub /= 2;
48710152Satgutier@umich.edu        break;
48810152Satgutier@umich.edu    case tg:
48910234Syasuko.eckert@amd.com        Isub = (nmos_leak + pmos_leak) / 2;
49010152Satgutier@umich.edu        break;
49110152Satgutier@umich.edu    default:
49210152Satgutier@umich.edu        assert(0);
49310152Satgutier@umich.edu        break;
49410234Syasuko.eckert@amd.com    }
49510152Satgutier@umich.edu
49610152Satgutier@umich.edu    return Isub;
49710152Satgutier@umich.edu}
49810152Satgutier@umich.edu
49910152Satgutier@umich.edu
50010152Satgutier@umich.edudouble cmos_Ig_leakage(
50110152Satgutier@umich.edu    double nWidth,
50210152Satgutier@umich.edu    double pWidth,
50310152Satgutier@umich.edu    int    fanin,
50410152Satgutier@umich.edu    enum Gate_type g_type,
50510152Satgutier@umich.edu    bool _is_dram,
50610152Satgutier@umich.edu    bool _is_cell,
50710152Satgutier@umich.edu    bool _is_wl_tr,
50810234Syasuko.eckert@amd.com    enum Half_net_topology topo) {
50910234Syasuko.eckert@amd.com    assert (fanin >= 1);
51010234Syasuko.eckert@amd.com    double nmos_leak = cmos_Ig_n(nWidth, _is_dram, _is_cell, _is_wl_tr);
51110234Syasuko.eckert@amd.com    double pmos_leak = cmos_Ig_p(pWidth, _is_dram, _is_cell, _is_wl_tr);
51210234Syasuko.eckert@amd.com    double Ig_on = 0;
51310234Syasuko.eckert@amd.com    int    num_states;
51410234Syasuko.eckert@amd.com    int    num_on_tx;
51510152Satgutier@umich.edu
51610234Syasuko.eckert@amd.com    num_states = int(pow(2.0, fanin));
51710152Satgutier@umich.edu
51810234Syasuko.eckert@amd.com    switch (g_type) {
51910234Syasuko.eckert@amd.com    case nmos:
52010234Syasuko.eckert@amd.com        if (fanin == 1) {
52110234Syasuko.eckert@amd.com            Ig_on = nmos_leak / num_states;
52210234Syasuko.eckert@amd.com        } else {
52310234Syasuko.eckert@amd.com            if (topo == parallel) {
52410234Syasuko.eckert@amd.com                for (num_on_tx = 1; num_on_tx <= fanin; num_on_tx++) {
52510234Syasuko.eckert@amd.com                    Ig_on += nmos_leak * combination(fanin, num_on_tx) *
52610234Syasuko.eckert@amd.com                        num_on_tx;
52710152Satgutier@umich.edu                }
52810234Syasuko.eckert@amd.com            } else {
52910234Syasuko.eckert@amd.com                //pull down network when all TXs are on.
53010234Syasuko.eckert@amd.com                Ig_on += nmos_leak * fanin;
53110234Syasuko.eckert@amd.com                //num_on_tx is the number of on tx
53210234Syasuko.eckert@amd.com                for (num_on_tx = 1; num_on_tx < fanin; num_on_tx++) {
53310234Syasuko.eckert@amd.com                     //when num_on_tx=[1,n-1]
53410234Syasuko.eckert@amd.com                    //TODO: this is a approximation now, a precise computation
53510234Syasuko.eckert@amd.com                    //will be very complicated.
53610234Syasuko.eckert@amd.com                    Ig_on += nmos_leak * combination(fanin, num_on_tx) *
53710234Syasuko.eckert@amd.com                        num_on_tx / 2;
53810152Satgutier@umich.edu                }
53910234Syasuko.eckert@amd.com                Ig_on /= num_states;
54010234Syasuko.eckert@amd.com            }
54110234Syasuko.eckert@amd.com        }
54210234Syasuko.eckert@amd.com        break;
54310234Syasuko.eckert@amd.com    case pmos:
54410234Syasuko.eckert@amd.com        if (fanin == 1) {
54510234Syasuko.eckert@amd.com            Ig_on = pmos_leak / num_states;
54610234Syasuko.eckert@amd.com        } else {
54710234Syasuko.eckert@amd.com            if (topo == parallel) {
54810234Syasuko.eckert@amd.com                for (num_on_tx = 1; num_on_tx <= fanin; num_on_tx++) {
54910234Syasuko.eckert@amd.com                    Ig_on += pmos_leak * combination(fanin, num_on_tx) *
55010234Syasuko.eckert@amd.com                        num_on_tx;
55110152Satgutier@umich.edu                }
55210234Syasuko.eckert@amd.com            } else {
55310234Syasuko.eckert@amd.com                //pull down network when all TXs are on.
55410234Syasuko.eckert@amd.com                Ig_on += pmos_leak * fanin;
55510234Syasuko.eckert@amd.com                //num_on_tx is the number of on tx
55610234Syasuko.eckert@amd.com                for (num_on_tx = 1; num_on_tx < fanin; num_on_tx++) {
55710234Syasuko.eckert@amd.com                    //when num_on_tx=[1,n-1]
55810234Syasuko.eckert@amd.com                    //TODO: this is a approximation now, a precise computation
55910234Syasuko.eckert@amd.com                    //will be very complicated.
56010234Syasuko.eckert@amd.com                    Ig_on += pmos_leak * combination(fanin, num_on_tx) *
56110234Syasuko.eckert@amd.com                        num_on_tx / 2;
56210152Satgutier@umich.edu                }
56310234Syasuko.eckert@amd.com                Ig_on /= num_states;
56410234Syasuko.eckert@amd.com            }
56510234Syasuko.eckert@amd.com        }
56610234Syasuko.eckert@amd.com        break;
56710152Satgutier@umich.edu
56810234Syasuko.eckert@amd.com    case inv:
56910234Syasuko.eckert@amd.com        Ig_on = (nmos_leak + pmos_leak) / 2;
57010234Syasuko.eckert@amd.com        break;
57110234Syasuko.eckert@amd.com    case nand:
57210234Syasuko.eckert@amd.com      //pull up network
57310234Syasuko.eckert@amd.com      //when num_on_tx=[1,n]
57410234Syasuko.eckert@amd.com      for (num_on_tx = 1; num_on_tx <= fanin; num_on_tx++) {
57510234Syasuko.eckert@amd.com          Ig_on += pmos_leak * combination(fanin, num_on_tx) * num_on_tx;
57610234Syasuko.eckert@amd.com      }
57710152Satgutier@umich.edu
57810234Syasuko.eckert@amd.com      //pull down network
57910234Syasuko.eckert@amd.com      Ig_on += nmos_leak * fanin;//pull down network when all TXs are on.
58010234Syasuko.eckert@amd.com      //num_on_tx is the number of on tx
58110234Syasuko.eckert@amd.com      for (num_on_tx = 1; num_on_tx < fanin; num_on_tx++) {
58210234Syasuko.eckert@amd.com          //when num_on_tx=[1,n-1]
58310234Syasuko.eckert@amd.com          //TODO: this is a approximation now, a precise computation will be
58410234Syasuko.eckert@amd.com          //very complicated.
58510234Syasuko.eckert@amd.com          Ig_on += nmos_leak * combination(fanin, num_on_tx) * num_on_tx / 2;
58610234Syasuko.eckert@amd.com        }
58710234Syasuko.eckert@amd.com        Ig_on /= num_states;
58810234Syasuko.eckert@amd.com        break;
58910234Syasuko.eckert@amd.com    case nor:
59010234Syasuko.eckert@amd.com        // num_on_tx is the number of on tx in pull up network
59110234Syasuko.eckert@amd.com        Ig_on += pmos_leak * fanin;//pull up network when all TXs are on.
59210234Syasuko.eckert@amd.com        for (num_on_tx = 1; num_on_tx < fanin; num_on_tx++) {
59310234Syasuko.eckert@amd.com            Ig_on += pmos_leak * combination(fanin, num_on_tx) * num_on_tx / 2;
59410152Satgutier@umich.edu
59510234Syasuko.eckert@amd.com        }
59610234Syasuko.eckert@amd.com        //pull down network
59710234Syasuko.eckert@amd.com        for (num_on_tx = 1; num_on_tx <= fanin; num_on_tx++) {
59810234Syasuko.eckert@amd.com            //when num_on_tx=[1,n]
59910234Syasuko.eckert@amd.com            Ig_on += nmos_leak * combination(fanin, num_on_tx) * num_on_tx;
60010234Syasuko.eckert@amd.com        }
60110234Syasuko.eckert@amd.com        Ig_on /= num_states;
60210234Syasuko.eckert@amd.com        break;
60310234Syasuko.eckert@amd.com    case tri:
60410234Syasuko.eckert@amd.com        Ig_on += (2 * nmos_leak + 2 * pmos_leak) / 2;//enabled
60510234Syasuko.eckert@amd.com        //disabled upper bound of leakage power
60610234Syasuko.eckert@amd.com        Ig_on += (nmos_leak + pmos_leak) / 2;
60710234Syasuko.eckert@amd.com        Ig_on /= 2;
60810234Syasuko.eckert@amd.com        break;
60910234Syasuko.eckert@amd.com    case tg:
61010234Syasuko.eckert@amd.com        Ig_on = (nmos_leak + pmos_leak) / 2;
61110234Syasuko.eckert@amd.com        break;
61210234Syasuko.eckert@amd.com    default:
61310234Syasuko.eckert@amd.com        assert(0);
61410234Syasuko.eckert@amd.com        break;
61510234Syasuko.eckert@amd.com    }
61610152Satgutier@umich.edu
61710234Syasuko.eckert@amd.com    return Ig_on;
61810152Satgutier@umich.edu}
61910152Satgutier@umich.edu
62010152Satgutier@umich.edudouble shortcircuit_simple(
62110152Satgutier@umich.edu    double vt,
62210152Satgutier@umich.edu    double velocity_index,
62310152Satgutier@umich.edu    double c_in,
62410152Satgutier@umich.edu    double c_out,
62510152Satgutier@umich.edu    double w_nmos,
62610152Satgutier@umich.edu    double w_pmos,
62710152Satgutier@umich.edu    double i_on_n,
62810152Satgutier@umich.edu    double i_on_p,
62910152Satgutier@umich.edu    double i_on_n_in,
63010152Satgutier@umich.edu    double i_on_p_in,
63110234Syasuko.eckert@amd.com    double vdd) {
63210152Satgutier@umich.edu
63310234Syasuko.eckert@amd.com    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
63410234Syasuko.eckert@amd.com    double fo_n, fo_p, fanout, beta_ratio, vt_to_vdd_ratio;
63510152Satgutier@umich.edu
63610234Syasuko.eckert@amd.com    fo_n	= i_on_n / i_on_n_in;
63710234Syasuko.eckert@amd.com    fo_p	= i_on_p / i_on_p_in;
63810234Syasuko.eckert@amd.com    fanout	= c_out / c_in;
63910234Syasuko.eckert@amd.com    beta_ratio = i_on_p / i_on_n;
64010234Syasuko.eckert@amd.com    vt_to_vdd_ratio = vt / vdd;
64110152Satgutier@umich.edu
64210234Syasuko.eckert@amd.com    //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;
64310234Syasuko.eckert@amd.com    p_short_circuit_discharge_low =
64410234Syasuko.eckert@amd.com        10 / 3 * (pow(((vdd - vt) - vt_to_vdd_ratio), 3.0) /
64510234Syasuko.eckert@amd.com                  pow(velocity_index, 2.0) / pow(2.0, 3 * vt_to_vdd_ratio *
64610234Syasuko.eckert@amd.com                                                 vt_to_vdd_ratio)) * c_in *
64710234Syasuko.eckert@amd.com        vdd * vdd * fo_p * fo_p / fanout / beta_ratio;
64810234Syasuko.eckert@amd.com    p_short_circuit_charge_low =
64910234Syasuko.eckert@amd.com        10 / 3 * (pow(((vdd - vt) - vt_to_vdd_ratio), 3.0) /
65010234Syasuko.eckert@amd.com                  pow(velocity_index, 2.0) / pow(2.0, 3 * vt_to_vdd_ratio *
65110234Syasuko.eckert@amd.com                                                 vt_to_vdd_ratio)) * c_in *
65210234Syasuko.eckert@amd.com        vdd * vdd * fo_n * fo_n / fanout * beta_ratio;
65310152Satgutier@umich.edu//	double t1, t2, t3, t4, t5;
65410152Satgutier@umich.edu//	t1=pow(((vdd-vt)-vt_to_vdd_ratio),3);
65510152Satgutier@umich.edu//	t2=pow(velocity_index,2.0);
65610152Satgutier@umich.edu//	t3=pow(2.0,3*vt_to_vdd_ratio*vt_to_vdd_ratio);
65710152Satgutier@umich.edu//	t4=t1/t2/t3;
65810152Satgutier@umich.edu//	cout <<t1<<"t1\n"<<t2<<"t2\n"<<t3<<"t3\n"<<t4<<"t4\n"<<fanout<<endl;
65910152Satgutier@umich.edu
66010234Syasuko.eckert@amd.com    p_short_circuit_discharge_high =
66110234Syasuko.eckert@amd.com        pow(((vdd - vt) - vt_to_vdd_ratio), 1.5) * c_in * vdd * vdd *
66210234Syasuko.eckert@amd.com        fo_p / 10 / pow(2, 3 * vt_to_vdd_ratio + 2 * velocity_index);
66310234Syasuko.eckert@amd.com    p_short_circuit_charge_high = pow(((vdd - vt) - vt_to_vdd_ratio), 1.5) *
66410234Syasuko.eckert@amd.com        c_in * vdd * vdd * fo_n / 10 / pow(2, 3 * vt_to_vdd_ratio + 2 *
66510234Syasuko.eckert@amd.com                                           velocity_index);
66610152Satgutier@umich.edu
66710152Satgutier@umich.edu//	t1=pow(((vdd-vt)-vt_to_vdd_ratio),1.5);
66810152Satgutier@umich.edu//	t2=pow(2, 3*vt_to_vdd_ratio+2*velocity_index);
66910152Satgutier@umich.edu//	t3=t1/t2;
67010152Satgutier@umich.edu//	cout <<t1<<"t1\n"<<t2<<"t2\n"<<t3<<"t3\n"<<t4<<"t4\n"<<fanout<<endl;
67110152Satgutier@umich.edu//	p_short_circuit_discharge = 1.0/(1.0/p_short_circuit_discharge_low + 1.0/p_short_circuit_discharge_high);
67210152Satgutier@umich.edu//	p_short_circuit_charge = 1/(1/p_short_circuit_charge_low + 1/p_short_circuit_charge_high); //harmmoic mean cannot be applied simple formulas.
67310152Satgutier@umich.edu
67410234Syasuko.eckert@amd.com    p_short_circuit_discharge = p_short_circuit_discharge_low;
67510234Syasuko.eckert@amd.com    p_short_circuit_charge = p_short_circuit_charge_low;
67610234Syasuko.eckert@amd.com    p_short_circuit = (p_short_circuit_discharge + p_short_circuit_charge) / 2;
67710152Satgutier@umich.edu
67810234Syasuko.eckert@amd.com    return (p_short_circuit);
67910152Satgutier@umich.edu}
68010152Satgutier@umich.edu
68110152Satgutier@umich.edudouble shortcircuit(
68210152Satgutier@umich.edu    double vt,
68310152Satgutier@umich.edu    double velocity_index,
68410152Satgutier@umich.edu    double c_in,
68510152Satgutier@umich.edu    double c_out,
68610152Satgutier@umich.edu    double w_nmos,
68710152Satgutier@umich.edu    double w_pmos,
68810152Satgutier@umich.edu    double i_on_n,
68910152Satgutier@umich.edu    double i_on_p,
69010152Satgutier@umich.edu    double i_on_n_in,
69110152Satgutier@umich.edu    double i_on_p_in,
69210234Syasuko.eckert@amd.com    double vdd) {
69310152Satgutier@umich.edu
69410234Syasuko.eckert@amd.com    //this is actually energy
69510234Syasuko.eckert@amd.com    double p_short_circuit = 0, p_short_circuit_discharge;
69610234Syasuko.eckert@amd.com    double fo_n, fo_p, fanout, beta_ratio, vt_to_vdd_ratio;
69710234Syasuko.eckert@amd.com    double f_alpha, k_v, e, g_v_alpha, h_v_alpha;
69810152Satgutier@umich.edu
69910234Syasuko.eckert@amd.com    fo_n = i_on_n / i_on_n_in;
70010234Syasuko.eckert@amd.com    fo_p = i_on_p / i_on_p_in;
70110234Syasuko.eckert@amd.com    fanout = 1;
70210234Syasuko.eckert@amd.com    beta_ratio = i_on_p / i_on_n;
70310234Syasuko.eckert@amd.com    vt_to_vdd_ratio = vt / vdd;
70410234Syasuko.eckert@amd.com    e =	2.71828;
70510234Syasuko.eckert@amd.com    f_alpha	= 1 / (velocity_index + 2) - velocity_index /
70610234Syasuko.eckert@amd.com        (2 * (velocity_index + 3)) + velocity_index / (velocity_index + 4) *
70710234Syasuko.eckert@amd.com        (velocity_index / 2 - 1);
70810234Syasuko.eckert@amd.com    k_v	= 0.9 / 0.8 + (vdd - vt) / 0.8 * log(10 * (vdd - vt) / e);
70910234Syasuko.eckert@amd.com    g_v_alpha =	(velocity_index + 1) *
71010234Syasuko.eckert@amd.com        pow((1 - velocity_index), velocity_index) *
71110234Syasuko.eckert@amd.com        pow((1 - velocity_index), velocity_index / 2) / f_alpha /
71210234Syasuko.eckert@amd.com        pow((1 - velocity_index - velocity_index),
71310234Syasuko.eckert@amd.com            (velocity_index / 2 + velocity_index + 2));
71410234Syasuko.eckert@amd.com    h_v_alpha	=   pow(2, velocity_index) * (velocity_index + 1) *
71510234Syasuko.eckert@amd.com        pow((1 - velocity_index), velocity_index) /
71610234Syasuko.eckert@amd.com        pow((1 - velocity_index - velocity_index), (velocity_index + 1));
71710152Satgutier@umich.edu
71810234Syasuko.eckert@amd.com    //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;
71910152Satgutier@umich.edu//	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;
72010152Satgutier@umich.edu//	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;
72110152Satgutier@umich.edu//	double t1, t2, t3, t4, t5;
72210152Satgutier@umich.edu//	t1=pow(((vdd-vt)-vt_to_vdd_ratio),3);
72310152Satgutier@umich.edu//	t2=pow(velocity_index,2.0);
72410152Satgutier@umich.edu//	t3=pow(2.0,3*vt_to_vdd_ratio*vt_to_vdd_ratio);
72510152Satgutier@umich.edu//	t4=t1/t2/t3;
72610152Satgutier@umich.edu//
72710152Satgutier@umich.edu//	cout <<t1<<"t1\n"<<t2<<"t2\n"<<t3<<"t3\n"<<t4<<"t4\n"<<fanout<<endl;
72810152Satgutier@umich.edu//
72910152Satgutier@umich.edu//
73010152Satgutier@umich.edu//	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);
73110152Satgutier@umich.edu//	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);
73210152Satgutier@umich.edu//
73310152Satgutier@umich.edu//	p_short_circuit_discharge = 1.0/(1.0/p_short_circuit_discharge_low + 1.0/p_short_circuit_discharge_high);
73410152Satgutier@umich.edu//	p_short_circuit_charge = 1/(1/p_short_circuit_charge_low + 1/p_short_circuit_charge_high);
73510152Satgutier@umich.edu//
73610152Satgutier@umich.edu//	p_short_circuit = (p_short_circuit_discharge + p_short_circuit_charge)/2;
73710152Satgutier@umich.edu//
73810152Satgutier@umich.edu//	p_short_circuit = p_short_circuit_discharge;
73910152Satgutier@umich.edu
74010234Syasuko.eckert@amd.com    p_short_circuit_discharge = k_v * vdd * vdd * c_in * fo_p * fo_p /
74110234Syasuko.eckert@amd.com        ((vdd - vt) * g_v_alpha * fanout * beta_ratio / 2 / k_v + h_v_alpha *
74210234Syasuko.eckert@amd.com         fo_p);
74310234Syasuko.eckert@amd.com    return (p_short_circuit);
74410152Satgutier@umich.edu}
745