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