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#include "wire.h"
3410152Satgutier@umich.edu#include "cmath"
3510152Satgutier@umich.edu// use this constructor to calculate wire stats
3610152Satgutier@umich.eduWire::Wire(
3710152Satgutier@umich.edu    enum Wire_type wire_model,
3810152Satgutier@umich.edu    double wl,
3910152Satgutier@umich.edu    int n,
4010152Satgutier@umich.edu    double w_s,
4110152Satgutier@umich.edu    double s_s,
4210152Satgutier@umich.edu    enum Wire_placement wp,
4310152Satgutier@umich.edu    double resistivity,
4410152Satgutier@umich.edu    TechnologyParameter::DeviceType *dt
4510234Syasuko.eckert@amd.com    ): wt(wire_model), wire_length(wl*1e-6), nsense(n), w_scale(w_s),
4610234Syasuko.eckert@amd.com       s_scale(s_s),
4710234Syasuko.eckert@amd.com       resistivity(resistivity), deviceType(dt) {
4810234Syasuko.eckert@amd.com    wire_placement = wp;
4910234Syasuko.eckert@amd.com    min_w_pmos     = deviceType->n_to_p_eff_curr_drv_ratio * g_tp.min_w_nmos_;
5010234Syasuko.eckert@amd.com    in_rise_time   = 0;
5110234Syasuko.eckert@amd.com    out_rise_time  = 0;
5210234Syasuko.eckert@amd.com    if (initialized != 1) {
5310234Syasuko.eckert@amd.com        cout << "Wire not initialized. Initializing it with default values\n";
5410234Syasuko.eckert@amd.com        Wire winit;
5510234Syasuko.eckert@amd.com    }
5610234Syasuko.eckert@amd.com    calculate_wire_stats();
5710234Syasuko.eckert@amd.com    // change everything back to seconds, microns, and Joules
5810234Syasuko.eckert@amd.com    repeater_spacing *= 1e6;
5910234Syasuko.eckert@amd.com    wire_length      *= 1e6;
6010234Syasuko.eckert@amd.com    wire_width       *= 1e6;
6110234Syasuko.eckert@amd.com    wire_spacing     *= 1e6;
6210234Syasuko.eckert@amd.com    assert(wire_length > 0);
6310234Syasuko.eckert@amd.com    assert(power.readOp.dynamic > 0);
6410234Syasuko.eckert@amd.com    assert(power.readOp.leakage > 0);
6510234Syasuko.eckert@amd.com    assert(power.readOp.gate_leakage > 0);
6610152Satgutier@umich.edu}
6710152Satgutier@umich.edu
6810234Syasuko.eckert@amd.com// the following values are for peripheral global technology
6910234Syasuko.eckert@amd.com// specified in the input config file
7010234Syasuko.eckert@amd.comComponent Wire::global;
7110234Syasuko.eckert@amd.comComponent Wire::global_5;
7210234Syasuko.eckert@amd.comComponent Wire::global_10;
7310234Syasuko.eckert@amd.comComponent Wire::global_20;
7410234Syasuko.eckert@amd.comComponent Wire::global_30;
7510234Syasuko.eckert@amd.comComponent Wire::low_swing;
7610152Satgutier@umich.edu
7710234Syasuko.eckert@amd.comint Wire::initialized;
7810234Syasuko.eckert@amd.comdouble Wire::wire_width_init;
7910234Syasuko.eckert@amd.comdouble Wire::wire_spacing_init;
8010152Satgutier@umich.edu
8110152Satgutier@umich.edu
8210234Syasuko.eckert@amd.comWire::Wire(double w_s, double s_s, enum Wire_placement wp, double resis,
8310234Syasuko.eckert@amd.com           TechnologyParameter::DeviceType *dt) {
8410234Syasuko.eckert@amd.com    w_scale        = w_s;
8510234Syasuko.eckert@amd.com    s_scale        = s_s;
8610234Syasuko.eckert@amd.com    deviceType     = dt;
8710234Syasuko.eckert@amd.com    wire_placement = wp;
8810234Syasuko.eckert@amd.com    resistivity    = resis;
8910234Syasuko.eckert@amd.com    min_w_pmos     = deviceType->n_to_p_eff_curr_drv_ratio * g_tp.min_w_nmos_;
9010234Syasuko.eckert@amd.com    in_rise_time   = 0;
9110234Syasuko.eckert@amd.com    out_rise_time  = 0;
9210152Satgutier@umich.edu
9310234Syasuko.eckert@amd.com    switch (wire_placement) {
9410234Syasuko.eckert@amd.com    case outside_mat:
9510234Syasuko.eckert@amd.com      wire_width = g_tp.wire_outside_mat.pitch;
9610234Syasuko.eckert@amd.com      break;
9710234Syasuko.eckert@amd.com    case inside_mat :
9810234Syasuko.eckert@amd.com      wire_width = g_tp.wire_inside_mat.pitch;
9910234Syasuko.eckert@amd.com      break;
10010234Syasuko.eckert@amd.com    default:
10110234Syasuko.eckert@amd.com      wire_width = g_tp.wire_local.pitch;
10210234Syasuko.eckert@amd.com      break;
10310234Syasuko.eckert@amd.com    }
10410152Satgutier@umich.edu
10510234Syasuko.eckert@amd.com    wire_spacing = wire_width;
10610152Satgutier@umich.edu
10710234Syasuko.eckert@amd.com    wire_width   *= (w_scale * 1e-6 / 2) /* (m) */;
10810234Syasuko.eckert@amd.com    wire_spacing *= (s_scale * 1e-6 / 2) /* (m) */;
10910152Satgutier@umich.edu
11010234Syasuko.eckert@amd.com    initialized = 1;
11110234Syasuko.eckert@amd.com    init_wire();
11210234Syasuko.eckert@amd.com    wire_width_init = wire_width;
11310234Syasuko.eckert@amd.com    wire_spacing_init = wire_spacing;
11410152Satgutier@umich.edu
11510234Syasuko.eckert@amd.com    assert(power.readOp.dynamic > 0);
11610234Syasuko.eckert@amd.com    assert(power.readOp.leakage > 0);
11710234Syasuko.eckert@amd.com    assert(power.readOp.gate_leakage > 0);
11810152Satgutier@umich.edu}
11910152Satgutier@umich.edu
12010152Satgutier@umich.edu
12110152Satgutier@umich.edu
12210234Syasuko.eckert@amd.comWire::~Wire() {
12310152Satgutier@umich.edu}
12410152Satgutier@umich.edu
12510152Satgutier@umich.edu
12610152Satgutier@umich.edu
12710152Satgutier@umich.eduvoid
12810234Syasuko.eckert@amd.comWire::calculate_wire_stats() {
12910152Satgutier@umich.edu
13010234Syasuko.eckert@amd.com    if (wire_placement == outside_mat) {
13110234Syasuko.eckert@amd.com        wire_width = g_tp.wire_outside_mat.pitch;
13210234Syasuko.eckert@amd.com    } else if (wire_placement == inside_mat) {
13310234Syasuko.eckert@amd.com        wire_width = g_tp.wire_inside_mat.pitch;
13410234Syasuko.eckert@amd.com    } else {
13510234Syasuko.eckert@amd.com        wire_width = g_tp.wire_local.pitch;
13610234Syasuko.eckert@amd.com    }
13710152Satgutier@umich.edu
13810234Syasuko.eckert@amd.com    wire_spacing = wire_width;
13910152Satgutier@umich.edu
14010234Syasuko.eckert@amd.com    wire_width   *= (w_scale * 1e-6 / 2) /* (m) */;
14110234Syasuko.eckert@amd.com    wire_spacing *= (s_scale * 1e-6 / 2) /* (m) */;
14210152Satgutier@umich.edu
14310152Satgutier@umich.edu
14410234Syasuko.eckert@amd.com    if (wt != Low_swing) {
14510152Satgutier@umich.edu
14610234Syasuko.eckert@amd.com        //    delay_optimal_wire();
14710152Satgutier@umich.edu
14810234Syasuko.eckert@amd.com        if (wt == Global) {
14910234Syasuko.eckert@amd.com            delay = global.delay * wire_length;
15010234Syasuko.eckert@amd.com            power.readOp.dynamic = global.power.readOp.dynamic * wire_length;
15110234Syasuko.eckert@amd.com            power.readOp.leakage = global.power.readOp.leakage * wire_length;
15210234Syasuko.eckert@amd.com            power.readOp.gate_leakage = global.power.readOp.gate_leakage * wire_length;
15310234Syasuko.eckert@amd.com            repeater_spacing = global.area.w;
15410234Syasuko.eckert@amd.com            repeater_size = global.area.h;
15510234Syasuko.eckert@amd.com            area.set_area((wire_length / repeater_spacing) *
15610234Syasuko.eckert@amd.com                          compute_gate_area(INV, 1, min_w_pmos * repeater_size,
15710234Syasuko.eckert@amd.com                                            g_tp.min_w_nmos_ * repeater_size,
15810234Syasuko.eckert@amd.com                                            g_tp.cell_h_def));
15910234Syasuko.eckert@amd.com        } else if (wt == Global_5) {
16010234Syasuko.eckert@amd.com            delay = global_5.delay * wire_length;
16110234Syasuko.eckert@amd.com            power.readOp.dynamic = global_5.power.readOp.dynamic * wire_length;
16210234Syasuko.eckert@amd.com            power.readOp.leakage = global_5.power.readOp.leakage * wire_length;
16310234Syasuko.eckert@amd.com            power.readOp.gate_leakage = global_5.power.readOp.gate_leakage * wire_length;
16410234Syasuko.eckert@amd.com            repeater_spacing = global_5.area.w;
16510234Syasuko.eckert@amd.com            repeater_size = global_5.area.h;
16610234Syasuko.eckert@amd.com            area.set_area((wire_length / repeater_spacing) *
16710234Syasuko.eckert@amd.com                          compute_gate_area(INV, 1, min_w_pmos * repeater_size,
16810234Syasuko.eckert@amd.com                                            g_tp.min_w_nmos_ * repeater_size,
16910234Syasuko.eckert@amd.com                                            g_tp.cell_h_def));
17010234Syasuko.eckert@amd.com        } else if (wt == Global_10) {
17110234Syasuko.eckert@amd.com            delay = global_10.delay * wire_length;
17210234Syasuko.eckert@amd.com            power.readOp.dynamic = global_10.power.readOp.dynamic * wire_length;
17310234Syasuko.eckert@amd.com            power.readOp.leakage = global_10.power.readOp.leakage * wire_length;
17410234Syasuko.eckert@amd.com            power.readOp.gate_leakage = global_10.power.readOp.gate_leakage * wire_length;
17510234Syasuko.eckert@amd.com            repeater_spacing = global_10.area.w;
17610234Syasuko.eckert@amd.com            repeater_size = global_10.area.h;
17710234Syasuko.eckert@amd.com            area.set_area((wire_length / repeater_spacing) *
17810234Syasuko.eckert@amd.com                          compute_gate_area(INV, 1, min_w_pmos * repeater_size,
17910234Syasuko.eckert@amd.com                                            g_tp.min_w_nmos_ * repeater_size,
18010234Syasuko.eckert@amd.com                                            g_tp.cell_h_def));
18110234Syasuko.eckert@amd.com        } else if (wt == Global_20) {
18210234Syasuko.eckert@amd.com            delay = global_20.delay * wire_length;
18310234Syasuko.eckert@amd.com            power.readOp.dynamic = global_20.power.readOp.dynamic * wire_length;
18410234Syasuko.eckert@amd.com            power.readOp.leakage = global_20.power.readOp.leakage * wire_length;
18510234Syasuko.eckert@amd.com            power.readOp.gate_leakage = global_20.power.readOp.gate_leakage * wire_length;
18610234Syasuko.eckert@amd.com            repeater_spacing = global_20.area.w;
18710234Syasuko.eckert@amd.com            repeater_size = global_20.area.h;
18810234Syasuko.eckert@amd.com            area.set_area((wire_length / repeater_spacing) *
18910234Syasuko.eckert@amd.com                          compute_gate_area(INV, 1, min_w_pmos * repeater_size,
19010234Syasuko.eckert@amd.com                                            g_tp.min_w_nmos_ * repeater_size,
19110234Syasuko.eckert@amd.com                                            g_tp.cell_h_def));
19210234Syasuko.eckert@amd.com        } else if (wt == Global_30) {
19310234Syasuko.eckert@amd.com            delay = global_30.delay * wire_length;
19410234Syasuko.eckert@amd.com            power.readOp.dynamic = global_30.power.readOp.dynamic * wire_length;
19510234Syasuko.eckert@amd.com            power.readOp.leakage = global_30.power.readOp.leakage * wire_length;
19610234Syasuko.eckert@amd.com            power.readOp.gate_leakage = global_30.power.readOp.gate_leakage * wire_length;
19710234Syasuko.eckert@amd.com            repeater_spacing = global_30.area.w;
19810234Syasuko.eckert@amd.com            repeater_size = global_30.area.h;
19910234Syasuko.eckert@amd.com            area.set_area((wire_length / repeater_spacing) *
20010234Syasuko.eckert@amd.com                          compute_gate_area(INV, 1, min_w_pmos * repeater_size,
20110234Syasuko.eckert@amd.com                                            g_tp.min_w_nmos_ * repeater_size,
20210234Syasuko.eckert@amd.com                                            g_tp.cell_h_def));
20310234Syasuko.eckert@amd.com        }
20410234Syasuko.eckert@amd.com        out_rise_time = delay * repeater_spacing / deviceType->Vth;
20510234Syasuko.eckert@amd.com    } else if (wt == Low_swing) {
20610234Syasuko.eckert@amd.com        low_swing_model ();
20710234Syasuko.eckert@amd.com        repeater_spacing = wire_length;
20810234Syasuko.eckert@amd.com        repeater_size = 1;
20910234Syasuko.eckert@amd.com    } else {
21010234Syasuko.eckert@amd.com        assert(0);
21110234Syasuko.eckert@amd.com    }
21210152Satgutier@umich.edu}
21310152Satgutier@umich.edu
21410152Satgutier@umich.edu
21510152Satgutier@umich.edu
21610152Satgutier@umich.edu/*
21710152Satgutier@umich.edu * The fall time of an input signal to the first stage of a circuit is
21810152Satgutier@umich.edu * assumed to be same as the fall time of the output signal of two
21910152Satgutier@umich.edu * inverters connected in series (refer: CACTI 1 Technical report,
22010152Satgutier@umich.edu * section 6.1.3)
22110152Satgutier@umich.edu */
22210234Syasuko.eckert@amd.comdouble
22310234Syasuko.eckert@amd.comWire::signal_fall_time () {
22410152Satgutier@umich.edu
22510234Syasuko.eckert@amd.com    /* rise time of inverter 1's output */
22610234Syasuko.eckert@amd.com    double rt;
22710234Syasuko.eckert@amd.com    /* fall time of inverter 2's output */
22810234Syasuko.eckert@amd.com    double ft;
22910234Syasuko.eckert@amd.com    double timeconst;
23010152Satgutier@umich.edu
23110234Syasuko.eckert@amd.com    timeconst = (drain_C_(g_tp.min_w_nmos_, NCH, 1, 1, g_tp.cell_h_def) +
23210234Syasuko.eckert@amd.com                 drain_C_(min_w_pmos, PCH, 1, 1, g_tp.cell_h_def) +
23310234Syasuko.eckert@amd.com                 gate_C(min_w_pmos + g_tp.min_w_nmos_, 0)) *
23410234Syasuko.eckert@amd.com                tr_R_on(min_w_pmos, PCH, 1);
23510234Syasuko.eckert@amd.com    rt = horowitz (0, timeconst, deviceType->Vth / deviceType->Vdd,
23610234Syasuko.eckert@amd.com                   deviceType->Vth / deviceType->Vdd, FALL) /
23710234Syasuko.eckert@amd.com        (deviceType->Vdd - deviceType->Vth);
23810234Syasuko.eckert@amd.com    timeconst = (drain_C_(g_tp.min_w_nmos_, NCH, 1, 1, g_tp.cell_h_def) +
23910234Syasuko.eckert@amd.com                 drain_C_(min_w_pmos, PCH, 1, 1, g_tp.cell_h_def) +
24010234Syasuko.eckert@amd.com                 gate_C(min_w_pmos + g_tp.min_w_nmos_, 0)) *
24110234Syasuko.eckert@amd.com        tr_R_on(g_tp.min_w_nmos_, NCH, 1);
24210234Syasuko.eckert@amd.com    ft = horowitz (rt, timeconst, deviceType->Vth / deviceType->Vdd,
24310234Syasuko.eckert@amd.com                   deviceType->Vth / deviceType->Vdd, RISE) / deviceType->Vth;
24410234Syasuko.eckert@amd.com    return ft;
24510152Satgutier@umich.edu}
24610152Satgutier@umich.edu
24710152Satgutier@umich.edu
24810152Satgutier@umich.edu
24910234Syasuko.eckert@amd.comdouble Wire::signal_rise_time () {
25010152Satgutier@umich.edu
25110234Syasuko.eckert@amd.com    /* rise time of inverter 1's output */
25210234Syasuko.eckert@amd.com    double ft;
25310234Syasuko.eckert@amd.com    /* fall time of inverter 2's output */
25410234Syasuko.eckert@amd.com    double rt;
25510234Syasuko.eckert@amd.com    double timeconst;
25610152Satgutier@umich.edu
25710234Syasuko.eckert@amd.com    timeconst = (drain_C_(g_tp.min_w_nmos_, NCH, 1, 1, g_tp.cell_h_def) +
25810234Syasuko.eckert@amd.com                 drain_C_(min_w_pmos, PCH, 1, 1, g_tp.cell_h_def) +
25910234Syasuko.eckert@amd.com                 gate_C(min_w_pmos + g_tp.min_w_nmos_, 0)) *
26010234Syasuko.eckert@amd.com        tr_R_on(g_tp.min_w_nmos_, NCH, 1);
26110234Syasuko.eckert@amd.com    rt = horowitz (0, timeconst, deviceType->Vth / deviceType->Vdd,
26210234Syasuko.eckert@amd.com                   deviceType->Vth / deviceType->Vdd, RISE) / deviceType->Vth;
26310234Syasuko.eckert@amd.com    timeconst = (drain_C_(g_tp.min_w_nmos_, NCH, 1, 1, g_tp.cell_h_def) +
26410234Syasuko.eckert@amd.com                 drain_C_(min_w_pmos, PCH, 1, 1, g_tp.cell_h_def) +
26510234Syasuko.eckert@amd.com                 gate_C(min_w_pmos + g_tp.min_w_nmos_, 0)) *
26610234Syasuko.eckert@amd.com        tr_R_on(min_w_pmos, PCH, 1);
26710234Syasuko.eckert@amd.com    ft = horowitz (rt, timeconst, deviceType->Vth / deviceType->Vdd,
26810234Syasuko.eckert@amd.com                   deviceType->Vth / deviceType->Vdd, FALL) /
26910234Syasuko.eckert@amd.com        (deviceType->Vdd - deviceType->Vth);
27010234Syasuko.eckert@amd.com    return ft; //sec
27110152Satgutier@umich.edu}
27210152Satgutier@umich.edu
27310152Satgutier@umich.edu
27410152Satgutier@umich.edu
27510152Satgutier@umich.edu/* Wire resistance and capacitance calculations
27610152Satgutier@umich.edu *   wire width
27710152Satgutier@umich.edu *
27810152Satgutier@umich.edu *    /__/
27910152Satgutier@umich.edu *   |  |
28010152Satgutier@umich.edu *   |  |  height = ASPECT_RATIO*wire width (ASPECT_RATIO = 2.2, ref: ITRS)
28110152Satgutier@umich.edu *   |__|/
28210152Satgutier@umich.edu *
28310152Satgutier@umich.edu *   spacing between wires in same level = wire width
28410152Satgutier@umich.edu *   spacing between wires in adjacent levels = wire width---this is incorrect,
28510152Satgutier@umich.edu *   according to R.Ho's paper and thesis. ILD != wire width
28610152Satgutier@umich.edu *
28710152Satgutier@umich.edu */
28810152Satgutier@umich.edu
28910234Syasuko.eckert@amd.comdouble Wire::wire_cap (double len /* in m */, bool call_from_outside) {
29010234Syasuko.eckert@amd.com    //TODO: this should be consistent with the wire_res in technology file
29110234Syasuko.eckert@amd.com    double sidewall, adj, tot_cap;
29210234Syasuko.eckert@amd.com    double wire_height;
29310234Syasuko.eckert@amd.com    double epsilon0 = 8.8542e-12;
29410234Syasuko.eckert@amd.com    double aspect_ratio;
29510234Syasuko.eckert@amd.com    double horiz_dielectric_constant;
29610234Syasuko.eckert@amd.com    double vert_dielectric_constant;
29710234Syasuko.eckert@amd.com    double miller_value;
29810234Syasuko.eckert@amd.com    double ild_thickness;
29910152Satgutier@umich.edu
30010234Syasuko.eckert@amd.com    switch (wire_placement) {
30110234Syasuko.eckert@amd.com    case outside_mat: {
30210234Syasuko.eckert@amd.com        aspect_ratio = g_tp.wire_outside_mat.aspect_ratio;
30310234Syasuko.eckert@amd.com        horiz_dielectric_constant = g_tp.wire_outside_mat.horiz_dielectric_constant;
30410234Syasuko.eckert@amd.com        vert_dielectric_constant = g_tp.wire_outside_mat.vert_dielectric_constant;
30510234Syasuko.eckert@amd.com        miller_value = g_tp.wire_outside_mat.miller_value;
30610234Syasuko.eckert@amd.com        ild_thickness = g_tp.wire_outside_mat.ild_thickness;
30710234Syasuko.eckert@amd.com        break;
30810234Syasuko.eckert@amd.com    }
30910234Syasuko.eckert@amd.com    case inside_mat : {
31010234Syasuko.eckert@amd.com        aspect_ratio = g_tp.wire_inside_mat.aspect_ratio;
31110234Syasuko.eckert@amd.com        horiz_dielectric_constant = g_tp.wire_inside_mat.horiz_dielectric_constant;
31210234Syasuko.eckert@amd.com        vert_dielectric_constant = g_tp.wire_inside_mat.vert_dielectric_constant;
31310234Syasuko.eckert@amd.com        miller_value = g_tp.wire_inside_mat.miller_value;
31410234Syasuko.eckert@amd.com        ild_thickness = g_tp.wire_inside_mat.ild_thickness;
31510234Syasuko.eckert@amd.com        break;
31610234Syasuko.eckert@amd.com    }
31710234Syasuko.eckert@amd.com    default: {
31810234Syasuko.eckert@amd.com        aspect_ratio = g_tp.wire_local.aspect_ratio;
31910234Syasuko.eckert@amd.com        horiz_dielectric_constant = g_tp.wire_local.horiz_dielectric_constant;
32010234Syasuko.eckert@amd.com        vert_dielectric_constant = g_tp.wire_local.vert_dielectric_constant;
32110234Syasuko.eckert@amd.com        miller_value = g_tp.wire_local.miller_value;
32210234Syasuko.eckert@amd.com        ild_thickness = g_tp.wire_local.ild_thickness;
32310234Syasuko.eckert@amd.com        break;
32410234Syasuko.eckert@amd.com    }
32510234Syasuko.eckert@amd.com    }
32610152Satgutier@umich.edu
32710234Syasuko.eckert@amd.com    if (call_from_outside) {
32810234Syasuko.eckert@amd.com        wire_width       *= 1e-6;
32910234Syasuko.eckert@amd.com        wire_spacing     *= 1e-6;
33010234Syasuko.eckert@amd.com    }
33110234Syasuko.eckert@amd.com    wire_height = wire_width / w_scale * aspect_ratio;
33210234Syasuko.eckert@amd.com    /*
33310234Syasuko.eckert@amd.com     * assuming height does not change. wire_width = width_original*w_scale
33410234Syasuko.eckert@amd.com     * So wire_height does not change as wire width increases
33510234Syasuko.eckert@amd.com     */
33610152Satgutier@umich.edu
33710152Satgutier@umich.edu// capacitance between wires in the same level
33810152Satgutier@umich.edu//  sidewall = 2*miller_value * horiz_dielectric_constant * (wire_height/wire_spacing)
33910152Satgutier@umich.edu//    * epsilon0;
34010152Satgutier@umich.edu
34110234Syasuko.eckert@amd.com    sidewall = miller_value * horiz_dielectric_constant *
34210234Syasuko.eckert@amd.com        (wire_height / wire_spacing)
34310234Syasuko.eckert@amd.com        * epsilon0;
34410152Satgutier@umich.edu
34510152Satgutier@umich.edu
34610234Syasuko.eckert@amd.com    // capacitance between wires in adjacent levels
34710234Syasuko.eckert@amd.com    //adj = miller_value * vert_dielectric_constant *w_scale * epsilon0;
34810234Syasuko.eckert@amd.com    //adj = 2*vert_dielectric_constant *wire_width/(ild_thickness*1e-6) * epsilon0;
34910152Satgutier@umich.edu
35010234Syasuko.eckert@amd.com    adj = miller_value * vert_dielectric_constant * wire_width /
35110234Syasuko.eckert@amd.com        (ild_thickness * 1e-6) * epsilon0;
35210234Syasuko.eckert@amd.com    //Change ild_thickness from micron to M
35310152Satgutier@umich.edu
35410234Syasuko.eckert@amd.com    //tot_cap =  (sidewall + adj + (deviceType->C_fringe * 1e6)); //F/m
35510234Syasuko.eckert@amd.com    tot_cap =  (sidewall + adj + (g_tp.fringe_cap * 1e6)); //F/m
35610152Satgutier@umich.edu
35710234Syasuko.eckert@amd.com    if (call_from_outside) {
35810234Syasuko.eckert@amd.com        wire_width       *= 1e6;
35910234Syasuko.eckert@amd.com        wire_spacing     *= 1e6;
36010234Syasuko.eckert@amd.com    }
36110234Syasuko.eckert@amd.com    return (tot_cap*len); // (F)
36210152Satgutier@umich.edu}
36310152Satgutier@umich.edu
36410152Satgutier@umich.edu
36510234Syasuko.eckert@amd.comdouble
36610234Syasuko.eckert@amd.comWire::wire_res (double len /*(in m)*/) {
36710152Satgutier@umich.edu
36810234Syasuko.eckert@amd.com    double aspect_ratio;
36910234Syasuko.eckert@amd.com    double alpha_scatter = 1.05;
37010234Syasuko.eckert@amd.com    double dishing_thickness = 0;
37110234Syasuko.eckert@amd.com    double barrier_thickness = 0;
37210234Syasuko.eckert@amd.com    //TODO: this should be consistent with the wire_res in technology file
37310234Syasuko.eckert@amd.com    //The whole computation should be consistent with the wire_res in technology.cc too!
37410152Satgutier@umich.edu
37510234Syasuko.eckert@amd.com    switch (wire_placement) {
37610234Syasuko.eckert@amd.com    case outside_mat: {
37710234Syasuko.eckert@amd.com        aspect_ratio = g_tp.wire_outside_mat.aspect_ratio;
37810234Syasuko.eckert@amd.com        break;
37910234Syasuko.eckert@amd.com    }
38010234Syasuko.eckert@amd.com    case inside_mat : {
38110234Syasuko.eckert@amd.com        aspect_ratio = g_tp.wire_inside_mat.aspect_ratio;
38210234Syasuko.eckert@amd.com        break;
38310234Syasuko.eckert@amd.com    }
38410234Syasuko.eckert@amd.com    default: {
38510234Syasuko.eckert@amd.com        aspect_ratio = g_tp.wire_local.aspect_ratio;
38610234Syasuko.eckert@amd.com        break;
38710234Syasuko.eckert@amd.com    }
38810234Syasuko.eckert@amd.com    }
38910234Syasuko.eckert@amd.com    return (alpha_scatter * resistivity * 1e-6 * len /
39010234Syasuko.eckert@amd.com            ((aspect_ratio*wire_width / w_scale - dishing_thickness -
39110234Syasuko.eckert@amd.com              barrier_thickness)*
39210234Syasuko.eckert@amd.com             (wire_width - 2*barrier_thickness)));
39310152Satgutier@umich.edu}
39410152Satgutier@umich.edu
39510152Satgutier@umich.edu/*
39610152Satgutier@umich.edu * Calculates the delay, power and area of the transmitter circuit.
39710152Satgutier@umich.edu *
39810152Satgutier@umich.edu * The transmitter delay is the sum of nand gate delay, inverter delay
39910152Satgutier@umich.edu * low swing nmos delay, and the wire delay
40010152Satgutier@umich.edu * (ref: Technical report 6)
40110152Satgutier@umich.edu */
40210234Syasuko.eckert@amd.comvoid
40310234Syasuko.eckert@amd.comWire::low_swing_model() {
40410234Syasuko.eckert@amd.com    double len = wire_length;
40510234Syasuko.eckert@amd.com    double beta = pmos_to_nmos_sz_ratio();
40610152Satgutier@umich.edu
40710152Satgutier@umich.edu
40810234Syasuko.eckert@amd.com    double inputrise = (in_rise_time == 0) ? signal_rise_time() : in_rise_time;
40910152Satgutier@umich.edu
41010234Syasuko.eckert@amd.com    /* Final nmos low swing driver size calculation:
41110234Syasuko.eckert@amd.com     * Try to size the driver such that the delay
41210234Syasuko.eckert@amd.com     * is less than 8FO4.
41310234Syasuko.eckert@amd.com     * If the driver size is greater than
41410234Syasuko.eckert@amd.com     * the max allowable size, assume max size for the driver.
41510234Syasuko.eckert@amd.com     * In either case, recalculate the delay using
41610234Syasuko.eckert@amd.com     * the final driver size assuming slow input with
41710234Syasuko.eckert@amd.com     * finite rise time instead of ideal step input
41810234Syasuko.eckert@amd.com     *
41910234Syasuko.eckert@amd.com     * (ref: Technical report 6)
42010234Syasuko.eckert@amd.com     */
42110234Syasuko.eckert@amd.com    double cwire = wire_cap(len); /* load capacitance */
42210234Syasuko.eckert@amd.com    double rwire = wire_res(len);
42310152Satgutier@umich.edu
42410152Satgutier@umich.edu#define RES_ADJ (8.6) // Increase in resistance due to low driving vol.
42510152Satgutier@umich.edu
42610234Syasuko.eckert@amd.com    double driver_res = (-8 * g_tp.FO4 / (log(0.5) * cwire)) / RES_ADJ;
42710234Syasuko.eckert@amd.com    double nsize = R_to_w(driver_res, NCH);
42810152Satgutier@umich.edu
42910234Syasuko.eckert@amd.com    nsize = MIN(nsize, g_tp.max_w_nmos_);
43010234Syasuko.eckert@amd.com    nsize = MAX(nsize, g_tp.min_w_nmos_);
43110152Satgutier@umich.edu
43210234Syasuko.eckert@amd.com    if (rwire*cwire > 8*g_tp.FO4) {
43310234Syasuko.eckert@amd.com        nsize = g_tp.max_w_nmos_;
43410234Syasuko.eckert@amd.com    }
43510152Satgutier@umich.edu
43610234Syasuko.eckert@amd.com    // size the inverter appropriately to minimize the transmitter delay
43710234Syasuko.eckert@amd.com    // Note - In order to minimize leakage, we are not adding a set of inverters to
43810234Syasuko.eckert@amd.com    // bring down delay. Instead, we are sizing the single gate
43910234Syasuko.eckert@amd.com    // based on the logical effort.
44010234Syasuko.eckert@amd.com    double st_eff = sqrt((2 + beta / 1 + beta) * gate_C(nsize, 0) /
44110234Syasuko.eckert@amd.com                         (gate_C(2 * g_tp.min_w_nmos_, 0)
44210234Syasuko.eckert@amd.com                          + gate_C(2 * min_w_pmos, 0)));
44310234Syasuko.eckert@amd.com    double req_cin = ((2 + beta / 1 + beta) * gate_C(nsize, 0)) / st_eff;
44410234Syasuko.eckert@amd.com    double inv_size = req_cin / (gate_C(min_w_pmos, 0) +
44510234Syasuko.eckert@amd.com                                 gate_C(g_tp.min_w_nmos_, 0));
44610234Syasuko.eckert@amd.com    inv_size = MAX(inv_size, 1);
44710152Satgutier@umich.edu
44810234Syasuko.eckert@amd.com    /* nand gate delay */
44910234Syasuko.eckert@amd.com    double res_eq = (2 * tr_R_on(g_tp.min_w_nmos_, NCH, 1));
45010234Syasuko.eckert@amd.com    double cap_eq = 2 * drain_C_(min_w_pmos, PCH, 1, 1, g_tp.cell_h_def) +
45110234Syasuko.eckert@amd.com        drain_C_(2 * g_tp.min_w_nmos_, NCH, 1, 1, g_tp.cell_h_def) +
45210234Syasuko.eckert@amd.com        gate_C(inv_size * g_tp.min_w_nmos_, 0) +
45310234Syasuko.eckert@amd.com        gate_C(inv_size * min_w_pmos, 0);
45410152Satgutier@umich.edu
45510234Syasuko.eckert@amd.com    double timeconst = res_eq * cap_eq;
45610152Satgutier@umich.edu
45710234Syasuko.eckert@amd.com    delay = horowitz(inputrise, timeconst, deviceType->Vth / deviceType->Vdd,
45810234Syasuko.eckert@amd.com                     deviceType->Vth / deviceType->Vdd, RISE);
45910234Syasuko.eckert@amd.com    double temp_power = cap_eq * deviceType->Vdd * deviceType->Vdd;
46010152Satgutier@umich.edu
46110234Syasuko.eckert@amd.com    inputrise = delay / (deviceType->Vdd - deviceType->Vth); /* for the next stage */
46210152Satgutier@umich.edu
46310234Syasuko.eckert@amd.com    /* Inverter delay:
46410234Syasuko.eckert@amd.com     * The load capacitance of this inv depends on
46510234Syasuko.eckert@amd.com     * the gate capacitance of the final stage nmos
46610234Syasuko.eckert@amd.com     * transistor which in turn depends on nsize
46710234Syasuko.eckert@amd.com     */
46810234Syasuko.eckert@amd.com    res_eq = tr_R_on(inv_size * min_w_pmos, PCH, 1);
46910234Syasuko.eckert@amd.com    cap_eq = drain_C_(inv_size * min_w_pmos, PCH, 1, 1, g_tp.cell_h_def) +
47010234Syasuko.eckert@amd.com        drain_C_(inv_size * g_tp.min_w_nmos_, NCH, 1, 1, g_tp.cell_h_def) +
47110234Syasuko.eckert@amd.com        gate_C(nsize, 0);
47210234Syasuko.eckert@amd.com    timeconst = res_eq * cap_eq;
47310152Satgutier@umich.edu
47410234Syasuko.eckert@amd.com    delay += horowitz(inputrise, timeconst, deviceType->Vth / deviceType->Vdd,
47510234Syasuko.eckert@amd.com                      deviceType->Vth / deviceType->Vdd, FALL);
47610234Syasuko.eckert@amd.com    temp_power += cap_eq * deviceType->Vdd * deviceType->Vdd;
47710152Satgutier@umich.edu
47810152Satgutier@umich.edu
47910234Syasuko.eckert@amd.com    transmitter.delay = delay;
48010234Syasuko.eckert@amd.com    /* since it is a diff. model*/
48110234Syasuko.eckert@amd.com    transmitter.power.readOp.dynamic = temp_power * 2;
48210234Syasuko.eckert@amd.com    transmitter.power.readOp.leakage = deviceType->Vdd *
48310234Syasuko.eckert@amd.com                                       (4 * cmos_Isub_leakage(g_tp.min_w_nmos_, min_w_pmos, 2, nand) +
48410234Syasuko.eckert@amd.com                                        4 * cmos_Isub_leakage(g_tp.min_w_nmos_, min_w_pmos, 1, inv));
48510152Satgutier@umich.edu
48610234Syasuko.eckert@amd.com    transmitter.power.readOp.gate_leakage = deviceType->Vdd *
48710234Syasuko.eckert@amd.com                                            (4 * cmos_Ig_leakage(g_tp.min_w_nmos_, min_w_pmos, 2, nand) +
48810234Syasuko.eckert@amd.com                                             4 * cmos_Ig_leakage(g_tp.min_w_nmos_, min_w_pmos, 1, inv));
48910152Satgutier@umich.edu
49010234Syasuko.eckert@amd.com    inputrise = delay / deviceType->Vth;
49110152Satgutier@umich.edu
49210234Syasuko.eckert@amd.com    /* nmos delay + wire delay */
49310234Syasuko.eckert@amd.com    cap_eq = cwire + drain_C_(nsize, NCH, 1, 1, g_tp.cell_h_def) * 2 +
49410234Syasuko.eckert@amd.com             nsense * sense_amp_input_cap(); //+receiver cap
49510234Syasuko.eckert@amd.com    /*
49610234Syasuko.eckert@amd.com     * NOTE: nmos is used as both pull up and pull down transistor
49710234Syasuko.eckert@amd.com     * in the transmitter. This is because for low voltage swing, drive
49810234Syasuko.eckert@amd.com     * resistance of nmos is less than pmos
49910234Syasuko.eckert@amd.com     * (for a detailed graph ref: On-Chip Wires: Scaling and Efficiency)
50010234Syasuko.eckert@amd.com     */
50110234Syasuko.eckert@amd.com    timeconst = (tr_R_on(nsize, NCH, 1) * RES_ADJ) * (cwire +
50210234Syasuko.eckert@amd.com                drain_C_(nsize, NCH, 1, 1, g_tp.cell_h_def) * 2) +
50310234Syasuko.eckert@amd.com                rwire * cwire / 2 +
50410234Syasuko.eckert@amd.com                (tr_R_on(nsize, NCH, 1) * RES_ADJ + rwire) *
50510234Syasuko.eckert@amd.com                nsense * sense_amp_input_cap();
50610152Satgutier@umich.edu
50710234Syasuko.eckert@amd.com    /*
50810234Syasuko.eckert@amd.com     * since we are pre-equalizing and overdriving the low
50910234Syasuko.eckert@amd.com     * swing wires, the net time constant is less
51010234Syasuko.eckert@amd.com     * than the actual value
51110234Syasuko.eckert@amd.com     */
51210234Syasuko.eckert@amd.com    delay += horowitz(inputrise, timeconst, deviceType->Vth /
51310234Syasuko.eckert@amd.com                      deviceType->Vdd, .25, 0);
51410152Satgutier@umich.edu#define VOL_SWING .1
51510234Syasuko.eckert@amd.com    temp_power += cap_eq * VOL_SWING * .400; /* .4v is the over drive voltage */
51610234Syasuko.eckert@amd.com    temp_power *= 2; /* differential wire */
51710152Satgutier@umich.edu
51810234Syasuko.eckert@amd.com    l_wire.delay = delay - transmitter.delay;
51910234Syasuko.eckert@amd.com    l_wire.power.readOp.dynamic = temp_power - transmitter.power.readOp.dynamic;
52010234Syasuko.eckert@amd.com    l_wire.power.readOp.leakage = deviceType->Vdd *
52110234Syasuko.eckert@amd.com        (4 * cmos_Isub_leakage(nsize, 0, 1, nmos));
52210152Satgutier@umich.edu
52310234Syasuko.eckert@amd.com    l_wire.power.readOp.gate_leakage = deviceType->Vdd *
52410234Syasuko.eckert@amd.com        (4 * cmos_Ig_leakage(nsize, 0, 1, nmos));
52510152Satgutier@umich.edu
52610234Syasuko.eckert@amd.com    //double rt = horowitz(inputrise, timeconst, deviceType->Vth/deviceType->Vdd,
52710234Syasuko.eckert@amd.com    //    deviceType->Vth/deviceType->Vdd, RISE)/deviceType->Vth;
52810152Satgutier@umich.edu
52910234Syasuko.eckert@amd.com    delay += g_tp.sense_delay;
53010152Satgutier@umich.edu
53110234Syasuko.eckert@amd.com    sense_amp.delay = g_tp.sense_delay;
53210234Syasuko.eckert@amd.com    out_rise_time = g_tp.sense_delay / (deviceType->Vth);
53310234Syasuko.eckert@amd.com    sense_amp.power.readOp.dynamic = g_tp.sense_dy_power;
53410234Syasuko.eckert@amd.com    sense_amp.power.readOp.leakage = 0; //FIXME
53510234Syasuko.eckert@amd.com    sense_amp.power.readOp.gate_leakage = 0;
53610152Satgutier@umich.edu
53710234Syasuko.eckert@amd.com    power.readOp.dynamic = temp_power + sense_amp.power.readOp.dynamic;
53810234Syasuko.eckert@amd.com    power.readOp.leakage = transmitter.power.readOp.leakage +
53910234Syasuko.eckert@amd.com                           l_wire.power.readOp.leakage +
54010234Syasuko.eckert@amd.com                           sense_amp.power.readOp.leakage;
54110234Syasuko.eckert@amd.com    power.readOp.gate_leakage = transmitter.power.readOp.gate_leakage +
54210234Syasuko.eckert@amd.com                                l_wire.power.readOp.gate_leakage +
54310234Syasuko.eckert@amd.com                                sense_amp.power.readOp.gate_leakage;
54410152Satgutier@umich.edu}
54510152Satgutier@umich.edu
54610234Syasuko.eckert@amd.comdouble
54710234Syasuko.eckert@amd.comWire::sense_amp_input_cap() {
54810234Syasuko.eckert@amd.com    return drain_C_(g_tp.w_iso, PCH, 1, 1, g_tp.cell_h_def) +
54910234Syasuko.eckert@amd.com           gate_C(g_tp.w_sense_en + g_tp.w_sense_n, 0) +
55010234Syasuko.eckert@amd.com           drain_C_(g_tp.w_sense_n, NCH, 1, 1, g_tp.cell_h_def) +
55110234Syasuko.eckert@amd.com           drain_C_(g_tp.w_sense_p, PCH, 1, 1, g_tp.cell_h_def);
55210152Satgutier@umich.edu}
55310152Satgutier@umich.edu
55410152Satgutier@umich.edu
55510234Syasuko.eckert@amd.comvoid Wire::delay_optimal_wire () {
55610234Syasuko.eckert@amd.com    double len       = wire_length;
55710234Syasuko.eckert@amd.com    //double min_wire_width = wire_width; //m
55810234Syasuko.eckert@amd.com    double beta = pmos_to_nmos_sz_ratio();
55910234Syasuko.eckert@amd.com    double switching = 0;  // switching energy
56010234Syasuko.eckert@amd.com    double short_ckt = 0;  // short-circuit energy
56110234Syasuko.eckert@amd.com    double tc        = 0;  // time constant
56210234Syasuko.eckert@amd.com    // input cap of min sized driver
56310234Syasuko.eckert@amd.com    double input_cap = gate_C(g_tp.min_w_nmos_ + min_w_pmos, 0);
56410152Satgutier@umich.edu
56510234Syasuko.eckert@amd.com    // output parasitic capacitance of
56610234Syasuko.eckert@amd.com    // the min. sized driver
56710234Syasuko.eckert@amd.com    double out_cap = drain_C_(min_w_pmos, PCH, 1, 1, g_tp.cell_h_def) +
56810234Syasuko.eckert@amd.com                     drain_C_(g_tp.min_w_nmos_, NCH, 1, 1, g_tp.cell_h_def);
56910234Syasuko.eckert@amd.com    // drive resistance
57010234Syasuko.eckert@amd.com    double out_res = (tr_R_on(g_tp.min_w_nmos_, NCH, 1) +
57110234Syasuko.eckert@amd.com                      tr_R_on(min_w_pmos, PCH, 1)) / 2;
57210234Syasuko.eckert@amd.com    double wr = wire_res(len); //ohm
57310152Satgutier@umich.edu
57410234Syasuko.eckert@amd.com    // wire cap /m
57510234Syasuko.eckert@amd.com    double wc = wire_cap(len);
57610152Satgutier@umich.edu
57710234Syasuko.eckert@amd.com    // size the repeater such that the delay of the wire is minimum
57810234Syasuko.eckert@amd.com    // len will cancel
57910234Syasuko.eckert@amd.com    double repeater_scaling = sqrt(out_res * wc / (wr * input_cap));
58010152Satgutier@umich.edu
58110234Syasuko.eckert@amd.com    // calc the optimum spacing between the repeaters (m)
58210152Satgutier@umich.edu
58310234Syasuko.eckert@amd.com    repeater_spacing = sqrt(2 * out_res * (out_cap + input_cap) /
58410234Syasuko.eckert@amd.com                            ((wr / len) * (wc / len)));
58510234Syasuko.eckert@amd.com    repeater_size = repeater_scaling;
58610152Satgutier@umich.edu
58710234Syasuko.eckert@amd.com    switching = (repeater_scaling * (input_cap + out_cap) +
58810234Syasuko.eckert@amd.com                 repeater_spacing * (wc / len)) * deviceType->Vdd *
58910234Syasuko.eckert@amd.com        deviceType->Vdd;
59010152Satgutier@umich.edu
59110234Syasuko.eckert@amd.com    tc = out_res * (input_cap + out_cap) +
59210234Syasuko.eckert@amd.com        out_res * wc / len * repeater_spacing / repeater_scaling +
59310234Syasuko.eckert@amd.com        wr / len * repeater_spacing * input_cap * repeater_scaling +
59410234Syasuko.eckert@amd.com        0.5 * (wr / len) * (wc / len) * repeater_spacing * repeater_spacing;
59510152Satgutier@umich.edu
59610234Syasuko.eckert@amd.com    delay = 0.693 * tc * len / repeater_spacing;
59710152Satgutier@umich.edu
59810152Satgutier@umich.edu#define Ishort_ckt 65e-6 /* across all tech Ref:Banerjee et al. {IEEE TED} */
59910234Syasuko.eckert@amd.com    short_ckt = deviceType->Vdd * g_tp.min_w_nmos_ * Ishort_ckt * 1.0986 *
60010234Syasuko.eckert@amd.com                repeater_scaling * tc;
60110152Satgutier@umich.edu
60210234Syasuko.eckert@amd.com    area.set_area((len / repeater_spacing) *
60310234Syasuko.eckert@amd.com                  compute_gate_area(INV, 1, min_w_pmos * repeater_scaling,
60410234Syasuko.eckert@amd.com                                    g_tp.min_w_nmos_ * repeater_scaling,
60510234Syasuko.eckert@amd.com                                    g_tp.cell_h_def));
60610234Syasuko.eckert@amd.com    power.readOp.dynamic = ((len / repeater_spacing) * (switching + short_ckt));
60710234Syasuko.eckert@amd.com    power.readOp.leakage = ((len / repeater_spacing) *
60810234Syasuko.eckert@amd.com                            deviceType->Vdd *
60910234Syasuko.eckert@amd.com                            cmos_Isub_leakage(g_tp.min_w_nmos_ *
61010234Syasuko.eckert@amd.com                                              repeater_scaling, beta *
61110234Syasuko.eckert@amd.com                                              g_tp.min_w_nmos_ *
61210234Syasuko.eckert@amd.com                                              repeater_scaling, 1, inv));
61310234Syasuko.eckert@amd.com    power.readOp.gate_leakage = ((len / repeater_spacing) *
61410234Syasuko.eckert@amd.com                                 deviceType->Vdd *
61510234Syasuko.eckert@amd.com                                 cmos_Ig_leakage(g_tp.min_w_nmos_ *
61610234Syasuko.eckert@amd.com                                                 repeater_scaling, beta *
61710234Syasuko.eckert@amd.com                                                 g_tp.min_w_nmos_ *
61810234Syasuko.eckert@amd.com                                                 repeater_scaling, 1, inv));
61910152Satgutier@umich.edu}
62010152Satgutier@umich.edu
62110152Satgutier@umich.edu
62210152Satgutier@umich.edu
62310152Satgutier@umich.edu// calculate power/delay values for wires with suboptimal repeater sizing/spacing
62410152Satgutier@umich.eduvoid
62510234Syasuko.eckert@amd.comWire::init_wire() {
62610234Syasuko.eckert@amd.com    wire_length = 1;
62710234Syasuko.eckert@amd.com    delay_optimal_wire();
62810152Satgutier@umich.edu    double sp, si;
62910234Syasuko.eckert@amd.com    powerDef pow;
63010234Syasuko.eckert@amd.com    si = repeater_size;
63110234Syasuko.eckert@amd.com    sp = repeater_spacing;
63210234Syasuko.eckert@amd.com    sp *= 1e6; // in microns
63310152Satgutier@umich.edu
63410234Syasuko.eckert@amd.com    double i, j, del;
63510234Syasuko.eckert@amd.com    repeated_wire.push_back(Component());
63610234Syasuko.eckert@amd.com    for (j = sp; j < 4*sp; j += 100) {
63710234Syasuko.eckert@amd.com        for (i = si; i > 1; i--) {
63810234Syasuko.eckert@amd.com            pow = wire_model(j * 1e-6, i, &del);
63910234Syasuko.eckert@amd.com            if (j == sp && i == si) {
64010234Syasuko.eckert@amd.com                global.delay = del;
64110234Syasuko.eckert@amd.com                global.power = pow;
64210234Syasuko.eckert@amd.com                global.area.h = si;
64310234Syasuko.eckert@amd.com                global.area.w = sp * 1e-6; // m
64410234Syasuko.eckert@amd.com            }
64510152Satgutier@umich.edu//      cout << "Repeater size - "<< i <<
64610152Satgutier@umich.edu//        " Repeater spacing - " << j <<
64710152Satgutier@umich.edu//        " Delay - " << del <<
64810152Satgutier@umich.edu//        " PowerD - " << pow.readOp.dynamic <<
64910152Satgutier@umich.edu//        " PowerL - " << pow.readOp.leakage <<endl;
65010234Syasuko.eckert@amd.com            repeated_wire.back().delay = del;
65110234Syasuko.eckert@amd.com            repeated_wire.back().power.readOp = pow.readOp;
65210234Syasuko.eckert@amd.com            repeated_wire.back().area.w = j * 1e-6; //m
65310234Syasuko.eckert@amd.com            repeated_wire.back().area.h = i;
65410234Syasuko.eckert@amd.com            repeated_wire.push_back(Component());
65510152Satgutier@umich.edu
65610234Syasuko.eckert@amd.com        }
65710152Satgutier@umich.edu    }
65810234Syasuko.eckert@amd.com    repeated_wire.pop_back();
65910234Syasuko.eckert@amd.com    update_fullswing();
66010234Syasuko.eckert@amd.com    Wire *l_wire = new Wire(Low_swing, 0.001/* 1 mm*/, 1);
66110234Syasuko.eckert@amd.com    low_swing.delay = l_wire->delay;
66210234Syasuko.eckert@amd.com    low_swing.power = l_wire->power;
66310234Syasuko.eckert@amd.com    delete l_wire;
66410152Satgutier@umich.edu}
66510152Satgutier@umich.edu
66610152Satgutier@umich.edu
66710152Satgutier@umich.edu
66810234Syasuko.eckert@amd.comvoid Wire::update_fullswing() {
66910152Satgutier@umich.edu
67010234Syasuko.eckert@amd.com    list<Component>::iterator citer;
67110234Syasuko.eckert@amd.com    double del[4];
67210234Syasuko.eckert@amd.com    del[3] = this->global.delay + this->global.delay * .3;
67310234Syasuko.eckert@amd.com    del[2] = global.delay + global.delay * .2;
67410234Syasuko.eckert@amd.com    del[1] = global.delay + global.delay * .1;
67510234Syasuko.eckert@amd.com    del[0] = global.delay + global.delay * .05;
67610234Syasuko.eckert@amd.com    double threshold;
67710234Syasuko.eckert@amd.com    double ncost;
67810234Syasuko.eckert@amd.com    double cost;
67910234Syasuko.eckert@amd.com    int i = 4;
68010234Syasuko.eckert@amd.com    while (i > 0) {
68110234Syasuko.eckert@amd.com        threshold = del[i-1];
68210234Syasuko.eckert@amd.com        cost = BIGNUM;
68310234Syasuko.eckert@amd.com        for (citer = repeated_wire.begin(); citer != repeated_wire.end();
68410234Syasuko.eckert@amd.com             citer++) {
68510234Syasuko.eckert@amd.com            if (citer->delay > threshold) {
68610234Syasuko.eckert@amd.com                citer = repeated_wire.erase(citer);
68710234Syasuko.eckert@amd.com                citer --;
68810234Syasuko.eckert@amd.com            } else {
68910234Syasuko.eckert@amd.com                ncost = citer->power.readOp.dynamic /
69010234Syasuko.eckert@amd.com                    global.power.readOp.dynamic +
69110234Syasuko.eckert@amd.com                    citer->power.readOp.leakage / global.power.readOp.leakage;
69210234Syasuko.eckert@amd.com                if (ncost < cost) {
69310234Syasuko.eckert@amd.com                    cost = ncost;
69410234Syasuko.eckert@amd.com                    if (i == 4) {
69510234Syasuko.eckert@amd.com                        global_30.delay = citer->delay;
69610234Syasuko.eckert@amd.com                        global_30.power = citer->power;
69710234Syasuko.eckert@amd.com                        global_30.area  = citer->area;
69810234Syasuko.eckert@amd.com                    } else if (i == 3) {
69910234Syasuko.eckert@amd.com                        global_20.delay = citer->delay;
70010234Syasuko.eckert@amd.com                        global_20.power = citer->power;
70110234Syasuko.eckert@amd.com                        global_20.area  = citer->area;
70210234Syasuko.eckert@amd.com                    } else if (i == 2) {
70310234Syasuko.eckert@amd.com                        global_10.delay = citer->delay;
70410234Syasuko.eckert@amd.com                        global_10.power = citer->power;
70510234Syasuko.eckert@amd.com                        global_10.area  = citer->area;
70610234Syasuko.eckert@amd.com                    } else if (i == 1) {
70710234Syasuko.eckert@amd.com                        global_5.delay = citer->delay;
70810234Syasuko.eckert@amd.com                        global_5.power = citer->power;
70910234Syasuko.eckert@amd.com                        global_5.area  = citer->area;
71010234Syasuko.eckert@amd.com                    }
71110234Syasuko.eckert@amd.com                }
71210234Syasuko.eckert@amd.com            }
71310152Satgutier@umich.edu        }
71410234Syasuko.eckert@amd.com        i--;
71510152Satgutier@umich.edu    }
71610152Satgutier@umich.edu}
71710152Satgutier@umich.edu
71810152Satgutier@umich.edu
71910152Satgutier@umich.edu
72010234Syasuko.eckert@amd.compowerDef Wire::wire_model (double space, double size, double *delay) {
72110234Syasuko.eckert@amd.com    powerDef ptemp;
72210234Syasuko.eckert@amd.com    double len = 1;
72310234Syasuko.eckert@amd.com    //double min_wire_width = wire_width; //m
72410234Syasuko.eckert@amd.com    double beta = pmos_to_nmos_sz_ratio();
72510234Syasuko.eckert@amd.com    // switching energy
72610234Syasuko.eckert@amd.com    double switching = 0;
72710234Syasuko.eckert@amd.com    // short-circuit energy
72810234Syasuko.eckert@amd.com    double short_ckt = 0;
72910234Syasuko.eckert@amd.com    // time constant
73010234Syasuko.eckert@amd.com    double tc = 0;
73110234Syasuko.eckert@amd.com    // input cap of min sized driver
73210234Syasuko.eckert@amd.com    double input_cap = gate_C (g_tp.min_w_nmos_ +
73310234Syasuko.eckert@amd.com                               min_w_pmos, 0);
73410152Satgutier@umich.edu
73510234Syasuko.eckert@amd.com    // output parasitic capacitance of
73610234Syasuko.eckert@amd.com    // the min. sized driver
73710234Syasuko.eckert@amd.com    double out_cap = drain_C_(min_w_pmos, PCH, 1, 1, g_tp.cell_h_def) +
73810234Syasuko.eckert@amd.com                     drain_C_(g_tp.min_w_nmos_, NCH, 1, 1, g_tp.cell_h_def);
73910234Syasuko.eckert@amd.com    // drive resistance
74010234Syasuko.eckert@amd.com    double out_res = (tr_R_on(g_tp.min_w_nmos_, NCH, 1) +
74110234Syasuko.eckert@amd.com                      tr_R_on(min_w_pmos, PCH, 1)) / 2;
74210234Syasuko.eckert@amd.com    double wr = wire_res(len); //ohm
74310152Satgutier@umich.edu
74410234Syasuko.eckert@amd.com    // wire cap /m
74510234Syasuko.eckert@amd.com    double wc = wire_cap(len);
74610152Satgutier@umich.edu
74710234Syasuko.eckert@amd.com    repeater_spacing = space;
74810234Syasuko.eckert@amd.com    repeater_size = size;
74910152Satgutier@umich.edu
75010234Syasuko.eckert@amd.com    switching = (repeater_size * (input_cap + out_cap) +
75110234Syasuko.eckert@amd.com                 repeater_spacing * (wc / len)) * deviceType->Vdd *
75210234Syasuko.eckert@amd.com        deviceType->Vdd;
75310152Satgutier@umich.edu
75410234Syasuko.eckert@amd.com    tc = out_res * (input_cap + out_cap) +
75510234Syasuko.eckert@amd.com        out_res * wc / len * repeater_spacing / repeater_size +
75610234Syasuko.eckert@amd.com        wr / len * repeater_spacing * out_cap * repeater_size +
75710234Syasuko.eckert@amd.com        0.5 * (wr / len) * (wc / len) * repeater_spacing * repeater_spacing;
75810152Satgutier@umich.edu
75910234Syasuko.eckert@amd.com    *delay = 0.693 * tc * len / repeater_spacing;
76010152Satgutier@umich.edu
76110152Satgutier@umich.edu#define Ishort_ckt 65e-6 /* across all tech Ref:Banerjee et al. {IEEE TED} */
76210234Syasuko.eckert@amd.com    short_ckt = deviceType->Vdd * g_tp.min_w_nmos_ * Ishort_ckt * 1.0986 *
76310234Syasuko.eckert@amd.com                repeater_size * tc;
76410152Satgutier@umich.edu
76510234Syasuko.eckert@amd.com    ptemp.readOp.dynamic = ((len / repeater_spacing) * (switching + short_ckt));
76610234Syasuko.eckert@amd.com    ptemp.readOp.leakage = ((len / repeater_spacing) *
76710234Syasuko.eckert@amd.com                            deviceType->Vdd *
76810234Syasuko.eckert@amd.com                            cmos_Isub_leakage(g_tp.min_w_nmos_ *
76910234Syasuko.eckert@amd.com                                              repeater_size, beta *
77010234Syasuko.eckert@amd.com                                              g_tp.min_w_nmos_ *
77110234Syasuko.eckert@amd.com                                              repeater_size, 1, inv));
77210152Satgutier@umich.edu
77310234Syasuko.eckert@amd.com    ptemp.readOp.gate_leakage = ((len / repeater_spacing) *
77410234Syasuko.eckert@amd.com                                 deviceType->Vdd *
77510234Syasuko.eckert@amd.com                                 cmos_Ig_leakage(g_tp.min_w_nmos_ *
77610234Syasuko.eckert@amd.com                                                 repeater_size, beta *
77710234Syasuko.eckert@amd.com                                                 g_tp.min_w_nmos_ *
77810234Syasuko.eckert@amd.com                                                 repeater_size, 1, inv));
77910152Satgutier@umich.edu
78010234Syasuko.eckert@amd.com    return ptemp;
78110152Satgutier@umich.edu}
78210152Satgutier@umich.edu
78310152Satgutier@umich.eduvoid
78410234Syasuko.eckert@amd.comWire::print_wire() {
78510152Satgutier@umich.edu
78610234Syasuko.eckert@amd.com    cout << "\nWire Properties:\n\n";
78710234Syasuko.eckert@amd.com    cout << "  Delay Optimal\n\tRepeater size - " << global.area.h <<
78810234Syasuko.eckert@amd.com        " \n\tRepeater spacing - " << global.area.w*1e3 << " (mm)"
78910234Syasuko.eckert@amd.com        " \n\tDelay - " << global.delay*1e6 <<  " (ns/mm)"
79010234Syasuko.eckert@amd.com        " \n\tPowerD - " << global.power.readOp.dynamic *1e6 << " (nJ/mm)"
79110234Syasuko.eckert@amd.com        " \n\tPowerL - " << global.power.readOp.leakage << " (mW/mm)"
79210234Syasuko.eckert@amd.com        " \n\tPowerLgate - " << global.power.readOp.gate_leakage <<
79310234Syasuko.eckert@amd.com        " (mW/mm)\n";
79410234Syasuko.eckert@amd.com    cout << "\tWire width - " << wire_width_init*1e6 << " microns\n";
79510234Syasuko.eckert@amd.com    cout << "\tWire spacing - " << wire_spacing_init*1e6 << " microns\n";
79610234Syasuko.eckert@amd.com    cout << endl;
79710152Satgutier@umich.edu
79810234Syasuko.eckert@amd.com    cout << "  5% Overhead\n\tRepeater size - " << global_5.area.h <<
79910234Syasuko.eckert@amd.com        " \n\tRepeater spacing - " << global_5.area.w*1e3 << " (mm)"
80010234Syasuko.eckert@amd.com        " \n\tDelay - " << global_5.delay *1e6 <<  " (ns/mm)"
80110234Syasuko.eckert@amd.com        " \n\tPowerD - " << global_5.power.readOp.dynamic *1e6 << " (nJ/mm)"
80210234Syasuko.eckert@amd.com        " \n\tPowerL - " << global_5.power.readOp.leakage << " (mW/mm)"
80310234Syasuko.eckert@amd.com        " \n\tPowerLgate - " << global_5.power.readOp.gate_leakage <<
80410234Syasuko.eckert@amd.com        " (mW/mm)\n";
80510234Syasuko.eckert@amd.com    cout << "\tWire width - " << wire_width_init*1e6 << " microns\n";
80610234Syasuko.eckert@amd.com    cout << "\tWire spacing - " << wire_spacing_init*1e6 << " microns\n";
80710234Syasuko.eckert@amd.com    cout << endl;
80810234Syasuko.eckert@amd.com    cout << "  10% Overhead\n\tRepeater size - " << global_10.area.h <<
80910234Syasuko.eckert@amd.com        " \n\tRepeater spacing - " << global_10.area.w*1e3 << " (mm)"
81010234Syasuko.eckert@amd.com        " \n\tDelay - " << global_10.delay *1e6 <<  " (ns/mm)"
81110234Syasuko.eckert@amd.com        " \n\tPowerD - " << global_10.power.readOp.dynamic *1e6 << " (nJ/mm)"
81210234Syasuko.eckert@amd.com        " \n\tPowerL - " << global_10.power.readOp.leakage << " (mW/mm)"
81310234Syasuko.eckert@amd.com        " \n\tPowerLgate - " << global_10.power.readOp.gate_leakage <<
81410234Syasuko.eckert@amd.com        " (mW/mm)\n";
81510234Syasuko.eckert@amd.com    cout << "\tWire width - " << wire_width_init*1e6 << " microns\n";
81610234Syasuko.eckert@amd.com    cout << "\tWire spacing - " << wire_spacing_init*1e6 << " microns\n";
81710234Syasuko.eckert@amd.com    cout << endl;
81810234Syasuko.eckert@amd.com    cout << "  20% Overhead\n\tRepeater size - " << global_20.area.h <<
81910234Syasuko.eckert@amd.com        " \n\tRepeater spacing - " << global_20.area.w*1e3 << " (mm)"
82010234Syasuko.eckert@amd.com        " \n\tDelay - " << global_20.delay *1e6 <<  " (ns/mm)"
82110234Syasuko.eckert@amd.com        " \n\tPowerD - " << global_20.power.readOp.dynamic *1e6 << " (nJ/mm)"
82210234Syasuko.eckert@amd.com        " \n\tPowerL - " << global_20.power.readOp.leakage << " (mW/mm)"
82310234Syasuko.eckert@amd.com        " \n\tPowerLgate - " << global_20.power.readOp.gate_leakage <<
82410234Syasuko.eckert@amd.com        " (mW/mm)\n";
82510234Syasuko.eckert@amd.com    cout << "\tWire width - " << wire_width_init*1e6 << " microns\n";
82610234Syasuko.eckert@amd.com    cout << "\tWire spacing - " << wire_spacing_init*1e6 << " microns\n";
82710234Syasuko.eckert@amd.com    cout << endl;
82810234Syasuko.eckert@amd.com    cout << "  30% Overhead\n\tRepeater size - " << global_30.area.h <<
82910234Syasuko.eckert@amd.com        " \n\tRepeater spacing - " << global_30.area.w*1e3 << " (mm)"
83010234Syasuko.eckert@amd.com        " \n\tDelay - " << global_30.delay *1e6 <<  " (ns/mm)"
83110234Syasuko.eckert@amd.com        " \n\tPowerD - " << global_30.power.readOp.dynamic *1e6 << " (nJ/mm)"
83210234Syasuko.eckert@amd.com        " \n\tPowerL - " << global_30.power.readOp.leakage << " (mW/mm)"
83310234Syasuko.eckert@amd.com        " \n\tPowerLgate - " << global_30.power.readOp.gate_leakage <<
83410234Syasuko.eckert@amd.com        " (mW/mm)\n";
83510234Syasuko.eckert@amd.com    cout << "\tWire width - " << wire_width_init*1e6 << " microns\n";
83610234Syasuko.eckert@amd.com    cout << "\tWire spacing - " << wire_spacing_init*1e6 << " microns\n";
83710234Syasuko.eckert@amd.com    cout << endl;
83810234Syasuko.eckert@amd.com    cout << "  Low-swing wire (1 mm) - Note: Unlike repeated wires, \n\t" <<
83910234Syasuko.eckert@amd.com        "delay and power values of low-swing wires do not\n\t" <<
84010234Syasuko.eckert@amd.com        "have a linear relationship with length." <<
84110234Syasuko.eckert@amd.com        " \n\tdelay - " << low_swing.delay *1e9 <<  " (ns)"
84210234Syasuko.eckert@amd.com        " \n\tpowerD - " << low_swing.power.readOp.dynamic *1e9 << " (nJ)"
84310234Syasuko.eckert@amd.com        " \n\tPowerL - " << low_swing.power.readOp.leakage << " (mW)"
84410234Syasuko.eckert@amd.com        " \n\tPowerLgate - " << low_swing.power.readOp.gate_leakage <<
84510234Syasuko.eckert@amd.com        " (mW)\n";
84610234Syasuko.eckert@amd.com    cout << "\tWire width - " << wire_width_init * 2 /* differential */ <<
84710234Syasuko.eckert@amd.com        " microns\n";
84810234Syasuko.eckert@amd.com    cout << "\tWire spacing - " << wire_spacing_init * 2 /* differential */ <<
84910234Syasuko.eckert@amd.com        " microns\n";
85010234Syasuko.eckert@amd.com    cout << endl;
85110234Syasuko.eckert@amd.com    cout << endl;
85210152Satgutier@umich.edu
85310152Satgutier@umich.edu}
85410152Satgutier@umich.edu
855