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