Inorder: Fix compilation of m5.fast.
[gem5.git] / util / stats / db.py
index 6e1ccec9508062e6725e53c2a5f1cc61a1742ea8..e1198d4380dd40eef6af84448ec472fe45ed0035 100644 (file)
@@ -23,6 +23,8 @@
 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# Authors: Nathan Binkert
 
 import MySQLdb, re, string
 
@@ -101,7 +103,21 @@ class Node(object):
     def __init__(self, name):
         self.name = name
     def __str__(self):
-        return name
+        return self.name
+
+class Result(object):
+    def __init__(self, x, y):
+        self.data = {}
+        self.x = x
+        self.y = y
+
+    def __contains__(self, run):
+        return run in self.data
+
+    def __getitem__(self, run):
+        if run not in self.data:
+            self.data[run] = [ [ 0.0 ] * self.y for i in xrange(self.x) ]
+        return self.data[run]
 
 class Database(object):
     def __init__(self):
@@ -121,10 +137,6 @@ class Database(object):
         self.allRunIds = {}
         self.allRunNames = {}
 
-        self.allBins = []
-        self.allBinIds = {}
-        self.allBinNames = {}
-
         self.allFormulas = {}
 
         self.stattop = {}
@@ -133,9 +145,30 @@ class Database(object):
 
         self.mode = 'sum';
         self.runs = None
-        self.bins = None
         self.ticks = None
-        self.__dict__['get'] = type(self).sum
+        self.method = 'sum'
+        self._method = type(self).sum
+
+    def get(self, job, stat, system=None):
+        run = self.allRunNames.get(str(job), None)
+        if run is None:
+            return None
+
+        from info import ProxyError, scalar, vector, value, values, total, len
+        if system is None and hasattr(job, 'system'):
+            system = job.system
+
+        if system is not None:
+            stat.system = self[system]
+        try:
+            if scalar(stat):
+                return value(stat, run.run)
+            if vector(stat):
+                return values(stat, run.run)
+        except ProxyError:
+            return None
+
+        return None
 
     def query(self, sql):
         self.cursor.execute(sql)
@@ -182,11 +215,6 @@ class Database(object):
             self.allRunIds[run.run] = run
             self.allRunNames[run.name] = run
 
-        self.query('select * from bins')
-        for id,name in self.cursor.fetchall():
-            self.allBinIds[int(id)] = name
-            self.allBinNames[name] = int(id)
-
         self.query('select sd_stat,sd_x,sd_y,sd_name,sd_descr from subdata')
         for result in self.cursor.fetchall():
             subdata = SubData(result)
@@ -203,24 +231,12 @@ class Database(object):
         self.query('select * from stats')
         import info
         for result in self.cursor.fetchall():
-            stat = info.NewStat(StatData(result))
+            stat = info.NewStat(self, StatData(result))
             self.append(stat)
             self.allStats.append(stat)
             self.allStatIds[stat.stat] = stat
             self.allStatNames[stat.name] = stat
 
-    # Name: listbins
-    # Desc: Prints all bins matching regex argument, if no argument
-    #       is given all bins are returned
-    def listBins(self, regex='.*'):
-        print '%-50s %-10s' % ('bin name', 'id')
-        print '-' * 61
-        names = self.allBinNames.keys()
-        names.sort()
-        for name in names:
-            id = self.allBinNames[name]
-            print '%-50s %-10d' % (name, id)
-
     # Name: listruns
     # Desc: Prints all runs matching a given user, if no argument
     #       is given all runs are returned
@@ -324,39 +340,10 @@ class Database(object):
                         ret.append(stat)
         return ret
 
-    def getBin(self, bins):
-        if type(bins) is not list:
-            bins = [ bins ]
-
-        ret = []
-        for bin in bins:
-            if type(bin) is int:
-                ret.append(bin)
-            elif type(bin) is str:
-                ret.append(self.allBinNames[bin])
-            else:
-                for name,id in self.allBinNames.items():
-                    if bin.match(name):
-                        ret.append(id)
-
-        return ret
-
-    def getNotBin(self, bin):
-        map = {}
-        for bin in getBin(bin):
-            map[bin] = 1
-
-        ret = []
-        for bin in self.allBinIds.keys():
-            if not map.has_key(bin):
-                ret.append(bin)
-
-        return ret
-
     #########################################
     # get the data
     #
-    def inner(self, op, stat, bins, ticks, group=False):
+    def query(self, op, stat, ticks, group=False):
         sql = 'select '
         sql += 'dt_stat as stat, '
         sql += 'dt_run as run, '
@@ -378,10 +365,6 @@ class Database(object):
             val = ' or '.join([ 'dt_run=%d' % r for r in self.runs ])
             sql += ' and (%s)' % val
 
-        if bins != None and len(bins):
-            val = ' or '.join([ 'dt_bin=%d' % b for b in bins ])
-            sql += ' and (%s)' % val
-
         if ticks != None and len(ticks):
             val = ' or '.join([ 'dt_tick=%d' % s for s in ticks ])
             sql += ' and (%s)' % val
@@ -391,72 +374,45 @@ class Database(object):
             sql += ',dt_tick'
         return sql
 
-    def outer(self, op_out, op_in, stat, bins, ticks):
-        sql = self.inner(op_in, stat, bins, ticks, True)
-        sql = 'select stat,run,x,y,%s(data) from (%s) as tb ' % (op_out, sql)
-        sql += 'group by stat,run,x,y'
-        return sql
-
     # Name: sum
-    # Desc: given a run, a stat and an array of samples and bins,
-    #        sum all the bins and then get the standard deviation of the
-    #        samples for non-binned runs. This will just return the average
-    #        of samples, however a bin array still must be passed
-    def sum(self, stat, bins, ticks):
-        return self.inner('sum', stat, bins, ticks)
+    # Desc: given a run, a stat and an array of samples, total the samples
+    def sum(self, *args, **kwargs):
+        return self.query('sum', *args, **kwargs)
 
     # Name: avg
-    # Desc: given a run, a stat and an array of samples and bins,
-    #        sum all the bins and then average the samples for non-binned
-    #        runs this will just return the average of samples, however
-    #        a bin array still must be passed
-    def avg(self, stat, bins, ticks):
-        return self.outer('avg', 'sum', stat, bins, ticks)
+    # Desc: given a run, a stat and an array of samples, average the samples
+    def avg(self, stat, ticks):
+        return self.query('avg', *args, **kwargs)
 
     # Name: stdev
-    # Desc: given a run, a stat and an array of samples and bins,
-    #        sum all the bins and then get the standard deviation of the
-    #        samples for non-binned runs. This will just return the average
-    #        of samples, however a bin array still must be passed
-    def stdev(self, stat, bins, ticks):
-        return self.outer('stddev', 'sum', stat, bins, ticks)
-
-    def __getattribute__(self, attr):
-        if attr != 'get':
-            return super(Database, self).__getattribute__(attr)
-
-        if self.__dict__['get'] == type(self).sum:
-            return 'sum'
-        elif self.__dict__['get'] == type(self).avg:
-            return 'avg'
-        elif self.__dict__['get'] == type(self).stdev:
-            return 'stdev'
-        else:
-            return ''
+    # Desc: given a run, a stat and an array of samples, get the standard
+    #       deviation
+    def stdev(self, stat, ticks):
+        return self.query('stddev', *args, **kwargs)
 
     def __setattr__(self, attr, value):
-        if attr != 'get':
-            super(Database, self).__setattr__(attr, value)
+        super(Database, self).__setattr__(attr, value)
+        if attr != 'method':
             return
 
         if value == 'sum':
-            self.__dict__['get'] = type(self).sum
+            self._method = self.sum
         elif value == 'avg':
-            self.__dict__['get'] = type(self).avg
+            self._method = self.avg
         elif value == 'stdev':
-            self.__dict__['get'] = type(self).stdev
+            self._method = self.stdev
         else:
             raise AttributeError, "can only set get to: sum | avg | stdev"
 
-    def data(self, stat, bins=None, ticks=None):
-        if bins is None:
-            bins = self.bins
+    def data(self, stat, ticks=None):
         if ticks is None:
             ticks = self.ticks
-        sql = self.__dict__['get'](self, stat, bins, ticks)
+        sql = self._method(self, stat, ticks)
         self.query(sql)
 
         runs = {}
+        xmax = 0
+        ymax = 0
         for x in self.cursor.fetchall():
             data = Data(x)
             if not runs.has_key(data.run):
@@ -464,5 +420,17 @@ class Database(object):
             if not runs[data.run].has_key(data.x):
                 runs[data.run][data.x] = {}
 
+            xmax = max(xmax, data.x)
+            ymax = max(ymax, data.y)
             runs[data.run][data.x][data.y] = data.data
-        return runs
+
+        results = Result(xmax + 1, ymax + 1)
+        for run,data in runs.iteritems():
+            result = results[run]
+            for x,ydata in data.iteritems():
+                for y,data in ydata.iteritems():
+                    result[x][y] = data
+        return results
+
+    def __getitem__(self, key):
+        return self.stattop[key]