1#!/usr/bin/env python
2
3# Copyright (c) 2003-2004 The Regents of The University of Michigan
4# All rights reserved.
5#
6# Redistribution and use in source and binary forms, with or without
7# modification, are permitted provided that the following conditions are
8# met: redistributions of source code must retain the above copyright
9# notice, this list of conditions and the following disclaimer;
10# redistributions in binary form must reproduce the above copyright
11# notice, this list of conditions and the following disclaimer in the
12# documentation and/or other materials provided with the distribution;
13# neither the name of the copyright holders nor the names of its
14# contributors may be used to endorse or promote products derived from
15# this software without specific prior written permission.
16#
17# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28#
29# Authors: Nathan Binkert
30
31from __future__ import division
32import re, sys, math
33
34def usage():
35 print '''\
36Usage: %s [-E] [-F] [ -G <get> ] [-d <db> ] [-g <graphdir> ] [-h <host>] [-p]
37 [-s <system>] [-r <runs> ] [-T <samples>] [-u <username>]
38 <command> [command args]
39
40 commands extra parameters description
41 ----------- ------------------ ---------------------------------------
42 bins [regex] List bins (only matching regex)
43 formula <formula> Evaluated formula specified
44 formulas [regex] List formulas (only matching regex)
45 runs none List all runs in database
46 samples none List samples present in database
47 stability <pairnum> <stats> Calculated statistical info about stats
48 stat <regex> Show stat data (only matching regex)
49 stats [regex] List all stats (only matching regex)
50
51 database <command> Where command is drop, init, or clean
52
53''' % sys.argv[0]
54 sys.exit(1)
55
56def getopts(list, flags):
57 import getopt
58 try:
59 opts, args = getopt.getopt(list, flags)
60 except getopt.GetoptError:
61 usage()
62
63 return opts, args
64
65class CommandException(Exception):
66 pass
67
68def commands(options, command, args):
69 if command == 'database':
70 if len(args) == 0: raise CommandException
71
72 import dbinit
73 mydb = dbinit.MyDB(options)
74
75 if args[0] == 'drop':
76 if len(args) > 2: raise CommandException
77 mydb.admin()
78 mydb.drop()
79 if len(args) == 2 and args[1] == 'init':
80 mydb.create()
81 mydb.connect()
82 mydb.populate()
83 mydb.close()
84 return
85
86 if args[0] == 'init':
87 if len(args) > 1: raise CommandException
88 mydb.admin()
89 mydb.create()
90 mydb.connect()
91 mydb.populate()
92 mydb.close()
93 return
94
95 if args[0] == 'clean':
96 if len(args) > 1: raise CommandException
97 mydb.connect()
98 mydb.clean()
99 return
100
101 raise CommandException
102
103 import db
104 source = db.Database()
105 source.host = options.host
106 source.db = options.db
107 source.passwd = options.passwd
108 source.user = options.user
109 source.connect()
110 #source.update_dict(globals())
111
112 if type(options.method) is str:
113 source.method = options.method
114
115 if options.runs is None:
116 runs = source.allRuns
117 else:
118 rx = re.compile(options.runs)
119 runs = []
120 for run in source.allRuns:
121 if rx.match(run.name):
122 runs.append(run)
123
124 if command == 'runs':
125 user = None
126 opts, args = getopts(args, '-u')
127 if len(args):
128 raise CommandException
129 for o,a in opts:
130 if o == '-u':
131 user = a
132 source.listRuns(user)
133 return
134
135 if command == 'stats':
136 if len(args) == 0:
137 source.listStats()
138 elif len(args) == 1:
139 source.listStats(args[0])
140 else:
141 raise CommandException
142
143 return
144
145 if command == 'bins':
146 if len(args) == 0:
147 source.listBins()
148 elif len(args) == 1:
149 source.listBins(args[0])
150 else:
151 raise CommandException
152
153 return
154
155 if command == 'formulas':
156 if len(args) == 0:
157 source.listFormulas()
158 elif len(args) == 1:
159 source.listFormulas(args[0])
160 else:
161 raise CommandException
162
163 return
164
165 if command == 'samples':
166 if len(args):
167 raise CommandException
168
169 source.listTicks(runs)
170 return
171
172 if command == 'stability':
173 if len(args) < 2:
174 raise CommandException
175
176 try:
177 merge = int(args[0])
178 except ValueError:
179 usage()
180 stats = source.getStat(args[1])
181 source.method = 'sum'
182
183 def disp(*args):
184 print "%-35s %12s %12s %4s %5s %5s %5s %10s" % args
185
186 # temporary variable containing a bunch of dashes
187 d = '-' * 100
188
189 #loop through all the stats selected
190 for stat in stats:
191 print "%s:" % stat.name
192 disp("run name", "average", "stdev", ">10%", ">1SDV", ">2SDV",
193 "SAMP", "CV")
194 disp(d[:35], d[:12], d[:12], d[:4], d[:5], d[:5], d[:5], d[:10])
195
196 #loop through all the selected runs
197 for run in runs:
198 runTicks = source.retTicks([ run ])
199 #throw away the first one, it's 0
200 runTicks.pop(0)
201 source.ticks = runTicks
202 avg = 0
203 stdev = 0
204 numoutsideavg = 0
205 numoutside1std = 0
206 numoutside2std = 0
207 pairRunTicks = []
208 if value(stat, run.run) == 1e300*1e300:
209 continue
210 for t in range(0, len(runTicks)-(merge-1), merge):
211 tempPair = []
212 for p in range(0,merge):
213 tempPair.append(runTicks[t+p])
214 pairRunTicks.append(tempPair)
215 #loop through all the various ticks for each run
216 for tick in pairRunTicks:
217 source.ticks = tick
218 avg += value(stat, run.run)
219 avg /= len(pairRunTicks)
220 for tick in pairRunTicks:
221 source.ticks = tick
222 val = value(stat, run.run)
223 stdev += pow((val-avg),2)
224 stdev = math.sqrt(stdev / len(pairRunTicks))
225 for tick in pairRunTicks:
226 source.ticks = tick
227 val = value(stat, run.run)
228 if (val < (avg * .9)) or (val > (avg * 1.1)):
229 numoutsideavg += 1
230 if (val < (avg - stdev)) or (val > (avg + stdev)):
231 numoutside1std += 1
232 if (val < (avg - (2*stdev))) or (val > (avg + (2*stdev))):
233 numoutside2std += 1
234 if avg > 1000:
235 disp(run.name, "%.1f" % avg, "%.1f" % stdev,
236 "%d" % numoutsideavg, "%d" % numoutside1std,
237 "%d" % numoutside2std, "%d" % len(pairRunTicks),
238 "%.3f" % (stdev/avg*100))
239 elif avg > 100:
240 disp(run.name, "%.1f" % avg, "%.1f" % stdev,
241 "%d" % numoutsideavg, "%d" % numoutside1std,
242 "%d" % numoutside2std, "%d" % len(pairRunTicks),
243 "%.5f" % (stdev/avg*100))
244 else:
245 disp(run.name, "%.5f" % avg, "%.5f" % stdev,
246 "%d" % numoutsideavg, "%d" % numoutside1std,
247 "%d" % numoutside2std, "%d" % len(pairRunTicks),
248 "%.7f" % (stdev/avg*100))
249 return
250
251 if command == 'all':
252 if len(args):
253 raise CommandException
254
255 all = [ 'bps', 'misses', 'mpkb', 'ipkb', 'pps', 'bpt' ]
256 for command in all:
257 commands(options, command, args)
258
259 if options.ticks:
260 if not options.graph:
261 print 'only displaying sample %s' % options.ticks
262 source.ticks = [ int(x) for x in options.ticks.split() ]
263
264 from output import StatOutput
265 output = StatOutput(options.jobfile, source)
266 output.xlabel = 'System Configuration'
267 output.colormap = 'RdYlGn'
268
269 if command == 'stat' or command == 'formula':
270 if len(args) != 1:
271 raise CommandException
272
273 if command == 'stat':
274 stats = source.getStat(args[0])
275 if command == 'formula':
276 stats = eval(args[0])
277
278 for stat in stats:
279 output.stat = stat
280 output.ylabel = stat.name
281 if options.graph:
282 output.graph(stat.name, options.graphdir)
283 else:
271 output.display(stat.name, options.printmode)
284 output.display(stat.name, options.binned, options.printmode)
285
286 return
287
288 if len(args):
289 raise CommandException
290
291 from info import ProxyGroup
292 proxy = ProxyGroup(system = source[options.system])
293 system = proxy.system
294
295 etherdev = system.tsunami.etherdev0
296 bytes = etherdev.rxBytes + etherdev.txBytes
297 kbytes = bytes / 1024
298 packets = etherdev.rxPackets + etherdev.txPackets
299
300 def display():
301 if options.graph:
302 output.graph(command, options.graphdir, proxy)
303 else:
291 output.display(command, options.printmode)
304 output.display(command, options.binned, options.printmode)
305
306 if command == 'usertime':
307 import copy
308 user = copy.copy(system.run0.numCycles)
309 user.bins = 'user'
310
311 output.stat = user / system.run0.numCycles
312 output.ylabel = 'User Fraction'
313
314 display()
315 return
316
317 if command == 'ticks':
318 output.stat = system.run0.numCycles
319 output.binstats = [ system.run0.numCycles ]
320
321 display()
322 return
323
324 if command == 'bytes':
325 output.stat = bytes
326 display()
327 return
328
329 if command == 'packets':
330 output.stat = packets
331 display()
332 return
333
334 if command == 'ppt' or command == 'tpp':
335 output.stat = packets / system.run0.numCycles
336 output.invert = command == 'tpp'
337 display()
338 return
339
340 if command == 'pps':
341 output.stat = packets / source['sim_seconds']
342 output.ylabel = 'Packets/s'
343 display()
344 return
345
346 if command == 'bpt' or command == 'tpb':
347 output.stat = bytes / system.run0.numCycles * 8
348 output.ylabel = 'bps / Hz'
349 output.invert = command == 'tpb'
350 display()
351 return
352
353 if command in ('rxbps', 'txbps', 'bps'):
354 if command == 'rxbps':
355 output.stat = etherdev.rxBandwidth / 1e9
356 if command == 'txbps':
357 output.stat = etherdev.txBandwidth / 1e9
358 if command == 'bps':
359 output.stat = (etherdev.rxBandwidth + etherdev.txBandwidth) / 1e9
360
361 output.ylabel = 'Bandwidth (Gbps)'
362 output.ylim = [ 0.0, 10.0 ]
363 display()
364 return
365
366 if command == 'bpp':
367 output.stat = bytes / packets
368 output.ylabel = 'Bytes / Packet'
369 display()
370 return
371
372 if command == 'rxbpp':
373 output.stat = etherdev.rxBytes / etherdev.rxPackets
374 output.ylabel = 'Receive Bytes / Packet'
375 display()
376 return
377
378 if command == 'txbpp':
379 output.stat = etherdev.txBytes / etherdev.txPackets
380 output.ylabel = 'Transmit Bytes / Packet'
381 display()
382 return
383
384 if command == 'rtp':
385 output.stat = etherdev.rxPackets / etherdev.txPackets
386 output.ylabel = 'rxPackets / txPackets'
387 display()
388 return
389
390 if command == 'rtb':
391 output.stat = etherdev.rxBytes / etherdev.txBytes
392 output.ylabel = 'rxBytes / txBytes'
393 display()
394 return
395
396 misses = system.l2.overall_mshr_misses
397
398 if command == 'misses':
399 output.stat = misses
400 output.ylabel = 'Overall MSHR Misses'
401 display()
402 return
403
404 if command == 'mpkb':
405 output.stat = misses / (bytes / 1024)
406 output.binstats = [ misses ]
407 output.ylabel = 'Misses / KB'
408 display()
409 return
410
411 if command == 'ipkb':
412 interrupts = system.run0.kern.faults[4]
413 output.stat = interrupts / kbytes
414 output.binstats = [ interrupts ]
415 output.ylabel = 'Interrupts / KB'
416 display()
417 return
418
419 if command == 'execute':
420 output.stat = system.run0.ISSUE__count
421 display()
422 return
423
424 if command == 'commit':
425 output.stat = system.run0.COM__count
426 display()
427 return
428
429 if command == 'fetch':
430 output.stat = system.run0.FETCH__count
431 display()
432 return
433
434 raise CommandException
435
436
437class Options: pass
438
439if __name__ == '__main__':
440 import getpass
441 from jobfile import JobFile
442
443 options = Options()
444 options.host = None
445 options.db = None
446 options.passwd = ''
447 options.user = getpass.getuser()
448 options.runs = None
449 options.system = 'client'
450 options.method = None
451 options.binned = False
452 options.graph = False
453 options.ticks = False
454 options.printmode = 'G'
455 jobfilename = 'Test.py'
456 options.jobfile = None
457 options.all = False
458
431 opts, args = getopts(sys.argv[1:], '-EFJad:g:h:j:m:pr:s:u:T:')
459 opts, args = getopts(sys.argv[1:], '-BEFJad:g:h:j:m:pr:s:u:T:')
460 for o,a in opts:
461 if o == '-B':
462 options.binned = True
463 if o == '-E':
464 options.printmode = 'E'
465 if o == '-F':
466 options.printmode = 'F'
467 if o == '-a':
468 options.all = True
469 if o == '-d':
470 options.db = a
471 if o == '-g':
472 options.graph = True;
473 options.graphdir = a
474 if o == '-h':
475 options.host = a
476 if o == '-J':
477 jobfilename = None
478 if o == '-j':
479 jobfilename = a
480 if o == '-m':
481 options.method = a
482 if o == '-p':
483 options.passwd = getpass.getpass()
484 if o == '-r':
485 options.runs = a
486 if o == '-u':
487 options.user = a
488 if o == '-s':
489 options.system = a
490 if o == '-T':
491 options.ticks = a
492
493 if jobfilename:
494 options.jobfile = JobFile(jobfilename)
495 if not options.host:
496 options.host = options.jobfile.dbhost
497 if not options.db:
498 options.db = options.jobfile.statdb
499
500 if not options.host:
501 sys.exit('Database server must be provided from a jobfile or -h')
502
503 if not options.db:
504 sys.exit('Database name must be provided from a jobfile or -d')
505
506 if len(args) == 0:
507 usage()
508
509 command = args[0]
510 args = args[1:]
511
512 try:
513 commands(options, command, args)
514 except CommandException:
515 usage()