diff options
Diffstat (limited to 'ext/mcpat/cacti/wire.cc')
-rw-r--r-- | ext/mcpat/cacti/wire.cc | 1368 |
1 files changed, 695 insertions, 673 deletions
diff --git a/ext/mcpat/cacti/wire.cc b/ext/mcpat/cacti/wire.cc index 742000c85..b7d9e34ce 100644 --- a/ext/mcpat/cacti/wire.cc +++ b/ext/mcpat/cacti/wire.cc @@ -2,6 +2,7 @@ * McPAT/CACTI * SOFTWARE LICENSE AGREEMENT * Copyright 2012 Hewlett-Packard Development Company, L.P. + * Copyright (c) 2010-2013 Advanced Micro Devices, Inc. * All Rights Reserved * * Redistribution and use in source and binary forms, with or without @@ -25,7 +26,7 @@ * 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 - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.” + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***************************************************************************/ @@ -41,173 +42,173 @@ Wire::Wire( enum Wire_placement wp, double resistivity, TechnologyParameter::DeviceType *dt - ):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); + ): 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); } - // 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); +// 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); } -Wire::~Wire() -{ +Wire::~Wire() { } void -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); - } +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); + } } @@ -218,51 +219,55 @@ Wire::calculate_wire_stats() * inverters connected in series (refer: CACTI 1 Technical report, * section 6.1.3) */ - 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; +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; } -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 +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 } @@ -281,111 +286,110 @@ double Wire::signal_rise_time () * */ -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, horiz_dielectric_constant, vert_dielectric_constant, miller_value,ild_thickness; +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; + } + } - 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; - } - } - - 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 - */ + 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 + */ // capacitance between wires in the same level // sidewall = 2*miller_value * horiz_dielectric_constant * (wire_height/wire_spacing) // * epsilon0; - sidewall = miller_value * horiz_dielectric_constant * (wire_height/wire_spacing) - * epsilon0; + sidewall = miller_value * horiz_dielectric_constant * + (wire_height / wire_spacing) + * epsilon0; - // 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; + // 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; - adj = miller_value *vert_dielectric_constant *wire_width/(ild_thickness*1e-6) * epsilon0; - //Change ild_thickness from micron to M + adj = miller_value * vert_dielectric_constant * wire_width / + (ild_thickness * 1e-6) * epsilon0; + //Change ild_thickness from micron to M - //tot_cap = (sidewall + adj + (deviceType->C_fringe * 1e6)); //F/m - tot_cap = (sidewall + adj + (g_tp.fringe_cap * 1e6)); //F/m + //tot_cap = (sidewall + adj + (deviceType->C_fringe * 1e6)); //F/m + tot_cap = (sidewall + adj + (g_tp.fringe_cap * 1e6)); //F/m - if (call_from_outside) - { - wire_width *= 1e6; - wire_spacing *= 1e6; - } - return (tot_cap*len); // (F) + if (call_from_outside) { + wire_width *= 1e6; + wire_spacing *= 1e6; + } + return (tot_cap*len); // (F) } - double -Wire::wire_res (double len /*(in m)*/) -{ - - double aspect_ratio,alpha_scatter =1.05, dishing_thickness=0, 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))); +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))); } /* @@ -395,438 +399,456 @@ Wire::wire_res (double len /*(in m)*/) * low swing nmos delay, and the wire delay * (ref: Technical report 6) */ - 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); +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); #define RES_ADJ (8.6) // Increase in resistance due to low driving vol. - 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; - transmitter.power.readOp.dynamic = temp_power*2; /* since it is a diff. model*/ - 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); + 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); #define VOL_SWING .1 - 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; + 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; } - 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); +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); } -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); +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); - // 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 + // 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); + // wire cap /m + double wc = wire_cap(len); - // size the repeater such that the delay of the wire is minimum - double repeater_scaling = sqrt(out_res*wc/(wr*input_cap)); // len will cancel + // 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)); - // calc the optimum spacing between the repeaters (m) + // calc the optimum spacing between the repeaters (m) - repeater_spacing = sqrt(2 * out_res * (out_cap + input_cap)/ - ((wr/len)*(wc/len))); - repeater_size = repeater_scaling; + repeater_spacing = sqrt(2 * out_res * (out_cap + input_cap) / + ((wr / len) * (wc / len))); + repeater_size = repeater_scaling; - switching = (repeater_scaling * (input_cap + out_cap) + - repeater_spacing * (wc/len)) * deviceType->Vdd * deviceType->Vdd; + switching = (repeater_scaling * (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_scaling + - wr/len * repeater_spacing * input_cap * repeater_scaling + - 0.5 * (wr/len) * (wc/len)* repeater_spacing * repeater_spacing; + 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; - delay = 0.693 * tc * len/repeater_spacing; + delay = 0.693 * tc * len / repeater_spacing; #define Ishort_ckt 65e-6 /* across all tech Ref:Banerjee et al. {IEEE TED} */ - 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)); + 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)); } // calculate power/delay values for wires with suboptimal repeater sizing/spacing void -Wire::init_wire(){ - wire_length = 1; - delay_optimal_wire(); +Wire::init_wire() { + wire_length = 1; + delay_optimal_wire(); double sp, si; - 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 - } + 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 + } // cout << "Repeater size - "<< i << // " Repeater spacing - " << j << // " Delay - " << del << // " PowerD - " << pow.readOp.dynamic << // " PowerL - " << pow.readOp.leakage <<endl; - 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()); + 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()); + } } - } - 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; + 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; } -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; - } +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; + } + } + } } - } + i--; } - i--; - } } -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; +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; #define Ishort_ckt 65e-6 /* across all tech Ref:Banerjee et al. {IEEE TED} */ - 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; + 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; } void -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\tdelay and power " - "values of low-swing wires do not\n\thave 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; +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; } |