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 38import matplotlib 39matplotlib.use('Agg') 40import matplotlib.pyplot as plt 41from matplotlib.font_manager import FontProperties 42import numpy as np 43import os 44 45# global results dict 46results = {} 47idleResults = {} 48 49# global vars for bank utilisation and seq_bytes values swept in the experiment 50bankUtilValues = [] 51seqBytesValues = [] 52delayValues = [] 53 54# settings for 3 values of bank util and 3 values of seq_bytes 55stackHeight = 6.0 56stackWidth = 18.0 57barWidth = 0.5 58plotFontSize = 18 59 60States = ['IDLE', 'ACT', 'REF', 'ACT_PDN', 'PRE_PDN', 'SREF'] 61 62EnergyStates = ['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 72StackColors = { 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 90StatToKey = { 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 104def 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 207def 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 227def 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 293def idlePlotName(plot_dir): 294 return (plot_dir + 'idle.eps') 295 296def stateTimePlotName(plot_dir): 297 return (plot_dir + 'state-time.eps') 298 299def stateEnergyPlotName(plot_dir): 300 return (plot_dir + 'state-energy.eps') 301 302def 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] = {} 309