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#include <cassert>
3610152Satgutier@umich.edu#include <cmath>
3710152Satgutier@umich.edu#include <iostream>
3810152Satgutier@umich.edu
3910152Satgutier@umich.edu#include "area.h"
4010152Satgutier@umich.edu#include "decoder.h"
4110152Satgutier@umich.edu#include "parameter.h"
4210152Satgutier@umich.edu
4310152Satgutier@umich.eduusing namespace std;
4410152Satgutier@umich.edu
4510152Satgutier@umich.edu
4610152Satgutier@umich.eduDecoder::Decoder(
4710152Satgutier@umich.edu    int    _num_dec_signals,
4810152Satgutier@umich.edu    bool   flag_way_select,
4910152Satgutier@umich.edu    double _C_ld_dec_out,
5010152Satgutier@umich.edu    double _R_wire_dec_out,
5110152Satgutier@umich.edu    bool   fully_assoc_,
5210152Satgutier@umich.edu    bool   is_dram_,
5310152Satgutier@umich.edu    bool   is_wl_tr_,
5410152Satgutier@umich.edu    const  Area & cell_)
5510234Syasuko.eckert@amd.com        : exist(false),
5610234Syasuko.eckert@amd.com        C_ld_dec_out(_C_ld_dec_out),
5710234Syasuko.eckert@amd.com        R_wire_dec_out(_R_wire_dec_out),
5810234Syasuko.eckert@amd.com        num_gates(0), num_gates_min(2),
5910234Syasuko.eckert@amd.com        delay(0),
6010234Syasuko.eckert@amd.com        //power(),
6110234Syasuko.eckert@amd.com        fully_assoc(fully_assoc_), is_dram(is_dram_),
6210234Syasuko.eckert@amd.com        is_wl_tr(is_wl_tr_), cell(cell_) {
6310152Satgutier@umich.edu
6410234Syasuko.eckert@amd.com    for (int i = 0; i < MAX_NUMBER_GATES_STAGE; i++) {
6510234Syasuko.eckert@amd.com        w_dec_n[i] = 0;
6610234Syasuko.eckert@amd.com        w_dec_p[i] = 0;
6710234Syasuko.eckert@amd.com    }
6810152Satgutier@umich.edu
6910234Syasuko.eckert@amd.com    /*
7010234Syasuko.eckert@amd.com     * _num_dec_signals is the number of decoded signal as output
7110234Syasuko.eckert@amd.com     * num_addr_bits_dec is the number of signal to be decoded
7210234Syasuko.eckert@amd.com     * as the decoders input.
7310234Syasuko.eckert@amd.com     */
7410234Syasuko.eckert@amd.com    int num_addr_bits_dec = _log2(_num_dec_signals);
7510152Satgutier@umich.edu
7610234Syasuko.eckert@amd.com    if (num_addr_bits_dec < 4) {
7710234Syasuko.eckert@amd.com        if (flag_way_select) {
7810234Syasuko.eckert@amd.com            exist = true;
7910234Syasuko.eckert@amd.com            num_in_signals = 2;
8010234Syasuko.eckert@amd.com        } else {
8110234Syasuko.eckert@amd.com            num_in_signals = 0;
8210234Syasuko.eckert@amd.com        }
8310234Syasuko.eckert@amd.com    } else {
8410234Syasuko.eckert@amd.com        exist = true;
8510234Syasuko.eckert@amd.com
8610234Syasuko.eckert@amd.com        if (flag_way_select) {
8710234Syasuko.eckert@amd.com            num_in_signals = 3;
8810234Syasuko.eckert@amd.com        } else {
8910234Syasuko.eckert@amd.com            num_in_signals = 2;
9010234Syasuko.eckert@amd.com        }
9110152Satgutier@umich.edu    }
9210152Satgutier@umich.edu
9310234Syasuko.eckert@amd.com    assert(cell.h > 0);
9410234Syasuko.eckert@amd.com    assert(cell.w > 0);
9510234Syasuko.eckert@amd.com    // the height of a row-decoder-driver cell is fixed to be 4 * cell.h;
9610234Syasuko.eckert@amd.com    //area.h = 4 * cell.h;
9710234Syasuko.eckert@amd.com    area.h = g_tp.h_dec * cell.h;
9810152Satgutier@umich.edu
9910234Syasuko.eckert@amd.com    compute_widths();
10010234Syasuko.eckert@amd.com    compute_area();
10110152Satgutier@umich.edu}
10210152Satgutier@umich.edu
10310152Satgutier@umich.edu
10410152Satgutier@umich.edu
10510234Syasuko.eckert@amd.comvoid Decoder::compute_widths() {
10610234Syasuko.eckert@amd.com    double F;
10710234Syasuko.eckert@amd.com    double p_to_n_sz_ratio = pmos_to_nmos_sz_ratio(is_dram, is_wl_tr);
10810234Syasuko.eckert@amd.com    double gnand2     = (2 + p_to_n_sz_ratio) / (1 + p_to_n_sz_ratio);
10910234Syasuko.eckert@amd.com    double gnand3     = (3 + p_to_n_sz_ratio) / (1 + p_to_n_sz_ratio);
11010152Satgutier@umich.edu
11110234Syasuko.eckert@amd.com    if (exist) {
11210234Syasuko.eckert@amd.com        if (num_in_signals == 2 || fully_assoc) {
11310234Syasuko.eckert@amd.com            w_dec_n[0] = 2 * g_tp.min_w_nmos_;
11410234Syasuko.eckert@amd.com            w_dec_p[0] = p_to_n_sz_ratio * g_tp.min_w_nmos_;
11510234Syasuko.eckert@amd.com            F = gnand2;
11610234Syasuko.eckert@amd.com        } else {
11710234Syasuko.eckert@amd.com            w_dec_n[0] = 3 * g_tp.min_w_nmos_;
11810234Syasuko.eckert@amd.com            w_dec_p[0] = p_to_n_sz_ratio * g_tp.min_w_nmos_;
11910234Syasuko.eckert@amd.com            F = gnand3;
12010234Syasuko.eckert@amd.com        }
12110234Syasuko.eckert@amd.com
12210234Syasuko.eckert@amd.com        F *= C_ld_dec_out / (gate_C(w_dec_n[0], 0, is_dram, false, is_wl_tr) +
12310234Syasuko.eckert@amd.com                             gate_C(w_dec_p[0], 0, is_dram, false, is_wl_tr));
12410234Syasuko.eckert@amd.com        num_gates = logical_effort(
12510234Syasuko.eckert@amd.com                        num_gates_min,
12610234Syasuko.eckert@amd.com                        num_in_signals == 2 ? gnand2 : gnand3,
12710234Syasuko.eckert@amd.com                        F,
12810234Syasuko.eckert@amd.com                        w_dec_n,
12910234Syasuko.eckert@amd.com                        w_dec_p,
13010234Syasuko.eckert@amd.com                        C_ld_dec_out,
13110234Syasuko.eckert@amd.com                        p_to_n_sz_ratio,
13210234Syasuko.eckert@amd.com                        is_dram,
13310234Syasuko.eckert@amd.com                        is_wl_tr,
13410234Syasuko.eckert@amd.com                        g_tp.max_w_nmos_dec);
13510152Satgutier@umich.edu    }
13610152Satgutier@umich.edu}
13710152Satgutier@umich.edu
13810152Satgutier@umich.edu
13910152Satgutier@umich.edu
14010234Syasuko.eckert@amd.comvoid Decoder::compute_area() {
14110234Syasuko.eckert@amd.com    double cumulative_area = 0;
14210234Syasuko.eckert@amd.com    double cumulative_curr = 0;  // cumulative leakage current
14310234Syasuko.eckert@amd.com    double cumulative_curr_Ig = 0;  // cumulative leakage current
14410152Satgutier@umich.edu
14510234Syasuko.eckert@amd.com    if (exist) { // First check if this decoder exists
14610234Syasuko.eckert@amd.com        if (num_in_signals == 2) {
14710234Syasuko.eckert@amd.com            cumulative_area =
14810234Syasuko.eckert@amd.com                compute_gate_area(NAND, 2, w_dec_p[0], w_dec_n[0], area.h);
14910234Syasuko.eckert@amd.com            cumulative_curr =
15010234Syasuko.eckert@amd.com                cmos_Isub_leakage(w_dec_n[0], w_dec_p[0], 2, nand, is_dram);
15110234Syasuko.eckert@amd.com            cumulative_curr_Ig =
15210234Syasuko.eckert@amd.com                cmos_Ig_leakage(w_dec_n[0], w_dec_p[0], 2, nand, is_dram);
15310234Syasuko.eckert@amd.com        } else if (num_in_signals == 3) {
15410234Syasuko.eckert@amd.com            cumulative_area =
15510234Syasuko.eckert@amd.com                compute_gate_area(NAND, 3, w_dec_p[0], w_dec_n[0], area.h);
15610234Syasuko.eckert@amd.com            cumulative_curr =
15710234Syasuko.eckert@amd.com                cmos_Isub_leakage(w_dec_n[0], w_dec_p[0], 3, nand, is_dram);;
15810234Syasuko.eckert@amd.com            cumulative_curr_Ig =
15910234Syasuko.eckert@amd.com                cmos_Ig_leakage(w_dec_n[0], w_dec_p[0], 3, nand, is_dram);
16010234Syasuko.eckert@amd.com        }
16110234Syasuko.eckert@amd.com
16210234Syasuko.eckert@amd.com        for (int i = 1; i < num_gates; i++) {
16310234Syasuko.eckert@amd.com            cumulative_area +=
16410234Syasuko.eckert@amd.com                compute_gate_area(INV, 1, w_dec_p[i], w_dec_n[i], area.h);
16510234Syasuko.eckert@amd.com            cumulative_curr +=
16610234Syasuko.eckert@amd.com                cmos_Isub_leakage(w_dec_n[i], w_dec_p[i], 1, inv, is_dram);
16710234Syasuko.eckert@amd.com            cumulative_curr_Ig =
16810234Syasuko.eckert@amd.com                cmos_Ig_leakage(w_dec_n[i], w_dec_p[i], 1, inv, is_dram);
16910234Syasuko.eckert@amd.com        }
17010234Syasuko.eckert@amd.com        power.readOp.leakage = cumulative_curr * g_tp.peri_global.Vdd;
17110234Syasuko.eckert@amd.com        power.readOp.gate_leakage = cumulative_curr_Ig * g_tp.peri_global.Vdd;
17210234Syasuko.eckert@amd.com
17310234Syasuko.eckert@amd.com        area.w = (cumulative_area / area.h);
17410152Satgutier@umich.edu    }
17510152Satgutier@umich.edu}
17610152Satgutier@umich.edu
17710152Satgutier@umich.edu
17810152Satgutier@umich.edu
17910234Syasuko.eckert@amd.comdouble Decoder::compute_delays(double inrisetime) {
18010234Syasuko.eckert@amd.com    if (exist) {
18110234Syasuko.eckert@amd.com        double ret_val = 0;  // outrisetime
18210234Syasuko.eckert@amd.com        int    i;
18310234Syasuko.eckert@amd.com        double rd, tf, this_delay, c_load, c_intrinsic, Vpp;
18410234Syasuko.eckert@amd.com        double Vdd = g_tp.peri_global.Vdd;
18510152Satgutier@umich.edu
18610234Syasuko.eckert@amd.com        if ((is_wl_tr) && (is_dram)) {
18710234Syasuko.eckert@amd.com            Vpp = g_tp.vpp;
18810234Syasuko.eckert@amd.com        } else if (is_wl_tr) {
18910234Syasuko.eckert@amd.com            Vpp = g_tp.sram_cell.Vdd;
19010234Syasuko.eckert@amd.com        } else {
19110234Syasuko.eckert@amd.com            Vpp = g_tp.peri_global.Vdd;
19210234Syasuko.eckert@amd.com        }
19310234Syasuko.eckert@amd.com
19410234Syasuko.eckert@amd.com        // first check whether a decoder is required at all
19510234Syasuko.eckert@amd.com        rd = tr_R_on(w_dec_n[0], NCH, num_in_signals, is_dram, false, is_wl_tr);
19610234Syasuko.eckert@amd.com        c_load = gate_C(w_dec_n[1] + w_dec_p[1], 0.0, is_dram, false, is_wl_tr);
19710234Syasuko.eckert@amd.com        c_intrinsic = drain_C_(w_dec_p[0], PCH, 1, 1, area.h, is_dram, false, is_wl_tr) * num_in_signals +
19810234Syasuko.eckert@amd.com                      drain_C_(w_dec_n[0], NCH, num_in_signals, 1, area.h, is_dram, false, is_wl_tr);
19910234Syasuko.eckert@amd.com        tf = rd * (c_intrinsic + c_load);
20010234Syasuko.eckert@amd.com        this_delay = horowitz(inrisetime, tf, 0.5, 0.5, RISE);
20110234Syasuko.eckert@amd.com        delay += this_delay;
20210234Syasuko.eckert@amd.com        inrisetime = this_delay / (1.0 - 0.5);
20310234Syasuko.eckert@amd.com        power.readOp.dynamic += (c_load + c_intrinsic) * Vdd * Vdd;
20410234Syasuko.eckert@amd.com
20510234Syasuko.eckert@amd.com        for (i = 1; i < num_gates - 1; ++i) {
20610234Syasuko.eckert@amd.com            rd = tr_R_on(w_dec_n[i], NCH, 1, is_dram, false, is_wl_tr);
20710234Syasuko.eckert@amd.com            c_load = gate_C(w_dec_p[i+1] + w_dec_n[i+1], 0.0, is_dram, false, is_wl_tr);
20810234Syasuko.eckert@amd.com            c_intrinsic = drain_C_(w_dec_p[i], PCH, 1, 1, area.h, is_dram, false, is_wl_tr) +
20910234Syasuko.eckert@amd.com                          drain_C_(w_dec_n[i], NCH, 1, 1, area.h, is_dram, false, is_wl_tr);
21010234Syasuko.eckert@amd.com            tf = rd * (c_intrinsic + c_load);
21110234Syasuko.eckert@amd.com            this_delay = horowitz(inrisetime, tf, 0.5, 0.5, RISE);
21210234Syasuko.eckert@amd.com            delay += this_delay;
21310234Syasuko.eckert@amd.com            inrisetime = this_delay / (1.0 - 0.5);
21410234Syasuko.eckert@amd.com            power.readOp.dynamic += (c_load + c_intrinsic) * Vdd * Vdd;
21510234Syasuko.eckert@amd.com        }
21610234Syasuko.eckert@amd.com
21710234Syasuko.eckert@amd.com        // add delay of final inverter that drives the wordline
21810234Syasuko.eckert@amd.com        i = num_gates - 1;
21910234Syasuko.eckert@amd.com        c_load = C_ld_dec_out;
22010234Syasuko.eckert@amd.com        rd = tr_R_on(w_dec_n[i], NCH, 1, is_dram, false, is_wl_tr);
22110234Syasuko.eckert@amd.com        c_intrinsic = drain_C_(w_dec_p[i], PCH, 1, 1, area.h, is_dram, false, is_wl_tr) +
22210234Syasuko.eckert@amd.com                      drain_C_(w_dec_n[i], NCH, 1, 1, area.h, is_dram, false, is_wl_tr);
22310234Syasuko.eckert@amd.com        tf = rd * (c_intrinsic + c_load) + R_wire_dec_out * c_load / 2;
22410234Syasuko.eckert@amd.com        this_delay = horowitz(inrisetime, tf, 0.5, 0.5, RISE);
22510234Syasuko.eckert@amd.com        delay  += this_delay;
22610234Syasuko.eckert@amd.com        ret_val = this_delay / (1.0 - 0.5);
22710234Syasuko.eckert@amd.com        power.readOp.dynamic += c_load * Vpp * Vpp + c_intrinsic * Vdd * Vdd;
22810234Syasuko.eckert@amd.com
22910234Syasuko.eckert@amd.com        return ret_val;
23010234Syasuko.eckert@amd.com    } else {
23110234Syasuko.eckert@amd.com        return 0.0;
23210152Satgutier@umich.edu    }
23310152Satgutier@umich.edu}
23410152Satgutier@umich.edu
23510152Satgutier@umich.eduvoid Decoder::leakage_feedback(double temperature)
23610152Satgutier@umich.edu{
23710152Satgutier@umich.edu  double cumulative_curr = 0;  // cumulative leakage current
23810152Satgutier@umich.edu  double cumulative_curr_Ig = 0;  // cumulative leakage current
23910152Satgutier@umich.edu
24010152Satgutier@umich.edu  if (exist)
24110152Satgutier@umich.edu  { // First check if this decoder exists
24210152Satgutier@umich.edu    if (num_in_signals == 2)
24310152Satgutier@umich.edu    {
24410152Satgutier@umich.edu      cumulative_curr = cmos_Isub_leakage(w_dec_n[0], w_dec_p[0], 2, nand,is_dram);
24510152Satgutier@umich.edu      cumulative_curr_Ig = cmos_Ig_leakage(w_dec_n[0], w_dec_p[0], 2, nand,is_dram);
24610152Satgutier@umich.edu    }
24710152Satgutier@umich.edu    else if (num_in_signals == 3)
24810152Satgutier@umich.edu    {
24910152Satgutier@umich.edu      cumulative_curr = cmos_Isub_leakage(w_dec_n[0], w_dec_p[0], 3, nand, is_dram);;
25010152Satgutier@umich.edu      cumulative_curr_Ig = cmos_Ig_leakage(w_dec_n[0], w_dec_p[0], 3, nand, is_dram);
25110152Satgutier@umich.edu    }
25210152Satgutier@umich.edu
25310152Satgutier@umich.edu    for (int i = 1; i < num_gates; i++)
25410152Satgutier@umich.edu    {
25510152Satgutier@umich.edu      cumulative_curr += cmos_Isub_leakage(w_dec_n[i], w_dec_p[i], 1, inv, is_dram);
25610152Satgutier@umich.edu      cumulative_curr_Ig = cmos_Ig_leakage(w_dec_n[i], w_dec_p[i], 1, inv, is_dram);
25710152Satgutier@umich.edu    }
25810152Satgutier@umich.edu
25910152Satgutier@umich.edu    power.readOp.leakage = cumulative_curr * g_tp.peri_global.Vdd;
26010152Satgutier@umich.edu    power.readOp.gate_leakage = cumulative_curr_Ig * g_tp.peri_global.Vdd;
26110152Satgutier@umich.edu  }
26210152Satgutier@umich.edu}
26310152Satgutier@umich.edu
26410152Satgutier@umich.eduPredecBlk::PredecBlk(
26510152Satgutier@umich.edu    int    num_dec_signals,
26610152Satgutier@umich.edu    Decoder * dec_,
26710152Satgutier@umich.edu    double C_wire_predec_blk_out,
26810152Satgutier@umich.edu    double R_wire_predec_blk_out_,
26910152Satgutier@umich.edu    int    num_dec_per_predec,
27010152Satgutier@umich.edu    bool   is_dram,
27110152Satgutier@umich.edu    bool   is_blk1)
27210234Syasuko.eckert@amd.com    : dec(dec_),
27310234Syasuko.eckert@amd.com        exist(false),
27410234Syasuko.eckert@amd.com        number_input_addr_bits(0),
27510234Syasuko.eckert@amd.com        C_ld_predec_blk_out(0),
27610234Syasuko.eckert@amd.com        R_wire_predec_blk_out(0),
27710234Syasuko.eckert@amd.com        branch_effort_nand2_gate_output(1),
27810234Syasuko.eckert@amd.com        branch_effort_nand3_gate_output(1),
27910234Syasuko.eckert@amd.com        flag_two_unique_paths(false),
28010234Syasuko.eckert@amd.com        flag_L2_gate(0),
28110234Syasuko.eckert@amd.com        number_inputs_L1_gate(0),
28210234Syasuko.eckert@amd.com        number_gates_L1_nand2_path(0),
28310234Syasuko.eckert@amd.com        number_gates_L1_nand3_path(0),
28410234Syasuko.eckert@amd.com        number_gates_L2(0),
28510234Syasuko.eckert@amd.com        min_number_gates_L1(2),
28610234Syasuko.eckert@amd.com        min_number_gates_L2(2),
28710234Syasuko.eckert@amd.com        num_L1_active_nand2_path(0),
28810234Syasuko.eckert@amd.com        num_L1_active_nand3_path(0),
28910234Syasuko.eckert@amd.com        delay_nand2_path(0),
29010234Syasuko.eckert@amd.com        delay_nand3_path(0),
29110234Syasuko.eckert@amd.com        power_nand2_path(),
29210234Syasuko.eckert@amd.com        power_nand3_path(),
29310234Syasuko.eckert@amd.com        power_L2(),
29410234Syasuko.eckert@amd.com        is_dram_(is_dram) {
29510234Syasuko.eckert@amd.com    int    branch_effort_predec_out;
29610234Syasuko.eckert@amd.com    double C_ld_dec_gate;
29710234Syasuko.eckert@amd.com    int    num_addr_bits_dec = _log2(num_dec_signals);
29810234Syasuko.eckert@amd.com    int    blk1_num_input_addr_bits = (num_addr_bits_dec + 1) / 2;
29910234Syasuko.eckert@amd.com    int    blk2_num_input_addr_bits = num_addr_bits_dec - blk1_num_input_addr_bits;
30010152Satgutier@umich.edu
30110234Syasuko.eckert@amd.com    w_L1_nand2_n[0] = 0;
30210234Syasuko.eckert@amd.com    w_L1_nand2_p[0] = 0;
30310234Syasuko.eckert@amd.com    w_L1_nand3_n[0] = 0;
30410234Syasuko.eckert@amd.com    w_L1_nand3_p[0] = 0;
30510152Satgutier@umich.edu
30610234Syasuko.eckert@amd.com    if (is_blk1 == true) {
30710234Syasuko.eckert@amd.com        if (num_addr_bits_dec <= 0) {
30810234Syasuko.eckert@amd.com            return;
30910234Syasuko.eckert@amd.com        } else if (num_addr_bits_dec < 4) {
31010234Syasuko.eckert@amd.com            // Just one predecoder block is required with NAND2 gates. No decoder required.
31110234Syasuko.eckert@amd.com            // The first level of predecoding directly drives the decoder output load
31210234Syasuko.eckert@amd.com            exist = true;
31310234Syasuko.eckert@amd.com            number_input_addr_bits = num_addr_bits_dec;
31410234Syasuko.eckert@amd.com            R_wire_predec_blk_out = dec->R_wire_dec_out;
31510234Syasuko.eckert@amd.com            C_ld_predec_blk_out = dec->C_ld_dec_out;
31610234Syasuko.eckert@amd.com        } else {
31710234Syasuko.eckert@amd.com            exist = true;
31810234Syasuko.eckert@amd.com            number_input_addr_bits   = blk1_num_input_addr_bits;
31910234Syasuko.eckert@amd.com            branch_effort_predec_out = (1 << blk2_num_input_addr_bits);
32010234Syasuko.eckert@amd.com            C_ld_dec_gate = num_dec_per_predec * gate_C(dec->w_dec_n[0] + dec->w_dec_p[0], 0, is_dram_, false, false);
32110234Syasuko.eckert@amd.com            R_wire_predec_blk_out = R_wire_predec_blk_out_;
32210234Syasuko.eckert@amd.com            C_ld_predec_blk_out = branch_effort_predec_out * C_ld_dec_gate + C_wire_predec_blk_out;
32310234Syasuko.eckert@amd.com        }
32410234Syasuko.eckert@amd.com    } else {
32510234Syasuko.eckert@amd.com        if (num_addr_bits_dec >= 4) {
32610234Syasuko.eckert@amd.com            exist = true;
32710234Syasuko.eckert@amd.com            number_input_addr_bits   = blk2_num_input_addr_bits;
32810234Syasuko.eckert@amd.com            branch_effort_predec_out = (1 << blk1_num_input_addr_bits);
32910234Syasuko.eckert@amd.com            C_ld_dec_gate = num_dec_per_predec * gate_C(dec->w_dec_n[0] + dec->w_dec_p[0], 0, is_dram_, false, false);
33010234Syasuko.eckert@amd.com            R_wire_predec_blk_out = R_wire_predec_blk_out_;
33110234Syasuko.eckert@amd.com            C_ld_predec_blk_out = branch_effort_predec_out * C_ld_dec_gate + C_wire_predec_blk_out;
33210234Syasuko.eckert@amd.com        }
33310152Satgutier@umich.edu    }
33410152Satgutier@umich.edu
33510234Syasuko.eckert@amd.com    compute_widths();
33610234Syasuko.eckert@amd.com    compute_area();
33710152Satgutier@umich.edu}
33810152Satgutier@umich.edu
33910152Satgutier@umich.edu
34010152Satgutier@umich.edu
34110234Syasuko.eckert@amd.comvoid PredecBlk::compute_widths() {
34210234Syasuko.eckert@amd.com    double F, c_load_nand3_path, c_load_nand2_path;
34310234Syasuko.eckert@amd.com    double p_to_n_sz_ratio = pmos_to_nmos_sz_ratio(is_dram_);
34410234Syasuko.eckert@amd.com    double gnand2 = (2 + p_to_n_sz_ratio) / (1 + p_to_n_sz_ratio);
34510234Syasuko.eckert@amd.com    double gnand3 = (3 + p_to_n_sz_ratio) / (1 + p_to_n_sz_ratio);
34610152Satgutier@umich.edu
34710234Syasuko.eckert@amd.com    if (exist == false) return;
34810152Satgutier@umich.edu
34910152Satgutier@umich.edu
35010234Syasuko.eckert@amd.com    switch (number_input_addr_bits) {
35110152Satgutier@umich.edu    case 1:
35210234Syasuko.eckert@amd.com        flag_two_unique_paths           = false;
35310234Syasuko.eckert@amd.com        number_inputs_L1_gate           = 2;
35410234Syasuko.eckert@amd.com        flag_L2_gate                    = 0;
35510234Syasuko.eckert@amd.com        break;
35610152Satgutier@umich.edu    case 2:
35710234Syasuko.eckert@amd.com        flag_two_unique_paths           = false;
35810234Syasuko.eckert@amd.com        number_inputs_L1_gate           = 2;
35910234Syasuko.eckert@amd.com        flag_L2_gate                    = 0;
36010234Syasuko.eckert@amd.com        break;
36110152Satgutier@umich.edu    case 3:
36210234Syasuko.eckert@amd.com        flag_two_unique_paths           = false;
36310234Syasuko.eckert@amd.com        number_inputs_L1_gate           = 3;
36410234Syasuko.eckert@amd.com        flag_L2_gate                    = 0;
36510234Syasuko.eckert@amd.com        break;
36610152Satgutier@umich.edu    case 4:
36710234Syasuko.eckert@amd.com        flag_two_unique_paths           = false;
36810234Syasuko.eckert@amd.com        number_inputs_L1_gate           = 2;
36910234Syasuko.eckert@amd.com        flag_L2_gate                    = 2;
37010234Syasuko.eckert@amd.com        branch_effort_nand2_gate_output = 4;
37110234Syasuko.eckert@amd.com        break;
37210152Satgutier@umich.edu    case 5:
37310234Syasuko.eckert@amd.com        flag_two_unique_paths           = true;
37410234Syasuko.eckert@amd.com        flag_L2_gate                    = 2;
37510234Syasuko.eckert@amd.com        branch_effort_nand2_gate_output = 8;
37610234Syasuko.eckert@amd.com        branch_effort_nand3_gate_output = 4;
37710234Syasuko.eckert@amd.com        break;
37810152Satgutier@umich.edu    case 6:
37910234Syasuko.eckert@amd.com        flag_two_unique_paths           = false;
38010234Syasuko.eckert@amd.com        number_inputs_L1_gate           = 3;
38110234Syasuko.eckert@amd.com        flag_L2_gate                    = 2;
38210234Syasuko.eckert@amd.com        branch_effort_nand3_gate_output = 8;
38310234Syasuko.eckert@amd.com        break;
38410152Satgutier@umich.edu    case 7:
38510234Syasuko.eckert@amd.com        flag_two_unique_paths           = true;
38610234Syasuko.eckert@amd.com        flag_L2_gate                    = 3;
38710234Syasuko.eckert@amd.com        branch_effort_nand2_gate_output = 32;
38810234Syasuko.eckert@amd.com        branch_effort_nand3_gate_output = 16;
38910234Syasuko.eckert@amd.com        break;
39010152Satgutier@umich.edu    case 8:
39110234Syasuko.eckert@amd.com        flag_two_unique_paths           = true;
39210234Syasuko.eckert@amd.com        flag_L2_gate                    = 3;
39310234Syasuko.eckert@amd.com        branch_effort_nand2_gate_output = 64;
39410234Syasuko.eckert@amd.com        branch_effort_nand3_gate_output = 32;
39510234Syasuko.eckert@amd.com        break;
39610152Satgutier@umich.edu    case 9:
39710234Syasuko.eckert@amd.com        flag_two_unique_paths           = false;
39810234Syasuko.eckert@amd.com        number_inputs_L1_gate           = 3;
39910234Syasuko.eckert@amd.com        flag_L2_gate                    = 3;
40010234Syasuko.eckert@amd.com        branch_effort_nand3_gate_output = 64;
40110234Syasuko.eckert@amd.com        break;
40210152Satgutier@umich.edu    default:
40310234Syasuko.eckert@amd.com        assert(0);
40410152Satgutier@umich.edu        break;
40510152Satgutier@umich.edu    }
40610152Satgutier@umich.edu
40710234Syasuko.eckert@amd.com    // find the number of gates and sizing in second level of predecoder (if there is a second level)
40810234Syasuko.eckert@amd.com    if (flag_L2_gate) {
40910234Syasuko.eckert@amd.com        if (flag_L2_gate == 2) { // 2nd level is a NAND2 gate
41010234Syasuko.eckert@amd.com            w_L2_n[0] = 2 * g_tp.min_w_nmos_;
41110234Syasuko.eckert@amd.com            F = gnand2;
41210234Syasuko.eckert@amd.com        } else { // 2nd level is a NAND3 gate
41310234Syasuko.eckert@amd.com            w_L2_n[0] = 3 * g_tp.min_w_nmos_;
41410234Syasuko.eckert@amd.com            F = gnand3;
41510234Syasuko.eckert@amd.com        }
41610234Syasuko.eckert@amd.com        w_L2_p[0] = p_to_n_sz_ratio * g_tp.min_w_nmos_;
41710234Syasuko.eckert@amd.com        F *= C_ld_predec_blk_out / (gate_C(w_L2_n[0], 0, is_dram_) + gate_C(w_L2_p[0], 0, is_dram_));
41810234Syasuko.eckert@amd.com        number_gates_L2 = logical_effort(
41910234Syasuko.eckert@amd.com                              min_number_gates_L2,
42010234Syasuko.eckert@amd.com                              flag_L2_gate == 2 ? gnand2 : gnand3,
42110234Syasuko.eckert@amd.com                              F,
42210234Syasuko.eckert@amd.com                              w_L2_n,
42310234Syasuko.eckert@amd.com                              w_L2_p,
42410234Syasuko.eckert@amd.com                              C_ld_predec_blk_out,
42510234Syasuko.eckert@amd.com                              p_to_n_sz_ratio,
42610234Syasuko.eckert@amd.com                              is_dram_, false,
42710234Syasuko.eckert@amd.com                              g_tp.max_w_nmos_);
42810234Syasuko.eckert@amd.com
42910234Syasuko.eckert@amd.com        // Now find the number of gates and widths in first level of predecoder
43010234Syasuko.eckert@amd.com        if ((flag_two_unique_paths) || (number_inputs_L1_gate == 2)) {
43110234Syasuko.eckert@amd.com            // Whenever flag_two_unique_paths is true, it means first level of
43210234Syasuko.eckert@amd.com            // decoder employs
43310234Syasuko.eckert@amd.com            // both NAND2 and NAND3 gates. Or when number_inputs_L1_gate is 2,
43410234Syasuko.eckert@amd.com            // it means
43510234Syasuko.eckert@amd.com            // a NAND2 gate is used in the first level of the predecoder
43610234Syasuko.eckert@amd.com            c_load_nand2_path = branch_effort_nand2_gate_output *
43710234Syasuko.eckert@amd.com                                (gate_C(w_L2_n[0], 0, is_dram_) +
43810234Syasuko.eckert@amd.com                                 gate_C(w_L2_p[0], 0, is_dram_));
43910234Syasuko.eckert@amd.com            w_L1_nand2_n[0] = 2 * g_tp.min_w_nmos_;
44010234Syasuko.eckert@amd.com            w_L1_nand2_p[0] = p_to_n_sz_ratio * g_tp.min_w_nmos_;
44110234Syasuko.eckert@amd.com            F = gnand2 * c_load_nand2_path /
44210234Syasuko.eckert@amd.com                (gate_C(w_L1_nand2_n[0], 0, is_dram_) +
44310234Syasuko.eckert@amd.com                 gate_C(w_L1_nand2_p[0], 0, is_dram_));
44410234Syasuko.eckert@amd.com            number_gates_L1_nand2_path = logical_effort(
44510234Syasuko.eckert@amd.com                                             min_number_gates_L1,
44610234Syasuko.eckert@amd.com                                             gnand2,
44710234Syasuko.eckert@amd.com                                             F,
44810234Syasuko.eckert@amd.com                                             w_L1_nand2_n,
44910234Syasuko.eckert@amd.com                                             w_L1_nand2_p,
45010234Syasuko.eckert@amd.com                                             c_load_nand2_path,
45110234Syasuko.eckert@amd.com                                             p_to_n_sz_ratio,
45210234Syasuko.eckert@amd.com                                             is_dram_, false,
45310234Syasuko.eckert@amd.com                                             g_tp.max_w_nmos_);
45410234Syasuko.eckert@amd.com        }
45510234Syasuko.eckert@amd.com
45610234Syasuko.eckert@amd.com        //Now find widths of gates along path in which first gate is a NAND3
45710234Syasuko.eckert@amd.com        if ((flag_two_unique_paths) || (number_inputs_L1_gate == 3)) { // Whenever flag_two_unique_paths is TRUE, it means first level of decoder employs
45810234Syasuko.eckert@amd.com            // both NAND2 and NAND3 gates. Or when number_inputs_L1_gate is 3, it means
45910234Syasuko.eckert@amd.com            // a NAND3 gate is used in the first level of the predecoder
46010234Syasuko.eckert@amd.com            c_load_nand3_path = branch_effort_nand3_gate_output *
46110234Syasuko.eckert@amd.com                                (gate_C(w_L2_n[0], 0, is_dram_) +
46210234Syasuko.eckert@amd.com                                 gate_C(w_L2_p[0], 0, is_dram_));
46310234Syasuko.eckert@amd.com            w_L1_nand3_n[0] = 3 * g_tp.min_w_nmos_;
46410234Syasuko.eckert@amd.com            w_L1_nand3_p[0] = p_to_n_sz_ratio * g_tp.min_w_nmos_;
46510234Syasuko.eckert@amd.com            F = gnand3 * c_load_nand3_path /
46610234Syasuko.eckert@amd.com                (gate_C(w_L1_nand3_n[0], 0, is_dram_) +
46710234Syasuko.eckert@amd.com                 gate_C(w_L1_nand3_p[0], 0, is_dram_));
46810234Syasuko.eckert@amd.com            number_gates_L1_nand3_path = logical_effort(
46910234Syasuko.eckert@amd.com                                             min_number_gates_L1,
47010234Syasuko.eckert@amd.com                                             gnand3,
47110234Syasuko.eckert@amd.com                                             F,
47210234Syasuko.eckert@amd.com                                             w_L1_nand3_n,
47310234Syasuko.eckert@amd.com                                             w_L1_nand3_p,
47410234Syasuko.eckert@amd.com                                             c_load_nand3_path,
47510234Syasuko.eckert@amd.com                                             p_to_n_sz_ratio,
47610234Syasuko.eckert@amd.com                                             is_dram_, false,
47710234Syasuko.eckert@amd.com                                             g_tp.max_w_nmos_);
47810234Syasuko.eckert@amd.com        }
47910234Syasuko.eckert@amd.com    } else { // find number of gates and widths in first level of predecoder block when there is no second level
48010234Syasuko.eckert@amd.com        if (number_inputs_L1_gate == 2) {
48110234Syasuko.eckert@amd.com            w_L1_nand2_n[0] = 2 * g_tp.min_w_nmos_;
48210234Syasuko.eckert@amd.com            w_L1_nand2_p[0] = p_to_n_sz_ratio * g_tp.min_w_nmos_;
48310234Syasuko.eckert@amd.com            F = gnand2 * C_ld_predec_blk_out /
48410234Syasuko.eckert@amd.com                (gate_C(w_L1_nand2_n[0], 0, is_dram_) +
48510234Syasuko.eckert@amd.com                 gate_C(w_L1_nand2_p[0], 0, is_dram_));
48610234Syasuko.eckert@amd.com            number_gates_L1_nand2_path = logical_effort(
48710234Syasuko.eckert@amd.com                                             min_number_gates_L1,
48810234Syasuko.eckert@amd.com                                             gnand2,
48910234Syasuko.eckert@amd.com                                             F,
49010234Syasuko.eckert@amd.com                                             w_L1_nand2_n,
49110234Syasuko.eckert@amd.com                                             w_L1_nand2_p,
49210234Syasuko.eckert@amd.com                                             C_ld_predec_blk_out,
49310234Syasuko.eckert@amd.com                                             p_to_n_sz_ratio,
49410234Syasuko.eckert@amd.com                                             is_dram_, false,
49510234Syasuko.eckert@amd.com                                             g_tp.max_w_nmos_);
49610234Syasuko.eckert@amd.com        } else if (number_inputs_L1_gate == 3) {
49710234Syasuko.eckert@amd.com            w_L1_nand3_n[0] = 3 * g_tp.min_w_nmos_;
49810234Syasuko.eckert@amd.com            w_L1_nand3_p[0] = p_to_n_sz_ratio * g_tp.min_w_nmos_;
49910234Syasuko.eckert@amd.com            F = gnand3 * C_ld_predec_blk_out /
50010234Syasuko.eckert@amd.com                (gate_C(w_L1_nand3_n[0], 0, is_dram_) +
50110234Syasuko.eckert@amd.com                 gate_C(w_L1_nand3_p[0], 0, is_dram_));
50210234Syasuko.eckert@amd.com            number_gates_L1_nand3_path = logical_effort(
50310234Syasuko.eckert@amd.com                                             min_number_gates_L1,
50410234Syasuko.eckert@amd.com                                             gnand3,
50510234Syasuko.eckert@amd.com                                             F,
50610234Syasuko.eckert@amd.com                                             w_L1_nand3_n,
50710234Syasuko.eckert@amd.com                                             w_L1_nand3_p,
50810234Syasuko.eckert@amd.com                                             C_ld_predec_blk_out,
50910234Syasuko.eckert@amd.com                                             p_to_n_sz_ratio,
51010234Syasuko.eckert@amd.com                                             is_dram_, false,
51110234Syasuko.eckert@amd.com                                             g_tp.max_w_nmos_);
51210234Syasuko.eckert@amd.com        }
51310152Satgutier@umich.edu    }
51410234Syasuko.eckert@amd.com}
51510152Satgutier@umich.edu
51610234Syasuko.eckert@amd.com
51710234Syasuko.eckert@amd.com
51810234Syasuko.eckert@amd.comvoid PredecBlk::compute_area() {
51910234Syasuko.eckert@amd.com    if (exist) { // First check whether a predecoder block is needed
52010234Syasuko.eckert@amd.com        int num_L1_nand2 = 0;
52110234Syasuko.eckert@amd.com        int num_L1_nand3 = 0;
52210234Syasuko.eckert@amd.com        int num_L2 = 0;
52310234Syasuko.eckert@amd.com        double tot_area_L1_nand3  = 0;
52410234Syasuko.eckert@amd.com        double leak_L1_nand3      = 0;
52510234Syasuko.eckert@amd.com        double gate_leak_L1_nand3 = 0;
52610234Syasuko.eckert@amd.com
52710234Syasuko.eckert@amd.com        double tot_area_L1_nand2  = compute_gate_area(NAND, 2, w_L1_nand2_p[0], w_L1_nand2_n[0], g_tp.cell_h_def);
52810234Syasuko.eckert@amd.com        double leak_L1_nand2      = cmos_Isub_leakage(w_L1_nand2_n[0], w_L1_nand2_p[0], 2, nand, is_dram_);
52910234Syasuko.eckert@amd.com        double gate_leak_L1_nand2 = cmos_Ig_leakage(w_L1_nand2_n[0], w_L1_nand2_p[0], 2, nand, is_dram_);
53010234Syasuko.eckert@amd.com        if (number_inputs_L1_gate != 3) {
53110234Syasuko.eckert@amd.com            tot_area_L1_nand3 = 0;
53210234Syasuko.eckert@amd.com            leak_L1_nand3 = 0;
53310234Syasuko.eckert@amd.com            gate_leak_L1_nand3 = 0;
53410234Syasuko.eckert@amd.com        } else {
53510234Syasuko.eckert@amd.com            tot_area_L1_nand3  = compute_gate_area(NAND, 3, w_L1_nand3_p[0], w_L1_nand3_n[0], g_tp.cell_h_def);
53610234Syasuko.eckert@amd.com            leak_L1_nand3      = cmos_Isub_leakage(w_L1_nand3_n[0], w_L1_nand3_p[0], 3, nand);
53710234Syasuko.eckert@amd.com            gate_leak_L1_nand3 = cmos_Ig_leakage(w_L1_nand3_n[0], w_L1_nand3_p[0], 3, nand);
53810234Syasuko.eckert@amd.com        }
53910234Syasuko.eckert@amd.com
54010234Syasuko.eckert@amd.com        switch (number_input_addr_bits) {
54110234Syasuko.eckert@amd.com        case 1: //2 NAND2 gates
54210234Syasuko.eckert@amd.com            num_L1_nand2 = 2;
54310234Syasuko.eckert@amd.com            num_L2       = 0;
54410234Syasuko.eckert@amd.com            num_L1_active_nand2_path = 1;
54510234Syasuko.eckert@amd.com            num_L1_active_nand3_path = 0;
54610234Syasuko.eckert@amd.com            break;
54710234Syasuko.eckert@amd.com        case 2: //4 NAND2 gates
54810234Syasuko.eckert@amd.com            num_L1_nand2 = 4;
54910234Syasuko.eckert@amd.com            num_L2       = 0;
55010234Syasuko.eckert@amd.com            num_L1_active_nand2_path = 1;
55110234Syasuko.eckert@amd.com            num_L1_active_nand3_path = 0;
55210234Syasuko.eckert@amd.com            break;
55310234Syasuko.eckert@amd.com        case 3: //8 NAND3 gates
55410234Syasuko.eckert@amd.com            num_L1_nand3 = 8;
55510234Syasuko.eckert@amd.com            num_L2       = 0;
55610234Syasuko.eckert@amd.com            num_L1_active_nand2_path = 0;
55710234Syasuko.eckert@amd.com            num_L1_active_nand3_path = 1;
55810234Syasuko.eckert@amd.com            break;
55910234Syasuko.eckert@amd.com        case 4: //4 + 4 NAND2 gates
56010234Syasuko.eckert@amd.com            num_L1_nand2 = 8;
56110234Syasuko.eckert@amd.com            num_L2       = 16;
56210234Syasuko.eckert@amd.com            num_L1_active_nand2_path = 2;
56310234Syasuko.eckert@amd.com            num_L1_active_nand3_path = 0;
56410234Syasuko.eckert@amd.com            break;
56510234Syasuko.eckert@amd.com        case 5: //4 NAND2 gates, 8 NAND3 gates
56610234Syasuko.eckert@amd.com            num_L1_nand2 = 4;
56710234Syasuko.eckert@amd.com            num_L1_nand3 = 8;
56810234Syasuko.eckert@amd.com            num_L2       = 32;
56910234Syasuko.eckert@amd.com            num_L1_active_nand2_path = 1;
57010234Syasuko.eckert@amd.com            num_L1_active_nand3_path = 1;
57110234Syasuko.eckert@amd.com            break;
57210234Syasuko.eckert@amd.com        case 6: //8 + 8 NAND3 gates
57310234Syasuko.eckert@amd.com            num_L1_nand3 = 16;
57410234Syasuko.eckert@amd.com            num_L2       = 64;
57510234Syasuko.eckert@amd.com            num_L1_active_nand2_path = 0;
57610234Syasuko.eckert@amd.com            num_L1_active_nand3_path = 2;
57710234Syasuko.eckert@amd.com            break;
57810234Syasuko.eckert@amd.com        case 7: //4 + 4 NAND2 gates, 8 NAND3 gates
57910234Syasuko.eckert@amd.com            num_L1_nand2 = 8;
58010234Syasuko.eckert@amd.com            num_L1_nand3 = 8;
58110234Syasuko.eckert@amd.com            num_L2       = 128;
58210234Syasuko.eckert@amd.com            num_L1_active_nand2_path = 2;
58310234Syasuko.eckert@amd.com            num_L1_active_nand3_path = 1;
58410234Syasuko.eckert@amd.com            break;
58510234Syasuko.eckert@amd.com        case 8: //4 NAND2 gates, 8 + 8 NAND3 gates
58610234Syasuko.eckert@amd.com            num_L1_nand2 = 4;
58710234Syasuko.eckert@amd.com            num_L1_nand3 = 16;
58810234Syasuko.eckert@amd.com            num_L2       = 256;
58910234Syasuko.eckert@amd.com            num_L1_active_nand2_path = 2;
59010234Syasuko.eckert@amd.com            num_L1_active_nand3_path = 2;
59110234Syasuko.eckert@amd.com            break;
59210234Syasuko.eckert@amd.com        case 9: //8 + 8 + 8 NAND3 gates
59310234Syasuko.eckert@amd.com            num_L1_nand3 = 24;
59410234Syasuko.eckert@amd.com            num_L2       = 512;
59510234Syasuko.eckert@amd.com            num_L1_active_nand2_path = 0;
59610234Syasuko.eckert@amd.com            num_L1_active_nand3_path = 3;
59710234Syasuko.eckert@amd.com            break;
59810234Syasuko.eckert@amd.com        default:
59910234Syasuko.eckert@amd.com            break;
60010234Syasuko.eckert@amd.com        }
60110234Syasuko.eckert@amd.com
60210234Syasuko.eckert@amd.com        for (int i = 1; i < number_gates_L1_nand2_path; ++i) {
60310234Syasuko.eckert@amd.com            tot_area_L1_nand2  += compute_gate_area(INV, 1, w_L1_nand2_p[i], w_L1_nand2_n[i], g_tp.cell_h_def);
60410234Syasuko.eckert@amd.com            leak_L1_nand2      += cmos_Isub_leakage(w_L1_nand2_n[i], w_L1_nand2_p[i], 2, nand, is_dram_);
60510234Syasuko.eckert@amd.com            gate_leak_L1_nand2 += cmos_Ig_leakage(w_L1_nand2_n[i], w_L1_nand2_p[i], 2, nand, is_dram_);
60610234Syasuko.eckert@amd.com        }
60710234Syasuko.eckert@amd.com        tot_area_L1_nand2  *= num_L1_nand2;
60810234Syasuko.eckert@amd.com        leak_L1_nand2      *= num_L1_nand2;
60910234Syasuko.eckert@amd.com        gate_leak_L1_nand2 *= num_L1_nand2;
61010234Syasuko.eckert@amd.com
61110234Syasuko.eckert@amd.com        for (int i = 1; i < number_gates_L1_nand3_path; ++i) {
61210234Syasuko.eckert@amd.com            tot_area_L1_nand3  += compute_gate_area(INV, 1, w_L1_nand3_p[i], w_L1_nand3_n[i], g_tp.cell_h_def);
61310234Syasuko.eckert@amd.com            leak_L1_nand3      += cmos_Isub_leakage(w_L1_nand3_n[i], w_L1_nand3_p[i], 3, nand, is_dram_);
61410234Syasuko.eckert@amd.com            gate_leak_L1_nand3 += cmos_Ig_leakage(w_L1_nand3_n[i], w_L1_nand3_p[i], 3, nand, is_dram_);
61510234Syasuko.eckert@amd.com        }
61610234Syasuko.eckert@amd.com        tot_area_L1_nand3  *= num_L1_nand3;
61710234Syasuko.eckert@amd.com        leak_L1_nand3      *= num_L1_nand3;
61810234Syasuko.eckert@amd.com        gate_leak_L1_nand3 *= num_L1_nand3;
61910234Syasuko.eckert@amd.com
62010234Syasuko.eckert@amd.com        double cumulative_area_L1 = tot_area_L1_nand2 + tot_area_L1_nand3;
62110234Syasuko.eckert@amd.com        double cumulative_area_L2 = 0.0;
62210234Syasuko.eckert@amd.com        double leakage_L2         = 0.0;
62310234Syasuko.eckert@amd.com        double gate_leakage_L2    = 0.0;
62410234Syasuko.eckert@amd.com
62510234Syasuko.eckert@amd.com        if (flag_L2_gate == 2) {
62610234Syasuko.eckert@amd.com            cumulative_area_L2 = compute_gate_area(NAND, 2, w_L2_p[0], w_L2_n[0], g_tp.cell_h_def);
62710234Syasuko.eckert@amd.com            leakage_L2         = cmos_Isub_leakage(w_L2_n[0], w_L2_p[0], 2, nand, is_dram_);
62810234Syasuko.eckert@amd.com            gate_leakage_L2    = cmos_Ig_leakage(w_L2_n[0], w_L2_p[0], 2, nand, is_dram_);
62910234Syasuko.eckert@amd.com        } else if (flag_L2_gate == 3) {
63010234Syasuko.eckert@amd.com            cumulative_area_L2 = compute_gate_area(NAND, 3, w_L2_p[0], w_L2_n[0], g_tp.cell_h_def);
63110234Syasuko.eckert@amd.com            leakage_L2         = cmos_Isub_leakage(w_L2_n[0], w_L2_p[0], 3, nand, is_dram_);
63210234Syasuko.eckert@amd.com            gate_leakage_L2    = cmos_Ig_leakage(w_L2_n[0], w_L2_p[0], 3, nand, is_dram_);
63310234Syasuko.eckert@amd.com        }
63410234Syasuko.eckert@amd.com
63510234Syasuko.eckert@amd.com        for (int i = 1; i < number_gates_L2; ++i) {
63610234Syasuko.eckert@amd.com            cumulative_area_L2 += compute_gate_area(INV, 1, w_L2_p[i], w_L2_n[i], g_tp.cell_h_def);
63710234Syasuko.eckert@amd.com            leakage_L2         += cmos_Isub_leakage(w_L2_n[i], w_L2_p[i], 2, inv, is_dram_);
63810234Syasuko.eckert@amd.com            gate_leakage_L2    += cmos_Ig_leakage(w_L2_n[i], w_L2_p[i], 2, inv, is_dram_);
63910234Syasuko.eckert@amd.com        }
64010234Syasuko.eckert@amd.com        cumulative_area_L2 *= num_L2;
64110234Syasuko.eckert@amd.com        leakage_L2         *= num_L2;
64210234Syasuko.eckert@amd.com        gate_leakage_L2    *= num_L2;
64310234Syasuko.eckert@amd.com
64410234Syasuko.eckert@amd.com        power_nand2_path.readOp.leakage = leak_L1_nand2 * g_tp.peri_global.Vdd;
64510234Syasuko.eckert@amd.com        power_nand3_path.readOp.leakage = leak_L1_nand3 * g_tp.peri_global.Vdd;
64610234Syasuko.eckert@amd.com        power_L2.readOp.leakage         = leakage_L2    * g_tp.peri_global.Vdd;
64710234Syasuko.eckert@amd.com        area.set_area(cumulative_area_L1 + cumulative_area_L2);
64810234Syasuko.eckert@amd.com        power_nand2_path.readOp.gate_leakage = gate_leak_L1_nand2 * g_tp.peri_global.Vdd;
64910234Syasuko.eckert@amd.com        power_nand3_path.readOp.gate_leakage = gate_leak_L1_nand3 * g_tp.peri_global.Vdd;
65010234Syasuko.eckert@amd.com        power_L2.readOp.gate_leakage         = gate_leakage_L2    * g_tp.peri_global.Vdd;
65110152Satgutier@umich.edu    }
65210234Syasuko.eckert@amd.com}
65310152Satgutier@umich.edu
65410152Satgutier@umich.edu
65510234Syasuko.eckert@amd.com
65610234Syasuko.eckert@amd.compair<double, double> PredecBlk::compute_delays(
65710234Syasuko.eckert@amd.com    pair<double, double> inrisetime) { // <nand2, nand3>
65810234Syasuko.eckert@amd.com    pair<double, double> ret_val;
65910234Syasuko.eckert@amd.com    ret_val.first  = 0;  // outrisetime_nand2_path
66010234Syasuko.eckert@amd.com    ret_val.second = 0;  // outrisetime_nand3_path
66110234Syasuko.eckert@amd.com
66210234Syasuko.eckert@amd.com    double inrisetime_nand2_path = inrisetime.first;
66310234Syasuko.eckert@amd.com    double inrisetime_nand3_path = inrisetime.second;
66410234Syasuko.eckert@amd.com    int    i;
66510234Syasuko.eckert@amd.com    double rd, c_load, c_intrinsic, tf, this_delay;
66610234Syasuko.eckert@amd.com    double Vdd = g_tp.peri_global.Vdd;
66710234Syasuko.eckert@amd.com
66810234Syasuko.eckert@amd.com    // TODO: following delay calculation part can be greatly simplified.
66910234Syasuko.eckert@amd.com    // first check whether a predecoder block is required
67010234Syasuko.eckert@amd.com    if (exist) {
67110234Syasuko.eckert@amd.com        //Find delay in first level of predecoder block
67210234Syasuko.eckert@amd.com        //First find delay in path
67310234Syasuko.eckert@amd.com        if ((flag_two_unique_paths) || (number_inputs_L1_gate == 2)) {
67410234Syasuko.eckert@amd.com            //First gate is a NAND2 gate
67510234Syasuko.eckert@amd.com            rd = tr_R_on(w_L1_nand2_n[0], NCH, 2, is_dram_);
67610234Syasuko.eckert@amd.com            c_load = gate_C(w_L1_nand2_n[1] + w_L1_nand2_p[1], 0.0, is_dram_);
67710234Syasuko.eckert@amd.com            c_intrinsic = 2 * drain_C_(w_L1_nand2_p[0], PCH, 1, 1, g_tp.cell_h_def, is_dram_) +
67810234Syasuko.eckert@amd.com                          drain_C_(w_L1_nand2_n[0], NCH, 2, 1, g_tp.cell_h_def, is_dram_);
67910234Syasuko.eckert@amd.com            tf = rd * (c_intrinsic + c_load);
68010234Syasuko.eckert@amd.com            this_delay = horowitz(inrisetime_nand2_path, tf, 0.5, 0.5, RISE);
68110234Syasuko.eckert@amd.com            delay_nand2_path += this_delay;
68210234Syasuko.eckert@amd.com            inrisetime_nand2_path = this_delay / (1.0 - 0.5);
68310234Syasuko.eckert@amd.com            power_nand2_path.readOp.dynamic += (c_load + c_intrinsic) * Vdd * Vdd;
68410234Syasuko.eckert@amd.com
68510234Syasuko.eckert@amd.com            //Add delays of all but the last inverter in the chain
68610234Syasuko.eckert@amd.com            for (i = 1; i < number_gates_L1_nand2_path - 1; ++i) {
68710234Syasuko.eckert@amd.com                rd = tr_R_on(w_L1_nand2_n[i], NCH, 1, is_dram_);
68810234Syasuko.eckert@amd.com                c_load = gate_C(w_L1_nand2_n[i+1] + w_L1_nand2_p[i+1], 0.0, is_dram_);
68910234Syasuko.eckert@amd.com                c_intrinsic = drain_C_(w_L1_nand2_p[i], PCH, 1, 1, g_tp.cell_h_def, is_dram_) +
69010234Syasuko.eckert@amd.com                              drain_C_(w_L1_nand2_n[i], NCH, 1, 1, g_tp.cell_h_def, is_dram_);
69110234Syasuko.eckert@amd.com                tf = rd * (c_intrinsic + c_load);
69210234Syasuko.eckert@amd.com                this_delay = horowitz(inrisetime_nand2_path, tf, 0.5, 0.5, RISE);
69310234Syasuko.eckert@amd.com                delay_nand2_path += this_delay;
69410234Syasuko.eckert@amd.com                inrisetime_nand2_path = this_delay / (1.0 - 0.5);
69510234Syasuko.eckert@amd.com                power_nand2_path.readOp.dynamic += (c_intrinsic + c_load) * Vdd * Vdd;
69610234Syasuko.eckert@amd.com            }
69710234Syasuko.eckert@amd.com
69810234Syasuko.eckert@amd.com            //Add delay of the last inverter
69910234Syasuko.eckert@amd.com            i = number_gates_L1_nand2_path - 1;
70010234Syasuko.eckert@amd.com            rd = tr_R_on(w_L1_nand2_n[i], NCH, 1, is_dram_);
70110234Syasuko.eckert@amd.com            if (flag_L2_gate) {
70210234Syasuko.eckert@amd.com                c_load = branch_effort_nand2_gate_output *
70310234Syasuko.eckert@amd.com                    (gate_C(w_L2_n[0], 0, is_dram_) +
70410234Syasuko.eckert@amd.com                     gate_C(w_L2_p[0], 0, is_dram_));
70510234Syasuko.eckert@amd.com                c_intrinsic = drain_C_(w_L1_nand2_p[i], PCH, 1, 1, g_tp.cell_h_def, is_dram_) +
70610234Syasuko.eckert@amd.com                              drain_C_(w_L1_nand2_n[i], NCH, 1, 1, g_tp.cell_h_def, is_dram_);
70710234Syasuko.eckert@amd.com                tf = rd * (c_intrinsic + c_load);
70810234Syasuko.eckert@amd.com                this_delay = horowitz(inrisetime_nand2_path, tf, 0.5, 0.5, RISE);
70910234Syasuko.eckert@amd.com                delay_nand2_path += this_delay;
71010234Syasuko.eckert@amd.com                inrisetime_nand2_path = this_delay / (1.0 - 0.5);
71110234Syasuko.eckert@amd.com                power_nand2_path.readOp.dynamic += (c_intrinsic + c_load) * Vdd * Vdd;
71210234Syasuko.eckert@amd.com            } else { //First level directly drives decoder output load
71310234Syasuko.eckert@amd.com                c_load = C_ld_predec_blk_out;
71410234Syasuko.eckert@amd.com                c_intrinsic = drain_C_(w_L1_nand2_p[i], PCH, 1, 1, g_tp.cell_h_def, is_dram_) +
71510234Syasuko.eckert@amd.com                              drain_C_(w_L1_nand2_n[i], NCH, 1, 1, g_tp.cell_h_def, is_dram_);
71610234Syasuko.eckert@amd.com                tf = rd * (c_intrinsic + c_load) + R_wire_predec_blk_out * c_load / 2;
71710234Syasuko.eckert@amd.com                this_delay = horowitz(inrisetime_nand2_path, tf, 0.5, 0.5, RISE);
71810234Syasuko.eckert@amd.com                delay_nand2_path += this_delay;
71910234Syasuko.eckert@amd.com                ret_val.first = this_delay / (1.0 - 0.5);
72010234Syasuko.eckert@amd.com                power_nand2_path.readOp.dynamic += (c_intrinsic + c_load) * Vdd * Vdd;
72110234Syasuko.eckert@amd.com            }
72210234Syasuko.eckert@amd.com        }
72310234Syasuko.eckert@amd.com
72410234Syasuko.eckert@amd.com        if ((flag_two_unique_paths) || (number_inputs_L1_gate == 3)) {
72510234Syasuko.eckert@amd.com            //Check if the number of gates in the first level is more than 1.
72610234Syasuko.eckert@amd.com            //First gate is a NAND3 gate
72710234Syasuko.eckert@amd.com            rd = tr_R_on(w_L1_nand3_n[0], NCH, 3, is_dram_);
72810234Syasuko.eckert@amd.com            c_load = gate_C(w_L1_nand3_n[1] + w_L1_nand3_p[1], 0.0, is_dram_);
72910234Syasuko.eckert@amd.com            c_intrinsic = 3 * drain_C_(w_L1_nand3_p[0], PCH, 1, 1, g_tp.cell_h_def, is_dram_) +
73010234Syasuko.eckert@amd.com                          drain_C_(w_L1_nand3_n[0], NCH, 3, 1, g_tp.cell_h_def, is_dram_);
73110234Syasuko.eckert@amd.com            tf = rd * (c_intrinsic + c_load);
73210234Syasuko.eckert@amd.com            this_delay = horowitz(inrisetime_nand3_path, tf, 0.5, 0.5, RISE);
73310234Syasuko.eckert@amd.com            delay_nand3_path += this_delay;
73410234Syasuko.eckert@amd.com            inrisetime_nand3_path = this_delay / (1.0 - 0.5);
73510234Syasuko.eckert@amd.com            power_nand3_path.readOp.dynamic += (c_intrinsic + c_load) * Vdd * Vdd;
73610234Syasuko.eckert@amd.com
73710234Syasuko.eckert@amd.com            //Add delays of all but the last inverter in the chain
73810234Syasuko.eckert@amd.com            for (i = 1; i < number_gates_L1_nand3_path - 1; ++i) {
73910234Syasuko.eckert@amd.com                rd = tr_R_on(w_L1_nand3_n[i], NCH, 1, is_dram_);
74010234Syasuko.eckert@amd.com                c_load = gate_C(w_L1_nand3_n[i+1] + w_L1_nand3_p[i+1], 0.0, is_dram_);
74110234Syasuko.eckert@amd.com                c_intrinsic = drain_C_(w_L1_nand3_p[i], PCH, 1, 1, g_tp.cell_h_def, is_dram_) +
74210234Syasuko.eckert@amd.com                              drain_C_(w_L1_nand3_n[i], NCH, 1, 1, g_tp.cell_h_def, is_dram_);
74310234Syasuko.eckert@amd.com                tf = rd * (c_intrinsic + c_load);
74410234Syasuko.eckert@amd.com                this_delay = horowitz(inrisetime_nand3_path, tf, 0.5, 0.5, RISE);
74510234Syasuko.eckert@amd.com                delay_nand3_path += this_delay;
74610234Syasuko.eckert@amd.com                inrisetime_nand3_path = this_delay / (1.0 - 0.5);
74710234Syasuko.eckert@amd.com                power_nand3_path.readOp.dynamic += (c_intrinsic + c_load) * Vdd * Vdd;
74810234Syasuko.eckert@amd.com            }
74910234Syasuko.eckert@amd.com
75010234Syasuko.eckert@amd.com            //Add delay of the last inverter
75110234Syasuko.eckert@amd.com            i = number_gates_L1_nand3_path - 1;
75210234Syasuko.eckert@amd.com            rd = tr_R_on(w_L1_nand3_n[i], NCH, 1, is_dram_);
75310234Syasuko.eckert@amd.com            if (flag_L2_gate) {
75410234Syasuko.eckert@amd.com                c_load = branch_effort_nand3_gate_output *
75510234Syasuko.eckert@amd.com                    (gate_C(w_L2_n[0], 0, is_dram_) + gate_C(w_L2_p[0], 0,
75610234Syasuko.eckert@amd.com                                                             is_dram_));
75710234Syasuko.eckert@amd.com                c_intrinsic = drain_C_(w_L1_nand3_p[i], PCH, 1, 1, g_tp.cell_h_def, is_dram_) +
75810234Syasuko.eckert@amd.com                              drain_C_(w_L1_nand3_n[i], NCH, 1, 1, g_tp.cell_h_def, is_dram_);
75910234Syasuko.eckert@amd.com                tf = rd * (c_intrinsic + c_load);
76010234Syasuko.eckert@amd.com                this_delay = horowitz(inrisetime_nand3_path, tf, 0.5, 0.5, RISE);
76110234Syasuko.eckert@amd.com                delay_nand3_path += this_delay;
76210234Syasuko.eckert@amd.com                inrisetime_nand3_path = this_delay / (1.0 - 0.5);
76310234Syasuko.eckert@amd.com                power_nand3_path.readOp.dynamic += (c_intrinsic + c_load) * Vdd * Vdd;
76410234Syasuko.eckert@amd.com            } else { //First level directly drives decoder output load
76510234Syasuko.eckert@amd.com                c_load = C_ld_predec_blk_out;
76610234Syasuko.eckert@amd.com                c_intrinsic = drain_C_(w_L1_nand3_p[i], PCH, 1, 1, g_tp.cell_h_def, is_dram_) +
76710234Syasuko.eckert@amd.com                              drain_C_(w_L1_nand3_n[i], NCH, 1, 1, g_tp.cell_h_def, is_dram_);
76810234Syasuko.eckert@amd.com                tf = rd * (c_intrinsic + c_load) + R_wire_predec_blk_out * c_load / 2;
76910234Syasuko.eckert@amd.com                this_delay = horowitz(inrisetime_nand3_path, tf, 0.5, 0.5, RISE);
77010234Syasuko.eckert@amd.com                delay_nand3_path += this_delay;
77110234Syasuko.eckert@amd.com                ret_val.second = this_delay / (1.0 - 0.5);
77210234Syasuko.eckert@amd.com                power_nand3_path.readOp.dynamic += (c_intrinsic + c_load) * Vdd * Vdd;
77310234Syasuko.eckert@amd.com            }
77410234Syasuko.eckert@amd.com        }
77510234Syasuko.eckert@amd.com
77610234Syasuko.eckert@amd.com        // Find delay through second level
77710234Syasuko.eckert@amd.com        if (flag_L2_gate) {
77810234Syasuko.eckert@amd.com            if (flag_L2_gate == 2) {
77910234Syasuko.eckert@amd.com                rd = tr_R_on(w_L2_n[0], NCH, 2, is_dram_);
78010234Syasuko.eckert@amd.com                c_load = gate_C(w_L2_n[1] + w_L2_p[1], 0.0, is_dram_);
78110234Syasuko.eckert@amd.com                c_intrinsic = 2 * drain_C_(w_L2_p[0], PCH, 1, 1, g_tp.cell_h_def, is_dram_) +
78210234Syasuko.eckert@amd.com                              drain_C_(w_L2_n[0], NCH, 2, 1, g_tp.cell_h_def, is_dram_);
78310234Syasuko.eckert@amd.com                tf = rd * (c_intrinsic + c_load);
78410234Syasuko.eckert@amd.com                this_delay = horowitz(inrisetime_nand2_path, tf, 0.5, 0.5, RISE);
78510234Syasuko.eckert@amd.com                delay_nand2_path += this_delay;
78610234Syasuko.eckert@amd.com                inrisetime_nand2_path = this_delay / (1.0 - 0.5);
78710234Syasuko.eckert@amd.com                power_L2.readOp.dynamic += (c_intrinsic + c_load) * Vdd * Vdd;
78810234Syasuko.eckert@amd.com            } else { // flag_L2_gate = 3
78910234Syasuko.eckert@amd.com                rd = tr_R_on(w_L2_n[0], NCH, 3, is_dram_);
79010234Syasuko.eckert@amd.com                c_load = gate_C(w_L2_n[1] + w_L2_p[1], 0.0, is_dram_);
79110234Syasuko.eckert@amd.com                c_intrinsic = 3 * drain_C_(w_L2_p[0], PCH, 1, 1, g_tp.cell_h_def, is_dram_) +
79210234Syasuko.eckert@amd.com                              drain_C_(w_L2_n[0], NCH, 3, 1, g_tp.cell_h_def, is_dram_);
79310234Syasuko.eckert@amd.com                tf = rd * (c_intrinsic + c_load);
79410234Syasuko.eckert@amd.com                this_delay = horowitz(inrisetime_nand3_path, tf, 0.5, 0.5, RISE);
79510234Syasuko.eckert@amd.com                delay_nand3_path += this_delay;
79610234Syasuko.eckert@amd.com                inrisetime_nand3_path = this_delay / (1.0 - 0.5);
79710234Syasuko.eckert@amd.com                power_L2.readOp.dynamic += (c_intrinsic + c_load) * Vdd * Vdd;
79810234Syasuko.eckert@amd.com            }
79910234Syasuko.eckert@amd.com
80010234Syasuko.eckert@amd.com            for (i = 1; i < number_gates_L2 - 1; ++i) {
80110234Syasuko.eckert@amd.com                rd = tr_R_on(w_L2_n[i], NCH, 1, is_dram_);
80210234Syasuko.eckert@amd.com                c_load = gate_C(w_L2_n[i+1] + w_L2_p[i+1], 0.0, is_dram_);
80310234Syasuko.eckert@amd.com                c_intrinsic = drain_C_(w_L2_p[i], PCH, 1, 1, g_tp.cell_h_def, is_dram_) +
80410234Syasuko.eckert@amd.com                              drain_C_(w_L2_n[i], NCH, 1, 1, g_tp.cell_h_def, is_dram_);
80510234Syasuko.eckert@amd.com                tf = rd * (c_intrinsic + c_load);
80610234Syasuko.eckert@amd.com                this_delay = horowitz(inrisetime_nand2_path, tf, 0.5, 0.5, RISE);
80710234Syasuko.eckert@amd.com                delay_nand2_path += this_delay;
80810234Syasuko.eckert@amd.com                inrisetime_nand2_path = this_delay / (1.0 - 0.5);
80910234Syasuko.eckert@amd.com                this_delay = horowitz(inrisetime_nand3_path, tf, 0.5, 0.5, RISE);
81010234Syasuko.eckert@amd.com                delay_nand3_path += this_delay;
81110234Syasuko.eckert@amd.com                inrisetime_nand3_path = this_delay / (1.0 - 0.5);
81210234Syasuko.eckert@amd.com                power_L2.readOp.dynamic += (c_intrinsic + c_load) * Vdd * Vdd;
81310234Syasuko.eckert@amd.com            }
81410234Syasuko.eckert@amd.com
81510234Syasuko.eckert@amd.com            //Add delay of final inverter that drives the wordline decoders
81610234Syasuko.eckert@amd.com            i = number_gates_L2 - 1;
81710234Syasuko.eckert@amd.com            c_load = C_ld_predec_blk_out;
81810234Syasuko.eckert@amd.com            rd = tr_R_on(w_L2_n[i], NCH, 1, is_dram_);
81910234Syasuko.eckert@amd.com            c_intrinsic = drain_C_(w_L2_p[i], PCH, 1, 1, g_tp.cell_h_def, is_dram_) +
82010234Syasuko.eckert@amd.com                          drain_C_(w_L2_n[i], NCH, 1, 1, g_tp.cell_h_def, is_dram_);
82110234Syasuko.eckert@amd.com            tf = rd * (c_intrinsic + c_load) + R_wire_predec_blk_out * c_load / 2;
82210234Syasuko.eckert@amd.com            this_delay = horowitz(inrisetime_nand2_path, tf, 0.5, 0.5, RISE);
82310234Syasuko.eckert@amd.com            delay_nand2_path += this_delay;
82410234Syasuko.eckert@amd.com            ret_val.first = this_delay / (1.0 - 0.5);
82510234Syasuko.eckert@amd.com            this_delay = horowitz(inrisetime_nand3_path, tf, 0.5, 0.5, RISE);
82610234Syasuko.eckert@amd.com            delay_nand3_path += this_delay;
82710234Syasuko.eckert@amd.com            ret_val.second = this_delay / (1.0 - 0.5);
82810234Syasuko.eckert@amd.com            power_L2.readOp.dynamic += (c_intrinsic + c_load) * Vdd * Vdd;
82910234Syasuko.eckert@amd.com        }
83010152Satgutier@umich.edu    }
83110152Satgutier@umich.edu
83210234Syasuko.eckert@amd.com    delay = (ret_val.first > ret_val.second) ? ret_val.first : ret_val.second;
83310234Syasuko.eckert@amd.com    return ret_val;
83410152Satgutier@umich.edu}
83510152Satgutier@umich.edu
83610152Satgutier@umich.eduvoid PredecBlk::leakage_feedback(double temperature)
83710152Satgutier@umich.edu{
83810152Satgutier@umich.edu  if (exist)
83910152Satgutier@umich.edu  { // First check whether a predecoder block is needed
84010152Satgutier@umich.edu    int num_L1_nand2 = 0;
84110152Satgutier@umich.edu    int num_L1_nand3 = 0;
84210152Satgutier@umich.edu    int num_L2 = 0;
84310152Satgutier@umich.edu    double leak_L1_nand3      =0;
84410152Satgutier@umich.edu    double gate_leak_L1_nand3 =0;
84510152Satgutier@umich.edu
84610152Satgutier@umich.edu    double leak_L1_nand2      = cmos_Isub_leakage(w_L1_nand2_n[0], w_L1_nand2_p[0], 2, nand, is_dram_);
84710152Satgutier@umich.edu    double gate_leak_L1_nand2 = cmos_Ig_leakage(w_L1_nand2_n[0], w_L1_nand2_p[0], 2, nand, is_dram_);
84810152Satgutier@umich.edu    if (number_inputs_L1_gate != 3) {
84910152Satgutier@umich.edu      leak_L1_nand3 = 0;
85010152Satgutier@umich.edu      gate_leak_L1_nand3 =0;
85110152Satgutier@umich.edu    }
85210152Satgutier@umich.edu    else {
85310152Satgutier@umich.edu      leak_L1_nand3      = cmos_Isub_leakage(w_L1_nand3_n[0], w_L1_nand3_p[0], 3, nand);
85410152Satgutier@umich.edu      gate_leak_L1_nand3 = cmos_Ig_leakage(w_L1_nand3_n[0], w_L1_nand3_p[0], 3, nand);
85510152Satgutier@umich.edu    }
85610152Satgutier@umich.edu
85710152Satgutier@umich.edu    switch (number_input_addr_bits)
85810152Satgutier@umich.edu    {
85910152Satgutier@umich.edu      case 1: //2 NAND2 gates
86010152Satgutier@umich.edu        num_L1_nand2 = 2;
86110152Satgutier@umich.edu        num_L2       = 0;
86210152Satgutier@umich.edu        num_L1_active_nand2_path =1;
86310152Satgutier@umich.edu        num_L1_active_nand3_path =0;
86410152Satgutier@umich.edu        break;
86510152Satgutier@umich.edu      case 2: //4 NAND2 gates
86610152Satgutier@umich.edu        num_L1_nand2 = 4;
86710152Satgutier@umich.edu        num_L2       = 0;
86810152Satgutier@umich.edu        num_L1_active_nand2_path =1;
86910152Satgutier@umich.edu        num_L1_active_nand3_path =0;
87010152Satgutier@umich.edu        break;
87110152Satgutier@umich.edu      case 3: //8 NAND3 gates
87210152Satgutier@umich.edu        num_L1_nand3 = 8;
87310152Satgutier@umich.edu        num_L2       = 0;
87410152Satgutier@umich.edu        num_L1_active_nand2_path =0;
87510152Satgutier@umich.edu        num_L1_active_nand3_path =1;
87610152Satgutier@umich.edu        break;
87710152Satgutier@umich.edu      case 4: //4 + 4 NAND2 gates
87810152Satgutier@umich.edu        num_L1_nand2 = 8;
87910152Satgutier@umich.edu        num_L2       = 16;
88010152Satgutier@umich.edu        num_L1_active_nand2_path =2;
88110152Satgutier@umich.edu        num_L1_active_nand3_path =0;
88210152Satgutier@umich.edu        break;
88310152Satgutier@umich.edu      case 5: //4 NAND2 gates, 8 NAND3 gates
88410152Satgutier@umich.edu        num_L1_nand2 = 4;
88510152Satgutier@umich.edu        num_L1_nand3 = 8;
88610152Satgutier@umich.edu        num_L2       = 32;
88710152Satgutier@umich.edu        num_L1_active_nand2_path =1;
88810152Satgutier@umich.edu        num_L1_active_nand3_path =1;
88910152Satgutier@umich.edu        break;
89010152Satgutier@umich.edu      case 6: //8 + 8 NAND3 gates
89110152Satgutier@umich.edu        num_L1_nand3 = 16;
89210152Satgutier@umich.edu        num_L2       = 64;
89310152Satgutier@umich.edu        num_L1_active_nand2_path =0;
89410152Satgutier@umich.edu        num_L1_active_nand3_path =2;
89510152Satgutier@umich.edu        break;
89610152Satgutier@umich.edu      case 7: //4 + 4 NAND2 gates, 8 NAND3 gates
89710152Satgutier@umich.edu        num_L1_nand2 = 8;
89810152Satgutier@umich.edu        num_L1_nand3 = 8;
89910152Satgutier@umich.edu        num_L2       = 128;
90010152Satgutier@umich.edu        num_L1_active_nand2_path =2;
90110152Satgutier@umich.edu        num_L1_active_nand3_path =1;
90210152Satgutier@umich.edu        break;
90310152Satgutier@umich.edu      case 8: //4 NAND2 gates, 8 + 8 NAND3 gates
90410152Satgutier@umich.edu        num_L1_nand2 = 4;
90510152Satgutier@umich.edu        num_L1_nand3 = 16;
90610152Satgutier@umich.edu        num_L2       = 256;
90710152Satgutier@umich.edu        num_L1_active_nand2_path =2;
90810152Satgutier@umich.edu        num_L1_active_nand3_path =2;
90910152Satgutier@umich.edu        break;
91010152Satgutier@umich.edu      case 9: //8 + 8 + 8 NAND3 gates
91110152Satgutier@umich.edu        num_L1_nand3 = 24;
91210152Satgutier@umich.edu        num_L2       = 512;
91310152Satgutier@umich.edu        num_L1_active_nand2_path =0;
91410152Satgutier@umich.edu        num_L1_active_nand3_path =3;
91510152Satgutier@umich.edu        break;
91610152Satgutier@umich.edu      default:
91710152Satgutier@umich.edu        break;
91810152Satgutier@umich.edu    }
91910152Satgutier@umich.edu
92010152Satgutier@umich.edu    for (int i = 1; i < number_gates_L1_nand2_path; ++i)
92110152Satgutier@umich.edu    {
92210152Satgutier@umich.edu      leak_L1_nand2      += cmos_Isub_leakage(w_L1_nand2_n[i], w_L1_nand2_p[i], 2, nand, is_dram_);
92310152Satgutier@umich.edu      gate_leak_L1_nand2 += cmos_Ig_leakage(w_L1_nand2_n[i], w_L1_nand2_p[i], 2, nand, is_dram_);
92410152Satgutier@umich.edu    }
92510152Satgutier@umich.edu    leak_L1_nand2      *= num_L1_nand2;
92610152Satgutier@umich.edu    gate_leak_L1_nand2 *= num_L1_nand2;
92710152Satgutier@umich.edu
92810152Satgutier@umich.edu    for (int i = 1; i < number_gates_L1_nand3_path; ++i)
92910152Satgutier@umich.edu    {
93010152Satgutier@umich.edu      leak_L1_nand3      += cmos_Isub_leakage(w_L1_nand3_n[i], w_L1_nand3_p[i], 3, nand, is_dram_);
93110152Satgutier@umich.edu      gate_leak_L1_nand3 += cmos_Ig_leakage(w_L1_nand3_n[i], w_L1_nand3_p[i], 3, nand, is_dram_);
93210152Satgutier@umich.edu    }
93310152Satgutier@umich.edu    leak_L1_nand3      *= num_L1_nand3;
93410152Satgutier@umich.edu    gate_leak_L1_nand3 *= num_L1_nand3;
93510152Satgutier@umich.edu
93610152Satgutier@umich.edu    double leakage_L2         = 0.0;
93710152Satgutier@umich.edu    double gate_leakage_L2    = 0.0;
93810152Satgutier@umich.edu
93910152Satgutier@umich.edu    if (flag_L2_gate == 2)
94010152Satgutier@umich.edu    {
94110152Satgutier@umich.edu      leakage_L2         = cmos_Isub_leakage(w_L2_n[0], w_L2_p[0], 2, nand, is_dram_);
94210152Satgutier@umich.edu      gate_leakage_L2    = cmos_Ig_leakage(w_L2_n[0], w_L2_p[0], 2, nand, is_dram_);
94310152Satgutier@umich.edu    }
94410152Satgutier@umich.edu    else if (flag_L2_gate == 3)
94510152Satgutier@umich.edu    {
94610152Satgutier@umich.edu      leakage_L2         = cmos_Isub_leakage(w_L2_n[0], w_L2_p[0], 3, nand, is_dram_);
94710152Satgutier@umich.edu      gate_leakage_L2    = cmos_Ig_leakage(w_L2_n[0], w_L2_p[0], 3, nand, is_dram_);
94810152Satgutier@umich.edu    }
94910152Satgutier@umich.edu
95010152Satgutier@umich.edu    for (int i = 1; i < number_gates_L2; ++i)
95110152Satgutier@umich.edu    {
95210152Satgutier@umich.edu      leakage_L2         += cmos_Isub_leakage(w_L2_n[i], w_L2_p[i], 2, inv, is_dram_);
95310152Satgutier@umich.edu      gate_leakage_L2    += cmos_Ig_leakage(w_L2_n[i], w_L2_p[i], 2, inv, is_dram_);
95410152Satgutier@umich.edu    }
95510152Satgutier@umich.edu    leakage_L2         *= num_L2;
95610152Satgutier@umich.edu    gate_leakage_L2    *= num_L2;
95710152Satgutier@umich.edu
95810152Satgutier@umich.edu    power_nand2_path.readOp.leakage = leak_L1_nand2 * g_tp.peri_global.Vdd;
95910152Satgutier@umich.edu    power_nand3_path.readOp.leakage = leak_L1_nand3 * g_tp.peri_global.Vdd;
96010152Satgutier@umich.edu    power_L2.readOp.leakage         = leakage_L2    * g_tp.peri_global.Vdd;
96110152Satgutier@umich.edu
96210152Satgutier@umich.edu    power_nand2_path.readOp.gate_leakage = gate_leak_L1_nand2 * g_tp.peri_global.Vdd;
96310152Satgutier@umich.edu    power_nand3_path.readOp.gate_leakage = gate_leak_L1_nand3 * g_tp.peri_global.Vdd;
96410152Satgutier@umich.edu    power_L2.readOp.gate_leakage         = gate_leakage_L2    * g_tp.peri_global.Vdd;
96510152Satgutier@umich.edu  }
96610152Satgutier@umich.edu}
96710152Satgutier@umich.edu
96810152Satgutier@umich.eduPredecBlkDrv::PredecBlkDrv(
96910152Satgutier@umich.edu    int    way_select_,
97010152Satgutier@umich.edu    PredecBlk * blk_,
97110152Satgutier@umich.edu    bool   is_dram)
97210234Syasuko.eckert@amd.com        : flag_driver_exists(0),
97310234Syasuko.eckert@amd.com        number_gates_nand2_path(0),
97410234Syasuko.eckert@amd.com        number_gates_nand3_path(0),
97510234Syasuko.eckert@amd.com        min_number_gates(2),
97610234Syasuko.eckert@amd.com        num_buffers_driving_1_nand2_load(0),
97710234Syasuko.eckert@amd.com        num_buffers_driving_2_nand2_load(0),
97810234Syasuko.eckert@amd.com        num_buffers_driving_4_nand2_load(0),
97910234Syasuko.eckert@amd.com        num_buffers_driving_2_nand3_load(0),
98010234Syasuko.eckert@amd.com        num_buffers_driving_8_nand3_load(0),
98110234Syasuko.eckert@amd.com        num_buffers_nand3_path(0),
98210234Syasuko.eckert@amd.com        c_load_nand2_path_out(0),
98310234Syasuko.eckert@amd.com        c_load_nand3_path_out(0),
98410234Syasuko.eckert@amd.com        r_load_nand2_path_out(0),
98510234Syasuko.eckert@amd.com        r_load_nand3_path_out(0),
98610234Syasuko.eckert@amd.com        delay_nand2_path(0),
98710234Syasuko.eckert@amd.com        delay_nand3_path(0),
98810234Syasuko.eckert@amd.com        power_nand2_path(),
98910234Syasuko.eckert@amd.com        power_nand3_path(),
99010234Syasuko.eckert@amd.com        blk(blk_), dec(blk->dec),
99110234Syasuko.eckert@amd.com        is_dram_(is_dram),
99210234Syasuko.eckert@amd.com        way_select(way_select_) {
99310234Syasuko.eckert@amd.com    for (int i = 0; i < MAX_NUMBER_GATES_STAGE; i++) {
99410234Syasuko.eckert@amd.com        width_nand2_path_n[i] = 0;
99510234Syasuko.eckert@amd.com        width_nand2_path_p[i] = 0;
99610234Syasuko.eckert@amd.com        width_nand3_path_n[i] = 0;
99710234Syasuko.eckert@amd.com        width_nand3_path_p[i] = 0;
99810234Syasuko.eckert@amd.com    }
99910152Satgutier@umich.edu
100010234Syasuko.eckert@amd.com    number_input_addr_bits = blk->number_input_addr_bits;
100110152Satgutier@umich.edu
100210234Syasuko.eckert@amd.com    if (way_select > 1) {
100310234Syasuko.eckert@amd.com        flag_driver_exists     = 1;
100410234Syasuko.eckert@amd.com        number_input_addr_bits = way_select;
100510234Syasuko.eckert@amd.com        if (dec->num_in_signals == 2) {
100610234Syasuko.eckert@amd.com            c_load_nand2_path_out = gate_C(dec->w_dec_n[0] + dec->w_dec_p[0], 0, is_dram_);
100710234Syasuko.eckert@amd.com            num_buffers_driving_2_nand2_load = number_input_addr_bits;
100810234Syasuko.eckert@amd.com        } else if (dec->num_in_signals == 3) {
100910234Syasuko.eckert@amd.com            c_load_nand3_path_out = gate_C(dec->w_dec_n[0] + dec->w_dec_p[0], 0, is_dram_);
101010234Syasuko.eckert@amd.com            num_buffers_driving_2_nand3_load = number_input_addr_bits;
101110234Syasuko.eckert@amd.com        }
101210234Syasuko.eckert@amd.com    } else if (way_select == 0) {
101310234Syasuko.eckert@amd.com        if (blk->exist) {
101410234Syasuko.eckert@amd.com            flag_driver_exists = 1;
101510234Syasuko.eckert@amd.com        }
101610152Satgutier@umich.edu    }
101710152Satgutier@umich.edu
101810234Syasuko.eckert@amd.com    compute_widths();
101910234Syasuko.eckert@amd.com    compute_area();
102010152Satgutier@umich.edu}
102110152Satgutier@umich.edu
102210152Satgutier@umich.edu
102310152Satgutier@umich.edu
102410234Syasuko.eckert@amd.comvoid PredecBlkDrv::compute_widths() {
102510234Syasuko.eckert@amd.com    // The predecode block driver accepts as input the address bits from the h-tree network. For
102610234Syasuko.eckert@amd.com    // each addr bit it then generates addr and addrbar as outputs. For now ignore the effect of
102710234Syasuko.eckert@amd.com    // inversion to generate addrbar and simply treat addrbar as addr.
102810152Satgutier@umich.edu
102910234Syasuko.eckert@amd.com    double F;
103010234Syasuko.eckert@amd.com    double p_to_n_sz_ratio = pmos_to_nmos_sz_ratio(is_dram_);
103110152Satgutier@umich.edu
103210234Syasuko.eckert@amd.com    if (flag_driver_exists) {
103310234Syasuko.eckert@amd.com        double C_nand2_gate_blk = gate_C(blk->w_L1_nand2_n[0] + blk->w_L1_nand2_p[0], 0, is_dram_);
103410234Syasuko.eckert@amd.com        double C_nand3_gate_blk = gate_C(blk->w_L1_nand3_n[0] + blk->w_L1_nand3_p[0], 0, is_dram_);
103510152Satgutier@umich.edu
103610234Syasuko.eckert@amd.com        if (way_select == 0) {
103710234Syasuko.eckert@amd.com            if (blk->number_input_addr_bits == 1) {
103810234Syasuko.eckert@amd.com                //2 NAND2 gates
103910234Syasuko.eckert@amd.com                num_buffers_driving_2_nand2_load = 1;
104010234Syasuko.eckert@amd.com                c_load_nand2_path_out            = 2 * C_nand2_gate_blk;
104110234Syasuko.eckert@amd.com            } else if (blk->number_input_addr_bits == 2) {
104210234Syasuko.eckert@amd.com                //4 NAND2 gates  one 2-4 decoder
104310234Syasuko.eckert@amd.com                num_buffers_driving_4_nand2_load = 2;
104410234Syasuko.eckert@amd.com                c_load_nand2_path_out            = 4 * C_nand2_gate_blk;
104510234Syasuko.eckert@amd.com            } else if (blk->number_input_addr_bits == 3) {
104610234Syasuko.eckert@amd.com                //8 NAND3 gates  one 3-8 decoder
104710234Syasuko.eckert@amd.com                num_buffers_driving_8_nand3_load = 3;
104810234Syasuko.eckert@amd.com                c_load_nand3_path_out            = 8 * C_nand3_gate_blk;
104910234Syasuko.eckert@amd.com            } else if (blk->number_input_addr_bits == 4) {
105010234Syasuko.eckert@amd.com                //4 + 4 NAND2 gates two 2-4 decoder
105110234Syasuko.eckert@amd.com                num_buffers_driving_4_nand2_load = 4;
105210234Syasuko.eckert@amd.com                c_load_nand2_path_out            = 4 * C_nand2_gate_blk;
105310234Syasuko.eckert@amd.com            } else if (blk->number_input_addr_bits == 5) {
105410234Syasuko.eckert@amd.com                //4 NAND2 gates, 8 NAND3 gates one 2-4 decoder and one 3-8
105510234Syasuko.eckert@amd.com                //decoder
105610234Syasuko.eckert@amd.com                num_buffers_driving_4_nand2_load = 2;
105710234Syasuko.eckert@amd.com                num_buffers_driving_8_nand3_load = 3;
105810234Syasuko.eckert@amd.com                c_load_nand2_path_out            = 4 * C_nand2_gate_blk;
105910234Syasuko.eckert@amd.com                c_load_nand3_path_out            = 8 * C_nand3_gate_blk;
106010234Syasuko.eckert@amd.com            } else if (blk->number_input_addr_bits == 6) {
106110234Syasuko.eckert@amd.com                //8 + 8 NAND3 gates two 3-8 decoder
106210234Syasuko.eckert@amd.com                num_buffers_driving_8_nand3_load = 6;
106310234Syasuko.eckert@amd.com                c_load_nand3_path_out            = 8 * C_nand3_gate_blk;
106410234Syasuko.eckert@amd.com            } else if (blk->number_input_addr_bits == 7) {
106510234Syasuko.eckert@amd.com                //4 + 4 NAND2 gates, 8 NAND3 gates two 2-4 decoder and one 3-8
106610234Syasuko.eckert@amd.com                //decoder
106710234Syasuko.eckert@amd.com                num_buffers_driving_4_nand2_load = 4;
106810234Syasuko.eckert@amd.com                num_buffers_driving_8_nand3_load = 3;
106910234Syasuko.eckert@amd.com                c_load_nand2_path_out            = 4 * C_nand2_gate_blk;
107010234Syasuko.eckert@amd.com                c_load_nand3_path_out            = 8 * C_nand3_gate_blk;
107110234Syasuko.eckert@amd.com            } else if (blk->number_input_addr_bits == 8) {
107210234Syasuko.eckert@amd.com                //4 NAND2 gates, 8 + 8 NAND3 gates one 2-4 decoder and two 3-8
107310234Syasuko.eckert@amd.com                //decoder
107410234Syasuko.eckert@amd.com                num_buffers_driving_4_nand2_load = 2;
107510234Syasuko.eckert@amd.com                num_buffers_driving_8_nand3_load = 6;
107610234Syasuko.eckert@amd.com                c_load_nand2_path_out            = 4 * C_nand2_gate_blk;
107710234Syasuko.eckert@amd.com                c_load_nand3_path_out            = 8 * C_nand3_gate_blk;
107810234Syasuko.eckert@amd.com            } else if (blk->number_input_addr_bits == 9) {
107910234Syasuko.eckert@amd.com                //8 + 8 + 8 NAND3 gates three 3-8 decoder
108010234Syasuko.eckert@amd.com                num_buffers_driving_8_nand3_load = 9;
108110234Syasuko.eckert@amd.com                c_load_nand3_path_out            = 8 * C_nand3_gate_blk;
108210234Syasuko.eckert@amd.com            }
108310234Syasuko.eckert@amd.com        }
108410234Syasuko.eckert@amd.com
108510234Syasuko.eckert@amd.com        if ((blk->flag_two_unique_paths) ||
108610234Syasuko.eckert@amd.com                (blk->number_inputs_L1_gate == 2) ||
108710234Syasuko.eckert@amd.com                (number_input_addr_bits == 0) ||
108810234Syasuko.eckert@amd.com                ((way_select) && (dec->num_in_signals == 2))) {
108910234Syasuko.eckert@amd.com            //this means that way_select is driving NAND2 in decoder.
109010234Syasuko.eckert@amd.com            width_nand2_path_n[0] = g_tp.min_w_nmos_;
109110234Syasuko.eckert@amd.com            width_nand2_path_p[0] = p_to_n_sz_ratio * width_nand2_path_n[0];
109210234Syasuko.eckert@amd.com            F = c_load_nand2_path_out / gate_C(width_nand2_path_n[0] + width_nand2_path_p[0], 0, is_dram_);
109310234Syasuko.eckert@amd.com            number_gates_nand2_path = logical_effort(
109410234Syasuko.eckert@amd.com                                          min_number_gates,
109510234Syasuko.eckert@amd.com                                          1,
109610234Syasuko.eckert@amd.com                                          F,
109710234Syasuko.eckert@amd.com                                          width_nand2_path_n,
109810234Syasuko.eckert@amd.com                                          width_nand2_path_p,
109910234Syasuko.eckert@amd.com                                          c_load_nand2_path_out,
110010234Syasuko.eckert@amd.com                                          p_to_n_sz_ratio,
110110234Syasuko.eckert@amd.com                                          is_dram_, false, g_tp.max_w_nmos_);
110210234Syasuko.eckert@amd.com        }
110310234Syasuko.eckert@amd.com
110410234Syasuko.eckert@amd.com        if ((blk->flag_two_unique_paths) ||
110510234Syasuko.eckert@amd.com                (blk->number_inputs_L1_gate == 3) ||
110610234Syasuko.eckert@amd.com                ((way_select) && (dec->num_in_signals == 3))) {
110710234Syasuko.eckert@amd.com            //this means that way_select is driving NAND3 in decoder.
110810234Syasuko.eckert@amd.com            width_nand3_path_n[0] = g_tp.min_w_nmos_;
110910234Syasuko.eckert@amd.com            width_nand3_path_p[0] = p_to_n_sz_ratio * width_nand3_path_n[0];
111010234Syasuko.eckert@amd.com            F = c_load_nand3_path_out / gate_C(width_nand3_path_n[0] + width_nand3_path_p[0], 0, is_dram_);
111110234Syasuko.eckert@amd.com            number_gates_nand3_path = logical_effort(
111210234Syasuko.eckert@amd.com                                          min_number_gates,
111310234Syasuko.eckert@amd.com                                          1,
111410234Syasuko.eckert@amd.com                                          F,
111510234Syasuko.eckert@amd.com                                          width_nand3_path_n,
111610234Syasuko.eckert@amd.com                                          width_nand3_path_p,
111710234Syasuko.eckert@amd.com                                          c_load_nand3_path_out,
111810234Syasuko.eckert@amd.com                                          p_to_n_sz_ratio,
111910234Syasuko.eckert@amd.com                                          is_dram_, false, g_tp.max_w_nmos_);
112010234Syasuko.eckert@amd.com        }
112110152Satgutier@umich.edu    }
112210152Satgutier@umich.edu}
112310152Satgutier@umich.edu
112410152Satgutier@umich.edu
112510152Satgutier@umich.edu
112610234Syasuko.eckert@amd.comvoid PredecBlkDrv::compute_area() {
112710234Syasuko.eckert@amd.com    double area_nand2_path = 0;
112810234Syasuko.eckert@amd.com    double area_nand3_path = 0;
112910234Syasuko.eckert@amd.com    double leak_nand2_path = 0;
113010234Syasuko.eckert@amd.com    double leak_nand3_path = 0;
113110234Syasuko.eckert@amd.com    double gate_leak_nand2_path = 0;
113210234Syasuko.eckert@amd.com    double gate_leak_nand3_path = 0;
113310152Satgutier@umich.edu
113410234Syasuko.eckert@amd.com    if (flag_driver_exists) {
113510234Syasuko.eckert@amd.com        // first check whether a predecoder block driver is needed
113610234Syasuko.eckert@amd.com        for (int i = 0; i < number_gates_nand2_path; ++i) {
113710234Syasuko.eckert@amd.com            area_nand2_path +=
113810234Syasuko.eckert@amd.com                compute_gate_area(INV, 1, width_nand2_path_p[i],
113910234Syasuko.eckert@amd.com                                  width_nand2_path_n[i], g_tp.cell_h_def);
114010234Syasuko.eckert@amd.com            leak_nand2_path +=
114110234Syasuko.eckert@amd.com                cmos_Isub_leakage(width_nand2_path_n[i], width_nand2_path_p[i],
114210234Syasuko.eckert@amd.com                                  1, inv, is_dram_);
114310234Syasuko.eckert@amd.com            gate_leak_nand2_path +=
114410234Syasuko.eckert@amd.com                cmos_Ig_leakage(width_nand2_path_n[i], width_nand2_path_p[i],
114510234Syasuko.eckert@amd.com                                1, inv, is_dram_);
114610234Syasuko.eckert@amd.com        }
114710234Syasuko.eckert@amd.com        area_nand2_path *= (num_buffers_driving_1_nand2_load +
114810152Satgutier@umich.edu                            num_buffers_driving_2_nand2_load +
114910152Satgutier@umich.edu                            num_buffers_driving_4_nand2_load);
115010234Syasuko.eckert@amd.com        leak_nand2_path *= (num_buffers_driving_1_nand2_load +
115110234Syasuko.eckert@amd.com                            num_buffers_driving_2_nand2_load +
115210234Syasuko.eckert@amd.com                            num_buffers_driving_4_nand2_load);
115310234Syasuko.eckert@amd.com        gate_leak_nand2_path *= (num_buffers_driving_1_nand2_load +
115410234Syasuko.eckert@amd.com                                 num_buffers_driving_2_nand2_load +
115510234Syasuko.eckert@amd.com                                 num_buffers_driving_4_nand2_load);
115610152Satgutier@umich.edu
115710234Syasuko.eckert@amd.com        for (int i = 0; i < number_gates_nand3_path; ++i) {
115810234Syasuko.eckert@amd.com            area_nand3_path +=
115910234Syasuko.eckert@amd.com                compute_gate_area(INV, 1, width_nand3_path_p[i],
116010234Syasuko.eckert@amd.com                                  width_nand3_path_n[i], g_tp.cell_h_def);
116110234Syasuko.eckert@amd.com            leak_nand3_path +=
116210234Syasuko.eckert@amd.com                cmos_Isub_leakage(width_nand3_path_n[i], width_nand3_path_p[i],
116310234Syasuko.eckert@amd.com                                  1, inv, is_dram_);
116410234Syasuko.eckert@amd.com            gate_leak_nand3_path +=
116510234Syasuko.eckert@amd.com                cmos_Ig_leakage(width_nand3_path_n[i], width_nand3_path_p[i],
116610234Syasuko.eckert@amd.com                                1, inv, is_dram_);
116710234Syasuko.eckert@amd.com        }
116810234Syasuko.eckert@amd.com        area_nand3_path *= (num_buffers_driving_2_nand3_load + num_buffers_driving_8_nand3_load);
116910234Syasuko.eckert@amd.com        leak_nand3_path *= (num_buffers_driving_2_nand3_load + num_buffers_driving_8_nand3_load);
117010234Syasuko.eckert@amd.com        gate_leak_nand3_path *= (num_buffers_driving_2_nand3_load + num_buffers_driving_8_nand3_load);
117110234Syasuko.eckert@amd.com
117210234Syasuko.eckert@amd.com        power_nand2_path.readOp.leakage = leak_nand2_path * g_tp.peri_global.Vdd;
117310234Syasuko.eckert@amd.com        power_nand3_path.readOp.leakage = leak_nand3_path * g_tp.peri_global.Vdd;
117410234Syasuko.eckert@amd.com        power_nand2_path.readOp.gate_leakage = gate_leak_nand2_path * g_tp.peri_global.Vdd;
117510234Syasuko.eckert@amd.com        power_nand3_path.readOp.gate_leakage = gate_leak_nand3_path * g_tp.peri_global.Vdd;
117610234Syasuko.eckert@amd.com        area.set_area(area_nand2_path + area_nand3_path);
117710152Satgutier@umich.edu    }
117810152Satgutier@umich.edu}
117910152Satgutier@umich.edu
118010152Satgutier@umich.edu
118110152Satgutier@umich.edu
118210152Satgutier@umich.edupair<double, double> PredecBlkDrv::compute_delays(
118310152Satgutier@umich.edu    double inrisetime_nand2_path,
118410234Syasuko.eckert@amd.com    double inrisetime_nand3_path) {
118510234Syasuko.eckert@amd.com    pair<double, double> ret_val;
118610234Syasuko.eckert@amd.com    ret_val.first  = 0;  // outrisetime_nand2_path
118710234Syasuko.eckert@amd.com    ret_val.second = 0;  // outrisetime_nand3_path
118810234Syasuko.eckert@amd.com    int i;
118910234Syasuko.eckert@amd.com    double rd, c_gate_load, c_load, c_intrinsic, tf, this_delay;
119010234Syasuko.eckert@amd.com    double Vdd = g_tp.peri_global.Vdd;
119110152Satgutier@umich.edu
119210234Syasuko.eckert@amd.com    if (flag_driver_exists) {
119310234Syasuko.eckert@amd.com        for (i = 0; i < number_gates_nand2_path - 1; ++i) {
119410234Syasuko.eckert@amd.com            rd = tr_R_on(width_nand2_path_n[i], NCH, 1, is_dram_);
119510234Syasuko.eckert@amd.com            c_gate_load = gate_C(width_nand2_path_p[i+1] + width_nand2_path_n[i+1], 0.0, is_dram_);
119610234Syasuko.eckert@amd.com            c_intrinsic = drain_C_(width_nand2_path_p[i], PCH, 1, 1, g_tp.cell_h_def, is_dram_) +
119710234Syasuko.eckert@amd.com                          drain_C_(width_nand2_path_n[i], NCH, 1, 1, g_tp.cell_h_def, is_dram_);
119810234Syasuko.eckert@amd.com            tf = rd * (c_intrinsic + c_gate_load);
119910234Syasuko.eckert@amd.com            this_delay = horowitz(inrisetime_nand2_path, tf, 0.5, 0.5, RISE);
120010234Syasuko.eckert@amd.com            delay_nand2_path += this_delay;
120110234Syasuko.eckert@amd.com            inrisetime_nand2_path = this_delay / (1.0 - 0.5);
120210234Syasuko.eckert@amd.com            power_nand2_path.readOp.dynamic += (c_gate_load + c_intrinsic) * 0.5 * Vdd * Vdd;
120310234Syasuko.eckert@amd.com        }
120410234Syasuko.eckert@amd.com
120510234Syasuko.eckert@amd.com        // Final inverter drives the predecoder block or the decoder output load
120610234Syasuko.eckert@amd.com        if (number_gates_nand2_path != 0) {
120710234Syasuko.eckert@amd.com            i = number_gates_nand2_path - 1;
120810234Syasuko.eckert@amd.com            rd = tr_R_on(width_nand2_path_n[i], NCH, 1, is_dram_);
120910234Syasuko.eckert@amd.com            c_intrinsic = drain_C_(width_nand2_path_p[i], PCH, 1, 1, g_tp.cell_h_def, is_dram_) +
121010234Syasuko.eckert@amd.com                          drain_C_(width_nand2_path_n[i], NCH, 1, 1, g_tp.cell_h_def, is_dram_);
121110234Syasuko.eckert@amd.com            c_load = c_load_nand2_path_out;
121210234Syasuko.eckert@amd.com            tf = rd * (c_intrinsic + c_load) + r_load_nand2_path_out * c_load / 2;
121310234Syasuko.eckert@amd.com            this_delay = horowitz(inrisetime_nand2_path, tf, 0.5, 0.5, RISE);
121410234Syasuko.eckert@amd.com            delay_nand2_path += this_delay;
121510234Syasuko.eckert@amd.com            ret_val.first = this_delay / (1.0 - 0.5);
121610234Syasuko.eckert@amd.com            power_nand2_path.readOp.dynamic += (c_intrinsic + c_load) * 0.5 * Vdd * Vdd;
121710234Syasuko.eckert@amd.com//      cout<< "c_intrinsic = " << c_intrinsic << "c_load" << c_load <<endl;
121810234Syasuko.eckert@amd.com        }
121910234Syasuko.eckert@amd.com
122010234Syasuko.eckert@amd.com        for (i = 0; i < number_gates_nand3_path - 1; ++i) {
122110234Syasuko.eckert@amd.com            rd = tr_R_on(width_nand3_path_n[i], NCH, 1, is_dram_);
122210234Syasuko.eckert@amd.com            c_gate_load = gate_C(width_nand3_path_p[i+1] + width_nand3_path_n[i+1], 0.0, is_dram_);
122310234Syasuko.eckert@amd.com            c_intrinsic = drain_C_(width_nand3_path_p[i], PCH, 1, 1, g_tp.cell_h_def, is_dram_) +
122410234Syasuko.eckert@amd.com                          drain_C_(width_nand3_path_n[i], NCH, 1, 1, g_tp.cell_h_def, is_dram_);
122510234Syasuko.eckert@amd.com            tf = rd * (c_intrinsic + c_gate_load);
122610234Syasuko.eckert@amd.com            this_delay = horowitz(inrisetime_nand3_path, tf, 0.5, 0.5, RISE);
122710234Syasuko.eckert@amd.com            delay_nand3_path += this_delay;
122810234Syasuko.eckert@amd.com            inrisetime_nand3_path = this_delay / (1.0 - 0.5);
122910234Syasuko.eckert@amd.com            power_nand3_path.readOp.dynamic += (c_gate_load + c_intrinsic) * 0.5 * Vdd * Vdd;
123010234Syasuko.eckert@amd.com        }
123110234Syasuko.eckert@amd.com
123210234Syasuko.eckert@amd.com        // Final inverter drives the predecoder block or the decoder output load
123310234Syasuko.eckert@amd.com        if (number_gates_nand3_path != 0) {
123410234Syasuko.eckert@amd.com            i = number_gates_nand3_path - 1;
123510234Syasuko.eckert@amd.com            rd = tr_R_on(width_nand3_path_n[i], NCH, 1, is_dram_);
123610234Syasuko.eckert@amd.com            c_intrinsic = drain_C_(width_nand3_path_p[i], PCH, 1, 1, g_tp.cell_h_def, is_dram_) +
123710234Syasuko.eckert@amd.com                          drain_C_(width_nand3_path_n[i], NCH, 1, 1, g_tp.cell_h_def, is_dram_);
123810234Syasuko.eckert@amd.com            c_load = c_load_nand3_path_out;
123910234Syasuko.eckert@amd.com            tf = rd * (c_intrinsic + c_load) + r_load_nand3_path_out * c_load / 2;
124010234Syasuko.eckert@amd.com            this_delay = horowitz(inrisetime_nand3_path, tf, 0.5, 0.5, RISE);
124110234Syasuko.eckert@amd.com            delay_nand3_path += this_delay;
124210234Syasuko.eckert@amd.com            ret_val.second = this_delay / (1.0 - 0.5);
124310234Syasuko.eckert@amd.com            power_nand3_path.readOp.dynamic += (c_intrinsic + c_load) * 0.5 * Vdd * Vdd;
124410234Syasuko.eckert@amd.com        }
124510152Satgutier@umich.edu    }
124610234Syasuko.eckert@amd.com    return ret_val;
124710152Satgutier@umich.edu}
124810152Satgutier@umich.edu
124910152Satgutier@umich.edu
125010234Syasuko.eckert@amd.comdouble PredecBlkDrv::get_rdOp_dynamic_E(int num_act_mats_hor_dir) {
125110234Syasuko.eckert@amd.com    return (num_addr_bits_nand2_path()*power_nand2_path.readOp.dynamic +
125210234Syasuko.eckert@amd.com            num_addr_bits_nand3_path()*power_nand3_path.readOp.dynamic) * num_act_mats_hor_dir;
125310152Satgutier@umich.edu}
125410152Satgutier@umich.edu
125510152Satgutier@umich.edu
125610152Satgutier@umich.edu
125710152Satgutier@umich.eduPredec::Predec(
125810152Satgutier@umich.edu    PredecBlkDrv * drv1_,
125910152Satgutier@umich.edu    PredecBlkDrv * drv2_)
126010234Syasuko.eckert@amd.com        : blk1(drv1_->blk), blk2(drv2_->blk), drv1(drv1_), drv2(drv2_) {
126110234Syasuko.eckert@amd.com    driver_power.readOp.leakage = drv1->power_nand2_path.readOp.leakage +
126210234Syasuko.eckert@amd.com                                  drv1->power_nand3_path.readOp.leakage +
126310234Syasuko.eckert@amd.com                                  drv2->power_nand2_path.readOp.leakage +
126410234Syasuko.eckert@amd.com                                  drv2->power_nand3_path.readOp.leakage;
126510234Syasuko.eckert@amd.com    block_power.readOp.leakage = blk1->power_nand2_path.readOp.leakage +
126610234Syasuko.eckert@amd.com                                 blk1->power_nand3_path.readOp.leakage +
126710234Syasuko.eckert@amd.com                                 blk1->power_L2.readOp.leakage +
126810234Syasuko.eckert@amd.com                                 blk2->power_nand2_path.readOp.leakage +
126910234Syasuko.eckert@amd.com                                 blk2->power_nand3_path.readOp.leakage +
127010234Syasuko.eckert@amd.com                                 blk2->power_L2.readOp.leakage;
127110234Syasuko.eckert@amd.com    power.readOp.leakage = driver_power.readOp.leakage + block_power.readOp.leakage;
127210152Satgutier@umich.edu
127310234Syasuko.eckert@amd.com    driver_power.readOp.gate_leakage = drv1->power_nand2_path.readOp.gate_leakage +
127410234Syasuko.eckert@amd.com                                       drv1->power_nand3_path.readOp.gate_leakage +
127510234Syasuko.eckert@amd.com                                       drv2->power_nand2_path.readOp.gate_leakage +
127610234Syasuko.eckert@amd.com                                       drv2->power_nand3_path.readOp.gate_leakage;
127710234Syasuko.eckert@amd.com    block_power.readOp.gate_leakage = blk1->power_nand2_path.readOp.gate_leakage +
127810234Syasuko.eckert@amd.com                                      blk1->power_nand3_path.readOp.gate_leakage +
127910234Syasuko.eckert@amd.com                                      blk1->power_L2.readOp.gate_leakage +
128010234Syasuko.eckert@amd.com                                      blk2->power_nand2_path.readOp.gate_leakage +
128110234Syasuko.eckert@amd.com                                      blk2->power_nand3_path.readOp.gate_leakage +
128210234Syasuko.eckert@amd.com                                      blk2->power_L2.readOp.gate_leakage;
128310234Syasuko.eckert@amd.com    power.readOp.gate_leakage = driver_power.readOp.gate_leakage + block_power.readOp.gate_leakage;
128410152Satgutier@umich.edu}
128510152Satgutier@umich.edu
128610152Satgutier@umich.eduvoid PredecBlkDrv::leakage_feedback(double temperature)
128710152Satgutier@umich.edu{
128810152Satgutier@umich.edu  double leak_nand2_path = 0;
128910152Satgutier@umich.edu  double leak_nand3_path = 0;
129010152Satgutier@umich.edu  double gate_leak_nand2_path = 0;
129110152Satgutier@umich.edu  double gate_leak_nand3_path = 0;
129210152Satgutier@umich.edu
129310152Satgutier@umich.edu  if (flag_driver_exists)
129410152Satgutier@umich.edu  { // first check whether a predecoder block driver is needed
129510152Satgutier@umich.edu    for (int i = 0; i < number_gates_nand2_path; ++i)
129610152Satgutier@umich.edu    {
129710152Satgutier@umich.edu      leak_nand2_path += cmos_Isub_leakage(width_nand2_path_n[i], width_nand2_path_p[i], 1, inv,is_dram_);
129810152Satgutier@umich.edu      gate_leak_nand2_path += cmos_Ig_leakage(width_nand2_path_n[i], width_nand2_path_p[i], 1, inv,is_dram_);
129910152Satgutier@umich.edu    }
130010152Satgutier@umich.edu    leak_nand2_path *= (num_buffers_driving_1_nand2_load +
130110152Satgutier@umich.edu                        num_buffers_driving_2_nand2_load +
130210152Satgutier@umich.edu                        num_buffers_driving_4_nand2_load);
130310152Satgutier@umich.edu    gate_leak_nand2_path *= (num_buffers_driving_1_nand2_load +
130410152Satgutier@umich.edu                            num_buffers_driving_2_nand2_load +
130510152Satgutier@umich.edu                            num_buffers_driving_4_nand2_load);
130610152Satgutier@umich.edu
130710152Satgutier@umich.edu    for (int i = 0; i < number_gates_nand3_path; ++i)
130810152Satgutier@umich.edu    {
130910152Satgutier@umich.edu      leak_nand3_path += cmos_Isub_leakage(width_nand3_path_n[i], width_nand3_path_p[i], 1, inv,is_dram_);
131010152Satgutier@umich.edu      gate_leak_nand3_path += cmos_Ig_leakage(width_nand3_path_n[i], width_nand3_path_p[i], 1, inv,is_dram_);
131110152Satgutier@umich.edu    }
131210152Satgutier@umich.edu    leak_nand3_path *= (num_buffers_driving_2_nand3_load + num_buffers_driving_8_nand3_load);
131310152Satgutier@umich.edu    gate_leak_nand3_path *= (num_buffers_driving_2_nand3_load + num_buffers_driving_8_nand3_load);
131410152Satgutier@umich.edu
131510152Satgutier@umich.edu    power_nand2_path.readOp.leakage = leak_nand2_path * g_tp.peri_global.Vdd;
131610152Satgutier@umich.edu    power_nand3_path.readOp.leakage = leak_nand3_path * g_tp.peri_global.Vdd;
131710152Satgutier@umich.edu    power_nand2_path.readOp.gate_leakage = gate_leak_nand2_path * g_tp.peri_global.Vdd;
131810152Satgutier@umich.edu    power_nand3_path.readOp.gate_leakage = gate_leak_nand3_path * g_tp.peri_global.Vdd;
131910152Satgutier@umich.edu  }
132010152Satgutier@umich.edu}
132110152Satgutier@umich.edu
132210234Syasuko.eckert@amd.comdouble Predec::compute_delays(double inrisetime) {
132310234Syasuko.eckert@amd.com    // TODO: Jung Ho thinks that predecoder block driver locates between decoder and predecoder block.
132410234Syasuko.eckert@amd.com    pair<double, double> tmp_pair1, tmp_pair2;
132510234Syasuko.eckert@amd.com    tmp_pair1 = drv1->compute_delays(inrisetime, inrisetime);
132610234Syasuko.eckert@amd.com    tmp_pair1 = blk1->compute_delays(tmp_pair1);
132710234Syasuko.eckert@amd.com    tmp_pair2 = drv2->compute_delays(inrisetime, inrisetime);
132810234Syasuko.eckert@amd.com    tmp_pair2 = blk2->compute_delays(tmp_pair2);
132910234Syasuko.eckert@amd.com    tmp_pair1 = get_max_delay_before_decoder(tmp_pair1, tmp_pair2);
133010152Satgutier@umich.edu
133110234Syasuko.eckert@amd.com    driver_power.readOp.dynamic =
133210234Syasuko.eckert@amd.com        drv1->num_addr_bits_nand2_path() * drv1->power_nand2_path.readOp.dynamic +
133310234Syasuko.eckert@amd.com        drv1->num_addr_bits_nand3_path() * drv1->power_nand3_path.readOp.dynamic +
133410234Syasuko.eckert@amd.com        drv2->num_addr_bits_nand2_path() * drv2->power_nand2_path.readOp.dynamic +
133510234Syasuko.eckert@amd.com        drv2->num_addr_bits_nand3_path() * drv2->power_nand3_path.readOp.dynamic;
133610152Satgutier@umich.edu
133710234Syasuko.eckert@amd.com    block_power.readOp.dynamic =
133810234Syasuko.eckert@amd.com        blk1->power_nand2_path.readOp.dynamic * blk1->num_L1_active_nand2_path +
133910234Syasuko.eckert@amd.com        blk1->power_nand3_path.readOp.dynamic * blk1->num_L1_active_nand3_path +
134010234Syasuko.eckert@amd.com        blk1->power_L2.readOp.dynamic +
134110234Syasuko.eckert@amd.com        blk2->power_nand2_path.readOp.dynamic * blk1->num_L1_active_nand2_path  +
134210234Syasuko.eckert@amd.com        blk2->power_nand3_path.readOp.dynamic * blk1->num_L1_active_nand3_path +
134310234Syasuko.eckert@amd.com        blk2->power_L2.readOp.dynamic;
134410152Satgutier@umich.edu
134510234Syasuko.eckert@amd.com    power.readOp.dynamic = driver_power.readOp.dynamic + block_power.readOp.dynamic;
134610152Satgutier@umich.edu
134710234Syasuko.eckert@amd.com    delay = tmp_pair1.first;
134810234Syasuko.eckert@amd.com    return  tmp_pair1.second;
134910152Satgutier@umich.edu}
135010152Satgutier@umich.edu
135110152Satgutier@umich.eduvoid Predec::leakage_feedback(double temperature)
135210152Satgutier@umich.edu{
135310152Satgutier@umich.edu  drv1->leakage_feedback(temperature);
135410152Satgutier@umich.edu  drv2->leakage_feedback(temperature);
135510152Satgutier@umich.edu  blk1->leakage_feedback(temperature);
135610152Satgutier@umich.edu  blk2->leakage_feedback(temperature);
135710152Satgutier@umich.edu
135810152Satgutier@umich.edu  driver_power.readOp.leakage = drv1->power_nand2_path.readOp.leakage +
135910152Satgutier@umich.edu                                drv1->power_nand3_path.readOp.leakage +
136010152Satgutier@umich.edu                                drv2->power_nand2_path.readOp.leakage +
136110152Satgutier@umich.edu                                drv2->power_nand3_path.readOp.leakage;
136210152Satgutier@umich.edu  block_power.readOp.leakage = blk1->power_nand2_path.readOp.leakage +
136310152Satgutier@umich.edu                               blk1->power_nand3_path.readOp.leakage +
136410152Satgutier@umich.edu                               blk1->power_L2.readOp.leakage +
136510152Satgutier@umich.edu                               blk2->power_nand2_path.readOp.leakage +
136610152Satgutier@umich.edu                               blk2->power_nand3_path.readOp.leakage +
136710152Satgutier@umich.edu                               blk2->power_L2.readOp.leakage;
136810152Satgutier@umich.edu  power.readOp.leakage = driver_power.readOp.leakage + block_power.readOp.leakage;
136910152Satgutier@umich.edu
137010152Satgutier@umich.edu  driver_power.readOp.gate_leakage = drv1->power_nand2_path.readOp.gate_leakage +
137110152Satgutier@umich.edu                                  drv1->power_nand3_path.readOp.gate_leakage +
137210152Satgutier@umich.edu                                  drv2->power_nand2_path.readOp.gate_leakage +
137310152Satgutier@umich.edu                                  drv2->power_nand3_path.readOp.gate_leakage;
137410152Satgutier@umich.edu  block_power.readOp.gate_leakage = blk1->power_nand2_path.readOp.gate_leakage +
137510152Satgutier@umich.edu                                 blk1->power_nand3_path.readOp.gate_leakage +
137610152Satgutier@umich.edu                                 blk1->power_L2.readOp.gate_leakage +
137710152Satgutier@umich.edu                                 blk2->power_nand2_path.readOp.gate_leakage +
137810152Satgutier@umich.edu                                 blk2->power_nand3_path.readOp.gate_leakage +
137910152Satgutier@umich.edu                                 blk2->power_L2.readOp.gate_leakage;
138010152Satgutier@umich.edu  power.readOp.gate_leakage = driver_power.readOp.gate_leakage + block_power.readOp.gate_leakage;
138110152Satgutier@umich.edu}
138210152Satgutier@umich.edu
138310152Satgutier@umich.edu// returns <delay, risetime>
138410152Satgutier@umich.edupair<double, double> Predec::get_max_delay_before_decoder(
138510152Satgutier@umich.edu    pair<double, double> input_pair1,
138610234Syasuko.eckert@amd.com    pair<double, double> input_pair2) {
138710234Syasuko.eckert@amd.com    pair<double, double> ret_val;
138810234Syasuko.eckert@amd.com    double delay;
138910152Satgutier@umich.edu
139010234Syasuko.eckert@amd.com    delay = drv1->delay_nand2_path + blk1->delay_nand2_path;
139110152Satgutier@umich.edu    ret_val.first  = delay;
139210234Syasuko.eckert@amd.com    ret_val.second = input_pair1.first;
139310234Syasuko.eckert@amd.com    delay = drv1->delay_nand3_path + blk1->delay_nand3_path;
139410234Syasuko.eckert@amd.com    if (ret_val.first < delay) {
139510234Syasuko.eckert@amd.com        ret_val.first  = delay;
139610234Syasuko.eckert@amd.com        ret_val.second = input_pair1.second;
139710234Syasuko.eckert@amd.com    }
139810234Syasuko.eckert@amd.com    delay = drv2->delay_nand2_path + blk2->delay_nand2_path;
139910234Syasuko.eckert@amd.com    if (ret_val.first < delay) {
140010234Syasuko.eckert@amd.com        ret_val.first  = delay;
140110234Syasuko.eckert@amd.com        ret_val.second = input_pair2.first;
140210234Syasuko.eckert@amd.com    }
140310234Syasuko.eckert@amd.com    delay = drv2->delay_nand3_path + blk2->delay_nand3_path;
140410234Syasuko.eckert@amd.com    if (ret_val.first < delay) {
140510234Syasuko.eckert@amd.com        ret_val.first  = delay;
140610234Syasuko.eckert@amd.com        ret_val.second = input_pair2.second;
140710234Syasuko.eckert@amd.com    }
140810152Satgutier@umich.edu
140910234Syasuko.eckert@amd.com    return ret_val;
141010152Satgutier@umich.edu}
141110152Satgutier@umich.edu
141210152Satgutier@umich.edu
141310152Satgutier@umich.edu
141410234Syasuko.eckert@amd.comDriver::Driver(double c_gate_load_, double c_wire_load_, double r_wire_load_,
141510234Syasuko.eckert@amd.com               bool is_dram)
141610234Syasuko.eckert@amd.com    : number_gates(0),
141710234Syasuko.eckert@amd.com      min_number_gates(2),
141810234Syasuko.eckert@amd.com      c_gate_load(c_gate_load_),
141910234Syasuko.eckert@amd.com      c_wire_load(c_wire_load_),
142010234Syasuko.eckert@amd.com      r_wire_load(r_wire_load_),
142110234Syasuko.eckert@amd.com      delay(0),
142210234Syasuko.eckert@amd.com      power(),
142310234Syasuko.eckert@amd.com      is_dram_(is_dram) {
142410234Syasuko.eckert@amd.com    for (int i = 0; i < MAX_NUMBER_GATES_STAGE; i++) {
142510234Syasuko.eckert@amd.com        width_n[i] = 0;
142610234Syasuko.eckert@amd.com        width_p[i] = 0;
142710234Syasuko.eckert@amd.com    }
142810152Satgutier@umich.edu
142910234Syasuko.eckert@amd.com    compute_widths();
143010152Satgutier@umich.edu}
143110152Satgutier@umich.edu
143210152Satgutier@umich.edu
143310234Syasuko.eckert@amd.comvoid Driver::compute_widths() {
143410234Syasuko.eckert@amd.com    double p_to_n_sz_ratio = pmos_to_nmos_sz_ratio(is_dram_);
143510234Syasuko.eckert@amd.com    double c_load = c_gate_load + c_wire_load;
143610234Syasuko.eckert@amd.com    width_n[0] = g_tp.min_w_nmos_;
143710234Syasuko.eckert@amd.com    width_p[0] = p_to_n_sz_ratio * g_tp.min_w_nmos_;
143810152Satgutier@umich.edu
143910234Syasuko.eckert@amd.com    double F = c_load / gate_C(width_n[0] + width_p[0], 0, is_dram_);
144010234Syasuko.eckert@amd.com    number_gates = logical_effort(
144110234Syasuko.eckert@amd.com                       min_number_gates,
144210234Syasuko.eckert@amd.com                       1,
144310234Syasuko.eckert@amd.com                       F,
144410234Syasuko.eckert@amd.com                       width_n,
144510234Syasuko.eckert@amd.com                       width_p,
144610234Syasuko.eckert@amd.com                       c_load,
144710234Syasuko.eckert@amd.com                       p_to_n_sz_ratio,
144810234Syasuko.eckert@amd.com                       is_dram_, false,
144910234Syasuko.eckert@amd.com                       g_tp.max_w_nmos_);
145010152Satgutier@umich.edu}
145110152Satgutier@umich.edu
145210152Satgutier@umich.edu
145310152Satgutier@umich.edu
145410234Syasuko.eckert@amd.comdouble Driver::compute_delay(double inrisetime) {
145510234Syasuko.eckert@amd.com    int    i;
145610234Syasuko.eckert@amd.com    double rd, c_load, c_intrinsic, tf;
145710234Syasuko.eckert@amd.com    double this_delay = 0;
145810152Satgutier@umich.edu
145910234Syasuko.eckert@amd.com    for (i = 0; i < number_gates - 1; ++i) {
146010234Syasuko.eckert@amd.com        rd = tr_R_on(width_n[i], NCH, 1, is_dram_);
146110234Syasuko.eckert@amd.com        c_load = gate_C(width_n[i+1] + width_p[i+1], 0.0, is_dram_);
146210234Syasuko.eckert@amd.com        c_intrinsic = drain_C_(width_p[i], PCH, 1, 1, g_tp.cell_h_def, is_dram_) +
146310234Syasuko.eckert@amd.com                      drain_C_(width_n[i], NCH, 1, 1, g_tp.cell_h_def, is_dram_);
146410234Syasuko.eckert@amd.com        tf = rd * (c_intrinsic + c_load);
146510234Syasuko.eckert@amd.com        this_delay = horowitz(inrisetime, tf, 0.5, 0.5, RISE);
146610234Syasuko.eckert@amd.com        delay += this_delay;
146710234Syasuko.eckert@amd.com        inrisetime = this_delay / (1.0 - 0.5);
146810234Syasuko.eckert@amd.com        power.readOp.dynamic += (c_intrinsic + c_load) * g_tp.peri_global.Vdd *
146910234Syasuko.eckert@amd.com            g_tp.peri_global.Vdd;
147010234Syasuko.eckert@amd.com        power.readOp.leakage +=
147110234Syasuko.eckert@amd.com            cmos_Isub_leakage(width_n[i], width_p[i], 1, inv, is_dram_) *
147210234Syasuko.eckert@amd.com            g_tp.peri_global.Vdd;
147310234Syasuko.eckert@amd.com        power.readOp.gate_leakage +=
147410234Syasuko.eckert@amd.com            cmos_Ig_leakage(width_n[i], width_p[i], 1, inv, is_dram_) *
147510234Syasuko.eckert@amd.com            g_tp.peri_global.Vdd;
147610234Syasuko.eckert@amd.com    }
147710234Syasuko.eckert@amd.com
147810234Syasuko.eckert@amd.com    i = number_gates - 1;
147910234Syasuko.eckert@amd.com    c_load = c_gate_load + c_wire_load;
148010152Satgutier@umich.edu    rd = tr_R_on(width_n[i], NCH, 1, is_dram_);
148110152Satgutier@umich.edu    c_intrinsic = drain_C_(width_p[i], PCH, 1, 1, g_tp.cell_h_def, is_dram_) +
148210234Syasuko.eckert@amd.com        drain_C_(width_n[i], NCH, 1, 1, g_tp.cell_h_def, is_dram_);
148310234Syasuko.eckert@amd.com    tf = rd * (c_intrinsic + c_load) + r_wire_load *
148410234Syasuko.eckert@amd.com        (c_wire_load / 2 + c_gate_load);
148510152Satgutier@umich.edu    this_delay = horowitz(inrisetime, tf, 0.5, 0.5, RISE);
148610152Satgutier@umich.edu    delay += this_delay;
148710234Syasuko.eckert@amd.com    power.readOp.dynamic += (c_intrinsic + c_load) * g_tp.peri_global.Vdd *
148810234Syasuko.eckert@amd.com        g_tp.peri_global.Vdd;
148910234Syasuko.eckert@amd.com    power.readOp.leakage +=
149010234Syasuko.eckert@amd.com        cmos_Isub_leakage(width_n[i], width_p[i], 1, inv, is_dram_) *
149110234Syasuko.eckert@amd.com        g_tp.peri_global.Vdd;
149210234Syasuko.eckert@amd.com    power.readOp.gate_leakage +=
149310234Syasuko.eckert@amd.com        cmos_Ig_leakage(width_n[i], width_p[i], 1, inv, is_dram_) *
149410234Syasuko.eckert@amd.com        g_tp.peri_global.Vdd;
149510152Satgutier@umich.edu
149610234Syasuko.eckert@amd.com    return this_delay / (1.0 - 0.5);
149710152Satgutier@umich.edu}
149810152Satgutier@umich.edu
1499