util: Enable DRAM sweep to print power and efficiency
authorAndreas Hansson <andreas.hansson@arm.com>
Wed, 5 Aug 2015 08:36:31 +0000 (04:36 -0400)
committerAndreas Hansson <andreas.hansson@arm.com>
Wed, 5 Aug 2015 08:36:31 +0000 (04:36 -0400)
This patch enhances the functionality of the DRAM sweep script to not
only plot the bandwidth utilisation, but also total power and power
efficiency. To do so, a command-line switch is added, and a bit more
data extracted from the stats.

util/dram_sweep_plot.py

index a57de3d1cf2ad043dad8dccec9cebf10ebdeb871..347986b2029c1d6fc39ba41b3de2152964b126aa 100755 (executable)
@@ -57,18 +57,28 @@ import re
 # generated by the config/dram/sweep.py script
 def main():
 
-    if len(sys.argv) != 2:
-        print "Usage: ", sys.argv[0], " <simout directory>"
+    if len(sys.argv) != 3:
+        print "Usage: ", sys.argv[0], "-u|p|e <simout directory>"
         exit(-1)
 
+    if len(sys.argv[1]) != 2 or sys.argv[1][0] != '-' or \
+            not sys.argv[1][1] in "upe":
+        print "Choose -u (utilisation), -p (total power), or -e " \
+            "(power efficiency)"
+        exit(-1)
+
+    # Choose the appropriate mode, either utilisation, total power, or
+    # efficiency
+    mode = sys.argv[1][1]
+
     try:
-        stats = open(sys.argv[1] + '/stats.txt', 'r')
+        stats = open(sys.argv[2] + '/stats.txt', 'r')
     except IOError:
         print "Failed to open ", sys.argv[1] + '/stats.txt', " for reading"
         exit(-1)
 
     try:
-        simout = open(sys.argv[1] + '/simout', 'r')
+        simout = open(sys.argv[2] + '/simout', 'r')
     except IOError:
         print "Failed to open ", sys.argv[1] + '/simout', " for reading"
         exit(-1)
@@ -92,29 +102,57 @@ def main():
         print "Failed to establish sweep details, ensure simout is up-to-date"
         exit(-1)
 
+    # Now parse the stats
+    peak_bw = []
+    bus_util = []
+    avg_pwr = []
+
+    for line in stats:
+        match = re.match(".*busUtil\s+(\d+\.\d+)\s+#.*", line)
+        if match:
+            bus_util.append(float(match.groups(0)[0]))
+
+        match = re.match(".*peakBW\s+(\d+\.\d+)\s+#.*", line)
+        if match:
+            peak_bw.append(float(match.groups(0)[0]))
 
-    # Collect the bus utilisation as our Z-axis, we do this in a 2D
+        match = re.match(".*averagePower\s+(\d+\.\d+)\s+#.*", line)
+        if match:
+            avg_pwr.append(float(match.groups(0)[0]))
+    stats.close()
+
+
+    # Sanity check
+    if not (len(peak_bw) == len(bus_util) and len(bus_util) == len(avg_pwr)):
+        print "Peak bandwidth, bus utilisation, and average power do not match"
+        exit(-1)
+
+    # Collect the selected metric as our Z-axis, we do this in a 2D
     # grid corresponding to each iteration over the various stride
     # sizes.
     z = []
     zs = []
     i = 0
 
-    # Now parse the stats
-    for line in stats:
-        match = re.match(".*busUtil\s+(\d+\.\d+)\s+#.*", line)
-        if match:
-            bus_util = float(match.groups(0)[0])
-            z.append(bus_util)
-            i += 1
-            # If we have completed a sweep over the stride sizes,
-            # start anew
-            if i == max_size / burst_size:
-                zs.append(z)
-                z = []
-                i = 0
-
-    stats.close()
+    for j in range(len(peak_bw)):
+        if mode == 'u':
+            z.append(bus_util[j])
+        elif mode == 'p':
+            z.append(avg_pwr[j])
+        elif mode == 'e':
+            # avg_pwr is in mW, peak_bw in MiByte/s, bus_util in percent
+            z.append(avg_pwr[j] / (bus_util[j] / 100.0 * peak_bw[j] / 1000.0))
+        else:
+            print "Unexpected mode %s" % mode
+            exit(-1)
+
+        i += 1
+        # If we have completed a sweep over the stride sizes,
+        # start anew
+        if i == max_size / burst_size:
+            zs.append(z)
+            z = []
+            i = 0
 
     # We should have a 2D grid with as many columns as banks
     if len(zs) != banks:
@@ -140,7 +178,13 @@ def main():
 
     ax.set_xlabel('Bytes per activate')
     ax.set_ylabel('Banks')
-    ax.set_zlabel('Efficiency (%)')
+
+    if mode == 'u':
+        ax.set_zlabel('Utilisation (%)')
+    elif mode == 'p':
+        ax.set_zlabel('Power (mW)')
+    elif mode == 'e':
+        ax.set_zlabel('Power efficiency (mW / GByte / s)')
 
     # Add a colorbar
     fig.colorbar(surf, shrink=0.5, pad=.1, aspect=10)