1#include "model/std_cells/CellMacros.h" 2 3#include <cmath> 4#include <vector> 5 6#include "model/std_cells/StdCell.h" 7#include "model/timing_graph/ElectricalNet.h" 8#include "model/timing_graph/ElectricalDriver.h" 9#include "model/timing_graph/ElectricalLoad.h" 10 11namespace DSENT 12{ 13 //------------------------------------------------------------------------- 14 // NOR2 Macro (TODO: Generalize to N-input macro once leakage calc is done) 15 //------------------------------------------------------------------------- 16 void CellMacros::addNor2(StdCell* cell_, const String& name_, 17 bool sizable_, bool a1_to_zn_path_, bool a2_to_zn_path_, 18 const String& a1_net_, const String& a2_net_, const String& zn_net_) 19 { 20 //Create electrical timing model for the nand 21 // Construct loads and drivers 22 cell_->createLoad(name_ + "_CgA1"); 23 cell_->createLoad(name_ + "_CgA2"); 24 cell_->createLoad(name_ + "_CdZN"); 25 cell_->createDriver(name_ + "_RonZN", sizable_); 26 27 //Get references to loads and drivers 28 ElectricalLoad* gate_a1_load = cell_->getLoad(name_ + "_CgA1"); 29 ElectricalLoad* gate_a2_load = cell_->getLoad(name_ + "_CgA2"); 30 ElectricalLoad* drain_load = cell_->getLoad(name_ + "_CdZN"); 31 ElectricalDriver* zn_drive = cell_->getDriver(name_ + "_RonZN"); 32 ElectricalNet* a1_net = cell_->getNet(a1_net_); 33 ElectricalNet* a2_net = cell_->getNet(a2_net_); 34 ElectricalNet* zn_net = cell_->getNet(zn_net_); 35 36 //Add loads and drivers to the specified nets 37 a1_net->addDownstreamNode(gate_a1_load); 38 a2_net->addDownstreamNode(gate_a2_load); 39 zn_net->addDownstreamNode(drain_load); 40 if (a1_to_zn_path_) gate_a1_load->addDownstreamNode(zn_drive); 41 if (a2_to_zn_path_) gate_a2_load->addDownstreamNode(zn_drive); 42 zn_drive->addDownstreamNode(zn_net); 43 44 return; 45 } 46 47 void CellMacros::updateNor2(StdCell* cell_, const String& name_, double normalized_size_) 48 { 49 ASSERT(normalized_size_ >= 0.0, "[Error] " + cell_->getInstanceName() + 50 " -> Cannot update a macro with a negative normalized size!"); 51 52 //Grab pointer to tech model 53 const TechModel* tech = cell_->getTechModel(); 54 55 // Get technology parameters 56 double vdd = tech->get("Vdd"); 57 double gate_cap = tech->get("Gate->CapPerWidth"); 58 double drain_cap = tech->get("Drain->CapPerWidth"); 59 double nmos_eff_res = tech->get("Nmos->EffResWidth"); 60 double pmos_eff_res = tech->get("Pmos->EffResWidth"); 61 double pmos_eff_res_stack_ratio = tech->get("Pmos->EffResStackRatio"); 62 double gate_pitch_contacted = tech->get("Gate->PitchContacted"); 63 double metal1_wire_min_width = tech->get("Wire->Metal1->MinWidth"); 64 65 //Calculate number of folds and gate pitches needed 66 unsigned int folds = (normalized_size_ < 1.0) ? 1 : (unsigned int)ceil(normalized_size_); 67 cell_->getGenProperties()->set(name_ + "_GatePitches", 2 * folds); 68 69 //Calculate widths, making sure they are above the minimum width 70 double nmos_width = std::max(calculateNmosWidth(cell_, 1, 2, 1) * normalized_size_ / folds, (double) tech->get("Gate->MinWidth")); 71 double pmos_width = std::max(calculatePmosWidth(cell_, 1, 2, 2) * normalized_size_ / folds, (double) tech->get("Gate->MinWidth")); 72 73 //Calculate leakage power for each given input state 74 double leakage_power_00 = vdd * folds * 2 * tech->calculateNmosLeakageCurrent(1, nmos_width, 0x0); 75 double leakage_power_01 = vdd * folds * tech->calculatePmosLeakageCurrent(2, pmos_width, ~0x1); 76 double leakage_power_10 = vdd * folds * tech->calculatePmosLeakageCurrent(2, pmos_width, ~0x2); 77 double leakage_power_11 = vdd * folds * tech->calculatePmosLeakageCurrent(2, pmos_width, ~0x3); 78 cell_->getGenProperties()->set(name_ + "_LeakagePower_00", leakage_power_00); 79 cell_->getGenProperties()->set(name_ + "_LeakagePower_01", leakage_power_01); 80 cell_->getGenProperties()->set(name_ + "_LeakagePower_10", leakage_power_10); 81 cell_->getGenProperties()->set(name_ + "_LeakagePower_11", leakage_power_11); 82 83 //Calculate R_on and capacitances 84 double pmos_stack2_balance = 1.0 + pmos_eff_res_stack_ratio; 85 double c_g = (nmos_width + pmos_width) * gate_cap * folds; 86 double c_d = (2 * pmos_width + 2 * nmos_width) * drain_cap * folds; 87 double r_on = (nmos_eff_res / nmos_width + pmos_stack2_balance * pmos_eff_res / pmos_width) / (folds * 2.0); 88 89 // Estimate the wire cap and add them all at the output 90 double cell_height = cell_->getTotalHeight(); 91 double wire_width = metal1_wire_min_width; 92 double wire_spacing = gate_pitch_contacted - metal1_wire_min_width; 93 double wire_length = 2.0 * folds * cell_height; 94 double wire_cap = tech->calculateWireCapacitance("Metal1", wire_width, wire_spacing, wire_length); 95 96 // Construct equivalent load and drive strength 97 cell_->getLoad(name_ + "_CgA1")->setLoadCap(c_g); 98 cell_->getLoad(name_ + "_CgA2")->setLoadCap(c_g); 99 cell_->getLoad(name_ + "_CdZN")->setLoadCap(c_d + wire_cap); 100 cell_->getDriver(name_ + "_RonZN")->setOutputRes(r_on); 101 102 // Calculate flip energies 103 double zn_flip_energy = 0.5 * (c_d + wire_cap) * vdd * vdd; 104 double a1_flip_energy = 0.5 * c_g * vdd * vdd; 105 double a2_flip_energy = 0.5 * c_g * vdd * vdd; 106 cell_->getGenProperties()->set(name_ + "_ZN_Flip", zn_flip_energy); 107 cell_->getGenProperties()->set(name_ + "_A1_Flip", a1_flip_energy); 108 cell_->getGenProperties()->set(name_ + "_A2_Flip", a2_flip_energy); 109 } 110 //------------------------------------------------------------------------- 111 112 //------------------------------------------------------------------------- 113 // NAND2 Macro (TODO: Generalize to N-input macro once leakage calc is done) 114 //------------------------------------------------------------------------- 115 //Adds a NAND2 to the standard cell, normalized to some size 116 void CellMacros::addNand2(StdCell* cell_, const String& name_, 117 bool sizable_, bool a1_to_zn_path_, bool a2_to_zn_path_, 118 const String& a1_net_, const String& a2_net_, const String& zn_net_) 119 { 120 //Create electrical timing model for the nor 121 // Construct loads and drivers 122 cell_->createLoad(name_ + "_CgA1"); 123 cell_->createLoad(name_ + "_CgA2"); 124 cell_->createLoad(name_ + "_CdZN"); 125 cell_->createDriver(name_ + "_RonZN", sizable_); 126 127 //Get references to loads and drivers 128 ElectricalLoad* gate_a1_load = cell_->getLoad(name_ + "_CgA1"); 129 ElectricalLoad* gate_a2_load = cell_->getLoad(name_ + "_CgA2"); 130 ElectricalLoad* drain_load = cell_->getLoad(name_ + "_CdZN"); 131 ElectricalDriver* zn_drive = cell_->getDriver(name_ + "_RonZN"); 132 ElectricalNet* a1_net = cell_->getNet(a1_net_); 133 ElectricalNet* a2_net = cell_->getNet(a2_net_); 134 ElectricalNet* zn_net = cell_->getNet(zn_net_); 135 136 a1_net->addDownstreamNode(gate_a1_load); 137 a2_net->addDownstreamNode(gate_a2_load); 138 zn_net->addDownstreamNode(drain_load); 139 if (a1_to_zn_path_) gate_a1_load->addDownstreamNode(zn_drive); 140 if (a2_to_zn_path_) gate_a2_load->addDownstreamNode(zn_drive); 141 zn_drive->addDownstreamNode(zn_net); 142 143 return; 144 } 145 146 //Updates a NAND2 to to the standard cell, normalized to some size 147 void CellMacros::updateNand2(StdCell* cell_, const String& name_, double normalized_size_) 148 { 149 ASSERT(normalized_size_ >= 0.0, "[Error] " + cell_->getInstanceName() + 150 " -> Cannot update a macro with a negative normalized size!"); 151 152 //Grab pointer to tech model 153 const TechModel* tech = cell_->getTechModel(); 154 155 // Get technology parameters 156 double vdd = tech->get("Vdd"); 157 double gate_cap = tech->get("Gate->CapPerWidth"); 158 double drain_cap = tech->get("Drain->CapPerWidth"); 159 double nmos_eff_res = tech->get("Nmos->EffResWidth"); 160 double pmos_eff_res = tech->get("Pmos->EffResWidth"); 161 double nmos_eff_res_stack_ratio = tech->get("Nmos->EffResStackRatio"); 162 double gate_pitch_contacted = tech->get("Gate->PitchContacted"); 163 double metal1_wire_min_width = tech->get("Wire->Metal1->MinWidth"); 164 165 //Calculate number of folds needed 166 unsigned int folds = (normalized_size_ < 1.0) ? 1 : (unsigned int)ceil(normalized_size_); 167 cell_->getGenProperties()->set(name_ + "_GatePitches", 2 * folds); 168 169 //Calculate widths, making sure they are above the minimum width 170 double nmos_width = std::max(calculateNmosWidth(cell_, 2, 1, 2) * normalized_size_ / folds, (double) tech->get("Gate->MinWidth")); 171 double pmos_width = std::max(calculatePmosWidth(cell_, 2, 1, 1) * normalized_size_ / folds, (double) tech->get("Gate->MinWidth")); 172 173 // Leakage power calculation 174 double leakage_power_00 = vdd * folds * tech->calculateNmosLeakageCurrent(2, nmos_width, 0x0); 175 double leakage_power_01 = vdd * folds * tech->calculateNmosLeakageCurrent(2, nmos_width, 0x1); 176 double leakage_power_10 = vdd * folds * tech->calculateNmosLeakageCurrent(2, nmos_width, 0x2); 177 double leakage_power_11 = vdd * folds * 2 * tech->calculatePmosLeakageCurrent(1, pmos_width, ~0x3); 178 cell_->getGenProperties()->set(name_ + "_LeakagePower_00", leakage_power_00); 179 cell_->getGenProperties()->set(name_ + "_LeakagePower_01", leakage_power_01); 180 cell_->getGenProperties()->set(name_ + "_LeakagePower_10", leakage_power_10); 181 cell_->getGenProperties()->set(name_ + "_LeakagePower_11", leakage_power_11); 182 183 // Get input parameters 184 double nmos_stack2_balance = 1.0 + nmos_eff_res_stack_ratio; 185 186 //Calculate caps 187 double c_g = (nmos_width + pmos_width) * gate_cap * folds; 188 double c_d = (2 * pmos_width + 2 * nmos_width) * drain_cap * folds; 189 double r_on = (nmos_stack2_balance * nmos_eff_res / nmos_width + pmos_eff_res / pmos_width) / (folds * 2.0); 190 191 // Estimate the wire cap and add them all at the output 192 double cell_height = cell_->getTotalHeight(); 193 double wire_width = metal1_wire_min_width; 194 double wire_spacing = gate_pitch_contacted - metal1_wire_min_width; 195 double wire_length = 2.0 * folds * cell_height; 196 double wire_cap = tech->calculateWireCapacitance("Metal1", wire_width, wire_spacing, wire_length); 197 198 // Construct equivalent load and drive strength 199 cell_->getLoad(name_ + "_CgA1")->setLoadCap(c_g); 200 cell_->getLoad(name_ + "_CgA2")->setLoadCap(c_g); 201 cell_->getLoad(name_ + "_CdZN")->setLoadCap(c_d + wire_cap); 202 cell_->getDriver(name_ + "_RonZN")->setOutputRes(r_on); 203 204 // Calculate flip energies 205 double zn_flip_energy = 0.5 * (c_d + wire_cap) * vdd * vdd; 206 double a1_flip_energy = 0.5 * c_g * vdd * vdd; 207 double a2_flip_energy = 0.5 * c_g * vdd * vdd; 208 cell_->getGenProperties()->set(name_ + "_ZN_Flip", zn_flip_energy); 209 cell_->getGenProperties()->set(name_ + "_A1_Flip", a1_flip_energy); 210 cell_->getGenProperties()->set(name_ + "_A2_Flip", a2_flip_energy); 211 } 212 //------------------------------------------------------------------------- 213 214 //------------------------------------------------------------------------- 215 // INV Macro 216 //------------------------------------------------------------------------- 217 //Adds an inverter to the model, normalized to some size 218 void CellMacros::addInverter(StdCell* cell_, const String& name_, 219 bool sizable_, bool a_to_zn_path_, 220 const String& a_net_, const String& zn_net_) 221 { 222 //Create electrical timing model for the inverter 223 // Construct loads and drivers 224 cell_->createLoad(name_ + "_CgA"); 225 cell_->createLoad(name_ + "_CdZN"); 226 cell_->createDriver(name_ + "_RonZN", sizable_); 227 228 //Get references to loads and drivers 229 ElectricalLoad* gate_load = cell_->getLoad(name_ + "_CgA"); 230 ElectricalLoad* drain_load = cell_->getLoad(name_ + "_CdZN"); 231 ElectricalDriver* out_drive = cell_->getDriver(name_ + "_RonZN"); 232 ElectricalNet* a_net = cell_->getNet(a_net_); 233 ElectricalNet* zn_net = cell_->getNet(zn_net_); 234 235 // Setup connectivity of loads and drivers 236 a_net->addDownstreamNode(gate_load); 237 if (a_to_zn_path_) gate_load->addDownstreamNode(out_drive); 238 zn_net->addDownstreamNode(drain_load); 239 out_drive->addDownstreamNode(zn_net); 240 241 return; 242 } 243 244 //Updates the numbers of an inverter for some normalized size 245 void CellMacros::updateInverter(StdCell* cell_, const String& name_, double normalized_size_) 246 { 247 ASSERT(normalized_size_ >= 0.0, "[Error] " + cell_->getInstanceName() + 248 " -> Cannot update a macro with a negative normalized size!"); 249 250 //Grab pointer to tech model 251 const TechModel* tech = cell_->getTechModel(); 252 253 //Get values from technology library 254 double vdd = tech->get("Vdd"); 255 double gate_cap = tech->get("Gate->CapPerWidth"); 256 double drain_cap = tech->get("Drain->CapPerWidth"); 257 double nmos_eff_res = tech->get("Nmos->EffResWidth"); 258 double pmos_eff_res = tech->get("Pmos->EffResWidth"); 259 double gate_pitch_contacted = tech->get("Gate->PitchContacted"); 260 double metal1_wire_min_width = tech->get("Wire->Metal1->MinWidth"); 261 262 //Calculate number of folds needed 263 unsigned int folds = (normalized_size_ < 1.0) ? 1 : (unsigned int)ceil(normalized_size_); 264 cell_->getGenProperties()->set(name_ + "_GatePitches", folds); 265 266 //Calculate widths, making sure they are above the minimum width 267 double nmos_width = std::max(calculateNmosWidth(cell_, 1, 1, 1) * normalized_size_ / folds, (double) tech->get("Gate->MinWidth")); 268 double pmos_width = std::max(calculatePmosWidth(cell_, 1, 1, 1) * normalized_size_ / folds, (double) tech->get("Gate->MinWidth")); 269 270 //Calculate leakage power for each given input state 271 double leakage_power_0 = vdd * folds * tech->calculateNmosLeakageCurrent(1, nmos_width, 0x0); 272 double leakage_power_1 = vdd * folds * tech->calculatePmosLeakageCurrent(1, pmos_width, ~0x1); 273 cell_->getGenProperties()->set(name_ + "_LeakagePower_0", leakage_power_0); 274 cell_->getGenProperties()->set(name_ + "_LeakagePower_1", leakage_power_1); 275 276 //Calculate caps 277 double c_g = (nmos_width + pmos_width) * gate_cap * folds; 278 double c_d = (pmos_width + nmos_width) * drain_cap * folds; 279 double r_on = (nmos_eff_res / nmos_width + pmos_eff_res / pmos_width) / (folds * 2.0); 280 281 // Estimate the wire cap and add them all at the output 282 double cell_height = cell_->getTotalHeight(); 283 double wire_width = metal1_wire_min_width; 284 double wire_spacing = gate_pitch_contacted - metal1_wire_min_width; 285 double wire_length = folds * cell_height; 286 double wire_cap = tech->calculateWireCapacitance("Metal1", wire_width, wire_spacing, wire_length); 287 288 // Construct equivalent load and drive strength 289 cell_->getLoad(name_ + "_CgA")->setLoadCap(c_g); 290 cell_->getLoad(name_ + "_CdZN")->setLoadCap(c_d + wire_cap); 291 cell_->getDriver(name_ + "_RonZN")->setOutputRes(r_on); 292 293 // Calculate flip energy (output flip) 294 // Calculate flip energies 295 double zn_flip_energy = 0.5 * (c_d + wire_cap) * vdd * vdd; 296 double a_flip_energy = 0.5 * c_g * vdd * vdd; 297 cell_->getGenProperties()->set(name_ + "_ZN_Flip", zn_flip_energy); 298 cell_->getGenProperties()->set(name_ + "_A_Flip", a_flip_energy); 299 300 return; 301 } 302 //------------------------------------------------------------------------- 303 304 //------------------------------------------------------------------------- 305 // INVZ Macro 306 //------------------------------------------------------------------------- 307 //Adds a tristated inverter to the model, normalized to some size 308 void CellMacros::addTristate(StdCell* cell_, const String& name_, 309 bool sizable_, bool a_to_zn_path_, bool oe_to_zn_path_, bool oen_to_zn_path_, 310 const String& a_net_, const String& oe_net_, const String& oen_net_, const String& zn_net_) 311 { 312 // Construct loads and drivers 313 cell_->createLoad(name_ + "_CgA"); 314 cell_->createLoad(name_ + "_CgOE"); 315 cell_->createLoad(name_ + "_CgOEN"); 316 cell_->createLoad(name_ + "_CdZN"); 317 cell_->createDriver(name_ + "_RonZN", sizable_); 318 319 // Get references to loads, nets and drivers 320 ElectricalLoad* gate_a_load = cell_->getLoad(name_ + "_CgA"); 321 ElectricalLoad* gate_oe_load = cell_->getLoad(name_ + "_CgOE"); 322 ElectricalLoad* gate_oen_load = cell_->getLoad(name_ + "_CgOEN"); 323 ElectricalLoad* drain_load = cell_->getLoad(name_ + "_CdZN"); 324 ElectricalDriver* out_drive = cell_->getDriver(name_ + "_RonZN"); 325 ElectricalNet* a_net = cell_->getNet(a_net_); 326 ElectricalNet* oe_net = cell_->getNet(oe_net_); 327 ElectricalNet* oen_net = cell_->getNet(oen_net_); 328 ElectricalNet* zn_net = cell_->getNet(zn_net_); 329 330 // Setup connectivity of loads and drivers 331 a_net->addDownstreamNode(gate_a_load); 332 oe_net->addDownstreamNode(gate_oe_load); 333 oen_net->addDownstreamNode(gate_oen_load); 334 if (a_to_zn_path_) gate_a_load->addDownstreamNode(out_drive); 335 if (oe_to_zn_path_) gate_oe_load->addDownstreamNode(out_drive); 336 if (oen_to_zn_path_) gate_oen_load->addDownstreamNode(out_drive); 337 zn_net->addDownstreamNode(drain_load); 338 out_drive->addDownstreamNode(zn_net); 339 340 return; 341 } 342 343 //Updates the numbers of an inverter for some normalized size 344 void CellMacros::updateTristate(StdCell* cell_, const String& name_, double normalized_size_) 345 { 346 ASSERT(normalized_size_ >= 0.0, "[Error] " + cell_->getInstanceName() + 347 " -> Cannot update a macro with a negative normalized size!"); 348 349 //Grab pointer to tech model 350 const TechModel* tech = cell_->getTechModel(); 351 352 //Get values from technology library 353 double vdd = tech->get("Vdd"); 354 double gate_cap = tech->get("Gate->CapPerWidth"); 355 double drain_cap = tech->get("Drain->CapPerWidth"); 356 double nmos_eff_res = tech->get("Nmos->EffResWidth"); 357 double pmos_eff_res = tech->get("Pmos->EffResWidth"); 358 double pmos_eff_res_stack_ratio = tech->get("Pmos->EffResStackRatio"); 359 double nmos_eff_res_stack_ratio = tech->get("Nmos->EffResStackRatio"); 360 double gate_pitch_contacted = tech->get("Gate->PitchContacted"); 361 double metal1_wire_min_width = tech->get("Wire->Metal1->MinWidth"); 362 363 //Calculate number of folds and gate pitches needed 364 unsigned int folds = (normalized_size_ < 1.0) ? 1 : (unsigned int)ceil(normalized_size_); 365 cell_->getGenProperties()->set(name_ + "_GatePitches", 2 * folds); 366 367 //Calculate widths, making sure they are above the minimum width 368 double nmos_width = std::max(calculateNmosWidth(cell_, 2, 2, 2) * normalized_size_ / folds, (double) tech->get("Gate->MinWidth")); 369 double pmos_width = std::max(calculatePmosWidth(cell_, 2, 2, 2) * normalized_size_ / folds, (double) tech->get("Gate->MinWidth")); 370 371 //Calculate leakage power for each given input state 372 //if output_enable = 0, then it is possible that the PMOS may leak (if output = 0), 373 //or the NMOS will leak (if output = 1) 374 375 //OE OEN A _ ZN 376 double leakage_power_010_0 = vdd * folds * tech->calculatePmosLeakageCurrent(2, pmos_width, ~0x2); 377 double leakage_power_010_1 = vdd * folds * tech->calculateNmosLeakageCurrent(2, nmos_width, 0x0); 378 double leakage_power_011_0 = vdd * folds * tech->calculatePmosLeakageCurrent(2, pmos_width, ~0x3); 379 double leakage_power_011_1 = vdd * folds * tech->calculateNmosLeakageCurrent(2, nmos_width, 0x1); 380 double leakage_power_100_1 = vdd * folds * tech->calculateNmosLeakageCurrent(2, nmos_width, 0x2); 381 double leakage_power_101_0 = vdd * folds * tech->calculatePmosLeakageCurrent(2, pmos_width, ~0x1); 382 cell_->getGenProperties()->set(name_ + "_LeakagePower_010_0", leakage_power_010_0); 383 cell_->getGenProperties()->set(name_ + "_LeakagePower_010_1", leakage_power_010_1); 384 cell_->getGenProperties()->set(name_ + "_LeakagePower_011_0", leakage_power_011_0); 385 cell_->getGenProperties()->set(name_ + "_LeakagePower_011_1", leakage_power_011_1); 386 cell_->getGenProperties()->set(name_ + "_LeakagePower_100_1", leakage_power_100_1); 387 cell_->getGenProperties()->set(name_ + "_LeakagePower_101_0", leakage_power_101_0); 388 389 //Caculate stack balance 390 double pmos_stack2_balance = 1.0 + pmos_eff_res_stack_ratio; 391 double nmos_stack2_balance = 1.0 + nmos_eff_res_stack_ratio; 392 393 //Calculate caps 394 double c_g_a = (nmos_width + pmos_width) * gate_cap * folds; 395 double c_g_oe = nmos_width * gate_cap * folds; 396 double c_g_oen = pmos_width * gate_cap * folds; 397 double c_d = (2 * pmos_width + 2 * nmos_width) * drain_cap * folds; 398 double r_on = (nmos_stack2_balance * nmos_eff_res / nmos_width + pmos_stack2_balance * pmos_eff_res / pmos_width) / (folds * 2.0); 399 400 // Estimate the wire cap and add them all at the output 401 double cell_height = cell_->getTotalHeight(); 402 double wire_width = metal1_wire_min_width; 403 double wire_spacing = gate_pitch_contacted - metal1_wire_min_width; 404 double wire_length = 2.0 * folds * cell_height; 405 double wire_cap = tech->calculateWireCapacitance("Metal1", wire_width, wire_spacing, wire_length); 406 407 // Construct equivalent load and drive strength 408 cell_->getLoad(name_ + "_CgA")->setLoadCap(c_g_a); 409 cell_->getLoad(name_ + "_CgOE")->setLoadCap(c_g_oe); 410 cell_->getLoad(name_ + "_CgOEN")->setLoadCap(c_g_oen); 411 cell_->getLoad(name_ + "_CdZN")->setLoadCap(c_d + wire_cap); 412 cell_->getDriver(name_ + "_RonZN")->setOutputRes(r_on); 413 414 // Calculate flip energy (output flip) 415 double zn_flip_energy = 0.5 * (c_d + wire_cap) * vdd * vdd; 416 double a_flip_energy = 0.5 * c_g_a * vdd * vdd; 417 double oe_flip_energy = 0.5 * c_g_oe * vdd * vdd; 418 double oen_flip_energy = 0.5 * c_g_oen * vdd * vdd; 419 cell_->getGenProperties()->set(name_ + "_ZN_Flip", zn_flip_energy); 420 cell_->getGenProperties()->set(name_ + "_A_Flip", a_flip_energy); 421 cell_->getGenProperties()->set(name_ + "_OE_Flip", oe_flip_energy); 422 cell_->getGenProperties()->set(name_ + "_OEN_Flip", oen_flip_energy); 423 return; 424 } 425 //------------------------------------------------------------------------- 426 427 428 //------------------------------------------------------------------------- 429 // Helper Functions 430 //------------------------------------------------------------------------- 431 //Returns the width of NMOS transistors, given the NMOS and PMOS stacking 432 double CellMacros::calculateNmosWidth(const StdCell* cell_, unsigned int max_stacked_nmos_, unsigned int max_stacked_pmos_, unsigned int current_stacked_nmos_) 433 { 434 //Grab pointer to tech model 435 const TechModel* tech = cell_->getTechModel(); 436 437 double nmos_eff_res_stack_ratio = tech->get("Nmos->EffResStackRatio"); 438 double pmos_eff_res_stack_ratio = tech->get("Pmos->EffResStackRatio"); 439 440 double nmos_stack_balance = 1.0 + nmos_eff_res_stack_ratio * (double) (max_stacked_nmos_ - 1); 441 double pmos_stack_balance = 1.0 + pmos_eff_res_stack_ratio * (double) (max_stacked_pmos_ - 1); 442 double current_nmos_stack_balance = 1.0 + nmos_eff_res_stack_ratio * (double) (current_stacked_nmos_ - 1); 443 444 double pn_ratio = cell_->getPToNRatio(); 445 double active_height = cell_->getActiveHeight(); 446 447 //Calculate the width of the current device 448 double nmos_width = active_height * current_nmos_stack_balance / (nmos_stack_balance + pn_ratio * pmos_stack_balance); 449 450 return nmos_width; 451 } 452 453 //Returns the width of PMOS transistors, given the NMOS and PMOS stacking 454 double CellMacros::calculatePmosWidth(const StdCell* cell_, unsigned int max_stacked_nmos_, unsigned int max_stacked_pmos_, unsigned int current_stacked_pmos_) 455 { 456 //Grab pointer to tech model 457 const TechModel* tech = cell_->getTechModel(); 458 459 double nmos_eff_res_stack_ratio = tech->get("Nmos->EffResStackRatio"); 460 double pmos_eff_res_stack_ratio = tech->get("Pmos->EffResStackRatio"); 461 462 double nmos_stack_balance = 1.0 + nmos_eff_res_stack_ratio * (double) (max_stacked_nmos_ - 1); 463 double pmos_stack_balance = 1.0 + pmos_eff_res_stack_ratio * (double) (max_stacked_pmos_ - 1); 464 double current_pmos_stack_balance = 1.0 + pmos_eff_res_stack_ratio * (double) (current_stacked_pmos_ - 1); 465 466 double pn_ratio = cell_->getPToNRatio(); 467 double active_height = cell_->getActiveHeight(); 468 469 //Calculate the width of the current device 470 double pmos_width = active_height * current_pmos_stack_balance * pn_ratio / (nmos_stack_balance + pn_ratio * pmos_stack_balance); 471 472 return pmos_width; 473 } 474 //------------------------------------------------------------------------- 475 476} // namespace DSENT 477
| 22#include "model/std_cells/CellMacros.h" 23 24#include <cmath> 25#include <vector> 26 27#include "model/std_cells/StdCell.h" 28#include "model/timing_graph/ElectricalNet.h" 29#include "model/timing_graph/ElectricalDriver.h" 30#include "model/timing_graph/ElectricalLoad.h" 31 32namespace DSENT 33{ 34 //------------------------------------------------------------------------- 35 // NOR2 Macro (TODO: Generalize to N-input macro once leakage calc is done) 36 //------------------------------------------------------------------------- 37 void CellMacros::addNor2(StdCell* cell_, const String& name_, 38 bool sizable_, bool a1_to_zn_path_, bool a2_to_zn_path_, 39 const String& a1_net_, const String& a2_net_, const String& zn_net_) 40 { 41 //Create electrical timing model for the nand 42 // Construct loads and drivers 43 cell_->createLoad(name_ + "_CgA1"); 44 cell_->createLoad(name_ + "_CgA2"); 45 cell_->createLoad(name_ + "_CdZN"); 46 cell_->createDriver(name_ + "_RonZN", sizable_); 47 48 //Get references to loads and drivers 49 ElectricalLoad* gate_a1_load = cell_->getLoad(name_ + "_CgA1"); 50 ElectricalLoad* gate_a2_load = cell_->getLoad(name_ + "_CgA2"); 51 ElectricalLoad* drain_load = cell_->getLoad(name_ + "_CdZN"); 52 ElectricalDriver* zn_drive = cell_->getDriver(name_ + "_RonZN"); 53 ElectricalNet* a1_net = cell_->getNet(a1_net_); 54 ElectricalNet* a2_net = cell_->getNet(a2_net_); 55 ElectricalNet* zn_net = cell_->getNet(zn_net_); 56 57 //Add loads and drivers to the specified nets 58 a1_net->addDownstreamNode(gate_a1_load); 59 a2_net->addDownstreamNode(gate_a2_load); 60 zn_net->addDownstreamNode(drain_load); 61 if (a1_to_zn_path_) gate_a1_load->addDownstreamNode(zn_drive); 62 if (a2_to_zn_path_) gate_a2_load->addDownstreamNode(zn_drive); 63 zn_drive->addDownstreamNode(zn_net); 64 65 return; 66 } 67 68 void CellMacros::updateNor2(StdCell* cell_, const String& name_, double normalized_size_) 69 { 70 ASSERT(normalized_size_ >= 0.0, "[Error] " + cell_->getInstanceName() + 71 " -> Cannot update a macro with a negative normalized size!"); 72 73 //Grab pointer to tech model 74 const TechModel* tech = cell_->getTechModel(); 75 76 // Get technology parameters 77 double vdd = tech->get("Vdd"); 78 double gate_cap = tech->get("Gate->CapPerWidth"); 79 double drain_cap = tech->get("Drain->CapPerWidth"); 80 double nmos_eff_res = tech->get("Nmos->EffResWidth"); 81 double pmos_eff_res = tech->get("Pmos->EffResWidth"); 82 double pmos_eff_res_stack_ratio = tech->get("Pmos->EffResStackRatio"); 83 double gate_pitch_contacted = tech->get("Gate->PitchContacted"); 84 double metal1_wire_min_width = tech->get("Wire->Metal1->MinWidth"); 85 86 //Calculate number of folds and gate pitches needed 87 unsigned int folds = (normalized_size_ < 1.0) ? 1 : (unsigned int)ceil(normalized_size_); 88 cell_->getGenProperties()->set(name_ + "_GatePitches", 2 * folds); 89 90 //Calculate widths, making sure they are above the minimum width 91 double nmos_width = std::max(calculateNmosWidth(cell_, 1, 2, 1) * normalized_size_ / folds, (double) tech->get("Gate->MinWidth")); 92 double pmos_width = std::max(calculatePmosWidth(cell_, 1, 2, 2) * normalized_size_ / folds, (double) tech->get("Gate->MinWidth")); 93 94 //Calculate leakage power for each given input state 95 double leakage_power_00 = vdd * folds * 2 * tech->calculateNmosLeakageCurrent(1, nmos_width, 0x0); 96 double leakage_power_01 = vdd * folds * tech->calculatePmosLeakageCurrent(2, pmos_width, ~0x1); 97 double leakage_power_10 = vdd * folds * tech->calculatePmosLeakageCurrent(2, pmos_width, ~0x2); 98 double leakage_power_11 = vdd * folds * tech->calculatePmosLeakageCurrent(2, pmos_width, ~0x3); 99 cell_->getGenProperties()->set(name_ + "_LeakagePower_00", leakage_power_00); 100 cell_->getGenProperties()->set(name_ + "_LeakagePower_01", leakage_power_01); 101 cell_->getGenProperties()->set(name_ + "_LeakagePower_10", leakage_power_10); 102 cell_->getGenProperties()->set(name_ + "_LeakagePower_11", leakage_power_11); 103 104 //Calculate R_on and capacitances 105 double pmos_stack2_balance = 1.0 + pmos_eff_res_stack_ratio; 106 double c_g = (nmos_width + pmos_width) * gate_cap * folds; 107 double c_d = (2 * pmos_width + 2 * nmos_width) * drain_cap * folds; 108 double r_on = (nmos_eff_res / nmos_width + pmos_stack2_balance * pmos_eff_res / pmos_width) / (folds * 2.0); 109 110 // Estimate the wire cap and add them all at the output 111 double cell_height = cell_->getTotalHeight(); 112 double wire_width = metal1_wire_min_width; 113 double wire_spacing = gate_pitch_contacted - metal1_wire_min_width; 114 double wire_length = 2.0 * folds * cell_height; 115 double wire_cap = tech->calculateWireCapacitance("Metal1", wire_width, wire_spacing, wire_length); 116 117 // Construct equivalent load and drive strength 118 cell_->getLoad(name_ + "_CgA1")->setLoadCap(c_g); 119 cell_->getLoad(name_ + "_CgA2")->setLoadCap(c_g); 120 cell_->getLoad(name_ + "_CdZN")->setLoadCap(c_d + wire_cap); 121 cell_->getDriver(name_ + "_RonZN")->setOutputRes(r_on); 122 123 // Calculate flip energies 124 double zn_flip_energy = 0.5 * (c_d + wire_cap) * vdd * vdd; 125 double a1_flip_energy = 0.5 * c_g * vdd * vdd; 126 double a2_flip_energy = 0.5 * c_g * vdd * vdd; 127 cell_->getGenProperties()->set(name_ + "_ZN_Flip", zn_flip_energy); 128 cell_->getGenProperties()->set(name_ + "_A1_Flip", a1_flip_energy); 129 cell_->getGenProperties()->set(name_ + "_A2_Flip", a2_flip_energy); 130 } 131 //------------------------------------------------------------------------- 132 133 //------------------------------------------------------------------------- 134 // NAND2 Macro (TODO: Generalize to N-input macro once leakage calc is done) 135 //------------------------------------------------------------------------- 136 //Adds a NAND2 to the standard cell, normalized to some size 137 void CellMacros::addNand2(StdCell* cell_, const String& name_, 138 bool sizable_, bool a1_to_zn_path_, bool a2_to_zn_path_, 139 const String& a1_net_, const String& a2_net_, const String& zn_net_) 140 { 141 //Create electrical timing model for the nor 142 // Construct loads and drivers 143 cell_->createLoad(name_ + "_CgA1"); 144 cell_->createLoad(name_ + "_CgA2"); 145 cell_->createLoad(name_ + "_CdZN"); 146 cell_->createDriver(name_ + "_RonZN", sizable_); 147 148 //Get references to loads and drivers 149 ElectricalLoad* gate_a1_load = cell_->getLoad(name_ + "_CgA1"); 150 ElectricalLoad* gate_a2_load = cell_->getLoad(name_ + "_CgA2"); 151 ElectricalLoad* drain_load = cell_->getLoad(name_ + "_CdZN"); 152 ElectricalDriver* zn_drive = cell_->getDriver(name_ + "_RonZN"); 153 ElectricalNet* a1_net = cell_->getNet(a1_net_); 154 ElectricalNet* a2_net = cell_->getNet(a2_net_); 155 ElectricalNet* zn_net = cell_->getNet(zn_net_); 156 157 a1_net->addDownstreamNode(gate_a1_load); 158 a2_net->addDownstreamNode(gate_a2_load); 159 zn_net->addDownstreamNode(drain_load); 160 if (a1_to_zn_path_) gate_a1_load->addDownstreamNode(zn_drive); 161 if (a2_to_zn_path_) gate_a2_load->addDownstreamNode(zn_drive); 162 zn_drive->addDownstreamNode(zn_net); 163 164 return; 165 } 166 167 //Updates a NAND2 to to the standard cell, normalized to some size 168 void CellMacros::updateNand2(StdCell* cell_, const String& name_, double normalized_size_) 169 { 170 ASSERT(normalized_size_ >= 0.0, "[Error] " + cell_->getInstanceName() + 171 " -> Cannot update a macro with a negative normalized size!"); 172 173 //Grab pointer to tech model 174 const TechModel* tech = cell_->getTechModel(); 175 176 // Get technology parameters 177 double vdd = tech->get("Vdd"); 178 double gate_cap = tech->get("Gate->CapPerWidth"); 179 double drain_cap = tech->get("Drain->CapPerWidth"); 180 double nmos_eff_res = tech->get("Nmos->EffResWidth"); 181 double pmos_eff_res = tech->get("Pmos->EffResWidth"); 182 double nmos_eff_res_stack_ratio = tech->get("Nmos->EffResStackRatio"); 183 double gate_pitch_contacted = tech->get("Gate->PitchContacted"); 184 double metal1_wire_min_width = tech->get("Wire->Metal1->MinWidth"); 185 186 //Calculate number of folds needed 187 unsigned int folds = (normalized_size_ < 1.0) ? 1 : (unsigned int)ceil(normalized_size_); 188 cell_->getGenProperties()->set(name_ + "_GatePitches", 2 * folds); 189 190 //Calculate widths, making sure they are above the minimum width 191 double nmos_width = std::max(calculateNmosWidth(cell_, 2, 1, 2) * normalized_size_ / folds, (double) tech->get("Gate->MinWidth")); 192 double pmos_width = std::max(calculatePmosWidth(cell_, 2, 1, 1) * normalized_size_ / folds, (double) tech->get("Gate->MinWidth")); 193 194 // Leakage power calculation 195 double leakage_power_00 = vdd * folds * tech->calculateNmosLeakageCurrent(2, nmos_width, 0x0); 196 double leakage_power_01 = vdd * folds * tech->calculateNmosLeakageCurrent(2, nmos_width, 0x1); 197 double leakage_power_10 = vdd * folds * tech->calculateNmosLeakageCurrent(2, nmos_width, 0x2); 198 double leakage_power_11 = vdd * folds * 2 * tech->calculatePmosLeakageCurrent(1, pmos_width, ~0x3); 199 cell_->getGenProperties()->set(name_ + "_LeakagePower_00", leakage_power_00); 200 cell_->getGenProperties()->set(name_ + "_LeakagePower_01", leakage_power_01); 201 cell_->getGenProperties()->set(name_ + "_LeakagePower_10", leakage_power_10); 202 cell_->getGenProperties()->set(name_ + "_LeakagePower_11", leakage_power_11); 203 204 // Get input parameters 205 double nmos_stack2_balance = 1.0 + nmos_eff_res_stack_ratio; 206 207 //Calculate caps 208 double c_g = (nmos_width + pmos_width) * gate_cap * folds; 209 double c_d = (2 * pmos_width + 2 * nmos_width) * drain_cap * folds; 210 double r_on = (nmos_stack2_balance * nmos_eff_res / nmos_width + pmos_eff_res / pmos_width) / (folds * 2.0); 211 212 // Estimate the wire cap and add them all at the output 213 double cell_height = cell_->getTotalHeight(); 214 double wire_width = metal1_wire_min_width; 215 double wire_spacing = gate_pitch_contacted - metal1_wire_min_width; 216 double wire_length = 2.0 * folds * cell_height; 217 double wire_cap = tech->calculateWireCapacitance("Metal1", wire_width, wire_spacing, wire_length); 218 219 // Construct equivalent load and drive strength 220 cell_->getLoad(name_ + "_CgA1")->setLoadCap(c_g); 221 cell_->getLoad(name_ + "_CgA2")->setLoadCap(c_g); 222 cell_->getLoad(name_ + "_CdZN")->setLoadCap(c_d + wire_cap); 223 cell_->getDriver(name_ + "_RonZN")->setOutputRes(r_on); 224 225 // Calculate flip energies 226 double zn_flip_energy = 0.5 * (c_d + wire_cap) * vdd * vdd; 227 double a1_flip_energy = 0.5 * c_g * vdd * vdd; 228 double a2_flip_energy = 0.5 * c_g * vdd * vdd; 229 cell_->getGenProperties()->set(name_ + "_ZN_Flip", zn_flip_energy); 230 cell_->getGenProperties()->set(name_ + "_A1_Flip", a1_flip_energy); 231 cell_->getGenProperties()->set(name_ + "_A2_Flip", a2_flip_energy); 232 } 233 //------------------------------------------------------------------------- 234 235 //------------------------------------------------------------------------- 236 // INV Macro 237 //------------------------------------------------------------------------- 238 //Adds an inverter to the model, normalized to some size 239 void CellMacros::addInverter(StdCell* cell_, const String& name_, 240 bool sizable_, bool a_to_zn_path_, 241 const String& a_net_, const String& zn_net_) 242 { 243 //Create electrical timing model for the inverter 244 // Construct loads and drivers 245 cell_->createLoad(name_ + "_CgA"); 246 cell_->createLoad(name_ + "_CdZN"); 247 cell_->createDriver(name_ + "_RonZN", sizable_); 248 249 //Get references to loads and drivers 250 ElectricalLoad* gate_load = cell_->getLoad(name_ + "_CgA"); 251 ElectricalLoad* drain_load = cell_->getLoad(name_ + "_CdZN"); 252 ElectricalDriver* out_drive = cell_->getDriver(name_ + "_RonZN"); 253 ElectricalNet* a_net = cell_->getNet(a_net_); 254 ElectricalNet* zn_net = cell_->getNet(zn_net_); 255 256 // Setup connectivity of loads and drivers 257 a_net->addDownstreamNode(gate_load); 258 if (a_to_zn_path_) gate_load->addDownstreamNode(out_drive); 259 zn_net->addDownstreamNode(drain_load); 260 out_drive->addDownstreamNode(zn_net); 261 262 return; 263 } 264 265 //Updates the numbers of an inverter for some normalized size 266 void CellMacros::updateInverter(StdCell* cell_, const String& name_, double normalized_size_) 267 { 268 ASSERT(normalized_size_ >= 0.0, "[Error] " + cell_->getInstanceName() + 269 " -> Cannot update a macro with a negative normalized size!"); 270 271 //Grab pointer to tech model 272 const TechModel* tech = cell_->getTechModel(); 273 274 //Get values from technology library 275 double vdd = tech->get("Vdd"); 276 double gate_cap = tech->get("Gate->CapPerWidth"); 277 double drain_cap = tech->get("Drain->CapPerWidth"); 278 double nmos_eff_res = tech->get("Nmos->EffResWidth"); 279 double pmos_eff_res = tech->get("Pmos->EffResWidth"); 280 double gate_pitch_contacted = tech->get("Gate->PitchContacted"); 281 double metal1_wire_min_width = tech->get("Wire->Metal1->MinWidth"); 282 283 //Calculate number of folds needed 284 unsigned int folds = (normalized_size_ < 1.0) ? 1 : (unsigned int)ceil(normalized_size_); 285 cell_->getGenProperties()->set(name_ + "_GatePitches", folds); 286 287 //Calculate widths, making sure they are above the minimum width 288 double nmos_width = std::max(calculateNmosWidth(cell_, 1, 1, 1) * normalized_size_ / folds, (double) tech->get("Gate->MinWidth")); 289 double pmos_width = std::max(calculatePmosWidth(cell_, 1, 1, 1) * normalized_size_ / folds, (double) tech->get("Gate->MinWidth")); 290 291 //Calculate leakage power for each given input state 292 double leakage_power_0 = vdd * folds * tech->calculateNmosLeakageCurrent(1, nmos_width, 0x0); 293 double leakage_power_1 = vdd * folds * tech->calculatePmosLeakageCurrent(1, pmos_width, ~0x1); 294 cell_->getGenProperties()->set(name_ + "_LeakagePower_0", leakage_power_0); 295 cell_->getGenProperties()->set(name_ + "_LeakagePower_1", leakage_power_1); 296 297 //Calculate caps 298 double c_g = (nmos_width + pmos_width) * gate_cap * folds; 299 double c_d = (pmos_width + nmos_width) * drain_cap * folds; 300 double r_on = (nmos_eff_res / nmos_width + pmos_eff_res / pmos_width) / (folds * 2.0); 301 302 // Estimate the wire cap and add them all at the output 303 double cell_height = cell_->getTotalHeight(); 304 double wire_width = metal1_wire_min_width; 305 double wire_spacing = gate_pitch_contacted - metal1_wire_min_width; 306 double wire_length = folds * cell_height; 307 double wire_cap = tech->calculateWireCapacitance("Metal1", wire_width, wire_spacing, wire_length); 308 309 // Construct equivalent load and drive strength 310 cell_->getLoad(name_ + "_CgA")->setLoadCap(c_g); 311 cell_->getLoad(name_ + "_CdZN")->setLoadCap(c_d + wire_cap); 312 cell_->getDriver(name_ + "_RonZN")->setOutputRes(r_on); 313 314 // Calculate flip energy (output flip) 315 // Calculate flip energies 316 double zn_flip_energy = 0.5 * (c_d + wire_cap) * vdd * vdd; 317 double a_flip_energy = 0.5 * c_g * vdd * vdd; 318 cell_->getGenProperties()->set(name_ + "_ZN_Flip", zn_flip_energy); 319 cell_->getGenProperties()->set(name_ + "_A_Flip", a_flip_energy); 320 321 return; 322 } 323 //------------------------------------------------------------------------- 324 325 //------------------------------------------------------------------------- 326 // INVZ Macro 327 //------------------------------------------------------------------------- 328 //Adds a tristated inverter to the model, normalized to some size 329 void CellMacros::addTristate(StdCell* cell_, const String& name_, 330 bool sizable_, bool a_to_zn_path_, bool oe_to_zn_path_, bool oen_to_zn_path_, 331 const String& a_net_, const String& oe_net_, const String& oen_net_, const String& zn_net_) 332 { 333 // Construct loads and drivers 334 cell_->createLoad(name_ + "_CgA"); 335 cell_->createLoad(name_ + "_CgOE"); 336 cell_->createLoad(name_ + "_CgOEN"); 337 cell_->createLoad(name_ + "_CdZN"); 338 cell_->createDriver(name_ + "_RonZN", sizable_); 339 340 // Get references to loads, nets and drivers 341 ElectricalLoad* gate_a_load = cell_->getLoad(name_ + "_CgA"); 342 ElectricalLoad* gate_oe_load = cell_->getLoad(name_ + "_CgOE"); 343 ElectricalLoad* gate_oen_load = cell_->getLoad(name_ + "_CgOEN"); 344 ElectricalLoad* drain_load = cell_->getLoad(name_ + "_CdZN"); 345 ElectricalDriver* out_drive = cell_->getDriver(name_ + "_RonZN"); 346 ElectricalNet* a_net = cell_->getNet(a_net_); 347 ElectricalNet* oe_net = cell_->getNet(oe_net_); 348 ElectricalNet* oen_net = cell_->getNet(oen_net_); 349 ElectricalNet* zn_net = cell_->getNet(zn_net_); 350 351 // Setup connectivity of loads and drivers 352 a_net->addDownstreamNode(gate_a_load); 353 oe_net->addDownstreamNode(gate_oe_load); 354 oen_net->addDownstreamNode(gate_oen_load); 355 if (a_to_zn_path_) gate_a_load->addDownstreamNode(out_drive); 356 if (oe_to_zn_path_) gate_oe_load->addDownstreamNode(out_drive); 357 if (oen_to_zn_path_) gate_oen_load->addDownstreamNode(out_drive); 358 zn_net->addDownstreamNode(drain_load); 359 out_drive->addDownstreamNode(zn_net); 360 361 return; 362 } 363 364 //Updates the numbers of an inverter for some normalized size 365 void CellMacros::updateTristate(StdCell* cell_, const String& name_, double normalized_size_) 366 { 367 ASSERT(normalized_size_ >= 0.0, "[Error] " + cell_->getInstanceName() + 368 " -> Cannot update a macro with a negative normalized size!"); 369 370 //Grab pointer to tech model 371 const TechModel* tech = cell_->getTechModel(); 372 373 //Get values from technology library 374 double vdd = tech->get("Vdd"); 375 double gate_cap = tech->get("Gate->CapPerWidth"); 376 double drain_cap = tech->get("Drain->CapPerWidth"); 377 double nmos_eff_res = tech->get("Nmos->EffResWidth"); 378 double pmos_eff_res = tech->get("Pmos->EffResWidth"); 379 double pmos_eff_res_stack_ratio = tech->get("Pmos->EffResStackRatio"); 380 double nmos_eff_res_stack_ratio = tech->get("Nmos->EffResStackRatio"); 381 double gate_pitch_contacted = tech->get("Gate->PitchContacted"); 382 double metal1_wire_min_width = tech->get("Wire->Metal1->MinWidth"); 383 384 //Calculate number of folds and gate pitches needed 385 unsigned int folds = (normalized_size_ < 1.0) ? 1 : (unsigned int)ceil(normalized_size_); 386 cell_->getGenProperties()->set(name_ + "_GatePitches", 2 * folds); 387 388 //Calculate widths, making sure they are above the minimum width 389 double nmos_width = std::max(calculateNmosWidth(cell_, 2, 2, 2) * normalized_size_ / folds, (double) tech->get("Gate->MinWidth")); 390 double pmos_width = std::max(calculatePmosWidth(cell_, 2, 2, 2) * normalized_size_ / folds, (double) tech->get("Gate->MinWidth")); 391 392 //Calculate leakage power for each given input state 393 //if output_enable = 0, then it is possible that the PMOS may leak (if output = 0), 394 //or the NMOS will leak (if output = 1) 395 396 //OE OEN A _ ZN 397 double leakage_power_010_0 = vdd * folds * tech->calculatePmosLeakageCurrent(2, pmos_width, ~0x2); 398 double leakage_power_010_1 = vdd * folds * tech->calculateNmosLeakageCurrent(2, nmos_width, 0x0); 399 double leakage_power_011_0 = vdd * folds * tech->calculatePmosLeakageCurrent(2, pmos_width, ~0x3); 400 double leakage_power_011_1 = vdd * folds * tech->calculateNmosLeakageCurrent(2, nmos_width, 0x1); 401 double leakage_power_100_1 = vdd * folds * tech->calculateNmosLeakageCurrent(2, nmos_width, 0x2); 402 double leakage_power_101_0 = vdd * folds * tech->calculatePmosLeakageCurrent(2, pmos_width, ~0x1); 403 cell_->getGenProperties()->set(name_ + "_LeakagePower_010_0", leakage_power_010_0); 404 cell_->getGenProperties()->set(name_ + "_LeakagePower_010_1", leakage_power_010_1); 405 cell_->getGenProperties()->set(name_ + "_LeakagePower_011_0", leakage_power_011_0); 406 cell_->getGenProperties()->set(name_ + "_LeakagePower_011_1", leakage_power_011_1); 407 cell_->getGenProperties()->set(name_ + "_LeakagePower_100_1", leakage_power_100_1); 408 cell_->getGenProperties()->set(name_ + "_LeakagePower_101_0", leakage_power_101_0); 409 410 //Caculate stack balance 411 double pmos_stack2_balance = 1.0 + pmos_eff_res_stack_ratio; 412 double nmos_stack2_balance = 1.0 + nmos_eff_res_stack_ratio; 413 414 //Calculate caps 415 double c_g_a = (nmos_width + pmos_width) * gate_cap * folds; 416 double c_g_oe = nmos_width * gate_cap * folds; 417 double c_g_oen = pmos_width * gate_cap * folds; 418 double c_d = (2 * pmos_width + 2 * nmos_width) * drain_cap * folds; 419 double r_on = (nmos_stack2_balance * nmos_eff_res / nmos_width + pmos_stack2_balance * pmos_eff_res / pmos_width) / (folds * 2.0); 420 421 // Estimate the wire cap and add them all at the output 422 double cell_height = cell_->getTotalHeight(); 423 double wire_width = metal1_wire_min_width; 424 double wire_spacing = gate_pitch_contacted - metal1_wire_min_width; 425 double wire_length = 2.0 * folds * cell_height; 426 double wire_cap = tech->calculateWireCapacitance("Metal1", wire_width, wire_spacing, wire_length); 427 428 // Construct equivalent load and drive strength 429 cell_->getLoad(name_ + "_CgA")->setLoadCap(c_g_a); 430 cell_->getLoad(name_ + "_CgOE")->setLoadCap(c_g_oe); 431 cell_->getLoad(name_ + "_CgOEN")->setLoadCap(c_g_oen); 432 cell_->getLoad(name_ + "_CdZN")->setLoadCap(c_d + wire_cap); 433 cell_->getDriver(name_ + "_RonZN")->setOutputRes(r_on); 434 435 // Calculate flip energy (output flip) 436 double zn_flip_energy = 0.5 * (c_d + wire_cap) * vdd * vdd; 437 double a_flip_energy = 0.5 * c_g_a * vdd * vdd; 438 double oe_flip_energy = 0.5 * c_g_oe * vdd * vdd; 439 double oen_flip_energy = 0.5 * c_g_oen * vdd * vdd; 440 cell_->getGenProperties()->set(name_ + "_ZN_Flip", zn_flip_energy); 441 cell_->getGenProperties()->set(name_ + "_A_Flip", a_flip_energy); 442 cell_->getGenProperties()->set(name_ + "_OE_Flip", oe_flip_energy); 443 cell_->getGenProperties()->set(name_ + "_OEN_Flip", oen_flip_energy); 444 return; 445 } 446 //------------------------------------------------------------------------- 447 448 449 //------------------------------------------------------------------------- 450 // Helper Functions 451 //------------------------------------------------------------------------- 452 //Returns the width of NMOS transistors, given the NMOS and PMOS stacking 453 double CellMacros::calculateNmosWidth(const StdCell* cell_, unsigned int max_stacked_nmos_, unsigned int max_stacked_pmos_, unsigned int current_stacked_nmos_) 454 { 455 //Grab pointer to tech model 456 const TechModel* tech = cell_->getTechModel(); 457 458 double nmos_eff_res_stack_ratio = tech->get("Nmos->EffResStackRatio"); 459 double pmos_eff_res_stack_ratio = tech->get("Pmos->EffResStackRatio"); 460 461 double nmos_stack_balance = 1.0 + nmos_eff_res_stack_ratio * (double) (max_stacked_nmos_ - 1); 462 double pmos_stack_balance = 1.0 + pmos_eff_res_stack_ratio * (double) (max_stacked_pmos_ - 1); 463 double current_nmos_stack_balance = 1.0 + nmos_eff_res_stack_ratio * (double) (current_stacked_nmos_ - 1); 464 465 double pn_ratio = cell_->getPToNRatio(); 466 double active_height = cell_->getActiveHeight(); 467 468 //Calculate the width of the current device 469 double nmos_width = active_height * current_nmos_stack_balance / (nmos_stack_balance + pn_ratio * pmos_stack_balance); 470 471 return nmos_width; 472 } 473 474 //Returns the width of PMOS transistors, given the NMOS and PMOS stacking 475 double CellMacros::calculatePmosWidth(const StdCell* cell_, unsigned int max_stacked_nmos_, unsigned int max_stacked_pmos_, unsigned int current_stacked_pmos_) 476 { 477 //Grab pointer to tech model 478 const TechModel* tech = cell_->getTechModel(); 479 480 double nmos_eff_res_stack_ratio = tech->get("Nmos->EffResStackRatio"); 481 double pmos_eff_res_stack_ratio = tech->get("Pmos->EffResStackRatio"); 482 483 double nmos_stack_balance = 1.0 + nmos_eff_res_stack_ratio * (double) (max_stacked_nmos_ - 1); 484 double pmos_stack_balance = 1.0 + pmos_eff_res_stack_ratio * (double) (max_stacked_pmos_ - 1); 485 double current_pmos_stack_balance = 1.0 + pmos_eff_res_stack_ratio * (double) (current_stacked_pmos_ - 1); 486 487 double pn_ratio = cell_->getPToNRatio(); 488 double active_height = cell_->getActiveHeight(); 489 490 //Calculate the width of the current device 491 double pmos_width = active_height * current_pmos_stack_balance * pn_ratio / (nmos_stack_balance + pn_ratio * pmos_stack_balance); 492 493 return pmos_width; 494 } 495 //------------------------------------------------------------------------- 496 497} // namespace DSENT 498
|