2014-04-01 18:44:30 +02:00
|
|
|
/*****************************************************************************
|
|
|
|
* McPAT/CACTI
|
|
|
|
* SOFTWARE LICENSE AGREEMENT
|
|
|
|
* Copyright 2012 Hewlett-Packard Development Company, L.P.
|
2014-06-03 22:32:59 +02:00
|
|
|
* Copyright (c) 2010-2013 Advanced Micro Devices, Inc.
|
2014-04-01 18:44:30 +02:00
|
|
|
* All Rights Reserved
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions are
|
|
|
|
* met: redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer;
|
|
|
|
* redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution;
|
|
|
|
* neither the name of the copyright holders nor the names of its
|
|
|
|
* contributors may be used to endorse or promote products derived from
|
|
|
|
* this software without specific prior written permission.
|
|
|
|
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
2014-06-03 22:32:59 +02:00
|
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
2014-04-01 18:44:30 +02:00
|
|
|
*
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
#include "wire.h"
|
|
|
|
#include "cmath"
|
|
|
|
// use this constructor to calculate wire stats
|
|
|
|
Wire::Wire(
|
|
|
|
enum Wire_type wire_model,
|
|
|
|
double wl,
|
|
|
|
int n,
|
|
|
|
double w_s,
|
|
|
|
double s_s,
|
|
|
|
enum Wire_placement wp,
|
|
|
|
double resistivity,
|
|
|
|
TechnologyParameter::DeviceType *dt
|
2014-06-03 22:32:59 +02:00
|
|
|
): wt(wire_model), wire_length(wl*1e-6), nsense(n), w_scale(w_s),
|
|
|
|
s_scale(s_s),
|
|
|
|
resistivity(resistivity), deviceType(dt) {
|
|
|
|
wire_placement = wp;
|
|
|
|
min_w_pmos = deviceType->n_to_p_eff_curr_drv_ratio * g_tp.min_w_nmos_;
|
|
|
|
in_rise_time = 0;
|
|
|
|
out_rise_time = 0;
|
|
|
|
if (initialized != 1) {
|
|
|
|
cout << "Wire not initialized. Initializing it with default values\n";
|
|
|
|
Wire winit;
|
|
|
|
}
|
|
|
|
calculate_wire_stats();
|
|
|
|
// change everything back to seconds, microns, and Joules
|
|
|
|
repeater_spacing *= 1e6;
|
|
|
|
wire_length *= 1e6;
|
|
|
|
wire_width *= 1e6;
|
|
|
|
wire_spacing *= 1e6;
|
|
|
|
assert(wire_length > 0);
|
|
|
|
assert(power.readOp.dynamic > 0);
|
|
|
|
assert(power.readOp.leakage > 0);
|
|
|
|
assert(power.readOp.gate_leakage > 0);
|
2014-04-01 18:44:30 +02:00
|
|
|
}
|
|
|
|
|
2014-06-03 22:32:59 +02:00
|
|
|
// the following values are for peripheral global technology
|
|
|
|
// specified in the input config file
|
|
|
|
Component Wire::global;
|
|
|
|
Component Wire::global_5;
|
|
|
|
Component Wire::global_10;
|
|
|
|
Component Wire::global_20;
|
|
|
|
Component Wire::global_30;
|
|
|
|
Component Wire::low_swing;
|
|
|
|
|
|
|
|
int Wire::initialized;
|
|
|
|
double Wire::wire_width_init;
|
|
|
|
double Wire::wire_spacing_init;
|
|
|
|
|
|
|
|
|
|
|
|
Wire::Wire(double w_s, double s_s, enum Wire_placement wp, double resis,
|
|
|
|
TechnologyParameter::DeviceType *dt) {
|
|
|
|
w_scale = w_s;
|
|
|
|
s_scale = s_s;
|
|
|
|
deviceType = dt;
|
|
|
|
wire_placement = wp;
|
|
|
|
resistivity = resis;
|
|
|
|
min_w_pmos = deviceType->n_to_p_eff_curr_drv_ratio * g_tp.min_w_nmos_;
|
|
|
|
in_rise_time = 0;
|
|
|
|
out_rise_time = 0;
|
|
|
|
|
|
|
|
switch (wire_placement) {
|
|
|
|
case outside_mat:
|
|
|
|
wire_width = g_tp.wire_outside_mat.pitch;
|
|
|
|
break;
|
|
|
|
case inside_mat :
|
|
|
|
wire_width = g_tp.wire_inside_mat.pitch;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
wire_width = g_tp.wire_local.pitch;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
wire_spacing = wire_width;
|
|
|
|
|
|
|
|
wire_width *= (w_scale * 1e-6 / 2) /* (m) */;
|
|
|
|
wire_spacing *= (s_scale * 1e-6 / 2) /* (m) */;
|
|
|
|
|
|
|
|
initialized = 1;
|
|
|
|
init_wire();
|
|
|
|
wire_width_init = wire_width;
|
|
|
|
wire_spacing_init = wire_spacing;
|
|
|
|
|
|
|
|
assert(power.readOp.dynamic > 0);
|
|
|
|
assert(power.readOp.leakage > 0);
|
|
|
|
assert(power.readOp.gate_leakage > 0);
|
2014-04-01 18:44:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-06-03 22:32:59 +02:00
|
|
|
Wire::~Wire() {
|
2014-04-01 18:44:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2014-06-03 22:32:59 +02:00
|
|
|
Wire::calculate_wire_stats() {
|
|
|
|
|
|
|
|
if (wire_placement == outside_mat) {
|
|
|
|
wire_width = g_tp.wire_outside_mat.pitch;
|
|
|
|
} else if (wire_placement == inside_mat) {
|
|
|
|
wire_width = g_tp.wire_inside_mat.pitch;
|
|
|
|
} else {
|
|
|
|
wire_width = g_tp.wire_local.pitch;
|
|
|
|
}
|
|
|
|
|
|
|
|
wire_spacing = wire_width;
|
|
|
|
|
|
|
|
wire_width *= (w_scale * 1e-6 / 2) /* (m) */;
|
|
|
|
wire_spacing *= (s_scale * 1e-6 / 2) /* (m) */;
|
|
|
|
|
|
|
|
|
|
|
|
if (wt != Low_swing) {
|
|
|
|
|
|
|
|
// delay_optimal_wire();
|
|
|
|
|
|
|
|
if (wt == Global) {
|
|
|
|
delay = global.delay * wire_length;
|
|
|
|
power.readOp.dynamic = global.power.readOp.dynamic * wire_length;
|
|
|
|
power.readOp.leakage = global.power.readOp.leakage * wire_length;
|
|
|
|
power.readOp.gate_leakage = global.power.readOp.gate_leakage * wire_length;
|
|
|
|
repeater_spacing = global.area.w;
|
|
|
|
repeater_size = global.area.h;
|
|
|
|
area.set_area((wire_length / repeater_spacing) *
|
|
|
|
compute_gate_area(INV, 1, min_w_pmos * repeater_size,
|
|
|
|
g_tp.min_w_nmos_ * repeater_size,
|
|
|
|
g_tp.cell_h_def));
|
|
|
|
} else if (wt == Global_5) {
|
|
|
|
delay = global_5.delay * wire_length;
|
|
|
|
power.readOp.dynamic = global_5.power.readOp.dynamic * wire_length;
|
|
|
|
power.readOp.leakage = global_5.power.readOp.leakage * wire_length;
|
|
|
|
power.readOp.gate_leakage = global_5.power.readOp.gate_leakage * wire_length;
|
|
|
|
repeater_spacing = global_5.area.w;
|
|
|
|
repeater_size = global_5.area.h;
|
|
|
|
area.set_area((wire_length / repeater_spacing) *
|
|
|
|
compute_gate_area(INV, 1, min_w_pmos * repeater_size,
|
|
|
|
g_tp.min_w_nmos_ * repeater_size,
|
|
|
|
g_tp.cell_h_def));
|
|
|
|
} else if (wt == Global_10) {
|
|
|
|
delay = global_10.delay * wire_length;
|
|
|
|
power.readOp.dynamic = global_10.power.readOp.dynamic * wire_length;
|
|
|
|
power.readOp.leakage = global_10.power.readOp.leakage * wire_length;
|
|
|
|
power.readOp.gate_leakage = global_10.power.readOp.gate_leakage * wire_length;
|
|
|
|
repeater_spacing = global_10.area.w;
|
|
|
|
repeater_size = global_10.area.h;
|
|
|
|
area.set_area((wire_length / repeater_spacing) *
|
|
|
|
compute_gate_area(INV, 1, min_w_pmos * repeater_size,
|
|
|
|
g_tp.min_w_nmos_ * repeater_size,
|
|
|
|
g_tp.cell_h_def));
|
|
|
|
} else if (wt == Global_20) {
|
|
|
|
delay = global_20.delay * wire_length;
|
|
|
|
power.readOp.dynamic = global_20.power.readOp.dynamic * wire_length;
|
|
|
|
power.readOp.leakage = global_20.power.readOp.leakage * wire_length;
|
|
|
|
power.readOp.gate_leakage = global_20.power.readOp.gate_leakage * wire_length;
|
|
|
|
repeater_spacing = global_20.area.w;
|
|
|
|
repeater_size = global_20.area.h;
|
|
|
|
area.set_area((wire_length / repeater_spacing) *
|
|
|
|
compute_gate_area(INV, 1, min_w_pmos * repeater_size,
|
|
|
|
g_tp.min_w_nmos_ * repeater_size,
|
|
|
|
g_tp.cell_h_def));
|
|
|
|
} else if (wt == Global_30) {
|
|
|
|
delay = global_30.delay * wire_length;
|
|
|
|
power.readOp.dynamic = global_30.power.readOp.dynamic * wire_length;
|
|
|
|
power.readOp.leakage = global_30.power.readOp.leakage * wire_length;
|
|
|
|
power.readOp.gate_leakage = global_30.power.readOp.gate_leakage * wire_length;
|
|
|
|
repeater_spacing = global_30.area.w;
|
|
|
|
repeater_size = global_30.area.h;
|
|
|
|
area.set_area((wire_length / repeater_spacing) *
|
|
|
|
compute_gate_area(INV, 1, min_w_pmos * repeater_size,
|
|
|
|
g_tp.min_w_nmos_ * repeater_size,
|
|
|
|
g_tp.cell_h_def));
|
|
|
|
}
|
|
|
|
out_rise_time = delay * repeater_spacing / deviceType->Vth;
|
|
|
|
} else if (wt == Low_swing) {
|
|
|
|
low_swing_model ();
|
|
|
|
repeater_spacing = wire_length;
|
|
|
|
repeater_size = 1;
|
|
|
|
} else {
|
|
|
|
assert(0);
|
|
|
|
}
|
2014-04-01 18:44:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The fall time of an input signal to the first stage of a circuit is
|
|
|
|
* assumed to be same as the fall time of the output signal of two
|
|
|
|
* inverters connected in series (refer: CACTI 1 Technical report,
|
|
|
|
* section 6.1.3)
|
|
|
|
*/
|
2014-06-03 22:32:59 +02:00
|
|
|
double
|
|
|
|
Wire::signal_fall_time () {
|
|
|
|
|
|
|
|
/* rise time of inverter 1's output */
|
|
|
|
double rt;
|
|
|
|
/* fall time of inverter 2's output */
|
|
|
|
double ft;
|
|
|
|
double timeconst;
|
|
|
|
|
|
|
|
timeconst = (drain_C_(g_tp.min_w_nmos_, NCH, 1, 1, g_tp.cell_h_def) +
|
|
|
|
drain_C_(min_w_pmos, PCH, 1, 1, g_tp.cell_h_def) +
|
|
|
|
gate_C(min_w_pmos + g_tp.min_w_nmos_, 0)) *
|
|
|
|
tr_R_on(min_w_pmos, PCH, 1);
|
|
|
|
rt = horowitz (0, timeconst, deviceType->Vth / deviceType->Vdd,
|
|
|
|
deviceType->Vth / deviceType->Vdd, FALL) /
|
|
|
|
(deviceType->Vdd - deviceType->Vth);
|
|
|
|
timeconst = (drain_C_(g_tp.min_w_nmos_, NCH, 1, 1, g_tp.cell_h_def) +
|
|
|
|
drain_C_(min_w_pmos, PCH, 1, 1, g_tp.cell_h_def) +
|
|
|
|
gate_C(min_w_pmos + g_tp.min_w_nmos_, 0)) *
|
|
|
|
tr_R_on(g_tp.min_w_nmos_, NCH, 1);
|
|
|
|
ft = horowitz (rt, timeconst, deviceType->Vth / deviceType->Vdd,
|
|
|
|
deviceType->Vth / deviceType->Vdd, RISE) / deviceType->Vth;
|
|
|
|
return ft;
|
2014-04-01 18:44:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-06-03 22:32:59 +02:00
|
|
|
double Wire::signal_rise_time () {
|
|
|
|
|
|
|
|
/* rise time of inverter 1's output */
|
|
|
|
double ft;
|
|
|
|
/* fall time of inverter 2's output */
|
|
|
|
double rt;
|
|
|
|
double timeconst;
|
|
|
|
|
|
|
|
timeconst = (drain_C_(g_tp.min_w_nmos_, NCH, 1, 1, g_tp.cell_h_def) +
|
|
|
|
drain_C_(min_w_pmos, PCH, 1, 1, g_tp.cell_h_def) +
|
|
|
|
gate_C(min_w_pmos + g_tp.min_w_nmos_, 0)) *
|
|
|
|
tr_R_on(g_tp.min_w_nmos_, NCH, 1);
|
|
|
|
rt = horowitz (0, timeconst, deviceType->Vth / deviceType->Vdd,
|
|
|
|
deviceType->Vth / deviceType->Vdd, RISE) / deviceType->Vth;
|
|
|
|
timeconst = (drain_C_(g_tp.min_w_nmos_, NCH, 1, 1, g_tp.cell_h_def) +
|
|
|
|
drain_C_(min_w_pmos, PCH, 1, 1, g_tp.cell_h_def) +
|
|
|
|
gate_C(min_w_pmos + g_tp.min_w_nmos_, 0)) *
|
|
|
|
tr_R_on(min_w_pmos, PCH, 1);
|
|
|
|
ft = horowitz (rt, timeconst, deviceType->Vth / deviceType->Vdd,
|
|
|
|
deviceType->Vth / deviceType->Vdd, FALL) /
|
|
|
|
(deviceType->Vdd - deviceType->Vth);
|
|
|
|
return ft; //sec
|
2014-04-01 18:44:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Wire resistance and capacitance calculations
|
|
|
|
* wire width
|
|
|
|
*
|
|
|
|
* /__/
|
|
|
|
* | |
|
|
|
|
* | | height = ASPECT_RATIO*wire width (ASPECT_RATIO = 2.2, ref: ITRS)
|
|
|
|
* |__|/
|
|
|
|
*
|
|
|
|
* spacing between wires in same level = wire width
|
|
|
|
* spacing between wires in adjacent levels = wire width---this is incorrect,
|
|
|
|
* according to R.Ho's paper and thesis. ILD != wire width
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2014-06-03 22:32:59 +02:00
|
|
|
double Wire::wire_cap (double len /* in m */, bool call_from_outside) {
|
|
|
|
//TODO: this should be consistent with the wire_res in technology file
|
|
|
|
double sidewall, adj, tot_cap;
|
|
|
|
double wire_height;
|
|
|
|
double epsilon0 = 8.8542e-12;
|
|
|
|
double aspect_ratio;
|
|
|
|
double horiz_dielectric_constant;
|
|
|
|
double vert_dielectric_constant;
|
|
|
|
double miller_value;
|
|
|
|
double ild_thickness;
|
|
|
|
|
|
|
|
switch (wire_placement) {
|
|
|
|
case outside_mat: {
|
|
|
|
aspect_ratio = g_tp.wire_outside_mat.aspect_ratio;
|
|
|
|
horiz_dielectric_constant = g_tp.wire_outside_mat.horiz_dielectric_constant;
|
|
|
|
vert_dielectric_constant = g_tp.wire_outside_mat.vert_dielectric_constant;
|
|
|
|
miller_value = g_tp.wire_outside_mat.miller_value;
|
|
|
|
ild_thickness = g_tp.wire_outside_mat.ild_thickness;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case inside_mat : {
|
|
|
|
aspect_ratio = g_tp.wire_inside_mat.aspect_ratio;
|
|
|
|
horiz_dielectric_constant = g_tp.wire_inside_mat.horiz_dielectric_constant;
|
|
|
|
vert_dielectric_constant = g_tp.wire_inside_mat.vert_dielectric_constant;
|
|
|
|
miller_value = g_tp.wire_inside_mat.miller_value;
|
|
|
|
ild_thickness = g_tp.wire_inside_mat.ild_thickness;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default: {
|
|
|
|
aspect_ratio = g_tp.wire_local.aspect_ratio;
|
|
|
|
horiz_dielectric_constant = g_tp.wire_local.horiz_dielectric_constant;
|
|
|
|
vert_dielectric_constant = g_tp.wire_local.vert_dielectric_constant;
|
|
|
|
miller_value = g_tp.wire_local.miller_value;
|
|
|
|
ild_thickness = g_tp.wire_local.ild_thickness;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2014-04-01 18:44:30 +02:00
|
|
|
|
2014-06-03 22:32:59 +02:00
|
|
|
if (call_from_outside) {
|
|
|
|
wire_width *= 1e-6;
|
|
|
|
wire_spacing *= 1e-6;
|
|
|
|
}
|
|
|
|
wire_height = wire_width / w_scale * aspect_ratio;
|
|
|
|
/*
|
|
|
|
* assuming height does not change. wire_width = width_original*w_scale
|
|
|
|
* So wire_height does not change as wire width increases
|
|
|
|
*/
|
2014-04-01 18:44:30 +02:00
|
|
|
|
|
|
|
// capacitance between wires in the same level
|
|
|
|
// sidewall = 2*miller_value * horiz_dielectric_constant * (wire_height/wire_spacing)
|
|
|
|
// * epsilon0;
|
|
|
|
|
2014-06-03 22:32:59 +02:00
|
|
|
sidewall = miller_value * horiz_dielectric_constant *
|
|
|
|
(wire_height / wire_spacing)
|
|
|
|
* epsilon0;
|
2014-04-01 18:44:30 +02:00
|
|
|
|
|
|
|
|
2014-06-03 22:32:59 +02:00
|
|
|
// capacitance between wires in adjacent levels
|
|
|
|
//adj = miller_value * vert_dielectric_constant *w_scale * epsilon0;
|
|
|
|
//adj = 2*vert_dielectric_constant *wire_width/(ild_thickness*1e-6) * epsilon0;
|
2014-04-01 18:44:30 +02:00
|
|
|
|
2014-06-03 22:32:59 +02:00
|
|
|
adj = miller_value * vert_dielectric_constant * wire_width /
|
|
|
|
(ild_thickness * 1e-6) * epsilon0;
|
|
|
|
//Change ild_thickness from micron to M
|
2014-04-01 18:44:30 +02:00
|
|
|
|
2014-06-03 22:32:59 +02:00
|
|
|
//tot_cap = (sidewall + adj + (deviceType->C_fringe * 1e6)); //F/m
|
|
|
|
tot_cap = (sidewall + adj + (g_tp.fringe_cap * 1e6)); //F/m
|
2014-04-01 18:44:30 +02:00
|
|
|
|
2014-06-03 22:32:59 +02:00
|
|
|
if (call_from_outside) {
|
|
|
|
wire_width *= 1e6;
|
|
|
|
wire_spacing *= 1e6;
|
|
|
|
}
|
|
|
|
return (tot_cap*len); // (F)
|
2014-04-01 18:44:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-06-03 22:32:59 +02:00
|
|
|
double
|
|
|
|
Wire::wire_res (double len /*(in m)*/) {
|
|
|
|
|
|
|
|
double aspect_ratio;
|
|
|
|
double alpha_scatter = 1.05;
|
|
|
|
double dishing_thickness = 0;
|
|
|
|
double barrier_thickness = 0;
|
|
|
|
//TODO: this should be consistent with the wire_res in technology file
|
|
|
|
//The whole computation should be consistent with the wire_res in technology.cc too!
|
|
|
|
|
|
|
|
switch (wire_placement) {
|
|
|
|
case outside_mat: {
|
|
|
|
aspect_ratio = g_tp.wire_outside_mat.aspect_ratio;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case inside_mat : {
|
|
|
|
aspect_ratio = g_tp.wire_inside_mat.aspect_ratio;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default: {
|
|
|
|
aspect_ratio = g_tp.wire_local.aspect_ratio;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return (alpha_scatter * resistivity * 1e-6 * len /
|
|
|
|
((aspect_ratio*wire_width / w_scale - dishing_thickness -
|
|
|
|
barrier_thickness)*
|
|
|
|
(wire_width - 2*barrier_thickness)));
|
2014-04-01 18:44:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Calculates the delay, power and area of the transmitter circuit.
|
|
|
|
*
|
|
|
|
* The transmitter delay is the sum of nand gate delay, inverter delay
|
|
|
|
* low swing nmos delay, and the wire delay
|
|
|
|
* (ref: Technical report 6)
|
|
|
|
*/
|
2014-06-03 22:32:59 +02:00
|
|
|
void
|
|
|
|
Wire::low_swing_model() {
|
|
|
|
double len = wire_length;
|
|
|
|
double beta = pmos_to_nmos_sz_ratio();
|
|
|
|
|
|
|
|
|
|
|
|
double inputrise = (in_rise_time == 0) ? signal_rise_time() : in_rise_time;
|
|
|
|
|
|
|
|
/* Final nmos low swing driver size calculation:
|
|
|
|
* Try to size the driver such that the delay
|
|
|
|
* is less than 8FO4.
|
|
|
|
* If the driver size is greater than
|
|
|
|
* the max allowable size, assume max size for the driver.
|
|
|
|
* In either case, recalculate the delay using
|
|
|
|
* the final driver size assuming slow input with
|
|
|
|
* finite rise time instead of ideal step input
|
|
|
|
*
|
|
|
|
* (ref: Technical report 6)
|
|
|
|
*/
|
|
|
|
double cwire = wire_cap(len); /* load capacitance */
|
|
|
|
double rwire = wire_res(len);
|
2014-04-01 18:44:30 +02:00
|
|
|
|
|
|
|
#define RES_ADJ (8.6) // Increase in resistance due to low driving vol.
|
|
|
|
|
2014-06-03 22:32:59 +02:00
|
|
|
double driver_res = (-8 * g_tp.FO4 / (log(0.5) * cwire)) / RES_ADJ;
|
|
|
|
double nsize = R_to_w(driver_res, NCH);
|
|
|
|
|
|
|
|
nsize = MIN(nsize, g_tp.max_w_nmos_);
|
|
|
|
nsize = MAX(nsize, g_tp.min_w_nmos_);
|
|
|
|
|
|
|
|
if (rwire*cwire > 8*g_tp.FO4) {
|
|
|
|
nsize = g_tp.max_w_nmos_;
|
|
|
|
}
|
|
|
|
|
|
|
|
// size the inverter appropriately to minimize the transmitter delay
|
|
|
|
// Note - In order to minimize leakage, we are not adding a set of inverters to
|
|
|
|
// bring down delay. Instead, we are sizing the single gate
|
|
|
|
// based on the logical effort.
|
|
|
|
double st_eff = sqrt((2 + beta / 1 + beta) * gate_C(nsize, 0) /
|
|
|
|
(gate_C(2 * g_tp.min_w_nmos_, 0)
|
|
|
|
+ gate_C(2 * min_w_pmos, 0)));
|
|
|
|
double req_cin = ((2 + beta / 1 + beta) * gate_C(nsize, 0)) / st_eff;
|
|
|
|
double inv_size = req_cin / (gate_C(min_w_pmos, 0) +
|
|
|
|
gate_C(g_tp.min_w_nmos_, 0));
|
|
|
|
inv_size = MAX(inv_size, 1);
|
|
|
|
|
|
|
|
/* nand gate delay */
|
|
|
|
double res_eq = (2 * tr_R_on(g_tp.min_w_nmos_, NCH, 1));
|
|
|
|
double cap_eq = 2 * drain_C_(min_w_pmos, PCH, 1, 1, g_tp.cell_h_def) +
|
|
|
|
drain_C_(2 * g_tp.min_w_nmos_, NCH, 1, 1, g_tp.cell_h_def) +
|
|
|
|
gate_C(inv_size * g_tp.min_w_nmos_, 0) +
|
|
|
|
gate_C(inv_size * min_w_pmos, 0);
|
|
|
|
|
|
|
|
double timeconst = res_eq * cap_eq;
|
|
|
|
|
|
|
|
delay = horowitz(inputrise, timeconst, deviceType->Vth / deviceType->Vdd,
|
|
|
|
deviceType->Vth / deviceType->Vdd, RISE);
|
|
|
|
double temp_power = cap_eq * deviceType->Vdd * deviceType->Vdd;
|
|
|
|
|
|
|
|
inputrise = delay / (deviceType->Vdd - deviceType->Vth); /* for the next stage */
|
|
|
|
|
|
|
|
/* Inverter delay:
|
|
|
|
* The load capacitance of this inv depends on
|
|
|
|
* the gate capacitance of the final stage nmos
|
|
|
|
* transistor which in turn depends on nsize
|
|
|
|
*/
|
|
|
|
res_eq = tr_R_on(inv_size * min_w_pmos, PCH, 1);
|
|
|
|
cap_eq = drain_C_(inv_size * min_w_pmos, PCH, 1, 1, g_tp.cell_h_def) +
|
|
|
|
drain_C_(inv_size * g_tp.min_w_nmos_, NCH, 1, 1, g_tp.cell_h_def) +
|
|
|
|
gate_C(nsize, 0);
|
|
|
|
timeconst = res_eq * cap_eq;
|
|
|
|
|
|
|
|
delay += horowitz(inputrise, timeconst, deviceType->Vth / deviceType->Vdd,
|
|
|
|
deviceType->Vth / deviceType->Vdd, FALL);
|
|
|
|
temp_power += cap_eq * deviceType->Vdd * deviceType->Vdd;
|
|
|
|
|
|
|
|
|
|
|
|
transmitter.delay = delay;
|
|
|
|
/* since it is a diff. model*/
|
|
|
|
transmitter.power.readOp.dynamic = temp_power * 2;
|
|
|
|
transmitter.power.readOp.leakage = deviceType->Vdd *
|
|
|
|
(4 * cmos_Isub_leakage(g_tp.min_w_nmos_, min_w_pmos, 2, nand) +
|
|
|
|
4 * cmos_Isub_leakage(g_tp.min_w_nmos_, min_w_pmos, 1, inv));
|
|
|
|
|
|
|
|
transmitter.power.readOp.gate_leakage = deviceType->Vdd *
|
|
|
|
(4 * cmos_Ig_leakage(g_tp.min_w_nmos_, min_w_pmos, 2, nand) +
|
|
|
|
4 * cmos_Ig_leakage(g_tp.min_w_nmos_, min_w_pmos, 1, inv));
|
|
|
|
|
|
|
|
inputrise = delay / deviceType->Vth;
|
|
|
|
|
|
|
|
/* nmos delay + wire delay */
|
|
|
|
cap_eq = cwire + drain_C_(nsize, NCH, 1, 1, g_tp.cell_h_def) * 2 +
|
|
|
|
nsense * sense_amp_input_cap(); //+receiver cap
|
|
|
|
/*
|
|
|
|
* NOTE: nmos is used as both pull up and pull down transistor
|
|
|
|
* in the transmitter. This is because for low voltage swing, drive
|
|
|
|
* resistance of nmos is less than pmos
|
|
|
|
* (for a detailed graph ref: On-Chip Wires: Scaling and Efficiency)
|
|
|
|
*/
|
|
|
|
timeconst = (tr_R_on(nsize, NCH, 1) * RES_ADJ) * (cwire +
|
|
|
|
drain_C_(nsize, NCH, 1, 1, g_tp.cell_h_def) * 2) +
|
|
|
|
rwire * cwire / 2 +
|
|
|
|
(tr_R_on(nsize, NCH, 1) * RES_ADJ + rwire) *
|
|
|
|
nsense * sense_amp_input_cap();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* since we are pre-equalizing and overdriving the low
|
|
|
|
* swing wires, the net time constant is less
|
|
|
|
* than the actual value
|
|
|
|
*/
|
|
|
|
delay += horowitz(inputrise, timeconst, deviceType->Vth /
|
|
|
|
deviceType->Vdd, .25, 0);
|
2014-04-01 18:44:30 +02:00
|
|
|
#define VOL_SWING .1
|
2014-06-03 22:32:59 +02:00
|
|
|
temp_power += cap_eq * VOL_SWING * .400; /* .4v is the over drive voltage */
|
|
|
|
temp_power *= 2; /* differential wire */
|
|
|
|
|
|
|
|
l_wire.delay = delay - transmitter.delay;
|
|
|
|
l_wire.power.readOp.dynamic = temp_power - transmitter.power.readOp.dynamic;
|
|
|
|
l_wire.power.readOp.leakage = deviceType->Vdd *
|
|
|
|
(4 * cmos_Isub_leakage(nsize, 0, 1, nmos));
|
|
|
|
|
|
|
|
l_wire.power.readOp.gate_leakage = deviceType->Vdd *
|
|
|
|
(4 * cmos_Ig_leakage(nsize, 0, 1, nmos));
|
|
|
|
|
|
|
|
//double rt = horowitz(inputrise, timeconst, deviceType->Vth/deviceType->Vdd,
|
|
|
|
// deviceType->Vth/deviceType->Vdd, RISE)/deviceType->Vth;
|
|
|
|
|
|
|
|
delay += g_tp.sense_delay;
|
|
|
|
|
|
|
|
sense_amp.delay = g_tp.sense_delay;
|
|
|
|
out_rise_time = g_tp.sense_delay / (deviceType->Vth);
|
|
|
|
sense_amp.power.readOp.dynamic = g_tp.sense_dy_power;
|
|
|
|
sense_amp.power.readOp.leakage = 0; //FIXME
|
|
|
|
sense_amp.power.readOp.gate_leakage = 0;
|
|
|
|
|
|
|
|
power.readOp.dynamic = temp_power + sense_amp.power.readOp.dynamic;
|
|
|
|
power.readOp.leakage = transmitter.power.readOp.leakage +
|
|
|
|
l_wire.power.readOp.leakage +
|
|
|
|
sense_amp.power.readOp.leakage;
|
|
|
|
power.readOp.gate_leakage = transmitter.power.readOp.gate_leakage +
|
|
|
|
l_wire.power.readOp.gate_leakage +
|
|
|
|
sense_amp.power.readOp.gate_leakage;
|
2014-04-01 18:44:30 +02:00
|
|
|
}
|
|
|
|
|
2014-06-03 22:32:59 +02:00
|
|
|
double
|
|
|
|
Wire::sense_amp_input_cap() {
|
|
|
|
return drain_C_(g_tp.w_iso, PCH, 1, 1, g_tp.cell_h_def) +
|
|
|
|
gate_C(g_tp.w_sense_en + g_tp.w_sense_n, 0) +
|
|
|
|
drain_C_(g_tp.w_sense_n, NCH, 1, 1, g_tp.cell_h_def) +
|
|
|
|
drain_C_(g_tp.w_sense_p, PCH, 1, 1, g_tp.cell_h_def);
|
2014-04-01 18:44:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-06-03 22:32:59 +02:00
|
|
|
void Wire::delay_optimal_wire () {
|
|
|
|
double len = wire_length;
|
|
|
|
//double min_wire_width = wire_width; //m
|
|
|
|
double beta = pmos_to_nmos_sz_ratio();
|
|
|
|
double switching = 0; // switching energy
|
|
|
|
double short_ckt = 0; // short-circuit energy
|
|
|
|
double tc = 0; // time constant
|
|
|
|
// input cap of min sized driver
|
|
|
|
double input_cap = gate_C(g_tp.min_w_nmos_ + min_w_pmos, 0);
|
2014-04-01 18:44:30 +02:00
|
|
|
|
2014-06-03 22:32:59 +02:00
|
|
|
// output parasitic capacitance of
|
|
|
|
// the min. sized driver
|
|
|
|
double out_cap = drain_C_(min_w_pmos, PCH, 1, 1, g_tp.cell_h_def) +
|
|
|
|
drain_C_(g_tp.min_w_nmos_, NCH, 1, 1, g_tp.cell_h_def);
|
|
|
|
// drive resistance
|
|
|
|
double out_res = (tr_R_on(g_tp.min_w_nmos_, NCH, 1) +
|
|
|
|
tr_R_on(min_w_pmos, PCH, 1)) / 2;
|
|
|
|
double wr = wire_res(len); //ohm
|
2014-04-01 18:44:30 +02:00
|
|
|
|
2014-06-03 22:32:59 +02:00
|
|
|
// wire cap /m
|
|
|
|
double wc = wire_cap(len);
|
2014-04-01 18:44:30 +02:00
|
|
|
|
2014-06-03 22:32:59 +02:00
|
|
|
// size the repeater such that the delay of the wire is minimum
|
|
|
|
// len will cancel
|
|
|
|
double repeater_scaling = sqrt(out_res * wc / (wr * input_cap));
|
2014-04-01 18:44:30 +02:00
|
|
|
|
2014-06-03 22:32:59 +02:00
|
|
|
// calc the optimum spacing between the repeaters (m)
|
2014-04-01 18:44:30 +02:00
|
|
|
|
2014-06-03 22:32:59 +02:00
|
|
|
repeater_spacing = sqrt(2 * out_res * (out_cap + input_cap) /
|
|
|
|
((wr / len) * (wc / len)));
|
|
|
|
repeater_size = repeater_scaling;
|
2014-04-01 18:44:30 +02:00
|
|
|
|
2014-06-03 22:32:59 +02:00
|
|
|
switching = (repeater_scaling * (input_cap + out_cap) +
|
|
|
|
repeater_spacing * (wc / len)) * deviceType->Vdd *
|
|
|
|
deviceType->Vdd;
|
2014-04-01 18:44:30 +02:00
|
|
|
|
2014-06-03 22:32:59 +02:00
|
|
|
tc = out_res * (input_cap + out_cap) +
|
|
|
|
out_res * wc / len * repeater_spacing / repeater_scaling +
|
|
|
|
wr / len * repeater_spacing * input_cap * repeater_scaling +
|
|
|
|
0.5 * (wr / len) * (wc / len) * repeater_spacing * repeater_spacing;
|
2014-04-01 18:44:30 +02:00
|
|
|
|
2014-06-03 22:32:59 +02:00
|
|
|
delay = 0.693 * tc * len / repeater_spacing;
|
2014-04-01 18:44:30 +02:00
|
|
|
|
|
|
|
#define Ishort_ckt 65e-6 /* across all tech Ref:Banerjee et al. {IEEE TED} */
|
2014-06-03 22:32:59 +02:00
|
|
|
short_ckt = deviceType->Vdd * g_tp.min_w_nmos_ * Ishort_ckt * 1.0986 *
|
|
|
|
repeater_scaling * tc;
|
|
|
|
|
|
|
|
area.set_area((len / repeater_spacing) *
|
|
|
|
compute_gate_area(INV, 1, min_w_pmos * repeater_scaling,
|
|
|
|
g_tp.min_w_nmos_ * repeater_scaling,
|
|
|
|
g_tp.cell_h_def));
|
|
|
|
power.readOp.dynamic = ((len / repeater_spacing) * (switching + short_ckt));
|
|
|
|
power.readOp.leakage = ((len / repeater_spacing) *
|
|
|
|
deviceType->Vdd *
|
|
|
|
cmos_Isub_leakage(g_tp.min_w_nmos_ *
|
|
|
|
repeater_scaling, beta *
|
|
|
|
g_tp.min_w_nmos_ *
|
|
|
|
repeater_scaling, 1, inv));
|
|
|
|
power.readOp.gate_leakage = ((len / repeater_spacing) *
|
|
|
|
deviceType->Vdd *
|
|
|
|
cmos_Ig_leakage(g_tp.min_w_nmos_ *
|
|
|
|
repeater_scaling, beta *
|
|
|
|
g_tp.min_w_nmos_ *
|
|
|
|
repeater_scaling, 1, inv));
|
2014-04-01 18:44:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// calculate power/delay values for wires with suboptimal repeater sizing/spacing
|
|
|
|
void
|
2014-06-03 22:32:59 +02:00
|
|
|
Wire::init_wire() {
|
|
|
|
wire_length = 1;
|
|
|
|
delay_optimal_wire();
|
2014-04-01 18:44:30 +02:00
|
|
|
double sp, si;
|
2014-06-03 22:32:59 +02:00
|
|
|
powerDef pow;
|
|
|
|
si = repeater_size;
|
|
|
|
sp = repeater_spacing;
|
|
|
|
sp *= 1e6; // in microns
|
|
|
|
|
|
|
|
double i, j, del;
|
|
|
|
repeated_wire.push_back(Component());
|
|
|
|
for (j = sp; j < 4*sp; j += 100) {
|
|
|
|
for (i = si; i > 1; i--) {
|
|
|
|
pow = wire_model(j * 1e-6, i, &del);
|
|
|
|
if (j == sp && i == si) {
|
|
|
|
global.delay = del;
|
|
|
|
global.power = pow;
|
|
|
|
global.area.h = si;
|
|
|
|
global.area.w = sp * 1e-6; // m
|
|
|
|
}
|
2014-04-01 18:44:30 +02:00
|
|
|
// cout << "Repeater size - "<< i <<
|
|
|
|
// " Repeater spacing - " << j <<
|
|
|
|
// " Delay - " << del <<
|
|
|
|
// " PowerD - " << pow.readOp.dynamic <<
|
|
|
|
// " PowerL - " << pow.readOp.leakage <<endl;
|
2014-06-03 22:32:59 +02:00
|
|
|
repeated_wire.back().delay = del;
|
|
|
|
repeated_wire.back().power.readOp = pow.readOp;
|
|
|
|
repeated_wire.back().area.w = j * 1e-6; //m
|
|
|
|
repeated_wire.back().area.h = i;
|
|
|
|
repeated_wire.push_back(Component());
|
2014-04-01 18:44:30 +02:00
|
|
|
|
2014-06-03 22:32:59 +02:00
|
|
|
}
|
2014-04-01 18:44:30 +02:00
|
|
|
}
|
2014-06-03 22:32:59 +02:00
|
|
|
repeated_wire.pop_back();
|
|
|
|
update_fullswing();
|
|
|
|
Wire *l_wire = new Wire(Low_swing, 0.001/* 1 mm*/, 1);
|
|
|
|
low_swing.delay = l_wire->delay;
|
|
|
|
low_swing.power = l_wire->power;
|
|
|
|
delete l_wire;
|
2014-04-01 18:44:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-06-03 22:32:59 +02:00
|
|
|
void Wire::update_fullswing() {
|
|
|
|
|
|
|
|
list<Component>::iterator citer;
|
|
|
|
double del[4];
|
|
|
|
del[3] = this->global.delay + this->global.delay * .3;
|
|
|
|
del[2] = global.delay + global.delay * .2;
|
|
|
|
del[1] = global.delay + global.delay * .1;
|
|
|
|
del[0] = global.delay + global.delay * .05;
|
|
|
|
double threshold;
|
|
|
|
double ncost;
|
|
|
|
double cost;
|
|
|
|
int i = 4;
|
|
|
|
while (i > 0) {
|
|
|
|
threshold = del[i-1];
|
|
|
|
cost = BIGNUM;
|
|
|
|
for (citer = repeated_wire.begin(); citer != repeated_wire.end();
|
|
|
|
citer++) {
|
|
|
|
if (citer->delay > threshold) {
|
|
|
|
citer = repeated_wire.erase(citer);
|
|
|
|
citer --;
|
|
|
|
} else {
|
|
|
|
ncost = citer->power.readOp.dynamic /
|
|
|
|
global.power.readOp.dynamic +
|
|
|
|
citer->power.readOp.leakage / global.power.readOp.leakage;
|
|
|
|
if (ncost < cost) {
|
|
|
|
cost = ncost;
|
|
|
|
if (i == 4) {
|
|
|
|
global_30.delay = citer->delay;
|
|
|
|
global_30.power = citer->power;
|
|
|
|
global_30.area = citer->area;
|
|
|
|
} else if (i == 3) {
|
|
|
|
global_20.delay = citer->delay;
|
|
|
|
global_20.power = citer->power;
|
|
|
|
global_20.area = citer->area;
|
|
|
|
} else if (i == 2) {
|
|
|
|
global_10.delay = citer->delay;
|
|
|
|
global_10.power = citer->power;
|
|
|
|
global_10.area = citer->area;
|
|
|
|
} else if (i == 1) {
|
|
|
|
global_5.delay = citer->delay;
|
|
|
|
global_5.power = citer->power;
|
|
|
|
global_5.area = citer->area;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-04-01 18:44:30 +02:00
|
|
|
}
|
2014-06-03 22:32:59 +02:00
|
|
|
i--;
|
2014-04-01 18:44:30 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2014-06-03 22:32:59 +02:00
|
|
|
powerDef Wire::wire_model (double space, double size, double *delay) {
|
|
|
|
powerDef ptemp;
|
|
|
|
double len = 1;
|
|
|
|
//double min_wire_width = wire_width; //m
|
|
|
|
double beta = pmos_to_nmos_sz_ratio();
|
|
|
|
// switching energy
|
|
|
|
double switching = 0;
|
|
|
|
// short-circuit energy
|
|
|
|
double short_ckt = 0;
|
|
|
|
// time constant
|
|
|
|
double tc = 0;
|
|
|
|
// input cap of min sized driver
|
|
|
|
double input_cap = gate_C (g_tp.min_w_nmos_ +
|
|
|
|
min_w_pmos, 0);
|
|
|
|
|
|
|
|
// output parasitic capacitance of
|
|
|
|
// the min. sized driver
|
|
|
|
double out_cap = drain_C_(min_w_pmos, PCH, 1, 1, g_tp.cell_h_def) +
|
|
|
|
drain_C_(g_tp.min_w_nmos_, NCH, 1, 1, g_tp.cell_h_def);
|
|
|
|
// drive resistance
|
|
|
|
double out_res = (tr_R_on(g_tp.min_w_nmos_, NCH, 1) +
|
|
|
|
tr_R_on(min_w_pmos, PCH, 1)) / 2;
|
|
|
|
double wr = wire_res(len); //ohm
|
|
|
|
|
|
|
|
// wire cap /m
|
|
|
|
double wc = wire_cap(len);
|
|
|
|
|
|
|
|
repeater_spacing = space;
|
|
|
|
repeater_size = size;
|
|
|
|
|
|
|
|
switching = (repeater_size * (input_cap + out_cap) +
|
|
|
|
repeater_spacing * (wc / len)) * deviceType->Vdd *
|
|
|
|
deviceType->Vdd;
|
|
|
|
|
|
|
|
tc = out_res * (input_cap + out_cap) +
|
|
|
|
out_res * wc / len * repeater_spacing / repeater_size +
|
|
|
|
wr / len * repeater_spacing * out_cap * repeater_size +
|
|
|
|
0.5 * (wr / len) * (wc / len) * repeater_spacing * repeater_spacing;
|
|
|
|
|
|
|
|
*delay = 0.693 * tc * len / repeater_spacing;
|
2014-04-01 18:44:30 +02:00
|
|
|
|
|
|
|
#define Ishort_ckt 65e-6 /* across all tech Ref:Banerjee et al. {IEEE TED} */
|
2014-06-03 22:32:59 +02:00
|
|
|
short_ckt = deviceType->Vdd * g_tp.min_w_nmos_ * Ishort_ckt * 1.0986 *
|
|
|
|
repeater_size * tc;
|
|
|
|
|
|
|
|
ptemp.readOp.dynamic = ((len / repeater_spacing) * (switching + short_ckt));
|
|
|
|
ptemp.readOp.leakage = ((len / repeater_spacing) *
|
|
|
|
deviceType->Vdd *
|
|
|
|
cmos_Isub_leakage(g_tp.min_w_nmos_ *
|
|
|
|
repeater_size, beta *
|
|
|
|
g_tp.min_w_nmos_ *
|
|
|
|
repeater_size, 1, inv));
|
|
|
|
|
|
|
|
ptemp.readOp.gate_leakage = ((len / repeater_spacing) *
|
|
|
|
deviceType->Vdd *
|
|
|
|
cmos_Ig_leakage(g_tp.min_w_nmos_ *
|
|
|
|
repeater_size, beta *
|
|
|
|
g_tp.min_w_nmos_ *
|
|
|
|
repeater_size, 1, inv));
|
|
|
|
|
|
|
|
return ptemp;
|
2014-04-01 18:44:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2014-06-03 22:32:59 +02:00
|
|
|
Wire::print_wire() {
|
|
|
|
|
|
|
|
cout << "\nWire Properties:\n\n";
|
|
|
|
cout << " Delay Optimal\n\tRepeater size - " << global.area.h <<
|
|
|
|
" \n\tRepeater spacing - " << global.area.w*1e3 << " (mm)"
|
|
|
|
" \n\tDelay - " << global.delay*1e6 << " (ns/mm)"
|
|
|
|
" \n\tPowerD - " << global.power.readOp.dynamic *1e6 << " (nJ/mm)"
|
|
|
|
" \n\tPowerL - " << global.power.readOp.leakage << " (mW/mm)"
|
|
|
|
" \n\tPowerLgate - " << global.power.readOp.gate_leakage <<
|
|
|
|
" (mW/mm)\n";
|
|
|
|
cout << "\tWire width - " << wire_width_init*1e6 << " microns\n";
|
|
|
|
cout << "\tWire spacing - " << wire_spacing_init*1e6 << " microns\n";
|
|
|
|
cout << endl;
|
|
|
|
|
|
|
|
cout << " 5% Overhead\n\tRepeater size - " << global_5.area.h <<
|
|
|
|
" \n\tRepeater spacing - " << global_5.area.w*1e3 << " (mm)"
|
|
|
|
" \n\tDelay - " << global_5.delay *1e6 << " (ns/mm)"
|
|
|
|
" \n\tPowerD - " << global_5.power.readOp.dynamic *1e6 << " (nJ/mm)"
|
|
|
|
" \n\tPowerL - " << global_5.power.readOp.leakage << " (mW/mm)"
|
|
|
|
" \n\tPowerLgate - " << global_5.power.readOp.gate_leakage <<
|
|
|
|
" (mW/mm)\n";
|
|
|
|
cout << "\tWire width - " << wire_width_init*1e6 << " microns\n";
|
|
|
|
cout << "\tWire spacing - " << wire_spacing_init*1e6 << " microns\n";
|
|
|
|
cout << endl;
|
|
|
|
cout << " 10% Overhead\n\tRepeater size - " << global_10.area.h <<
|
|
|
|
" \n\tRepeater spacing - " << global_10.area.w*1e3 << " (mm)"
|
|
|
|
" \n\tDelay - " << global_10.delay *1e6 << " (ns/mm)"
|
|
|
|
" \n\tPowerD - " << global_10.power.readOp.dynamic *1e6 << " (nJ/mm)"
|
|
|
|
" \n\tPowerL - " << global_10.power.readOp.leakage << " (mW/mm)"
|
|
|
|
" \n\tPowerLgate - " << global_10.power.readOp.gate_leakage <<
|
|
|
|
" (mW/mm)\n";
|
|
|
|
cout << "\tWire width - " << wire_width_init*1e6 << " microns\n";
|
|
|
|
cout << "\tWire spacing - " << wire_spacing_init*1e6 << " microns\n";
|
|
|
|
cout << endl;
|
|
|
|
cout << " 20% Overhead\n\tRepeater size - " << global_20.area.h <<
|
|
|
|
" \n\tRepeater spacing - " << global_20.area.w*1e3 << " (mm)"
|
|
|
|
" \n\tDelay - " << global_20.delay *1e6 << " (ns/mm)"
|
|
|
|
" \n\tPowerD - " << global_20.power.readOp.dynamic *1e6 << " (nJ/mm)"
|
|
|
|
" \n\tPowerL - " << global_20.power.readOp.leakage << " (mW/mm)"
|
|
|
|
" \n\tPowerLgate - " << global_20.power.readOp.gate_leakage <<
|
|
|
|
" (mW/mm)\n";
|
|
|
|
cout << "\tWire width - " << wire_width_init*1e6 << " microns\n";
|
|
|
|
cout << "\tWire spacing - " << wire_spacing_init*1e6 << " microns\n";
|
|
|
|
cout << endl;
|
|
|
|
cout << " 30% Overhead\n\tRepeater size - " << global_30.area.h <<
|
|
|
|
" \n\tRepeater spacing - " << global_30.area.w*1e3 << " (mm)"
|
|
|
|
" \n\tDelay - " << global_30.delay *1e6 << " (ns/mm)"
|
|
|
|
" \n\tPowerD - " << global_30.power.readOp.dynamic *1e6 << " (nJ/mm)"
|
|
|
|
" \n\tPowerL - " << global_30.power.readOp.leakage << " (mW/mm)"
|
|
|
|
" \n\tPowerLgate - " << global_30.power.readOp.gate_leakage <<
|
|
|
|
" (mW/mm)\n";
|
|
|
|
cout << "\tWire width - " << wire_width_init*1e6 << " microns\n";
|
|
|
|
cout << "\tWire spacing - " << wire_spacing_init*1e6 << " microns\n";
|
|
|
|
cout << endl;
|
|
|
|
cout << " Low-swing wire (1 mm) - Note: Unlike repeated wires, \n\t" <<
|
|
|
|
"delay and power values of low-swing wires do not\n\t" <<
|
|
|
|
"have a linear relationship with length." <<
|
|
|
|
" \n\tdelay - " << low_swing.delay *1e9 << " (ns)"
|
|
|
|
" \n\tpowerD - " << low_swing.power.readOp.dynamic *1e9 << " (nJ)"
|
|
|
|
" \n\tPowerL - " << low_swing.power.readOp.leakage << " (mW)"
|
|
|
|
" \n\tPowerLgate - " << low_swing.power.readOp.gate_leakage <<
|
|
|
|
" (mW)\n";
|
|
|
|
cout << "\tWire width - " << wire_width_init * 2 /* differential */ <<
|
|
|
|
" microns\n";
|
|
|
|
cout << "\tWire spacing - " << wire_spacing_init * 2 /* differential */ <<
|
|
|
|
" microns\n";
|
|
|
|
cout << endl;
|
|
|
|
cout << endl;
|
2014-04-01 18:44:30 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|