util: Enable DRAM sweep to print power and efficiency

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.
This commit is contained in:
Andreas Hansson 2015-08-05 04:36:31 -04:00
parent 646994e599
commit d540ba0325

View file

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