diff -r d3f96871d795 -r 9835f2157f30 src/python/m5/stats/__init__.py --- a/src/python/m5/stats/__init__.py Tue Jan 15 18:35:56 2013 +0000 +++ b/src/python/m5/stats/__init__.py Tue Jan 15 18:36:36 2013 +0000 @@ -334,7 +334,7 @@ # database. if dump_count == 0: for name,stat in context.iterate(): - add_stat_info(stat, name, self.session) + add_stat_info(stat, self.session) # Write the values to the database. for name,stat in context.iterate(): diff -r d3f96871d795 -r 9835f2157f30 src/python/m5/stats/sql.py --- a/src/python/m5/stats/sql.py Tue Jan 15 18:35:56 2013 +0000 +++ b/src/python/m5/stats/sql.py Tue Jan 15 18:36:36 2013 +0000 @@ -45,6 +45,7 @@ raise from m5.util import fatal, panic +from math import isnan # @brief Create the database used to store the stats. If it exists, we delete @@ -156,13 +157,19 @@ formula = Column(String) def __init__(self, stat): + self.name = stat.name + + # All stats are stored in a list, and are accessed using the index in that + # list. We want to directly access the stat to avoid unnecessary calls to + # getattr. This results in faster stats processing. + stat = stat.stat + self.id = stat.id - self.name = stat.name self.desc = stat.desc self.flags = stat.flags self.precision = stat.precision if stat.prereq: - self.prereq = stat.prereq.id + self.prereq = stat.prereq self.type = stat.type if stat.type == "VectorInfo": @@ -315,8 +322,23 @@ # @param session The session associated with the database. # @param dumpCount The number of dumps that have occured. Used to store multiple # stats dumps in one database. -def store_stat_value(stat, session, dumpCount): +def store_stat_value(statContainer, session, dumpCount): + from m5.stats import flags + # All stats are stored in a list, and are accessed using the index in that + # list. We want to directly access the stat to avoid unnecessary calls to + # getattr. This results in faster stats processing. + stat = statContainer.stat + if stat.type == "ScalarInfo": + + # Don't write to the database if nan & corresponding flag is set + if isnan(stat.value) and (stat.flags & flags.nonan): + return + + # Don't write to the database if 0 & corresponding flag is set + if stat.value == 0 and (stat.flags & flags.nozero): + return + temp = ScalarValueClass(id = stat.id, dump = dumpCount, value = stat.value) session.add(temp) @@ -329,10 +351,36 @@ # statistic is. theTotal = [] if stat.type == "FormulaInfo": + + # Check if the value of the formula has been passed into python. If + # not, then we calculate it. + if hasattr(stat, "value"): + theValue = stat.value + else: + import m5.stats.info as info + # We need to fetch the value in a different way depending on if + # the stat is a scalar or a vector. + if info.scalar(stat): + theValue = [ info.value(stat) ] + else: + theValue = [ info.value(stat, i) for i in + xrange(info.len(stat)) ] + # The total for the formula can be caculated directly. This - # calculation takes place in the info.formula class. - theTotal.append(stat.total) + # calculation takes place in the info.formula class. However, we + # first check if we already have a value for the total, before we + # calculate it. + try: + # See if we have a value + theTotal.append(stat.total) + except: + # If not, calculate it. We need to access the stat container, + # i.e. the Formula class in the case + theTotal.append(statContainer._the_total) + elif stat.type == "VectorInfo": + theValue = stat.value + # The total for a vector is the sum of all values. However, as we # are unable to sum NaNs, these need to first be removed. import math @@ -343,6 +391,8 @@ # stats system. theTotal.append(sum(noNan)) else: + theValue = stat.value + # For a 2D vector we want to calculate the total for each value of # x, and therefore get an array of totals. If an overall total is # desired, this would be the sum of this array. This, however, is @@ -354,45 +404,65 @@ total += stat.value[iy + j] theTotal.append(total) + # Remove the NaNs in order to check if we should write this to the stats + # database, or not. + noNan = [ x for x in theValue if not isnan(x)] + + # Don't write to the database if all values are nan & corresponding flag + # is set + if not noNan and (stat.flags & flags.nonan): + return + + # Don't write to the database if all values are 0 & corresponding flag + # is set + if all(v == 0 for v in noNan) and (stat.flags & flags.nozero): + return + temp = VectorValueClass(id = stat.id, dump = dumpCount, - value = stat.value, total = theTotal) + value = theValue, total = theTotal) session.add(temp) elif stat.type == "DistInfo": from m5.stats.info import Deviation, Distribution, Histogram import array - data = stat.value + # If there are no samples, then there is no point writing this to the + # database. Don't check flags here. + if stat.value.samples: + data = stat.value - temp = DistValueClass(id = stat.id, dump = dumpCount) + temp = DistValueClass(id = stat.id, dump = dumpCount) - temp.sum = data.sum - temp.squares = data.squares - temp.samples = data.samples + temp.sum = data.sum + temp.squares = data.squares + temp.samples = data.samples - if type(data) == Distribution or type(data) == Histogram: - temp.min = data.min - temp.max = data.max - temp.bucket = data.bucket_size - a = array.array('f', data.vector) - temp.vector = a.tostring() + if type(data) == Distribution or type(data) == Histogram: + temp.min = data.min + temp.max = data.max + temp.bucket = data.bucket_size + a = array.array('f', data.vector) + temp.vector = a.tostring() - if type(data) == Histogram: - temp.logs = data.logs + if type(data) == Histogram: + temp.logs = data.logs - if type(data) == Distribution: - temp.min_val = data.min_val - temp.max_val = data.max_val - temp.underflow = data.underflow - temp.overflow = data.overflow + if type(data) == Distribution: + temp.min_val = data.min_val + temp.max_val = data.max_val + temp.underflow = data.underflow + temp.overflow = data.overflow - session.add(temp) + session.add(temp) elif stat.type == "SparseHistInfo": - data = stat.value - temp = SparseHistValueClass(id = stat.id, dump = dumpCount, - samples = data.samples, storage = data.storage) - session.add(temp) + # If there are no samples, then there is no point writing this to the + # database. Don't check flags here. + if stat.value.samples: + data = stat.value + temp = SparseHistValueClass(id = stat.id, dump = dumpCount, + samples = data.samples, storage = data.storage) + session.add(temp) else: panic("Unable to output stat %s. Unsupported stat type!", stat.name)