ruby: clean up a few warnings
[gem5.git] / src / mem / ruby / network / orion / NetworkPower.cc
1 /*
2 * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
3 * All rights reserved.
4 *
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.
15 *
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.
27 */
28
29 #include <stdio.h>
30 #include <math.h>
31
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"
43
44 /* --------- Static energy calculation functions ------------ */
45
46 //Input buffer
47 double SIM_reg_stat_energy(power_array_info *info, power_array *arr, double n_read, double n_write)
48 {
49 double Eavg = 0, Eatomic, Estruct, Estatic;
50
51
52 /* decoder */
53 if (info->row_dec_model) {
54 //row decoder
55 Estruct = 0;
56 /* assume switch probability 0.5 for address bits */
57 //input
58 Eatomic = arr->row_dec.e_chg_addr * arr->row_dec.n_bits * SWITCHING_FACTOR * (n_read + n_write);
59 Estruct += Eatomic;
60
61 //output
62 Eatomic = arr->row_dec.e_chg_output * (n_read + n_write);
63 Estruct += Eatomic;
64
65 /* assume all 1st-level decoders change output */
66 //internal node
67 Eatomic = arr->row_dec.e_chg_l1 * arr->row_dec.n_in_2nd * (n_read + n_write);
68 Estruct += Eatomic;
69
70 Eavg += Estruct;
71 }
72
73 /* wordline */
74 Estruct = 0;
75 //read
76 Eatomic = arr->data_wordline.e_read * n_read;
77 Estruct += Eatomic;
78 //write
79 Eatomic = arr->data_wordline.e_write * n_write;
80 Estruct += Eatomic;
81
82 Eavg += Estruct;
83
84 /* bitlines */
85 Estruct = 0;
86 //read
87 if (arr->data_bitline.end == 2) {
88 Eatomic = arr->data_bitline.e_col_read * info->eff_data_cols * n_read;
89 }
90 else {
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;
93 }
94
95 Estruct += Eatomic;
96 //write
97 /* assume switch probability 0.5 for write bitlines */
98 Eatomic = arr->data_bitline.e_col_write * info->data_width * SWITCHING_FACTOR * n_write;
99 Estruct += Eatomic;
100 //precharge
101 Eatomic = arr->data_bitline_pre.e_charge * info->eff_data_cols * n_read;
102 Estruct += Eatomic;
103
104 Eavg += Estruct;
105
106 /* memory cells */
107 Estruct = 0;
108
109 /* assume switch probability 0.5 for memory cells */
110 Eatomic = arr->data_mem.e_switch * info->data_width * SWITCHING_FACTOR * n_write;
111 Estruct += Eatomic;
112
113 Eavg += Estruct;
114
115 /* sense amplifier */
116 if (info->data_end == 2) {
117 Estruct = 0;
118
119 Eatomic = arr->data_amp.e_access * info->eff_data_cols * n_read;
120 Estruct += Eatomic;
121
122 Eavg += Estruct;
123 }
124
125 /* output driver */
126 if (info->outdrv_model) {
127 Estruct = 0;
128 //enable
129 Eatomic = arr->outdrv.e_select * n_read;
130 Estruct += Eatomic;
131 //data
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;
134 Estruct += Eatomic;
135 //output 1
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;
139 Estruct += Eatomic;
140 }
141 //output 0
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;
144 Estruct += Eatomic;
145 }
146
147 Eavg += Estruct;
148 }
149
150 /* static power */
151 Estatic = arr->i_leakage * Vdd * Period * SCALE_S;
152
153 //static energy
154 Eavg += Estatic;
155
156 return Eavg;
157 }
158
159 //crossbar
160 double SIM_crossbar_stat_energy(power_crossbar *crsbar, double n_data)
161 {
162 double Eavg = 0, Eatomic;
163
164 if (n_data > crsbar->n_out) {
165 n_data = crsbar->n_out;
166 }
167
168
169 switch (crsbar->model) {
170 case MATRIX_CROSSBAR:
171 case CUT_THRU_CROSSBAR:
172 case MULTREE_CROSSBAR:
173 /* assume 0.5 data switch probability */
174 //input
175 Eatomic = crsbar->e_chg_in * crsbar->data_width * SWITCHING_FACTOR * n_data;
176 Eavg += Eatomic;
177
178 //output
179 Eatomic = crsbar->e_chg_out * crsbar->data_width * SWITCHING_FACTOR * n_data;
180 Eavg += Eatomic;
181
182 //control
183 Eatomic = crsbar->e_chg_ctr * n_data;
184 Eavg += Eatomic;
185
186 if (crsbar->model == MULTREE_CROSSBAR && crsbar->depth > 1) {
187 //internal node
188 Eatomic = crsbar->e_chg_int * crsbar->data_width * (crsbar->depth - 1) * SWITCHING_FACTOR * n_data;
189 Eavg += Eatomic;
190 }
191 break;
192
193 default: break;/* some error handler */
194 }
195
196 return Eavg;
197 }
198
199 //arbiter
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)
203 {
204 double Eavg = 0, Estruct, Eatomic;
205 double total_pri, n_chg_pri, n_grant;
206
207 /* energy cycle distribution */
208 if (n_req > arb->req_width) {
209 n_req = arb->req_width;
210 }
211 if (n_req >= 1) n_grant = 1;
212 else n_grant = 1.0 / ceil(1.0 / n_req);
213
214 switch (arb->model) {
215 case RR_ARBITER:
216 /* FIXME: we may overestimate request switch */
217 //request
218 Eatomic = arb->e_chg_req * n_req;
219 Eavg += Eatomic;
220
221 //grant
222 Eatomic = arb->e_chg_grant * n_grant;
223 Eavg += Eatomic;
224
225 /* assume carry signal propagates half length in average case */
226 /* carry does not propagate in maximum case, i.e. all carrys go down */
227 //carry
228 Eatomic = arb->e_chg_carry * arb->req_width * SWITCHING_FACTOR * n_grant;
229 Eavg += Eatomic;
230
231 //internal carry
232 Eatomic = arb->e_chg_carry_in * (arb->req_width * SWITCHING_FACTOR - 1) * n_grant;
233 Eavg += Eatomic;
234
235 /* priority registers */
236 Estruct = 0;
237 //priority
238
239 //switch
240 Eatomic = arb->pri_ff.e_switch * 2 * n_grant;
241 Estruct += Eatomic;
242
243 //keep 0
244 Eatomic = arb->pri_ff.e_keep_0 * (arb->req_width - 2 * n_grant);
245 Estruct += Eatomic;
246
247 //clock
248 Eatomic = arb->pri_ff.e_clock * arb->req_width;
249 Estruct += Eatomic;
250
251 Eavg += Estruct;
252 break;
253
254 case MATRIX_ARBITER:
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;
258
259 /* FIXME: we may overestimate request switch */
260 //request
261 Eatomic = arb->e_chg_req * n_req;
262 Eavg += Eatomic;
263
264 //grant
265 Eatomic = arb->e_chg_grant * n_grant;
266 Eavg += Eatomic;
267
268 /* priority registers */
269 Estruct = 0;
270 //priority
271
272 //switch
273 Eatomic = arb->pri_ff.e_switch * n_chg_pri * n_grant;
274 Estruct += Eatomic;
275
276 /* assume 1 and 0 are uniformly distributed */
277 //keep 0
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;
280 Estruct += Eatomic;
281 }
282
283 //keep 1
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;
286 Estruct += Eatomic;
287 }
288
289 //clock
290 Eatomic = arb->pri_ff.e_clock * total_pri;
291 Estruct += Eatomic;
292
293 Eavg += Estruct;
294
295 /* based on above assumptions */
296 //internal node
297 /* p(n-1)/2 + (n-1)/2 */
298 Eatomic = arb->e_chg_mint * (n_req + 1) * (arb->req_width - 1) * 0.5;
299 Eavg += Eatomic;
300 break;
301
302 case QUEUE_ARBITER:
303 /* FIXME: what if n_req > 1? */
304 Eavg = SIM_reg_stat_energy(info, &arb->queue, n_req, n_grant);
305 break;
306
307 default: break;/* some error handler */
308 }
309
310
311 return Eavg;
312 }
313
314 double SIM_bus_stat_energy(power_bus *bus, double e_link)
315 {
316 double Ebus;
317 Ebus = bus->e_switch * e_link * SWITCHING_FACTOR * bus->bit_width;
318
319 return (Ebus);
320 }
321
322 double Router_d::calculate_offline_power(power_router *router, power_router_info *info)
323 {
324 double Eavg = 0;
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;
326
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;
329 double sim_cycles;
330
331 sim_cycles = g_eventQueue_ptr->getTime() - m_network_ptr->getRubyStartTime();
332
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);
343
344 /* input buffers */
345 if (info->in_buf)
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;
348 Eavg += E_in_buf;
349
350 /* main crossbar */
351 if (info->crossbar_model)
352 E_xbar= SIM_crossbar_stat_energy(&router->crossbar, e_crossbar);
353 P_xbar = E_xbar * PARM_Freq;
354 Eavg += E_xbar;
355
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;
360 Eavg += E_vc_in_arb;
361
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;
367
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;
372 Eavg += E_sw_in_arb;
373
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;
379
380 /* static power */
381 E_leakage = router->i_leakage * Vdd * Period * SCALE_S;
382 P_leakage = E_leakage * PARM_Freq;
383 Eavg += E_leakage;
384
385 P_total = Eavg * PARM_Freq;
386
387 return Eavg;
388 }
389
390 double NetworkLink_d::calculate_offline_power(power_bus* bus)
391 {
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;
396 return P_link;
397 }
398
399 double NetworkLink_d::calculate_power()
400 {
401 power_bus bus;
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);
404 return total_power;
405 }
406
407 void Router_d::power_router_initialize(power_router *router, power_router_info *info)
408 {
409 info->n_in = m_input_unit.size();
410 info->n_out = m_output_unit.size();
411 info->flit_width = PARM_flit_width;
412
413 info->n_v_channel = m_num_vcs;
414 info->n_v_class = m_virtual_networks;
415
416 }
417
418 double Router_d::calculate_power()
419 {
420 power_router router;
421 power_router_info router_info;
422 double total_energy, total_power;
423
424 power_router_initialize(&router, &router_info);
425 power_router_init(&router, &router_info);
426
427 total_energy = calculate_offline_power(&router, &router_info);
428 total_power = total_energy * PARM_Freq;
429 return total_power;
430 }