1/* Copyright (c) 2012 Massachusetts Institute of Technology 2 * 3 * Permission is hereby granted, free of charge, to any person obtaining a copy 4 * of this software and associated documentation files (the "Software"), to deal 5 * in the Software without restriction, including without limitation the rights 6 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 * copies of the Software, and to permit persons to whom the Software is 8 * furnished to do so, subject to the following conditions: 9 * 10 * The above copyright notice and this permission notice shall be included in 11 * all copies or substantial portions of the Software. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 * THE SOFTWARE. 20 */ 21 22#include "tech/TechModel.h" 23 24#include <cmath> 25 26#include "model/std_cells/StdCellLib.h" 27 28namespace DSENT 29{ 30 TechModel::TechModel() 31 : m_std_cell_lib_(NULL), m_available_wire_layers_(NULL) 32 {} 33 34 TechModel::~TechModel() 35 {} 36 37 const String& TechModel::get(const String &key_) const 38 { 39 return params.at(key_); 40 } 41 42 void TechModel::setStdCellLib(const StdCellLib* std_cell_lib_) 43 { 44 m_std_cell_lib_ = std_cell_lib_; 45 return; 46 } 47 48 const StdCellLib* TechModel::getStdCellLib() const 49 { 50 return m_std_cell_lib_; 51 } 52 53 TechModel* TechModel::clone() const 54 { 55 return new TechModel(*this); 56 } 57 58 void TechModel::readFile(const String& filename_) 59 { 60 // Read the main technology file 61 LibUtil::readFile(filename_, params); 62 63 // Search for "INCLUDE" to include more technology files 64 for (const auto &it : params) 65 { 66 const String& key = it.first; 67 if(key.compare(0, 8, "INCLUDE_") == 0) 68 { 69 const String& include_filename = it.second; 70 LibUtil::readFile(include_filename, params); 71 } 72 } 73 74 // Set the available wire layers 75 const vector<String>& available_wire_layer_vector = get("Wire->AvailableLayers").split("[,]"); 76 m_available_wire_layers_ = new std::set<String>; 77 for(unsigned int i = 0; i < available_wire_layer_vector.size(); ++i) 78 { 79 m_available_wire_layers_->insert(available_wire_layer_vector[i]); 80 } 81 } 82 83 //------------------------------------------------------------------------- 84 // Transistor Related Functions 85 //------------------------------------------------------------------------- 86 //Returns the leakage current of NMOS transistors, given the transistor stakcing, transistor widths, and input combination 87 double TechModel::calculateNmosLeakageCurrent(unsigned int num_stacks_, double uni_stacked_mos_width_, unsigned int input_vector_) const 88 { 89 vector<double> stacked_mos_widths_(num_stacks_, uni_stacked_mos_width_); 90 return calculateNmosLeakageCurrent(num_stacks_, stacked_mos_widths_, input_vector_); 91 } 92 93 //Returns the leakage current of NMOS transistors, given the transistor stakcing, transistor widths, and input combination 94 double TechModel::calculateNmosLeakageCurrent(unsigned int num_stacks_, const vector<double>& stacked_mos_widths_, unsigned int input_vector_) const 95 { 96 // Get technology parameters 97 double vdd = get("Vdd"); 98 double temp = get("Temperature"); 99 double char_temp = get("Nmos->CharacterizedTemperature"); 100 double min_off_current = get("Nmos->MinOffCurrent"); 101 double off_current = get("Nmos->OffCurrent"); 102 double subthreshold_swing = get("Nmos->SubthresholdSwing"); 103 double dibl = get("Nmos->DIBL"); 104 double temp_swing = get("Nmos->SubthresholdTempSwing"); 105 106 // Map dibl to a swing value for easier calculation 107 double dibl_swing = subthreshold_swing / dibl; 108 109 //Calculate the leakage current factor 110 double leakage_current_factor = calculateLeakageCurrentFactor(num_stacks_, stacked_mos_widths_, input_vector_, vdd, subthreshold_swing, dibl_swing); 111 112 // Calcualte actual leakage current at characterized temperature 113 double leakage_current_char_tmp = stacked_mos_widths_[0] * off_current * std::pow(10.0, leakage_current_factor); 114 leakage_current_char_tmp = std::max(min_off_current, leakage_current_char_tmp); 115 116 // Calculate actual leakage current at temp 117 double leakage_current = leakage_current_char_tmp * std::pow(10.0, (temp - char_temp) / temp_swing); 118 119 return leakage_current; 120 } 121 122 double TechModel::calculatePmosLeakageCurrent(unsigned int num_stacks_, double uni_stacked_mos_width_, unsigned int input_vector_) const 123 { 124 vector<double> stacked_mos_widths_(num_stacks_, uni_stacked_mos_width_); 125 return calculatePmosLeakageCurrent(num_stacks_, stacked_mos_widths_, input_vector_); 126 } 127 128 //Returns the leakage current of PMOS transistors, given the transistor stakcing, transistor widths, and input combination 129 double TechModel::calculatePmosLeakageCurrent(unsigned int num_stacks_, const vector<double>& stacked_mos_widths_, unsigned int input_vector_) const 130 { 131 // Get technology parameters 132 double vdd = get("Vdd"); 133 double temp = get("Temperature"); 134 double char_temp = get("Pmos->CharacterizedTemperature"); 135 double min_off_current = get("Pmos->MinOffCurrent"); 136 double off_current = get("Pmos->OffCurrent"); 137 double dibl = get("Pmos->DIBL"); 138 double subthreshold_swing = get("Pmos->SubthresholdSwing"); 139 double temp_swing = get("Nmos->SubthresholdTempSwing"); 140 141 // Map dibl to a swing value for easier calculation 142 double dibl_swing = subthreshold_swing / dibl; 143 144 //Calculate the leakage current factor 145 double leakage_current_factor = calculateLeakageCurrentFactor(num_stacks_, stacked_mos_widths_, input_vector_, vdd, subthreshold_swing, dibl_swing); 146 147 // Calcualte actual leakage current at characterized temperature 148 double leakage_current_char_tmp = stacked_mos_widths_[0] * off_current * std::pow(10.0, leakage_current_factor); 149 leakage_current_char_tmp = std::max(min_off_current, leakage_current_char_tmp); 150 151 // Calculate actual leakage current at temp 152 double leakage_current = leakage_current_char_tmp * std::pow(10.0, (temp - char_temp) / temp_swing); 153 154 return leakage_current; 155 } 156 157 //Returns the leakage current, given the transistor stakcing, transistor widths, input combination, 158 //and technology information (vdd, subthreshold swing, subthreshold dibl swing) 159 double TechModel::calculateLeakageCurrentFactor(unsigned int num_stacks_, const vector<double>& stacked_mos_widths_, unsigned int input_vector_, double vdd_, double subthreshold_swing_, double dibl_swing_) const 160 { 161 // check everything is valid 162 ASSERT(num_stacks_ >= 1, "[Error] Number of stacks must be >= 1!"); 163 ASSERT(stacked_mos_widths_.size() == num_stacks_, "[Error] Mismatch in number of stacks and the widths specified!"); 164 165 //Use short name in this method 166 const double s1 = subthreshold_swing_; 167 const double s2 = dibl_swing_; 168 169 // Decode input combinations from input_vector_ 170 std::vector<double> vs(num_stacks_, 0.0); 171 for(int i = 0; i < (int)num_stacks_; ++i) 172 { 173 double current_input = (double(input_vector_ & 0x1))*vdd_; 174 vs[i] = (current_input); 175 input_vector_ >>= 1; 176 } 177 // If the widths pointer is NULL, width is set to 1 by default 178 vector<double> ws = stacked_mos_widths_; 179 180 //Solve voltages at internal nodes of stacked transistors 181 // v[0] = 0 182 // v[num_stacks_] = vdd_ 183 // v[i] = (1.0/(2*s1 + s2))*((s1 + s2)*v[i - 1] + s1*v[i + 1] 184 // + s2*(vs[i + 1] - vs[i]) + s1*s2*log10(ws[i + 1]/ws[i])) 185 //Use tri-matrix solver to solve the above linear system 186 187 double A = -(s1 + s2); 188 double B = 2*s1 + s2; 189 double C = -s1; 190 std::vector<double> a(num_stacks_ - 1, 0); 191 std::vector<double> b(num_stacks_ - 1, 0); 192 std::vector<double> c(num_stacks_ - 1, 0); 193 std::vector<double> d(num_stacks_ - 1, 0); 194 std::vector<double> v(num_stacks_ + 1, 0); 195 unsigned int eff_num_stacks = num_stacks_; 196 bool is_found_valid_v = false; 197 do 198 { 199 //Set boundary condition 200 v[0] = 0; 201 v[eff_num_stacks] = vdd_; 202 203 //If the effective number of stacks is 1, no matrix needs to be solved 204 if(eff_num_stacks == 1) 205 { 206 break; 207 } 208 209 //---------------------------------------------------------------------- 210 //Setup the tri-matrix 211 //---------------------------------------------------------------------- 212 for(int i = 0; i < (int)eff_num_stacks-2; ++i) 213 { 214 a[i + 1] = A; 215 c[i] = C; 216 } 217 for(int i = 0; i < (int)eff_num_stacks-1; ++i) 218 { 219 b[i] = B; 220 d[i] = s2*(vs[i + 1] - vs[i]) + s1*s2*std::log10(ws[i + 1]/ws[i]); 221 if(i == ((int)eff_num_stacks - 2)) 222 { 223 d[i] -= C*vdd_; 224 } 225 } 226 //---------------------------------------------------------------------- 227 228 //---------------------------------------------------------------------- 229 //Solve the tri-matrix 230 //---------------------------------------------------------------------- 231 for(int i = 1; i < (int)eff_num_stacks-1; ++i) 232 { 233 double m = a[i]/b[i - 1]; 234 b[i] -= m*c[i - 1]; 235 d[i] -= m*d[i - 1]; 236 } 237 238 v[eff_num_stacks - 1] = d[eff_num_stacks - 2]/b[eff_num_stacks - 2]; 239 for(int i = eff_num_stacks - 3; i >= 0; --i) 240 { 241 v[i + 1] = (d[i] - c[i]*v[i + 2])/b[i]; 242 } 243 //---------------------------------------------------------------------- 244 245 //Check if the internal voltages are in increasing order 246 is_found_valid_v = true; 247 for(int i = 1; i <= (int)eff_num_stacks; ++i) 248 { 249 //If the ith internal voltage is not in increasing order 250 //(i-1)th transistor is in triode region 251 //Remove the transistors in triode region as it does not exist 252 if(v[i] < v[i - 1]) 253 { 254 is_found_valid_v = false; 255 eff_num_stacks--; 256 vs.erase(vs.begin() + i - 1); 257 ws.erase(ws.begin() + i - 1); 258 break; 259 } 260 } 261 } while(!is_found_valid_v); 262 263 //Calculate the leakage current of the bottom transistor (first not in triode region) 264 double vgs = vs[0] - v[0]; 265 double vds = v[1] - v[0]; 266 double leakage_current_factor = vgs/s1 + (vds - vdd_)/s2; 267 //TODO - Check if the leakage current calculate for other transistors is identical 268 269 return leakage_current_factor; 270 } 271 //------------------------------------------------------------------------- 272 273 //------------------------------------------------------------------------- 274 // Wire Related Functions 275 //------------------------------------------------------------------------- 276 bool TechModel::isWireLayerExist(const String& layer_name_) const 277 { 278 std::set<String>::const_iterator it; 279 it = m_available_wire_layers_->find(layer_name_); 280 return (it != m_available_wire_layers_->end()); 281 } 282 283 const std::set<String>* TechModel::getAvailableWireLayers() const 284 { 285 return m_available_wire_layers_; 286 } 287 288 double TechModel::calculateWireCapacitance(const String& layer_name_, double width_, double spacing_, double length_) const 289 { 290 // Get technology parameter 291 double min_width = get("Wire->" + layer_name_ + "->MinWidth").toDouble(); 292 double min_spacing = get("Wire->" + layer_name_ + "->MinSpacing").toDouble(); 293 double metal_thickness = get("Wire->" + layer_name_ + "->MetalThickness").toDouble(); 294 double dielec_thickness = get("Wire->" + layer_name_ + "->DielectricThickness").toDouble(); 295 double dielec_const = get("Wire->" + layer_name_ + "->DielectricConstant").toDouble(); 296 297 ASSERT(width_ >= min_width, "[Error] Wire width must be >= " + (String) min_width + "!"); 298 ASSERT(spacing_ >= min_spacing, "[Error] Wire spacing must be >= " + (String) min_spacing + "!"); 299 ASSERT(length_ >= 0, "[Error] Wire length must be >= 0!"); 300 301 double A, B, C; 302 // Calculate ground capacitance 303 A = width_ / dielec_thickness; 304 B = 2.04*std::pow((spacing_ / (spacing_ + 0.54 * dielec_thickness)), 1.77); 305 C = std::pow((metal_thickness / (metal_thickness + 4.53 * dielec_thickness)), 0.07); 306 double unit_gnd_cap = dielec_const * 8.85e-12 * (A + B * C); 307 308 A = 1.14 * (metal_thickness / spacing_) * std::exp(-4.0 * spacing_ / (spacing_ + 8.01 * dielec_thickness)); 309 B = 2.37 * std::pow((width_ / (width_ + 0.31 * spacing_)), 0.28); 310 C = std::pow((dielec_thickness / (dielec_thickness + 8.96 * spacing_)), 0.76) * 311 std::exp(-2.0 * spacing_ / (spacing_ + 6.0 * dielec_thickness)); 312 double unit_coupling_cap = dielec_const * 8.85e-12 * (A + B * C); 313 314 double total_cap = 2 * (unit_gnd_cap + unit_coupling_cap) * length_; 315 return total_cap; 316 } 317 318 double TechModel::calculateWireResistance(const String& layer_name_, double width_, double length_) const 319 { 320 // Get technology parameter 321 double min_width = get("Wire->" + layer_name_ + "->MinWidth"); 322 //double barrier_thickness = get("Wire->" + layer_name_ + "->BarrierThickness"); 323 double resistivity = get("Wire->" + layer_name_ + "->Resistivity"); 324 double metal_thickness = get("Wire->" + layer_name_ + "->MetalThickness"); 325 326 ASSERT(width_ >= min_width, "[Error] Wire width must be >= " + (String) min_width + "!"); 327 ASSERT(length_ >= 0, "[Error] Wire length must be >= 0!"); 328 329 // Calculate Rho 330 // double rho = 2.202e-8 + (1.030e-15 / (width_ - 2.0 * barrier_thickness)); 331 332 double unit_res = resistivity / (width_ * metal_thickness); 333 //double unit_res = rho / ((width_ - 2.0 * barrier_thickness) * (metal_thickness - barrier_thickness)); 334 335 double total_res = unit_res * length_; 336 return total_res; 337 } 338 //------------------------------------------------------------------------- 339 340 TechModel::TechModel(const TechModel& tech_model_) 341 : m_std_cell_lib_(tech_model_.m_std_cell_lib_), 342 params(tech_model_.params) 343 {} 344} // namespace DSENT 345