summaryrefslogtreecommitdiff
path: root/src/mem/ruby/network/orion/NetworkPower.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/mem/ruby/network/orion/NetworkPower.cc')
-rw-r--r--src/mem/ruby/network/orion/NetworkPower.cc430
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;
+}