2 * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #include "mem/ruby/network/orion/power_router_init.hh"
33 #include "mem/ruby/network/orion/power_array.hh"
34 #include "mem/ruby/network/orion/power_crossbar.hh"
35 #include "mem/ruby/network/orion/power_arbiter.hh"
36 #include "mem/ruby/network/orion/power_bus.hh"
37 #include "mem/ruby/network/orion/NetworkPower.hh"
38 #include "mem/ruby/network/garnet-fixed-pipeline/Router_d.hh"
39 #include "mem/ruby/network/garnet-fixed-pipeline/NetworkLink_d.hh"
40 #include "mem/ruby/network/garnet-fixed-pipeline/GarnetNetwork_d.hh"
41 #include "mem/ruby/network/orion/SIM_port.hh"
42 #include "mem/ruby/network/orion/parm_technology.hh"
44 /* --------- Static energy calculation functions ------------ */
47 double SIM_reg_stat_energy(power_array_info
*info
, power_array
*arr
, double n_read
, double n_write
)
49 double Eavg
= 0, Eatomic
, Estruct
, Estatic
;
53 if (info
->row_dec_model
) {
56 /* assume switch probability 0.5 for address bits */
58 Eatomic
= arr
->row_dec
.e_chg_addr
* arr
->row_dec
.n_bits
* SWITCHING_FACTOR
* (n_read
+ n_write
);
62 Eatomic
= arr
->row_dec
.e_chg_output
* (n_read
+ n_write
);
65 /* assume all 1st-level decoders change output */
67 Eatomic
= arr
->row_dec
.e_chg_l1
* arr
->row_dec
.n_in_2nd
* (n_read
+ n_write
);
76 Eatomic
= arr
->data_wordline
.e_read
* n_read
;
79 Eatomic
= arr
->data_wordline
.e_write
* n_write
;
87 if (arr
->data_bitline
.end
== 2) {
88 Eatomic
= arr
->data_bitline
.e_col_read
* info
->eff_data_cols
* n_read
;
91 /* assume switch probability 0.5 for single-ended bitlines */
92 Eatomic
= arr
->data_bitline
.e_col_read
* info
->eff_data_cols
* SWITCHING_FACTOR
* n_read
;
97 /* assume switch probability 0.5 for write bitlines */
98 Eatomic
= arr
->data_bitline
.e_col_write
* info
->data_width
* SWITCHING_FACTOR
* n_write
;
101 Eatomic
= arr
->data_bitline_pre
.e_charge
* info
->eff_data_cols
* n_read
;
109 /* assume switch probability 0.5 for memory cells */
110 Eatomic
= arr
->data_mem
.e_switch
* info
->data_width
* SWITCHING_FACTOR
* n_write
;
115 /* sense amplifier */
116 if (info
->data_end
== 2) {
119 Eatomic
= arr
->data_amp
.e_access
* info
->eff_data_cols
* n_read
;
126 if (info
->outdrv_model
) {
129 Eatomic
= arr
->outdrv
.e_select
* n_read
;
132 /* same switch probability as bitlines */
133 Eatomic
= arr
->outdrv
.e_chg_data
* arr
->outdrv
.item_width
* SWITCHING_FACTOR
* info
->n_item
* info
->assoc
* n_read
;
136 /* assume 1 and 0 are uniformly distributed */
137 if (arr
->outdrv
.e_out_1
>= arr
->outdrv
.e_out_0
) {
138 Eatomic
= arr
->outdrv
.e_out_1
* arr
->outdrv
.item_width
* SWITCHING_FACTOR
* n_read
;
142 if (arr
->outdrv
.e_out_1
< arr
->outdrv
.e_out_0
) {
143 Eatomic
= arr
->outdrv
.e_out_0
* arr
->outdrv
.item_width
* SWITCHING_FACTOR
* n_read
;
151 Estatic
= arr
->i_leakage
* Vdd
* Period
* SCALE_S
;
160 double SIM_crossbar_stat_energy(power_crossbar
*crsbar
, double n_data
)
162 double Eavg
= 0, Eatomic
;
164 if (n_data
> crsbar
->n_out
) {
165 n_data
= crsbar
->n_out
;
169 switch (crsbar
->model
) {
170 case MATRIX_CROSSBAR
:
171 case CUT_THRU_CROSSBAR
:
172 case MULTREE_CROSSBAR
:
173 /* assume 0.5 data switch probability */
175 Eatomic
= crsbar
->e_chg_in
* crsbar
->data_width
* SWITCHING_FACTOR
* n_data
;
179 Eatomic
= crsbar
->e_chg_out
* crsbar
->data_width
* SWITCHING_FACTOR
* n_data
;
183 Eatomic
= crsbar
->e_chg_ctr
* n_data
;
186 if (crsbar
->model
== MULTREE_CROSSBAR
&& crsbar
->depth
> 1) {
188 Eatomic
= crsbar
->e_chg_int
* crsbar
->data_width
* (crsbar
->depth
- 1) * SWITCHING_FACTOR
* n_data
;
193 default: break;/* some error handler */
200 /* stat over one cycle */
201 /* info is only used by queuing arbiter */
202 double SIM_arbiter_stat_energy(power_arbiter
*arb
, power_array_info
*info
, double n_req
)
204 double Eavg
= 0, Estruct
, Eatomic
;
205 double total_pri
, n_chg_pri
, n_grant
;
207 /* energy cycle distribution */
208 if (n_req
> arb
->req_width
) {
209 n_req
= arb
->req_width
;
211 if (n_req
>= 1) n_grant
= 1;
212 else n_grant
= 1.0 / ceil(1.0 / n_req
);
214 switch (arb
->model
) {
216 /* FIXME: we may overestimate request switch */
218 Eatomic
= arb
->e_chg_req
* n_req
;
222 Eatomic
= arb
->e_chg_grant
* n_grant
;
225 /* assume carry signal propagates half length in average case */
226 /* carry does not propagate in maximum case, i.e. all carrys go down */
228 Eatomic
= arb
->e_chg_carry
* arb
->req_width
* SWITCHING_FACTOR
* n_grant
;
232 Eatomic
= arb
->e_chg_carry_in
* (arb
->req_width
* SWITCHING_FACTOR
- 1) * n_grant
;
235 /* priority registers */
240 Eatomic
= arb
->pri_ff
.e_switch
* 2 * n_grant
;
244 Eatomic
= arb
->pri_ff
.e_keep_0
* (arb
->req_width
- 2 * n_grant
);
248 Eatomic
= arb
->pri_ff
.e_clock
* arb
->req_width
;
255 total_pri
= arb
->req_width
* (arb
->req_width
- 1) * 0.5;
256 /* assume switch probability 0.5 for priorities */
257 n_chg_pri
= (arb
->req_width
- 1) * SWITCHING_FACTOR
;
259 /* FIXME: we may overestimate request switch */
261 Eatomic
= arb
->e_chg_req
* n_req
;
265 Eatomic
= arb
->e_chg_grant
* n_grant
;
268 /* priority registers */
273 Eatomic
= arb
->pri_ff
.e_switch
* n_chg_pri
* n_grant
;
276 /* assume 1 and 0 are uniformly distributed */
278 if (arb
->pri_ff
.e_keep_0
>= arb
->pri_ff
.e_keep_1
) {
279 Eatomic
= arb
->pri_ff
.e_keep_0
* (total_pri
- n_chg_pri
* n_grant
) * SWITCHING_FACTOR
;
284 if (arb
->pri_ff
.e_keep_0
< arb
->pri_ff
.e_keep_1
) {
285 Eatomic
= arb
->pri_ff
.e_keep_1
* (total_pri
- n_chg_pri
* n_grant
) * SWITCHING_FACTOR
;
290 Eatomic
= arb
->pri_ff
.e_clock
* total_pri
;
295 /* based on above assumptions */
297 /* p(n-1)/2 + (n-1)/2 */
298 Eatomic
= arb
->e_chg_mint
* (n_req
+ 1) * (arb
->req_width
- 1) * 0.5;
303 /* FIXME: what if n_req > 1? */
304 Eavg
= SIM_reg_stat_energy(info
, &arb
->queue
, n_req
, n_grant
);
307 default: break;/* some error handler */
314 double SIM_bus_stat_energy(power_bus
*bus
, double e_link
)
317 Ebus
= bus
->e_switch
* e_link
* SWITCHING_FACTOR
* bus
->bit_width
;
322 double Router_d::calculate_offline_power(power_router
*router
, power_router_info
*info
)
325 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
;
327 double E_in_buf
, E_xbar
, E_vc_in_arb
, E_vc_out_arb
, E_sw_in_arb
, E_sw_out_arb
, E_leakage
;
328 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
;
331 sim_cycles
= g_eventQueue_ptr
->getTime() - m_network_ptr
->getRubyStartTime();
333 calculate_performance_numbers();
334 //counts obtained from perf. simulator
335 e_in_buf_read
= (double )(buf_read_count
/sim_cycles
);
336 e_in_buf_write
= (double )(buf_write_count
/sim_cycles
);
337 e_crossbar
= (double )(crossbar_count
/sim_cycles
);
338 e_vc_local_arb
= (double)(vc_local_arbit_count
/sim_cycles
);
339 e_vc_global_arb
= (double)(vc_global_arbit_count
/sim_cycles
);
340 e_sw_local_arb
= (double )(sw_local_arbit_count
/sim_cycles
);
341 e_sw_global_arb
= (double )(sw_global_arbit_count
/sim_cycles
);
342 // e_link = (double )(link_traversal_count/sim_cycles);
346 E_in_buf
= SIM_reg_stat_energy(&info
->in_buf_info
, &router
->in_buf
, e_in_buf_read
, e_in_buf_write
);
347 P_in_buf
= E_in_buf
* PARM_Freq
;
351 if (info
->crossbar_model
)
352 E_xbar
= SIM_crossbar_stat_energy(&router
->crossbar
, e_crossbar
);
353 P_xbar
= E_xbar
* PARM_Freq
;
356 /* vc input (local) arbiter */
357 if (info
->vc_in_arb_model
)
358 E_vc_in_arb
= SIM_arbiter_stat_energy(&router
->vc_in_arb
, &info
->vc_in_arb_queue_info
, e_sw_local_arb
);
359 P_vc_in_arb
= E_vc_in_arb
* PARM_Freq
;
362 /* vc output (global) arbiter */
363 if (info
->vc_out_arb_model
)
364 E_vc_out_arb
= SIM_arbiter_stat_energy(&router
->vc_out_arb
, &info
->vc_out_arb_queue_info
, e_sw_global_arb
);
365 P_vc_out_arb
= E_vc_out_arb
* PARM_Freq
;
366 Eavg
+= E_vc_out_arb
;
368 /* sw input (local) arbiter */
369 if (info
->sw_in_arb_model
)
370 E_sw_in_arb
= SIM_arbiter_stat_energy(&router
->sw_in_arb
, &info
->sw_in_arb_queue_info
, e_sw_local_arb
);
371 P_sw_in_arb
= E_sw_in_arb
* PARM_Freq
;
374 /* sw output (global) arbiter */
375 if (info
->sw_out_arb_model
)
376 E_sw_out_arb
= SIM_arbiter_stat_energy(&router
->sw_out_arb
, &info
->sw_out_arb_queue_info
, e_sw_global_arb
);
377 P_sw_out_arb
= E_sw_out_arb
* PARM_Freq
;
378 Eavg
+= E_sw_out_arb
;
381 E_leakage
= router
->i_leakage
* Vdd
* Period
* SCALE_S
;
382 P_leakage
= E_leakage
* PARM_Freq
;
385 P_total
= Eavg
* PARM_Freq
;
390 double NetworkLink_d::calculate_offline_power(power_bus
* bus
)
392 double sim_cycles
= (double) (g_eventQueue_ptr
->getTime() - m_net_ptr
->getRubyStartTime());
393 double e_link
= (double) (m_link_utilized
)/ sim_cycles
;
394 double E_link
= SIM_bus_stat_energy(bus
, e_link
);
395 double P_link
= E_link
* PARM_Freq
;
399 double NetworkLink_d::calculate_power()
402 power_bus_init(&bus
, GENERIC_BUS
, IDENT_ENC
, PARM_flit_width
, 0, 1, 1, PARM_link_length
, 0);
403 double total_power
= calculate_offline_power(&bus
);
407 void Router_d::power_router_initialize(power_router
*router
, power_router_info
*info
)
409 info
->n_in
= m_input_unit
.size();
410 info
->n_out
= m_output_unit
.size();
411 info
->flit_width
= PARM_flit_width
;
413 info
->n_v_channel
= m_num_vcs
;
414 info
->n_v_class
= m_virtual_networks
;
418 double Router_d::calculate_power()
421 power_router_info router_info
;
422 double total_energy
, total_power
;
424 power_router_initialize(&router
, &router_info
);
425 power_router_init(&router
, &router_info
);
427 total_energy
= calculate_offline_power(&router
, &router_info
);
428 total_power
= total_energy
* PARM_Freq
;