1/***************************************************************************** 2 * McPAT/CACTI 3 * SOFTWARE LICENSE AGREEMENT 4 * Copyright 2012 Hewlett-Packard Development Company, L.P. 5 * Copyright (c) 2010-2013 Advanced Micro Devices, Inc. 6 * All Rights Reserved 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions are 10 * met: redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer; 12 * redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution; 15 * neither the name of the copyright holders nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 * 31 ***************************************************************************/ 32 33 34 35 36#include <cassert> 37#include <cmath> 38#include <iostream> 39 40#include "bank.h" 41#include "component.h" 42#include "decoder.h" 43 44using namespace std; 45 46 47 48Component::Component() 49 : area(), power(), rt_power(), delay(0) { 50} 51 52 53 54Component::~Component() { 55} 56 57 58 59double Component::compute_diffusion_width(int num_stacked_in, int num_folded_tr) { 60 double w_poly = g_ip->F_sz_um; 61 double spacing_poly_to_poly = g_tp.w_poly_contact + 2 * g_tp.spacing_poly_to_contact; 62 double total_diff_w = 2 * spacing_poly_to_poly + // for both source and drain 63 num_stacked_in * w_poly + 64 (num_stacked_in - 1) * g_tp.spacing_poly_to_poly; 65 66 if (num_folded_tr > 1) { 67 total_diff_w += (num_folded_tr - 2) * 2 * spacing_poly_to_poly + 68 (num_folded_tr - 1) * num_stacked_in * w_poly + 69 (num_folded_tr - 1) * (num_stacked_in - 1) * g_tp.spacing_poly_to_poly; 70 } 71 72 return total_diff_w; 73} 74 75 76 77double Component::compute_gate_area( 78 int gate_type, 79 int num_inputs, 80 double w_pmos, 81 double w_nmos, 82 double h_gate) { 83 if (w_pmos <= 0.0 || w_nmos <= 0.0) { 84 return 0.0; 85 } 86 87 double w_folded_pmos, w_folded_nmos; 88 int num_folded_pmos, num_folded_nmos; 89 double total_ndiff_w, total_pdiff_w; 90 Area gate; 91 92 double h_tr_region = h_gate - 2 * g_tp.HPOWERRAIL; 93 double ratio_p_to_n = w_pmos / (w_pmos + w_nmos); 94 95 if (ratio_p_to_n >= 1 || ratio_p_to_n <= 0) { 96 return 0.0; 97 } 98 99 w_folded_pmos = (h_tr_region - g_tp.MIN_GAP_BET_P_AND_N_DIFFS) * ratio_p_to_n; 100 w_folded_nmos = (h_tr_region - g_tp.MIN_GAP_BET_P_AND_N_DIFFS) * (1 - ratio_p_to_n); 101 assert(w_folded_pmos > 0); 102 103 num_folded_pmos = (int) (ceil(w_pmos / w_folded_pmos)); 104 num_folded_nmos = (int) (ceil(w_nmos / w_folded_nmos)); 105 106 switch (gate_type) { 107 case INV: 108 total_ndiff_w = compute_diffusion_width(1, num_folded_nmos); 109 total_pdiff_w = compute_diffusion_width(1, num_folded_pmos); 110 break; 111 112 case NOR: 113 total_ndiff_w = compute_diffusion_width(1, num_inputs * num_folded_nmos); 114 total_pdiff_w = compute_diffusion_width(num_inputs, num_folded_pmos); 115 break; 116 117 case NAND: 118 total_ndiff_w = compute_diffusion_width(num_inputs, num_folded_nmos); 119 total_pdiff_w = compute_diffusion_width(1, num_inputs * num_folded_pmos); 120 break; 121 default: 122 cout << "Unknown gate type: " << gate_type << endl; 123 exit(1); 124 } 125 126 gate.w = MAX(total_ndiff_w, total_pdiff_w); 127 128 if (w_folded_nmos > w_nmos) { 129 //means that the height of the gate can 130 //be made smaller than the input height specified, so calculate the height of the gate. 131 gate.h = w_nmos + w_pmos + g_tp.MIN_GAP_BET_P_AND_N_DIFFS + 2 * g_tp.HPOWERRAIL; 132 } else { 133 gate.h = h_gate; 134 } 135 return gate.get_area(); 136} 137 138 139 140double Component::compute_tr_width_after_folding( 141 double input_width, 142 double threshold_folding_width) { 143 //This is actually the width of the cell not the width of a device. 144 //The width of a cell and the width of a device is orthogonal. 145 if (input_width <= 0) { 146 return 0; 147 } 148 149 int num_folded_tr = (int) (ceil(input_width / threshold_folding_width)); 150 double spacing_poly_to_poly = g_tp.w_poly_contact + 2 * g_tp.spacing_poly_to_contact; 151 double width_poly = g_ip->F_sz_um; 152 double total_diff_width = num_folded_tr * width_poly + (num_folded_tr + 1) * spacing_poly_to_poly; 153 154 return total_diff_width; 155} 156 157 158 159double Component::height_sense_amplifier(double pitch_sense_amp) { 160 // compute the height occupied by all PMOS transistors 161 double h_pmos_tr = compute_tr_width_after_folding(g_tp.w_sense_p, pitch_sense_amp) * 2 + 162 compute_tr_width_after_folding(g_tp.w_iso, pitch_sense_amp) + 163 2 * g_tp.MIN_GAP_BET_SAME_TYPE_DIFFS; 164 165 // compute the height occupied by all NMOS transistors 166 double h_nmos_tr = compute_tr_width_after_folding(g_tp.w_sense_n, pitch_sense_amp) * 2 + 167 compute_tr_width_after_folding(g_tp.w_sense_en, pitch_sense_amp) + 168 2 * g_tp.MIN_GAP_BET_SAME_TYPE_DIFFS; 169 170 // compute total height by considering gap between the p and n diffusion areas 171 return h_pmos_tr + h_nmos_tr + g_tp.MIN_GAP_BET_P_AND_N_DIFFS; 172} 173 174 175 176int Component::logical_effort( 177 int num_gates_min, 178 double g, 179 double F, 180 double * w_n, 181 double * w_p, 182 double C_load, 183 double p_to_n_sz_ratio, 184 bool is_dram_, 185 bool is_wl_tr_, 186 double max_w_nmos) { 187 int num_gates = (int) (log(F) / log(fopt)); 188 189 // check if num_gates is odd. if so, add 1 to make it even 190 num_gates += (num_gates % 2) ? 1 : 0; 191 num_gates = MAX(num_gates, num_gates_min); 192 193 // recalculate the effective fanout of each stage 194 double f = pow(F, 1.0 / num_gates); 195 int i = num_gates - 1; 196 double C_in = C_load / f; 197 w_n[i] = (1.0 / (1.0 + p_to_n_sz_ratio)) * C_in / gate_C(1, 0, is_dram_, false, is_wl_tr_); 198 w_n[i] = MAX(w_n[i], g_tp.min_w_nmos_); 199 w_p[i] = p_to_n_sz_ratio * w_n[i]; 200 201 if (w_n[i] > max_w_nmos) { 202 double C_ld = gate_C((1 + p_to_n_sz_ratio) * max_w_nmos, 0, is_dram_, false, is_wl_tr_); 203 F = g * C_ld / gate_C(w_n[0] + w_p[0], 0, is_dram_, false, is_wl_tr_); 204 num_gates = (int) (log(F) / log(fopt)) + 1; 205 num_gates += (num_gates % 2) ? 1 : 0; 206 num_gates = MAX(num_gates, num_gates_min); 207 f = pow(F, 1.0 / (num_gates - 1)); 208 i = num_gates - 1; 209 w_n[i] = max_w_nmos; 210 w_p[i] = p_to_n_sz_ratio * w_n[i]; 211 } 212 213 for (i = num_gates - 2; i >= 1; i--) { 214 w_n[i] = MAX(w_n[i+1] / f, g_tp.min_w_nmos_); 215 w_p[i] = p_to_n_sz_ratio * w_n[i]; 216 } 217 218 assert(num_gates <= MAX_NUMBER_GATES_STAGE); 219 return num_gates; 220} 221 222