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