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