gpu-compute: Cleanup the scheduler a bit
[gem5.git] / util / plot_dram / PlotPowerStates.py
1 # Copyright (c) 2017 ARM Limited
2 # All rights reserved
3 #
4 # The license below extends only to copyright in the software and shall
5 # not be construed as granting a license to any other intellectual
6 # property including but not limited to intellectual property relating
7 # to a hardware implementation of the functionality of the software
8 # licensed hereunder. You may use the software subject to the license
9 # terms below provided that you ensure that this notice is replicated
10 # unmodified and in its entirety in all distributions of the software,
11 # modified or unmodified, in source code or in binary form.
12 #
13 # Redistribution and use in source and binary forms, with or without
14 # modification, are permitted provided that the following conditions are
15 # met: redistributions of source code must retain the above copyright
16 # notice, this list of conditions and the following disclaimer;
17 # redistributions in binary form must reproduce the above copyright
18 # notice, this list of conditions and the following disclaimer in the
19 # documentation and/or other materials provided with the distribution;
20 # neither the name of the copyright holders nor the names of its
21 # contributors may be used to endorse or promote products derived from
22 # this software without specific prior written permission.
23 #
24 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
27 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
28 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
30 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 #
36 # Authors: Radhika Jagtap
37
38 import matplotlib
39 matplotlib.use('Agg')
40 import matplotlib.pyplot as plt
41 from matplotlib.font_manager import FontProperties
42 import numpy as np
43 import os
44
45 # global results dict
46 results = {}
47 idleResults = {}
48
49 # global vars for bank utilisation and seq_bytes values swept in the experiment
50 bankUtilValues = []
51 seqBytesValues = []
52 delayValues = []
53
54 # settings for 3 values of bank util and 3 values of seq_bytes
55 stackHeight = 6.0
56 stackWidth = 18.0
57 barWidth = 0.5
58 plotFontSize = 18
59
60 States = ['IDLE', 'ACT', 'REF', 'ACT_PDN', 'PRE_PDN', 'SREF']
61
62 EnergyStates = ['ACT_E',
63 'PRE_E',
64 'READ_E',
65 'REF_E',
66 'ACT_BACK_E',
67 'PRE_BACK_E',
68 'ACT_PDN_E',
69 'PRE_PDN_E',
70 'SREF_E']
71
72 StackColors = {
73 'IDLE' : 'black', # time spent in states
74 'ACT' : 'lightskyblue',
75 'REF' : 'limegreen',
76 'ACT_PDN' : 'crimson',
77 'PRE_PDN' : 'orange',
78 'SREF' : 'gold',
79 'ACT_E' : 'lightskyblue', # energy of states
80 'PRE_E' : 'black',
81 'READ_E' : 'white',
82 'REF_E' : 'limegreen',
83 'ACT_BACK_E' : 'lightgray',
84 'PRE_BACK_E' : 'gray',
85 'ACT_PDN_E' : 'crimson',
86 'PRE_PDN_E' : 'orange',
87 'SREF_E' : 'gold'
88 }
89
90 StatToKey = {
91 'system.mem_ctrls_0.actEnergy' : 'ACT_E',
92 'system.mem_ctrls_0.preEnergy' : 'PRE_E',
93 'system.mem_ctrls_0.readEnergy' : 'READ_E',
94 'system.mem_ctrls_0.refreshEnergy' : 'REF_E',
95 'system.mem_ctrls_0.actBackEnergy' : 'ACT_BACK_E',
96 'system.mem_ctrls_0.preBackEnergy' : 'PRE_BACK_E',
97 'system.mem_ctrls_0.actPowerDownEnergy' : 'ACT_PDN_E',
98 'system.mem_ctrls_0.prePowerDownEnergy' : 'PRE_PDN_E',
99 'system.mem_ctrls_0.selfRefreshEnergy' : 'SREF_E'
100 }
101 # Skipping write energy, the example script issues 100% reads by default
102 # 'system.mem_ctrls_0.writeEnergy' : "WRITE"
103
104 def plotLowPStates(plot_dir, stats_fname, bank_util_list, seqbytes_list,
105 delay_list):
106 """
107 plotLowPStates generates plots by parsing statistics output by the DRAM
108 sweep simulation described in the the configs/dram/low_power_sweep.py
109 script.
110
111 The function outputs eps format images for the following plots
112 (1) time spent in the DRAM Power states as a stacked bar chart
113 (2) energy consumed by the DRAM Power states as a stacked bar chart
114 (3) idle plot for the last stats dump corresponding to an idle period
115
116 For all plots, the time and energy values of the first rank (i.e. rank0)
117 are plotted because the way the script is written means stats across ranks
118 are similar.
119
120 @param plot_dir: the dir to output the plots
121 @param stats_fname: the stats file name of the low power sweep sim
122 @param bank_util_list: list of bank utilisation values (e.g. [1, 4, 8])
123 @param seqbytes_list: list of seq_bytes values (e.g. [64, 456, 512])
124 @param delay_list: list of itt max multipliers (e.g. [1, 20, 200])
125
126 """
127 stats_file = open(stats_fname, 'r')
128
129 global bankUtilValues
130 bankUtilValues = bank_util_list
131
132 global seqBytesValues
133 seqBytesValues = seqbytes_list
134
135 global delayValues
136 delayValues = delay_list
137 initResults()
138
139 # throw away the first two lines of the stats file
140 stats_file.readline()
141 stats_file.readline() # the 'Begin' line
142
143 #######################################
144 # Parse stats file and gather results
145 ########################################
146
147 for delay in delayValues:
148 for bank_util in bankUtilValues:
149 for seq_bytes in seqBytesValues:
150
151 for line in stats_file:
152 if 'Begin' in line:
153 break
154
155 if len(line.strip()) == 0:
156 continue
157
158 #### state time values ####
159 if 'system.mem_ctrls_0.memoryStateTime' in line:
160 # remove leading and trailing white spaces
161 line = line.strip()
162 # Example format:
163 # 'system.mem_ctrls_0.memoryStateTime::ACT 1000000'
164 statistic, stime = line.split()[0:2]
165 # Now grab the state, i.e. 'ACT'
166 state = statistic.split('::')[1]
167 # store the value of the stat in the results dict
168 results[delay][bank_util][seq_bytes][state] = \
169 int(stime)
170 #### state energy values ####
171 elif line.strip().split()[0] in StatToKey.keys():
172 # Example format:
173 # system.mem_ctrls_0.actEnergy 35392980
174 statistic, e_val = line.strip().split()[0:2]
175 senergy = int(float(e_val))
176 state = StatToKey[statistic]
177 # store the value of the stat in the results dict
178 results[delay][bank_util][seq_bytes][state] = senergy
179
180 # To add last traffic gen idle period stats to the results dict
181 for line in stats_file:
182 if 'system.mem_ctrls_0.memoryStateTime' in line:
183 line = line.strip() # remove leading and trailing white spaces
184 # Example format:
185 # 'system.mem_ctrls_0.memoryStateTime::ACT 1000000'
186 statistic, stime = line.split()[0:2]
187 # Now grab the state energy, .e.g 'ACT'
188 state = statistic.split('::')[1]
189 idleResults[state] = int(stime)
190 if state == 'ACT_PDN':
191 break
192
193 ########################################
194 # Call plot functions
195 ########################################
196 # one plot per delay value
197 for delay in delayValues:
198 plot_path = plot_dir + delay + '-'
199
200 plotStackedStates(delay, States, 'IDLE', stateTimePlotName(plot_path),
201 'Time (ps) spent in a power state')
202 plotStackedStates(delay, EnergyStates, 'ACT_E',
203 stateEnergyPlotName(plot_path),
204 'Energy (pJ) of a power state')
205 plotIdle(plot_dir)
206
207 def plotIdle(plot_dir):
208 """
209 Create a bar chart for the time spent in power states during the idle phase
210
211 @param plot_dir: the dir to output the plots
212 """
213 fig, ax = plt.subplots()
214 width = 0.35
215 ind = np.arange(len(States))
216 l1 = ax.bar(ind, map(lambda x : idleResults[x], States), width)
217
218 ax.xaxis.set_ticks(ind + width/2)
219 ax.xaxis.set_ticklabels(States)
220 ax.set_ylabel('Time (ps) spent in a power state')
221 fig.suptitle("Idle 50 us")
222
223 print "saving plot:", idlePlotName(plot_dir)
224 plt.savefig(idlePlotName(plot_dir), format='eps')
225 plt.close(fig)
226
227 def plotStackedStates(delay, states_list, bottom_state, plot_name, ylabel_str):
228 """
229 Create a stacked bar chart for the list that is passed in as arg, which
230 is either time spent or energy consumed in power states.
231
232 @param delay: one plot is output per delay value
233 @param states_list: list of either time or energy state names
234 @param bottom_state: the bottom-most component of the stacked bar
235 @param plot_name: the file name of the image to write the plot to
236 @param ylabel_str: Y-axis label depending on plotting time or energy
237 """
238 fig, ax = plt.subplots(1, len(bankUtilValues), sharey=True)
239 fig.set_figheight(stackHeight)
240 fig.set_figwidth(stackWidth)
241 width = barWidth
242 plt.rcParams.update({'font.size': plotFontSize})
243
244 # Get the number of seq_bytes values
245 N = len(seqBytesValues)
246 ind = np.arange(N)
247
248 for sub_idx, bank_util in enumerate(bankUtilValues):
249
250 l_states = {}
251 p_states = {}
252
253 # Must have a bottom of the stack first
254 state = bottom_state
255
256 l_states[state] = map(lambda x: results[delay][bank_util][x][state],
257 seqBytesValues)
258 p_states[state] = ax[sub_idx].bar(ind, l_states[state], width,
259 color=StackColors[state])
260
261 time_sum = l_states[state]
262 for state in states_list[1:]:
263 l_states[state] = map(lambda x:
264 results[delay][bank_util][x][state],
265 seqBytesValues)
266 # Now add on top of the bottom = sum of values up until now
267 p_states[state] = ax[sub_idx].bar(ind, l_states[state], width,
268 color=StackColors[state],
269 bottom=time_sum)
270 # Now add the bit of the stack that we just ploted to the bottom
271 # resulting in a new bottom for the next iteration
272 time_sum = [prev_sum + new_s for prev_sum, new_s in \
273 zip(time_sum, l_states[state])]
274
275 ax[sub_idx].set_title('Bank util %s' % bank_util)
276 ax[sub_idx].xaxis.set_ticks(ind + width/2.)
277 ax[sub_idx].xaxis.set_ticklabels(seqBytesValues, rotation=45)
278 ax[sub_idx].set_xlabel('Seq. bytes')
279 if bank_util == bankUtilValues[0]:
280 ax[sub_idx].set_ylabel(ylabel_str)
281
282 myFontSize='small'
283 fontP = FontProperties()
284 fontP.set_size(myFontSize)
285 fig.legend(map(lambda x: p_states[x], states_list), states_list,
286 prop=fontP)
287
288 plt.savefig(plot_name, format='eps', bbox_inches='tight')
289 print "saving plot:", plot_name
290 plt.close(fig)
291
292 # These plat name functions are also called in the main script
293 def idlePlotName(plot_dir):
294 return (plot_dir + 'idle.eps')
295
296 def stateTimePlotName(plot_dir):
297 return (plot_dir + 'state-time.eps')
298
299 def stateEnergyPlotName(plot_dir):
300 return (plot_dir + 'state-energy.eps')
301
302 def initResults():
303 for delay in delayValues:
304 results[delay] = {}
305 for bank_util in bankUtilValues:
306 results[delay][bank_util] = {}
307 for seq_bytes in seqBytesValues:
308 results[delay][bank_util][seq_bytes] = {}