113540Sandrea.mondelli@ucf.edu#!/usr/bin/env python2.7 212269Sradhika.jagtap@arm.com 312269Sradhika.jagtap@arm.com# Copyright (c) 2014 ARM Limited 412269Sradhika.jagtap@arm.com# All rights reserved 512269Sradhika.jagtap@arm.com# 612269Sradhika.jagtap@arm.com# The license below extends only to copyright in the software and shall 712269Sradhika.jagtap@arm.com# not be construed as granting a license to any other intellectual 812269Sradhika.jagtap@arm.com# property including but not limited to intellectual property relating 912269Sradhika.jagtap@arm.com# to a hardware implementation of the functionality of the software 1012269Sradhika.jagtap@arm.com# licensed hereunder. You may use the software subject to the license 1112269Sradhika.jagtap@arm.com# terms below provided that you ensure that this notice is replicated 1212269Sradhika.jagtap@arm.com# unmodified and in its entirety in all distributions of the software, 1312269Sradhika.jagtap@arm.com# modified or unmodified, in source code or in binary form. 1412269Sradhika.jagtap@arm.com# 1512269Sradhika.jagtap@arm.com# Redistribution and use in source and binary forms, with or without 1612269Sradhika.jagtap@arm.com# modification, are permitted provided that the following conditions are 1712269Sradhika.jagtap@arm.com# met: redistributions of source code must retain the above copyright 1812269Sradhika.jagtap@arm.com# notice, this list of conditions and the following disclaimer; 1912269Sradhika.jagtap@arm.com# redistributions in binary form must reproduce the above copyright 2012269Sradhika.jagtap@arm.com# notice, this list of conditions and the following disclaimer in the 2112269Sradhika.jagtap@arm.com# documentation and/or other materials provided with the distribution; 2212269Sradhika.jagtap@arm.com# neither the name of the copyright holders nor the names of its 2312269Sradhika.jagtap@arm.com# contributors may be used to endorse or promote products derived from 2412269Sradhika.jagtap@arm.com# this software without specific prior written permission. 2512269Sradhika.jagtap@arm.com# 2612269Sradhika.jagtap@arm.com# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2712269Sradhika.jagtap@arm.com# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2812269Sradhika.jagtap@arm.com# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2912269Sradhika.jagtap@arm.com# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3012269Sradhika.jagtap@arm.com# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 3112269Sradhika.jagtap@arm.com# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 3212269Sradhika.jagtap@arm.com# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3312269Sradhika.jagtap@arm.com# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3412269Sradhika.jagtap@arm.com# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3512269Sradhika.jagtap@arm.com# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3612269Sradhika.jagtap@arm.com# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3712269Sradhika.jagtap@arm.com# 3812269Sradhika.jagtap@arm.com# Authors: Andreas Hansson 3912269Sradhika.jagtap@arm.com 4012269Sradhika.jagtap@arm.comtry: 4112269Sradhika.jagtap@arm.com from mpl_toolkits.mplot3d import Axes3D 4212269Sradhika.jagtap@arm.com from matplotlib import cm 4312269Sradhika.jagtap@arm.com import matplotlib.pyplot as plt 4412269Sradhika.jagtap@arm.com import numpy as np 4512269Sradhika.jagtap@arm.comexcept ImportError: 4612269Sradhika.jagtap@arm.com print "Failed to import matplotlib and numpy" 4712269Sradhika.jagtap@arm.com exit(-1) 4812269Sradhika.jagtap@arm.com 4912269Sradhika.jagtap@arm.comimport sys 5012269Sradhika.jagtap@arm.comimport re 5112269Sradhika.jagtap@arm.com 5212269Sradhika.jagtap@arm.com# Determine the parameters of the sweep from the simout output, and 5312269Sradhika.jagtap@arm.com# then parse the stats and plot the 3D surface corresponding to the 5412269Sradhika.jagtap@arm.com# different combinations of parallel banks, and stride size, as 5512269Sradhika.jagtap@arm.com# generated by the config/dram/sweep.py script 5612269Sradhika.jagtap@arm.comdef main(): 5712269Sradhika.jagtap@arm.com 5812269Sradhika.jagtap@arm.com if len(sys.argv) != 3: 5912269Sradhika.jagtap@arm.com print "Usage: ", sys.argv[0], "-u|p|e <simout directory>" 6012269Sradhika.jagtap@arm.com exit(-1) 6112269Sradhika.jagtap@arm.com 6212269Sradhika.jagtap@arm.com if len(sys.argv[1]) != 2 or sys.argv[1][0] != '-' or \ 6312269Sradhika.jagtap@arm.com not sys.argv[1][1] in "upe": 6412269Sradhika.jagtap@arm.com print "Choose -u (utilisation), -p (total power), or -e " \ 6512269Sradhika.jagtap@arm.com "(power efficiency)" 6612269Sradhika.jagtap@arm.com exit(-1) 6712269Sradhika.jagtap@arm.com 6812269Sradhika.jagtap@arm.com # Choose the appropriate mode, either utilisation, total power, or 6912269Sradhika.jagtap@arm.com # efficiency 7012269Sradhika.jagtap@arm.com mode = sys.argv[1][1] 7112269Sradhika.jagtap@arm.com 7212269Sradhika.jagtap@arm.com try: 7312269Sradhika.jagtap@arm.com stats = open(sys.argv[2] + '/stats.txt', 'r') 7412269Sradhika.jagtap@arm.com except IOError: 7512269Sradhika.jagtap@arm.com print "Failed to open ", sys.argv[2] + '/stats.txt', " for reading" 7612269Sradhika.jagtap@arm.com exit(-1) 7712269Sradhika.jagtap@arm.com 7812269Sradhika.jagtap@arm.com try: 7912269Sradhika.jagtap@arm.com simout = open(sys.argv[2] + '/simout', 'r') 8012269Sradhika.jagtap@arm.com except IOError: 8112269Sradhika.jagtap@arm.com print "Failed to open ", sys.argv[2] + '/simout', " for reading" 8212269Sradhika.jagtap@arm.com exit(-1) 8312269Sradhika.jagtap@arm.com 8412269Sradhika.jagtap@arm.com # Get the burst size, number of banks and the maximum stride from 8512269Sradhika.jagtap@arm.com # the simulation output 8612269Sradhika.jagtap@arm.com got_sweep = False 8712269Sradhika.jagtap@arm.com 8812269Sradhika.jagtap@arm.com for line in simout: 8912269Sradhika.jagtap@arm.com match = re.match("DRAM sweep with " 9012269Sradhika.jagtap@arm.com "burst: (\d+), banks: (\d+), max stride: (\d+)", line) 9112269Sradhika.jagtap@arm.com if match: 9212269Sradhika.jagtap@arm.com burst_size = int(match.groups(0)[0]) 9312269Sradhika.jagtap@arm.com banks = int(match.groups(0)[1]) 9412269Sradhika.jagtap@arm.com max_size = int(match.groups(0)[2]) 9512269Sradhika.jagtap@arm.com got_sweep = True 9612269Sradhika.jagtap@arm.com 9712269Sradhika.jagtap@arm.com simout.close() 9812269Sradhika.jagtap@arm.com 9912269Sradhika.jagtap@arm.com if not got_sweep: 10012269Sradhika.jagtap@arm.com print "Failed to establish sweep details, ensure simout is up-to-date" 10112269Sradhika.jagtap@arm.com exit(-1) 10212269Sradhika.jagtap@arm.com 10312269Sradhika.jagtap@arm.com # Now parse the stats 10412269Sradhika.jagtap@arm.com peak_bw = [] 10512269Sradhika.jagtap@arm.com bus_util = [] 10612269Sradhika.jagtap@arm.com avg_pwr = [] 10712269Sradhika.jagtap@arm.com 10812269Sradhika.jagtap@arm.com for line in stats: 10912269Sradhika.jagtap@arm.com match = re.match(".*busUtil\s+(\d+\.\d+)\s+#.*", line) 11012269Sradhika.jagtap@arm.com if match: 11112269Sradhika.jagtap@arm.com bus_util.append(float(match.groups(0)[0])) 11212269Sradhika.jagtap@arm.com 11312269Sradhika.jagtap@arm.com match = re.match(".*peakBW\s+(\d+\.\d+)\s+#.*", line) 11412269Sradhika.jagtap@arm.com if match: 11512269Sradhika.jagtap@arm.com peak_bw.append(float(match.groups(0)[0])) 11612269Sradhika.jagtap@arm.com 11712269Sradhika.jagtap@arm.com match = re.match(".*averagePower\s+(\d+\.?\d*)\s+#.*", line) 11812269Sradhika.jagtap@arm.com if match: 11912269Sradhika.jagtap@arm.com avg_pwr.append(float(match.groups(0)[0])) 12012269Sradhika.jagtap@arm.com stats.close() 12112269Sradhika.jagtap@arm.com 12212269Sradhika.jagtap@arm.com 12312269Sradhika.jagtap@arm.com # Sanity check 12412269Sradhika.jagtap@arm.com if not (len(peak_bw) == len(bus_util) and len(bus_util) == len(avg_pwr)): 12512269Sradhika.jagtap@arm.com print "Peak bandwidth, bus utilisation, and average power do not match" 12612269Sradhika.jagtap@arm.com exit(-1) 12712269Sradhika.jagtap@arm.com 12812269Sradhika.jagtap@arm.com # Collect the selected metric as our Z-axis, we do this in a 2D 12912269Sradhika.jagtap@arm.com # grid corresponding to each iteration over the various stride 13012269Sradhika.jagtap@arm.com # sizes. 13112269Sradhika.jagtap@arm.com z = [] 13212269Sradhika.jagtap@arm.com zs = [] 13312269Sradhika.jagtap@arm.com i = 0 13412269Sradhika.jagtap@arm.com 13512269Sradhika.jagtap@arm.com for j in range(len(peak_bw)): 13612269Sradhika.jagtap@arm.com if mode == 'u': 13712269Sradhika.jagtap@arm.com z.append(bus_util[j]) 13812269Sradhika.jagtap@arm.com elif mode == 'p': 13912269Sradhika.jagtap@arm.com z.append(avg_pwr[j]) 14012269Sradhika.jagtap@arm.com elif mode == 'e': 14112269Sradhika.jagtap@arm.com # avg_pwr is in mW, peak_bw in MiByte/s, bus_util in percent 14212269Sradhika.jagtap@arm.com z.append(avg_pwr[j] / (bus_util[j] / 100.0 * peak_bw[j] / 1000.0)) 14312269Sradhika.jagtap@arm.com else: 14412269Sradhika.jagtap@arm.com print "Unexpected mode %s" % mode 14512269Sradhika.jagtap@arm.com exit(-1) 14612269Sradhika.jagtap@arm.com 14712269Sradhika.jagtap@arm.com i += 1 14812269Sradhika.jagtap@arm.com # If we have completed a sweep over the stride sizes, 14912269Sradhika.jagtap@arm.com # start anew 15012269Sradhika.jagtap@arm.com if i == max_size / burst_size: 15112269Sradhika.jagtap@arm.com zs.append(z) 15212269Sradhika.jagtap@arm.com z = [] 15312269Sradhika.jagtap@arm.com i = 0 15412269Sradhika.jagtap@arm.com 15512269Sradhika.jagtap@arm.com # We should have a 2D grid with as many columns as banks 15612269Sradhika.jagtap@arm.com if len(zs) != banks: 15712269Sradhika.jagtap@arm.com print "Unexpected number of data points in stats output" 15812269Sradhika.jagtap@arm.com exit(-1) 15912269Sradhika.jagtap@arm.com 16012269Sradhika.jagtap@arm.com fig = plt.figure() 16112269Sradhika.jagtap@arm.com ax = fig.gca(projection='3d') 16212269Sradhika.jagtap@arm.com X = np.arange(burst_size, max_size + 1, burst_size) 16312269Sradhika.jagtap@arm.com Y = np.arange(1, banks + 1, 1) 16412269Sradhika.jagtap@arm.com X, Y = np.meshgrid(X, Y) 16512269Sradhika.jagtap@arm.com 16612269Sradhika.jagtap@arm.com # the values in the util are banks major, so we see groups for each 16712269Sradhika.jagtap@arm.com # stride size in order 16812269Sradhika.jagtap@arm.com Z = np.array(zs) 16912269Sradhika.jagtap@arm.com 17012269Sradhika.jagtap@arm.com surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.coolwarm, 17112269Sradhika.jagtap@arm.com linewidth=0, antialiased=False) 17212269Sradhika.jagtap@arm.com 17312269Sradhika.jagtap@arm.com # Change the tick frequency to 64 17412269Sradhika.jagtap@arm.com start, end = ax.get_xlim() 17512269Sradhika.jagtap@arm.com ax.xaxis.set_ticks(np.arange(start, end + 1, 64)) 17612269Sradhika.jagtap@arm.com 17712269Sradhika.jagtap@arm.com ax.set_xlabel('Bytes per activate') 17812269Sradhika.jagtap@arm.com ax.set_ylabel('Banks') 17912269Sradhika.jagtap@arm.com 18012269Sradhika.jagtap@arm.com if mode == 'u': 18112269Sradhika.jagtap@arm.com ax.set_zlabel('Utilisation (%)') 18212269Sradhika.jagtap@arm.com elif mode == 'p': 18312269Sradhika.jagtap@arm.com ax.set_zlabel('Power (mW)') 18412269Sradhika.jagtap@arm.com elif mode == 'e': 18512269Sradhika.jagtap@arm.com ax.set_zlabel('Power efficiency (mW / GByte / s)') 18612269Sradhika.jagtap@arm.com 18712269Sradhika.jagtap@arm.com # Add a colorbar 18812269Sradhika.jagtap@arm.com fig.colorbar(surf, shrink=0.5, pad=.1, aspect=10) 18912269Sradhika.jagtap@arm.com 19012269Sradhika.jagtap@arm.com plt.show() 19112269Sradhika.jagtap@arm.com 19212269Sradhika.jagtap@arm.comif __name__ == "__main__": 19312269Sradhika.jagtap@arm.com main() 194