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#include "wire.h" 34#include "cmath" 35// use this constructor to calculate wire stats 36Wire::Wire( 37 enum Wire_type wire_model, 38 double wl, 39 int n, 40 double w_s, 41 double s_s, 42 enum Wire_placement wp, 43 double resistivity, 44 TechnologyParameter::DeviceType *dt 45 ): wt(wire_model), wire_length(wl*1e-6), nsense(n), w_scale(w_s), 46 s_scale(s_s), 47 resistivity(resistivity), deviceType(dt) { 48 wire_placement = wp; 49 min_w_pmos = deviceType->n_to_p_eff_curr_drv_ratio * g_tp.min_w_nmos_; 50 in_rise_time = 0; 51 out_rise_time = 0; 52 if (initialized != 1) { 53 cout << "Wire not initialized. Initializing it with default values\n"; 54 Wire winit; 55 } 56 calculate_wire_stats(); 57 // change everything back to seconds, microns, and Joules 58 repeater_spacing *= 1e6; 59 wire_length *= 1e6; 60 wire_width *= 1e6; 61 wire_spacing *= 1e6; 62 assert(wire_length > 0); 63 assert(power.readOp.dynamic > 0); 64 assert(power.readOp.leakage > 0); 65 assert(power.readOp.gate_leakage > 0); 66} 67 68// the following values are for peripheral global technology 69// specified in the input config file 70Component Wire::global; 71Component Wire::global_5; 72Component Wire::global_10; 73Component Wire::global_20; 74Component Wire::global_30; 75Component Wire::low_swing; 76 77int Wire::initialized; 78double Wire::wire_width_init; 79double Wire::wire_spacing_init; 80 81 82Wire::Wire(double w_s, double s_s, enum Wire_placement wp, double resis, 83 TechnologyParameter::DeviceType *dt) { 84 w_scale = w_s; 85 s_scale = s_s; 86 deviceType = dt; 87 wire_placement = wp; 88 resistivity = resis; 89 min_w_pmos = deviceType->n_to_p_eff_curr_drv_ratio * g_tp.min_w_nmos_; 90 in_rise_time = 0; 91 out_rise_time = 0; 92 93 switch (wire_placement) { 94 case outside_mat: 95 wire_width = g_tp.wire_outside_mat.pitch; 96 break; 97 case inside_mat : 98 wire_width = g_tp.wire_inside_mat.pitch; 99 break; 100 default: 101 wire_width = g_tp.wire_local.pitch; 102 break; 103 } 104 105 wire_spacing = wire_width; 106 107 wire_width *= (w_scale * 1e-6 / 2) /* (m) */; 108 wire_spacing *= (s_scale * 1e-6 / 2) /* (m) */; 109 110 initialized = 1; 111 init_wire(); 112 wire_width_init = wire_width; 113 wire_spacing_init = wire_spacing; 114 115 assert(power.readOp.dynamic > 0); 116 assert(power.readOp.leakage > 0); 117 assert(power.readOp.gate_leakage > 0); 118} 119 120 121 122Wire::~Wire() { 123} 124 125 126 127void 128Wire::calculate_wire_stats() { 129 130 if (wire_placement == outside_mat) { 131 wire_width = g_tp.wire_outside_mat.pitch; 132 } else if (wire_placement == inside_mat) { 133 wire_width = g_tp.wire_inside_mat.pitch; 134 } else { 135 wire_width = g_tp.wire_local.pitch; 136 } 137 138 wire_spacing = wire_width; 139 140 wire_width *= (w_scale * 1e-6 / 2) /* (m) */; 141 wire_spacing *= (s_scale * 1e-6 / 2) /* (m) */; 142 143 144 if (wt != Low_swing) { 145 146 // delay_optimal_wire(); 147 148 if (wt == Global) { 149 delay = global.delay * wire_length; 150 power.readOp.dynamic = global.power.readOp.dynamic * wire_length; 151 power.readOp.leakage = global.power.readOp.leakage * wire_length; 152 power.readOp.gate_leakage = global.power.readOp.gate_leakage * wire_length; 153 repeater_spacing = global.area.w; 154 repeater_size = global.area.h; 155 area.set_area((wire_length / repeater_spacing) * 156 compute_gate_area(INV, 1, min_w_pmos * repeater_size, 157 g_tp.min_w_nmos_ * repeater_size, 158 g_tp.cell_h_def)); 159 } else if (wt == Global_5) { 160 delay = global_5.delay * wire_length; 161 power.readOp.dynamic = global_5.power.readOp.dynamic * wire_length; 162 power.readOp.leakage = global_5.power.readOp.leakage * wire_length; 163 power.readOp.gate_leakage = global_5.power.readOp.gate_leakage * wire_length; 164 repeater_spacing = global_5.area.w; 165 repeater_size = global_5.area.h; 166 area.set_area((wire_length / repeater_spacing) * 167 compute_gate_area(INV, 1, min_w_pmos * repeater_size, 168 g_tp.min_w_nmos_ * repeater_size, 169 g_tp.cell_h_def)); 170 } else if (wt == Global_10) { 171 delay = global_10.delay * wire_length; 172 power.readOp.dynamic = global_10.power.readOp.dynamic * wire_length; 173 power.readOp.leakage = global_10.power.readOp.leakage * wire_length; 174 power.readOp.gate_leakage = global_10.power.readOp.gate_leakage * wire_length; 175 repeater_spacing = global_10.area.w; 176 repeater_size = global_10.area.h; 177 area.set_area((wire_length / repeater_spacing) * 178 compute_gate_area(INV, 1, min_w_pmos * repeater_size, 179 g_tp.min_w_nmos_ * repeater_size, 180 g_tp.cell_h_def)); 181 } else if (wt == Global_20) { 182 delay = global_20.delay * wire_length; 183 power.readOp.dynamic = global_20.power.readOp.dynamic * wire_length; 184 power.readOp.leakage = global_20.power.readOp.leakage * wire_length; 185 power.readOp.gate_leakage = global_20.power.readOp.gate_leakage * wire_length; 186 repeater_spacing = global_20.area.w; 187 repeater_size = global_20.area.h; 188 area.set_area((wire_length / repeater_spacing) * 189 compute_gate_area(INV, 1, min_w_pmos * repeater_size, 190 g_tp.min_w_nmos_ * repeater_size, 191 g_tp.cell_h_def)); 192 } else if (wt == Global_30) { 193 delay = global_30.delay * wire_length; 194 power.readOp.dynamic = global_30.power.readOp.dynamic * wire_length; 195 power.readOp.leakage = global_30.power.readOp.leakage * wire_length; 196 power.readOp.gate_leakage = global_30.power.readOp.gate_leakage * wire_length; 197 repeater_spacing = global_30.area.w; 198 repeater_size = global_30.area.h; 199 area.set_area((wire_length / repeater_spacing) * 200 compute_gate_area(INV, 1, min_w_pmos * repeater_size, 201 g_tp.min_w_nmos_ * repeater_size, 202 g_tp.cell_h_def)); 203 } 204 out_rise_time = delay * repeater_spacing / deviceType->Vth; 205 } else if (wt == Low_swing) { 206 low_swing_model (); 207 repeater_spacing = wire_length; 208 repeater_size = 1; 209 } else { 210 assert(0); 211 } 212} 213 214 215 216/* 217 * The fall time of an input signal to the first stage of a circuit is 218 * assumed to be same as the fall time of the output signal of two 219 * inverters connected in series (refer: CACTI 1 Technical report, 220 * section 6.1.3) 221 */ 222double 223Wire::signal_fall_time () { 224 225 /* rise time of inverter 1's output */ 226 double rt; 227 /* fall time of inverter 2's output */ 228 double ft; 229 double timeconst; 230 231 timeconst = (drain_C_(g_tp.min_w_nmos_, NCH, 1, 1, g_tp.cell_h_def) + 232 drain_C_(min_w_pmos, PCH, 1, 1, g_tp.cell_h_def) + 233 gate_C(min_w_pmos + g_tp.min_w_nmos_, 0)) * 234 tr_R_on(min_w_pmos, PCH, 1); 235 rt = horowitz (0, timeconst, deviceType->Vth / deviceType->Vdd, 236 deviceType->Vth / deviceType->Vdd, FALL) / 237 (deviceType->Vdd - deviceType->Vth); 238 timeconst = (drain_C_(g_tp.min_w_nmos_, NCH, 1, 1, g_tp.cell_h_def) + 239 drain_C_(min_w_pmos, PCH, 1, 1, g_tp.cell_h_def) + 240 gate_C(min_w_pmos + g_tp.min_w_nmos_, 0)) * 241 tr_R_on(g_tp.min_w_nmos_, NCH, 1); 242 ft = horowitz (rt, timeconst, deviceType->Vth / deviceType->Vdd, 243 deviceType->Vth / deviceType->Vdd, RISE) / deviceType->Vth; 244 return ft; 245} 246 247 248 249double Wire::signal_rise_time () { 250 251 /* rise time of inverter 1's output */ 252 double ft; 253 /* fall time of inverter 2's output */ 254 double rt; 255 double timeconst; 256 257 timeconst = (drain_C_(g_tp.min_w_nmos_, NCH, 1, 1, g_tp.cell_h_def) + 258 drain_C_(min_w_pmos, PCH, 1, 1, g_tp.cell_h_def) + 259 gate_C(min_w_pmos + g_tp.min_w_nmos_, 0)) * 260 tr_R_on(g_tp.min_w_nmos_, NCH, 1); 261 rt = horowitz (0, timeconst, deviceType->Vth / deviceType->Vdd, 262 deviceType->Vth / deviceType->Vdd, RISE) / deviceType->Vth; 263 timeconst = (drain_C_(g_tp.min_w_nmos_, NCH, 1, 1, g_tp.cell_h_def) + 264 drain_C_(min_w_pmos, PCH, 1, 1, g_tp.cell_h_def) + 265 gate_C(min_w_pmos + g_tp.min_w_nmos_, 0)) * 266 tr_R_on(min_w_pmos, PCH, 1); 267 ft = horowitz (rt, timeconst, deviceType->Vth / deviceType->Vdd, 268 deviceType->Vth / deviceType->Vdd, FALL) / 269 (deviceType->Vdd - deviceType->Vth); 270 return ft; //sec 271} 272 273 274 275/* Wire resistance and capacitance calculations 276 * wire width 277 * 278 * /__/ 279 * | | 280 * | | height = ASPECT_RATIO*wire width (ASPECT_RATIO = 2.2, ref: ITRS) 281 * |__|/ 282 * 283 * spacing between wires in same level = wire width 284 * spacing between wires in adjacent levels = wire width---this is incorrect, 285 * according to R.Ho's paper and thesis. ILD != wire width 286 * 287 */ 288 289double Wire::wire_cap (double len /* in m */, bool call_from_outside) { 290 //TODO: this should be consistent with the wire_res in technology file 291 double sidewall, adj, tot_cap; 292 double wire_height; 293 double epsilon0 = 8.8542e-12; 294 double aspect_ratio; 295 double horiz_dielectric_constant; 296 double vert_dielectric_constant; 297 double miller_value; 298 double ild_thickness; 299 300 switch (wire_placement) { 301 case outside_mat: { 302 aspect_ratio = g_tp.wire_outside_mat.aspect_ratio; 303 horiz_dielectric_constant = g_tp.wire_outside_mat.horiz_dielectric_constant; 304 vert_dielectric_constant = g_tp.wire_outside_mat.vert_dielectric_constant; 305 miller_value = g_tp.wire_outside_mat.miller_value; 306 ild_thickness = g_tp.wire_outside_mat.ild_thickness; 307 break; 308 } 309 case inside_mat : { 310 aspect_ratio = g_tp.wire_inside_mat.aspect_ratio; 311 horiz_dielectric_constant = g_tp.wire_inside_mat.horiz_dielectric_constant; 312 vert_dielectric_constant = g_tp.wire_inside_mat.vert_dielectric_constant; 313 miller_value = g_tp.wire_inside_mat.miller_value; 314 ild_thickness = g_tp.wire_inside_mat.ild_thickness; 315 break; 316 } 317 default: { 318 aspect_ratio = g_tp.wire_local.aspect_ratio; 319 horiz_dielectric_constant = g_tp.wire_local.horiz_dielectric_constant; 320 vert_dielectric_constant = g_tp.wire_local.vert_dielectric_constant; 321 miller_value = g_tp.wire_local.miller_value; 322 ild_thickness = g_tp.wire_local.ild_thickness; 323 break; 324 } 325 } 326 327 if (call_from_outside) { 328 wire_width *= 1e-6; 329 wire_spacing *= 1e-6; 330 } 331 wire_height = wire_width / w_scale * aspect_ratio; 332 /* 333 * assuming height does not change. wire_width = width_original*w_scale 334 * So wire_height does not change as wire width increases 335 */ 336 337// capacitance between wires in the same level 338// sidewall = 2*miller_value * horiz_dielectric_constant * (wire_height/wire_spacing) 339// * epsilon0; 340 341 sidewall = miller_value * horiz_dielectric_constant * 342 (wire_height / wire_spacing) 343 * epsilon0; 344 345 346 // capacitance between wires in adjacent levels 347 //adj = miller_value * vert_dielectric_constant *w_scale * epsilon0; 348 //adj = 2*vert_dielectric_constant *wire_width/(ild_thickness*1e-6) * epsilon0; 349 350 adj = miller_value * vert_dielectric_constant * wire_width / 351 (ild_thickness * 1e-6) * epsilon0; 352 //Change ild_thickness from micron to M 353 354 //tot_cap = (sidewall + adj + (deviceType->C_fringe * 1e6)); //F/m 355 tot_cap = (sidewall + adj + (g_tp.fringe_cap * 1e6)); //F/m 356 357 if (call_from_outside) { 358 wire_width *= 1e6; 359 wire_spacing *= 1e6; 360 } 361 return (tot_cap*len); // (F) 362} 363 364 365double 366Wire::wire_res (double len /*(in m)*/) { 367 368 double aspect_ratio; 369 double alpha_scatter = 1.05; 370 double dishing_thickness = 0; 371 double barrier_thickness = 0; 372 //TODO: this should be consistent with the wire_res in technology file 373 //The whole computation should be consistent with the wire_res in technology.cc too! 374 375 switch (wire_placement) { 376 case outside_mat: { 377 aspect_ratio = g_tp.wire_outside_mat.aspect_ratio; 378 break; 379 } 380 case inside_mat : { 381 aspect_ratio = g_tp.wire_inside_mat.aspect_ratio; 382 break; 383 } 384 default: { 385 aspect_ratio = g_tp.wire_local.aspect_ratio; 386 break; 387 } 388 } 389 return (alpha_scatter * resistivity * 1e-6 * len / 390 ((aspect_ratio*wire_width / w_scale - dishing_thickness - 391 barrier_thickness)* 392 (wire_width - 2*barrier_thickness))); 393} 394 395/* 396 * Calculates the delay, power and area of the transmitter circuit. 397 * 398 * The transmitter delay is the sum of nand gate delay, inverter delay 399 * low swing nmos delay, and the wire delay 400 * (ref: Technical report 6) 401 */ 402void 403Wire::low_swing_model() { 404 double len = wire_length; 405 double beta = pmos_to_nmos_sz_ratio(); 406 407 408 double inputrise = (in_rise_time == 0) ? signal_rise_time() : in_rise_time; 409 410 /* Final nmos low swing driver size calculation: 411 * Try to size the driver such that the delay 412 * is less than 8FO4. 413 * If the driver size is greater than 414 * the max allowable size, assume max size for the driver. 415 * In either case, recalculate the delay using 416 * the final driver size assuming slow input with 417 * finite rise time instead of ideal step input 418 * 419 * (ref: Technical report 6) 420 */ 421 double cwire = wire_cap(len); /* load capacitance */ 422 double rwire = wire_res(len); 423 424#define RES_ADJ (8.6) // Increase in resistance due to low driving vol. 425 426 double driver_res = (-8 * g_tp.FO4 / (log(0.5) * cwire)) / RES_ADJ; 427 double nsize = R_to_w(driver_res, NCH); 428 429 nsize = MIN(nsize, g_tp.max_w_nmos_); 430 nsize = MAX(nsize, g_tp.min_w_nmos_); 431 432 if (rwire*cwire > 8*g_tp.FO4) { 433 nsize = g_tp.max_w_nmos_; 434 } 435 436 // size the inverter appropriately to minimize the transmitter delay 437 // Note - In order to minimize leakage, we are not adding a set of inverters to 438 // bring down delay. Instead, we are sizing the single gate 439 // based on the logical effort. 440 double st_eff = sqrt((2 + beta / 1 + beta) * gate_C(nsize, 0) / 441 (gate_C(2 * g_tp.min_w_nmos_, 0) 442 + gate_C(2 * min_w_pmos, 0))); 443 double req_cin = ((2 + beta / 1 + beta) * gate_C(nsize, 0)) / st_eff; 444 double inv_size = req_cin / (gate_C(min_w_pmos, 0) + 445 gate_C(g_tp.min_w_nmos_, 0)); 446 inv_size = MAX(inv_size, 1); 447 448 /* nand gate delay */ 449 double res_eq = (2 * tr_R_on(g_tp.min_w_nmos_, NCH, 1)); 450 double cap_eq = 2 * drain_C_(min_w_pmos, PCH, 1, 1, g_tp.cell_h_def) + 451 drain_C_(2 * g_tp.min_w_nmos_, NCH, 1, 1, g_tp.cell_h_def) + 452 gate_C(inv_size * g_tp.min_w_nmos_, 0) + 453 gate_C(inv_size * min_w_pmos, 0); 454 455 double timeconst = res_eq * cap_eq; 456 457 delay = horowitz(inputrise, timeconst, deviceType->Vth / deviceType->Vdd, 458 deviceType->Vth / deviceType->Vdd, RISE); 459 double temp_power = cap_eq * deviceType->Vdd * deviceType->Vdd; 460 461 inputrise = delay / (deviceType->Vdd - deviceType->Vth); /* for the next stage */ 462 463 /* Inverter delay: 464 * The load capacitance of this inv depends on 465 * the gate capacitance of the final stage nmos 466 * transistor which in turn depends on nsize 467 */ 468 res_eq = tr_R_on(inv_size * min_w_pmos, PCH, 1); 469 cap_eq = drain_C_(inv_size * min_w_pmos, PCH, 1, 1, g_tp.cell_h_def) + 470 drain_C_(inv_size * g_tp.min_w_nmos_, NCH, 1, 1, g_tp.cell_h_def) + 471 gate_C(nsize, 0); 472 timeconst = res_eq * cap_eq; 473 474 delay += horowitz(inputrise, timeconst, deviceType->Vth / deviceType->Vdd, 475 deviceType->Vth / deviceType->Vdd, FALL); 476 temp_power += cap_eq * deviceType->Vdd * deviceType->Vdd; 477 478 479 transmitter.delay = delay; 480 /* since it is a diff. model*/ 481 transmitter.power.readOp.dynamic = temp_power * 2; 482 transmitter.power.readOp.leakage = deviceType->Vdd * 483 (4 * cmos_Isub_leakage(g_tp.min_w_nmos_, min_w_pmos, 2, nand) + 484 4 * cmos_Isub_leakage(g_tp.min_w_nmos_, min_w_pmos, 1, inv)); 485 486 transmitter.power.readOp.gate_leakage = deviceType->Vdd * 487 (4 * cmos_Ig_leakage(g_tp.min_w_nmos_, min_w_pmos, 2, nand) + 488 4 * cmos_Ig_leakage(g_tp.min_w_nmos_, min_w_pmos, 1, inv)); 489 490 inputrise = delay / deviceType->Vth; 491 492 /* nmos delay + wire delay */ 493 cap_eq = cwire + drain_C_(nsize, NCH, 1, 1, g_tp.cell_h_def) * 2 + 494 nsense * sense_amp_input_cap(); //+receiver cap 495 /* 496 * NOTE: nmos is used as both pull up and pull down transistor 497 * in the transmitter. This is because for low voltage swing, drive 498 * resistance of nmos is less than pmos 499 * (for a detailed graph ref: On-Chip Wires: Scaling and Efficiency) 500 */ 501 timeconst = (tr_R_on(nsize, NCH, 1) * RES_ADJ) * (cwire + 502 drain_C_(nsize, NCH, 1, 1, g_tp.cell_h_def) * 2) + 503 rwire * cwire / 2 + 504 (tr_R_on(nsize, NCH, 1) * RES_ADJ + rwire) * 505 nsense * sense_amp_input_cap(); 506 507 /* 508 * since we are pre-equalizing and overdriving the low 509 * swing wires, the net time constant is less 510 * than the actual value 511 */ 512 delay += horowitz(inputrise, timeconst, deviceType->Vth / 513 deviceType->Vdd, .25, 0); 514#define VOL_SWING .1 515 temp_power += cap_eq * VOL_SWING * .400; /* .4v is the over drive voltage */ 516 temp_power *= 2; /* differential wire */ 517 518 l_wire.delay = delay - transmitter.delay; 519 l_wire.power.readOp.dynamic = temp_power - transmitter.power.readOp.dynamic; 520 l_wire.power.readOp.leakage = deviceType->Vdd * 521 (4 * cmos_Isub_leakage(nsize, 0, 1, nmos)); 522 523 l_wire.power.readOp.gate_leakage = deviceType->Vdd * 524 (4 * cmos_Ig_leakage(nsize, 0, 1, nmos)); 525 526 //double rt = horowitz(inputrise, timeconst, deviceType->Vth/deviceType->Vdd, 527 // deviceType->Vth/deviceType->Vdd, RISE)/deviceType->Vth; 528 529 delay += g_tp.sense_delay; 530 531 sense_amp.delay = g_tp.sense_delay; 532 out_rise_time = g_tp.sense_delay / (deviceType->Vth); 533 sense_amp.power.readOp.dynamic = g_tp.sense_dy_power; 534 sense_amp.power.readOp.leakage = 0; //FIXME 535 sense_amp.power.readOp.gate_leakage = 0; 536 537 power.readOp.dynamic = temp_power + sense_amp.power.readOp.dynamic; 538 power.readOp.leakage = transmitter.power.readOp.leakage + 539 l_wire.power.readOp.leakage + 540 sense_amp.power.readOp.leakage; 541 power.readOp.gate_leakage = transmitter.power.readOp.gate_leakage + 542 l_wire.power.readOp.gate_leakage + 543 sense_amp.power.readOp.gate_leakage; 544} 545 546double 547Wire::sense_amp_input_cap() { 548 return drain_C_(g_tp.w_iso, PCH, 1, 1, g_tp.cell_h_def) + 549 gate_C(g_tp.w_sense_en + g_tp.w_sense_n, 0) + 550 drain_C_(g_tp.w_sense_n, NCH, 1, 1, g_tp.cell_h_def) + 551 drain_C_(g_tp.w_sense_p, PCH, 1, 1, g_tp.cell_h_def); 552} 553 554 555void Wire::delay_optimal_wire () { 556 double len = wire_length; 557 //double min_wire_width = wire_width; //m 558 double beta = pmos_to_nmos_sz_ratio(); 559 double switching = 0; // switching energy 560 double short_ckt = 0; // short-circuit energy 561 double tc = 0; // time constant 562 // input cap of min sized driver 563 double input_cap = gate_C(g_tp.min_w_nmos_ + min_w_pmos, 0); 564 565 // output parasitic capacitance of 566 // the min. sized driver 567 double out_cap = drain_C_(min_w_pmos, PCH, 1, 1, g_tp.cell_h_def) + 568 drain_C_(g_tp.min_w_nmos_, NCH, 1, 1, g_tp.cell_h_def); 569 // drive resistance 570 double out_res = (tr_R_on(g_tp.min_w_nmos_, NCH, 1) + 571 tr_R_on(min_w_pmos, PCH, 1)) / 2; 572 double wr = wire_res(len); //ohm 573 574 // wire cap /m 575 double wc = wire_cap(len); 576 577 // size the repeater such that the delay of the wire is minimum 578 // len will cancel 579 double repeater_scaling = sqrt(out_res * wc / (wr * input_cap)); 580 581 // calc the optimum spacing between the repeaters (m) 582 583 repeater_spacing = sqrt(2 * out_res * (out_cap + input_cap) / 584 ((wr / len) * (wc / len))); 585 repeater_size = repeater_scaling; 586 587 switching = (repeater_scaling * (input_cap + out_cap) + 588 repeater_spacing * (wc / len)) * deviceType->Vdd * 589 deviceType->Vdd; 590 591 tc = out_res * (input_cap + out_cap) + 592 out_res * wc / len * repeater_spacing / repeater_scaling + 593 wr / len * repeater_spacing * input_cap * repeater_scaling + 594 0.5 * (wr / len) * (wc / len) * repeater_spacing * repeater_spacing; 595 596 delay = 0.693 * tc * len / repeater_spacing; 597 598#define Ishort_ckt 65e-6 /* across all tech Ref:Banerjee et al. {IEEE TED} */ 599 short_ckt = deviceType->Vdd * g_tp.min_w_nmos_ * Ishort_ckt * 1.0986 * 600 repeater_scaling * tc; 601 602 area.set_area((len / repeater_spacing) * 603 compute_gate_area(INV, 1, min_w_pmos * repeater_scaling, 604 g_tp.min_w_nmos_ * repeater_scaling, 605 g_tp.cell_h_def)); 606 power.readOp.dynamic = ((len / repeater_spacing) * (switching + short_ckt)); 607 power.readOp.leakage = ((len / repeater_spacing) * 608 deviceType->Vdd * 609 cmos_Isub_leakage(g_tp.min_w_nmos_ * 610 repeater_scaling, beta * 611 g_tp.min_w_nmos_ * 612 repeater_scaling, 1, inv)); 613 power.readOp.gate_leakage = ((len / repeater_spacing) * 614 deviceType->Vdd * 615 cmos_Ig_leakage(g_tp.min_w_nmos_ * 616 repeater_scaling, beta * 617 g_tp.min_w_nmos_ * 618 repeater_scaling, 1, inv)); 619} 620 621 622 623// calculate power/delay values for wires with suboptimal repeater sizing/spacing 624void 625Wire::init_wire() { 626 wire_length = 1; 627 delay_optimal_wire(); 628 double sp, si; 629 powerDef pow; 630 si = repeater_size; 631 sp = repeater_spacing; 632 sp *= 1e6; // in microns 633 634 double i, j, del; 635 repeated_wire.push_back(Component()); 636 for (j = sp; j < 4*sp; j += 100) { 637 for (i = si; i > 1; i--) { 638 pow = wire_model(j * 1e-6, i, &del); 639 if (j == sp && i == si) { 640 global.delay = del; 641 global.power = pow; 642 global.area.h = si; 643 global.area.w = sp * 1e-6; // m 644 } 645// cout << "Repeater size - "<< i << 646// " Repeater spacing - " << j << 647// " Delay - " << del << 648// " PowerD - " << pow.readOp.dynamic << 649// " PowerL - " << pow.readOp.leakage <<endl; 650 repeated_wire.back().delay = del; 651 repeated_wire.back().power.readOp = pow.readOp; 652 repeated_wire.back().area.w = j * 1e-6; //m 653 repeated_wire.back().area.h = i; 654 repeated_wire.push_back(Component()); 655 656 } 657 } 658 repeated_wire.pop_back(); 659 update_fullswing(); 660 Wire *l_wire = new Wire(Low_swing, 0.001/* 1 mm*/, 1); 661 low_swing.delay = l_wire->delay; 662 low_swing.power = l_wire->power; 663 delete l_wire; 664} 665 666 667 668void Wire::update_fullswing() { 669 670 list<Component>::iterator citer; 671 double del[4]; 672 del[3] = this->global.delay + this->global.delay * .3; 673 del[2] = global.delay + global.delay * .2; 674 del[1] = global.delay + global.delay * .1; 675 del[0] = global.delay + global.delay * .05; 676 double threshold; 677 double ncost; 678 double cost; 679 int i = 4; 680 while (i > 0) { 681 threshold = del[i-1]; 682 cost = BIGNUM; 683 for (citer = repeated_wire.begin(); citer != repeated_wire.end(); 684 citer++) { 685 if (citer->delay > threshold) { 686 citer = repeated_wire.erase(citer); 687 citer --; 688 } else { 689 ncost = citer->power.readOp.dynamic / 690 global.power.readOp.dynamic + 691 citer->power.readOp.leakage / global.power.readOp.leakage; 692 if (ncost < cost) { 693 cost = ncost; 694 if (i == 4) { 695 global_30.delay = citer->delay; 696 global_30.power = citer->power; 697 global_30.area = citer->area; 698 } else if (i == 3) { 699 global_20.delay = citer->delay; 700 global_20.power = citer->power; 701 global_20.area = citer->area; 702 } else if (i == 2) { 703 global_10.delay = citer->delay; 704 global_10.power = citer->power; 705 global_10.area = citer->area; 706 } else if (i == 1) { 707 global_5.delay = citer->delay; 708 global_5.power = citer->power; 709 global_5.area = citer->area; 710 } 711 } 712 } 713 } 714 i--; 715 } 716} 717 718 719 720powerDef Wire::wire_model (double space, double size, double *delay) { 721 powerDef ptemp; 722 double len = 1; 723 //double min_wire_width = wire_width; //m 724 double beta = pmos_to_nmos_sz_ratio(); 725 // switching energy 726 double switching = 0; 727 // short-circuit energy 728 double short_ckt = 0; 729 // time constant 730 double tc = 0; 731 // input cap of min sized driver 732 double input_cap = gate_C (g_tp.min_w_nmos_ + 733 min_w_pmos, 0); 734 735 // output parasitic capacitance of 736 // the min. sized driver 737 double out_cap = drain_C_(min_w_pmos, PCH, 1, 1, g_tp.cell_h_def) + 738 drain_C_(g_tp.min_w_nmos_, NCH, 1, 1, g_tp.cell_h_def); 739 // drive resistance 740 double out_res = (tr_R_on(g_tp.min_w_nmos_, NCH, 1) + 741 tr_R_on(min_w_pmos, PCH, 1)) / 2; 742 double wr = wire_res(len); //ohm 743 744 // wire cap /m 745 double wc = wire_cap(len); 746 747 repeater_spacing = space; 748 repeater_size = size; 749 750 switching = (repeater_size * (input_cap + out_cap) + 751 repeater_spacing * (wc / len)) * deviceType->Vdd * 752 deviceType->Vdd; 753 754 tc = out_res * (input_cap + out_cap) + 755 out_res * wc / len * repeater_spacing / repeater_size + 756 wr / len * repeater_spacing * out_cap * repeater_size + 757 0.5 * (wr / len) * (wc / len) * repeater_spacing * repeater_spacing; 758 759 *delay = 0.693 * tc * len / repeater_spacing; 760 761#define Ishort_ckt 65e-6 /* across all tech Ref:Banerjee et al. {IEEE TED} */ 762 short_ckt = deviceType->Vdd * g_tp.min_w_nmos_ * Ishort_ckt * 1.0986 * 763 repeater_size * tc; 764 765 ptemp.readOp.dynamic = ((len / repeater_spacing) * (switching + short_ckt)); 766 ptemp.readOp.leakage = ((len / repeater_spacing) * 767 deviceType->Vdd * 768 cmos_Isub_leakage(g_tp.min_w_nmos_ * 769 repeater_size, beta * 770 g_tp.min_w_nmos_ * 771 repeater_size, 1, inv)); 772 773 ptemp.readOp.gate_leakage = ((len / repeater_spacing) * 774 deviceType->Vdd * 775 cmos_Ig_leakage(g_tp.min_w_nmos_ * 776 repeater_size, beta * 777 g_tp.min_w_nmos_ * 778 repeater_size, 1, inv)); 779 780 return ptemp; 781} 782 783void 784Wire::print_wire() { 785 786 cout << "\nWire Properties:\n\n"; 787 cout << " Delay Optimal\n\tRepeater size - " << global.area.h << 788 " \n\tRepeater spacing - " << global.area.w*1e3 << " (mm)" 789 " \n\tDelay - " << global.delay*1e6 << " (ns/mm)" 790 " \n\tPowerD - " << global.power.readOp.dynamic *1e6 << " (nJ/mm)" 791 " \n\tPowerL - " << global.power.readOp.leakage << " (mW/mm)" 792 " \n\tPowerLgate - " << global.power.readOp.gate_leakage << 793 " (mW/mm)\n"; 794 cout << "\tWire width - " << wire_width_init*1e6 << " microns\n"; 795 cout << "\tWire spacing - " << wire_spacing_init*1e6 << " microns\n"; 796 cout << endl; 797 798 cout << " 5% Overhead\n\tRepeater size - " << global_5.area.h << 799 " \n\tRepeater spacing - " << global_5.area.w*1e3 << " (mm)" 800 " \n\tDelay - " << global_5.delay *1e6 << " (ns/mm)" 801 " \n\tPowerD - " << global_5.power.readOp.dynamic *1e6 << " (nJ/mm)" 802 " \n\tPowerL - " << global_5.power.readOp.leakage << " (mW/mm)" 803 " \n\tPowerLgate - " << global_5.power.readOp.gate_leakage << 804 " (mW/mm)\n"; 805 cout << "\tWire width - " << wire_width_init*1e6 << " microns\n"; 806 cout << "\tWire spacing - " << wire_spacing_init*1e6 << " microns\n"; 807 cout << endl; 808 cout << " 10% Overhead\n\tRepeater size - " << global_10.area.h << 809 " \n\tRepeater spacing - " << global_10.area.w*1e3 << " (mm)" 810 " \n\tDelay - " << global_10.delay *1e6 << " (ns/mm)" 811 " \n\tPowerD - " << global_10.power.readOp.dynamic *1e6 << " (nJ/mm)" 812 " \n\tPowerL - " << global_10.power.readOp.leakage << " (mW/mm)" 813 " \n\tPowerLgate - " << global_10.power.readOp.gate_leakage << 814 " (mW/mm)\n"; 815 cout << "\tWire width - " << wire_width_init*1e6 << " microns\n"; 816 cout << "\tWire spacing - " << wire_spacing_init*1e6 << " microns\n"; 817 cout << endl; 818 cout << " 20% Overhead\n\tRepeater size - " << global_20.area.h << 819 " \n\tRepeater spacing - " << global_20.area.w*1e3 << " (mm)" 820 " \n\tDelay - " << global_20.delay *1e6 << " (ns/mm)" 821 " \n\tPowerD - " << global_20.power.readOp.dynamic *1e6 << " (nJ/mm)" 822 " \n\tPowerL - " << global_20.power.readOp.leakage << " (mW/mm)" 823 " \n\tPowerLgate - " << global_20.power.readOp.gate_leakage << 824 " (mW/mm)\n"; 825 cout << "\tWire width - " << wire_width_init*1e6 << " microns\n"; 826 cout << "\tWire spacing - " << wire_spacing_init*1e6 << " microns\n"; 827 cout << endl; 828 cout << " 30% Overhead\n\tRepeater size - " << global_30.area.h << 829 " \n\tRepeater spacing - " << global_30.area.w*1e3 << " (mm)" 830 " \n\tDelay - " << global_30.delay *1e6 << " (ns/mm)" 831 " \n\tPowerD - " << global_30.power.readOp.dynamic *1e6 << " (nJ/mm)" 832 " \n\tPowerL - " << global_30.power.readOp.leakage << " (mW/mm)" 833 " \n\tPowerLgate - " << global_30.power.readOp.gate_leakage << 834 " (mW/mm)\n"; 835 cout << "\tWire width - " << wire_width_init*1e6 << " microns\n"; 836 cout << "\tWire spacing - " << wire_spacing_init*1e6 << " microns\n"; 837 cout << endl; 838 cout << " Low-swing wire (1 mm) - Note: Unlike repeated wires, \n\t" << 839 "delay and power values of low-swing wires do not\n\t" << 840 "have a linear relationship with length." << 841 " \n\tdelay - " << low_swing.delay *1e9 << " (ns)" 842 " \n\tpowerD - " << low_swing.power.readOp.dynamic *1e9 << " (nJ)" 843 " \n\tPowerL - " << low_swing.power.readOp.leakage << " (mW)" 844 " \n\tPowerLgate - " << low_swing.power.readOp.gate_leakage << 845 " (mW)\n"; 846 cout << "\tWire width - " << wire_width_init * 2 /* differential */ << 847 " microns\n"; 848 cout << "\tWire spacing - " << wire_spacing_init * 2 /* differential */ << 849 " microns\n"; 850 cout << endl; 851 cout << endl; 852 853} 854 855