mem: Store snoop filter lookup result to avoid second lookup
[gem5.git] / util / dram_sweep_plot.py
1 #!/usr/bin/env python
2
3 # Copyright (c) 2014 ARM Limited
4 # All rights reserved
5 #
6 # The license below extends only to copyright in the software and shall
7 # not be construed as granting a license to any other intellectual
8 # property including but not limited to intellectual property relating
9 # to a hardware implementation of the functionality of the software
10 # licensed hereunder. You may use the software subject to the license
11 # terms below provided that you ensure that this notice is replicated
12 # unmodified and in its entirety in all distributions of the software,
13 # modified or unmodified, in source code or in binary form.
14 #
15 # Redistribution and use in source and binary forms, with or without
16 # modification, are permitted provided that the following conditions are
17 # met: redistributions of source code must retain the above copyright
18 # notice, this list of conditions and the following disclaimer;
19 # redistributions in binary form must reproduce the above copyright
20 # notice, this list of conditions and the following disclaimer in the
21 # documentation and/or other materials provided with the distribution;
22 # neither the name of the copyright holders nor the names of its
23 # contributors may be used to endorse or promote products derived from
24 # this software without specific prior written permission.
25 #
26 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 #
38 # Authors: Andreas Hansson
39
40 try:
41
42 from mpl_toolkits.mplot3d import Axes3D
43 from matplotlib import cm
44 from matplotlib.ticker import LinearLocator, FormatStrFormatter
45 import matplotlib.pyplot as plt
46 import numpy as np
47 except ImportError:
48 print "Failed to import matplotlib and numpy"
49 exit(-1)
50
51 import sys
52 import re
53
54 # Determine the parameters of the sweep from the simout output, and
55 # then parse the stats and plot the 3D surface corresponding to the
56 # different combinations of parallel banks, and stride size, as
57 # generated by the config/dram/sweep.py script
58 def main():
59
60 if len(sys.argv) != 3:
61 print "Usage: ", sys.argv[0], "-u|p|e <simout directory>"
62 exit(-1)
63
64 if len(sys.argv[1]) != 2 or sys.argv[1][0] != '-' or \
65 not sys.argv[1][1] in "upe":
66 print "Choose -u (utilisation), -p (total power), or -e " \
67 "(power efficiency)"
68 exit(-1)
69
70 # Choose the appropriate mode, either utilisation, total power, or
71 # efficiency
72 mode = sys.argv[1][1]
73
74 try:
75 stats = open(sys.argv[2] + '/stats.txt', 'r')
76 except IOError:
77 print "Failed to open ", sys.argv[1] + '/stats.txt', " for reading"
78 exit(-1)
79
80 try:
81 simout = open(sys.argv[2] + '/simout', 'r')
82 except IOError:
83 print "Failed to open ", sys.argv[1] + '/simout', " for reading"
84 exit(-1)
85
86 # Get the burst size, number of banks and the maximum stride from
87 # the simulation output
88 got_sweep = False
89
90 for line in simout:
91 match = re.match("DRAM sweep with "
92 "burst: (\d+), banks: (\d+), max stride: (\d+)", line)
93 if match:
94 burst_size = int(match.groups(0)[0])
95 banks = int(match.groups(0)[1])
96 max_size = int(match.groups(0)[2])
97 got_sweep = True
98
99 simout.close()
100
101 if not got_sweep:
102 print "Failed to establish sweep details, ensure simout is up-to-date"
103 exit(-1)
104
105 # Now parse the stats
106 peak_bw = []
107 bus_util = []
108 avg_pwr = []
109
110 for line in stats:
111 match = re.match(".*busUtil\s+(\d+\.\d+)\s+#.*", line)
112 if match:
113 bus_util.append(float(match.groups(0)[0]))
114
115 match = re.match(".*peakBW\s+(\d+\.\d+)\s+#.*", line)
116 if match:
117 peak_bw.append(float(match.groups(0)[0]))
118
119 match = re.match(".*averagePower\s+(\d+\.?\d*)\s+#.*", line)
120 if match:
121 avg_pwr.append(float(match.groups(0)[0]))
122 stats.close()
123
124
125 # Sanity check
126 if not (len(peak_bw) == len(bus_util) and len(bus_util) == len(avg_pwr)):
127 print "Peak bandwidth, bus utilisation, and average power do not match"
128 exit(-1)
129
130 # Collect the selected metric as our Z-axis, we do this in a 2D
131 # grid corresponding to each iteration over the various stride
132 # sizes.
133 z = []
134 zs = []
135 i = 0
136
137 for j in range(len(peak_bw)):
138 if mode == 'u':
139 z.append(bus_util[j])
140 elif mode == 'p':
141 z.append(avg_pwr[j])
142 elif mode == 'e':
143 # avg_pwr is in mW, peak_bw in MiByte/s, bus_util in percent
144 z.append(avg_pwr[j] / (bus_util[j] / 100.0 * peak_bw[j] / 1000.0))
145 else:
146 print "Unexpected mode %s" % mode
147 exit(-1)
148
149 i += 1
150 # If we have completed a sweep over the stride sizes,
151 # start anew
152 if i == max_size / burst_size:
153 zs.append(z)
154 z = []
155 i = 0
156
157 # We should have a 2D grid with as many columns as banks
158 if len(zs) != banks:
159 print "Unexpected number of data points in stats output"
160 exit(-1)
161
162 fig = plt.figure()
163 ax = fig.gca(projection='3d')
164 X = np.arange(burst_size, max_size + 1, burst_size)
165 Y = np.arange(1, banks + 1, 1)
166 X, Y = np.meshgrid(X, Y)
167
168 # the values in the util are banks major, so we see groups for each
169 # stride size in order
170 Z = np.array(zs)
171
172 surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.coolwarm,
173 linewidth=0, antialiased=False)
174
175 # Change the tick frequency to 64
176 start, end = ax.get_xlim()
177 ax.xaxis.set_ticks(np.arange(start, end + 1, 64))
178
179 ax.set_xlabel('Bytes per activate')
180 ax.set_ylabel('Banks')
181
182 if mode == 'u':
183 ax.set_zlabel('Utilisation (%)')
184 elif mode == 'p':
185 ax.set_zlabel('Power (mW)')
186 elif mode == 'e':
187 ax.set_zlabel('Power efficiency (mW / GByte / s)')
188
189 # Add a colorbar
190 fig.colorbar(surf, shrink=0.5, pad=.1, aspect=10)
191
192 plt.show()
193
194 if __name__ == "__main__":
195 main()