diff options
Diffstat (limited to 'src/mem/ruby/network/orion/NetworkPower.cc')
-rw-r--r-- | src/mem/ruby/network/orion/NetworkPower.cc | 430 |
1 files changed, 430 insertions, 0 deletions
diff --git a/src/mem/ruby/network/orion/NetworkPower.cc b/src/mem/ruby/network/orion/NetworkPower.cc new file mode 100644 index 000000000..6e5994071 --- /dev/null +++ b/src/mem/ruby/network/orion/NetworkPower.cc @@ -0,0 +1,430 @@ +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * 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 + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stdio.h> +#include <math.h> + +#include "power_router_init.hh" +#include "power_array.hh" +#include "power_crossbar.hh" +#include "power_arbiter.hh" +#include "power_bus.hh" +#include "NetworkPower.hh" +#include "Router_d.hh" +#include "NetworkLink_d.hh" +#include "GarnetNetwork_d.hh" +#include "SIM_port.hh" +#include "parm_technology.hh" + +/* --------- Static energy calculation functions ------------ */ + +//Input buffer +double SIM_reg_stat_energy(power_array_info *info, power_array *arr, double n_read, double n_write) +{ + double Eavg = 0, Eatomic, Estruct, Estatic; + + + /* decoder */ + if (info->row_dec_model) { + //row decoder + Estruct = 0; + /* assume switch probability 0.5 for address bits */ + //input + Eatomic = arr->row_dec.e_chg_addr * arr->row_dec.n_bits * SWITCHING_FACTOR * (n_read + n_write); + Estruct += Eatomic; + + //output + Eatomic = arr->row_dec.e_chg_output * (n_read + n_write); + Estruct += Eatomic; + + /* assume all 1st-level decoders change output */ + //internal node + Eatomic = arr->row_dec.e_chg_l1 * arr->row_dec.n_in_2nd * (n_read + n_write); + Estruct += Eatomic; + + Eavg += Estruct; + } + + /* wordline */ + Estruct = 0; + //read + Eatomic = arr->data_wordline.e_read * n_read; + Estruct += Eatomic; + //write + Eatomic = arr->data_wordline.e_write * n_write; + Estruct += Eatomic; + + Eavg += Estruct; + + /* bitlines */ + Estruct = 0; + //read + if (arr->data_bitline.end == 2) { + Eatomic = arr->data_bitline.e_col_read * info->eff_data_cols * n_read; + } + else { + /* assume switch probability 0.5 for single-ended bitlines */ + Eatomic = arr->data_bitline.e_col_read * info->eff_data_cols * SWITCHING_FACTOR * n_read; + } + + Estruct += Eatomic; + //write + /* assume switch probability 0.5 for write bitlines */ + Eatomic = arr->data_bitline.e_col_write * info->data_width * SWITCHING_FACTOR * n_write; + Estruct += Eatomic; + //precharge + Eatomic = arr->data_bitline_pre.e_charge * info->eff_data_cols * n_read; + Estruct += Eatomic; + + Eavg += Estruct; + + /* memory cells */ + Estruct = 0; + + /* assume switch probability 0.5 for memory cells */ + Eatomic = arr->data_mem.e_switch * info->data_width * SWITCHING_FACTOR * n_write; + Estruct += Eatomic; + + Eavg += Estruct; + + /* sense amplifier */ + if (info->data_end == 2) { + Estruct = 0; + + Eatomic = arr->data_amp.e_access * info->eff_data_cols * n_read; + Estruct += Eatomic; + + Eavg += Estruct; + } + + /* output driver */ + if (info->outdrv_model) { + Estruct = 0; + //enable + Eatomic = arr->outdrv.e_select * n_read; + Estruct += Eatomic; + //data + /* same switch probability as bitlines */ + Eatomic = arr->outdrv.e_chg_data * arr->outdrv.item_width * SWITCHING_FACTOR * info->n_item * info->assoc * n_read; + Estruct += Eatomic; + //output 1 + /* assume 1 and 0 are uniformly distributed */ + if (arr->outdrv.e_out_1 >= arr->outdrv.e_out_0 ) { + Eatomic = arr->outdrv.e_out_1 * arr->outdrv.item_width * SWITCHING_FACTOR * n_read; + Estruct += Eatomic; + } + //output 0 + if (arr->outdrv.e_out_1 < arr->outdrv.e_out_0) { + Eatomic = arr->outdrv.e_out_0 * arr->outdrv.item_width * SWITCHING_FACTOR * n_read; + Estruct += Eatomic; + } + + Eavg += Estruct; + } + + /* static power */ + Estatic = arr->i_leakage * Vdd * Period * SCALE_S; + + //static energy + Eavg += Estatic; + + return Eavg; +} + +//crossbar +double SIM_crossbar_stat_energy(power_crossbar *crsbar, double n_data) +{ + double Eavg = 0, Eatomic, Estatic; + + if (n_data > crsbar->n_out) { + n_data = crsbar->n_out; + } + + + switch (crsbar->model) { + case MATRIX_CROSSBAR: + case CUT_THRU_CROSSBAR: + case MULTREE_CROSSBAR: + /* assume 0.5 data switch probability */ + //input + Eatomic = crsbar->e_chg_in * crsbar->data_width * SWITCHING_FACTOR * n_data; + Eavg += Eatomic; + + //output + Eatomic = crsbar->e_chg_out * crsbar->data_width * SWITCHING_FACTOR * n_data; + Eavg += Eatomic; + + //control + Eatomic = crsbar->e_chg_ctr * n_data; + Eavg += Eatomic; + + if (crsbar->model == MULTREE_CROSSBAR && crsbar->depth > 1) { + //internal node + Eatomic = crsbar->e_chg_int * crsbar->data_width * (crsbar->depth - 1) * SWITCHING_FACTOR * n_data; + Eavg += Eatomic; + } + break; + + default: break;/* some error handler */ + } + + return Eavg; +} + +//arbiter +/* stat over one cycle */ +/* info is only used by queuing arbiter */ +double SIM_arbiter_stat_energy(power_arbiter *arb, power_array_info *info, double n_req) +{ + double Eavg = 0, Estruct, Eatomic; + double total_pri, n_chg_pri, n_grant; + + /* energy cycle distribution */ + if (n_req > arb->req_width) { + n_req = arb->req_width; + } + if (n_req >= 1) n_grant = 1; + else n_grant = 1.0 / ceil(1.0 / n_req); + + switch (arb->model) { + case RR_ARBITER: + /* FIXME: we may overestimate request switch */ + //request + Eatomic = arb->e_chg_req * n_req; + Eavg += Eatomic; + + //grant + Eatomic = arb->e_chg_grant * n_grant; + Eavg += Eatomic; + + /* assume carry signal propagates half length in average case */ + /* carry does not propagate in maximum case, i.e. all carrys go down */ + //carry + Eatomic = arb->e_chg_carry * arb->req_width * SWITCHING_FACTOR * n_grant; + Eavg += Eatomic; + + //internal carry + Eatomic = arb->e_chg_carry_in * (arb->req_width * SWITCHING_FACTOR - 1) * n_grant; + Eavg += Eatomic; + + /* priority registers */ + Estruct = 0; + //priority + + //switch + Eatomic = arb->pri_ff.e_switch * 2 * n_grant; + Estruct += Eatomic; + + //keep 0 + Eatomic = arb->pri_ff.e_keep_0 * (arb->req_width - 2 * n_grant); + Estruct += Eatomic; + + //clock + Eatomic = arb->pri_ff.e_clock * arb->req_width; + Estruct += Eatomic; + + Eavg += Estruct; + break; + + case MATRIX_ARBITER: + total_pri = arb->req_width * (arb->req_width - 1) * 0.5; + /* assume switch probability 0.5 for priorities */ + n_chg_pri = (arb->req_width - 1) * SWITCHING_FACTOR; + + /* FIXME: we may overestimate request switch */ + //request + Eatomic = arb->e_chg_req * n_req; + Eavg += Eatomic; + + //grant + Eatomic = arb->e_chg_grant * n_grant; + Eavg += Eatomic; + + /* priority registers */ + Estruct = 0; + //priority + + //switch + Eatomic = arb->pri_ff.e_switch * n_chg_pri * n_grant; + Estruct += Eatomic; + + /* assume 1 and 0 are uniformly distributed */ + //keep 0 + if (arb->pri_ff.e_keep_0 >= arb->pri_ff.e_keep_1) { + Eatomic = arb->pri_ff.e_keep_0 * (total_pri - n_chg_pri * n_grant) * SWITCHING_FACTOR; + Estruct += Eatomic; + } + + //keep 1 + if (arb->pri_ff.e_keep_0 < arb->pri_ff.e_keep_1) { + Eatomic = arb->pri_ff.e_keep_1 * (total_pri - n_chg_pri * n_grant) * SWITCHING_FACTOR; + Estruct += Eatomic; + } + + //clock + Eatomic = arb->pri_ff.e_clock * total_pri; + Estruct += Eatomic; + + Eavg += Estruct; + + /* based on above assumptions */ + //internal node + /* p(n-1)/2 + (n-1)/2 */ + Eatomic = arb->e_chg_mint * (n_req + 1) * (arb->req_width - 1) * 0.5; + Eavg += Eatomic; + break; + + case QUEUE_ARBITER: + /* FIXME: what if n_req > 1? */ + Eavg = SIM_reg_stat_energy(info, &arb->queue, n_req, n_grant); + break; + + default: break;/* some error handler */ + } + + + return Eavg; +} + +double SIM_bus_stat_energy(power_bus *bus, double e_link) +{ + double Ebus; + Ebus = bus->e_switch * e_link * SWITCHING_FACTOR * bus->bit_width; + + return (Ebus); +} + +double Router_d::calculate_offline_power(power_router *router, power_router_info *info) +{ + double Eavg = 0; + double P_in_buf, P_xbar, P_vc_in_arb, P_vc_out_arb, P_sw_in_arb, P_sw_out_arb, P_leakage, P_total; + + double E_in_buf, E_xbar, E_vc_in_arb, E_vc_out_arb, E_sw_in_arb, E_sw_out_arb, E_leakage; + double e_in_buf_read, e_in_buf_write, e_crossbar, e_vc_local_arb, e_vc_global_arb, e_sw_local_arb, e_sw_global_arb; + double sim_cycles; + + sim_cycles = g_eventQueue_ptr->getTime() - m_network_ptr->getRubyStartTime(); + + calculate_performance_numbers(); + //counts obtained from perf. simulator + e_in_buf_read = (double )(buf_read_count/sim_cycles); + e_in_buf_write = (double )(buf_write_count/sim_cycles); + e_crossbar = (double )(crossbar_count/sim_cycles); + e_vc_local_arb = (double)(vc_local_arbit_count/sim_cycles); + e_vc_global_arb = (double)(vc_global_arbit_count/sim_cycles); + e_sw_local_arb = (double )(sw_local_arbit_count/sim_cycles); + e_sw_global_arb = (double )(sw_global_arbit_count/sim_cycles); + // e_link = (double )(link_traversal_count/sim_cycles); + + /* input buffers */ + if (info->in_buf) + E_in_buf = SIM_reg_stat_energy(&info->in_buf_info, &router->in_buf, e_in_buf_read, e_in_buf_write); + P_in_buf = E_in_buf * PARM_Freq; + Eavg += E_in_buf; + + /* main crossbar */ + if (info->crossbar_model) + E_xbar= SIM_crossbar_stat_energy(&router->crossbar, e_crossbar); + P_xbar = E_xbar * PARM_Freq; + Eavg += E_xbar; + + /* vc input (local) arbiter */ + if (info->vc_in_arb_model) + E_vc_in_arb = SIM_arbiter_stat_energy(&router->vc_in_arb, &info->vc_in_arb_queue_info, e_sw_local_arb); + P_vc_in_arb = E_vc_in_arb * PARM_Freq; + Eavg += E_vc_in_arb; + + /* vc output (global) arbiter */ + if (info->vc_out_arb_model) + E_vc_out_arb = SIM_arbiter_stat_energy(&router->vc_out_arb, &info->vc_out_arb_queue_info, e_sw_global_arb); + P_vc_out_arb = E_vc_out_arb * PARM_Freq; + Eavg += E_vc_out_arb; + + /* sw input (local) arbiter */ + if (info->sw_in_arb_model) + E_sw_in_arb = SIM_arbiter_stat_energy(&router->sw_in_arb, &info->sw_in_arb_queue_info, e_sw_local_arb); + P_sw_in_arb = E_sw_in_arb * PARM_Freq; + Eavg += E_sw_in_arb; + + /* sw output (global) arbiter */ + if (info->sw_out_arb_model) + E_sw_out_arb = SIM_arbiter_stat_energy(&router->sw_out_arb, &info->sw_out_arb_queue_info, e_sw_global_arb); + P_sw_out_arb = E_sw_out_arb * PARM_Freq; + Eavg += E_sw_out_arb; + + /* static power */ + E_leakage = router->i_leakage * Vdd * Period * SCALE_S; + P_leakage = E_leakage * PARM_Freq; + Eavg += E_leakage; + + P_total = Eavg * PARM_Freq; + + return Eavg; +} + +double NetworkLink_d::calculate_offline_power(power_bus* bus) +{ + double sim_cycles = (double) (g_eventQueue_ptr->getTime() - m_net_ptr->getRubyStartTime()); + double e_link = (double) (m_link_utilized)/ sim_cycles; + double E_link = SIM_bus_stat_energy(bus, e_link); + double P_link = E_link * PARM_Freq; + return P_link; +} + +double NetworkLink_d::calculate_power() +{ + power_bus bus; + power_bus_init(&bus, GENERIC_BUS, IDENT_ENC, PARM_flit_width, 0, 1, 1, PARM_link_length, 0); + double total_power = calculate_offline_power(&bus); + return total_power; +} + +void Router_d::power_router_initialize(power_router *router, power_router_info *info) +{ + info->n_in = m_input_unit.size(); + info->n_out = m_output_unit.size(); + info->flit_width = PARM_flit_width; + + info->n_v_channel = m_num_vcs; + info->n_v_class = m_virtual_networks; + +} + +double Router_d::calculate_power() +{ + power_router router; + power_router_info router_info; + double total_energy, total_power; + + power_router_initialize(&router, &router_info); + power_router_init(&router, &router_info); + + total_energy = calculate_offline_power(&router, &router_info); + total_power = total_energy * PARM_Freq; + return total_power; +} |