Deleted Added
sdiff udiff text old ( 10152:52c552138ba1 ) new ( 10234:5cb711fa6176 )
full compact
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

--- 7 unchanged lines hidden (view full) ---

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