Sweeping change in the stats package....again...
authorNathan Binkert <binkertn@umich.edu>
Tue, 9 Dec 2003 18:05:43 +0000 (13:05 -0500)
committerNathan Binkert <binkertn@umich.edu>
Tue, 9 Dec 2003 18:05:43 +0000 (13:05 -0500)
base/statistics.cc:
    -  Merge the m5 display and simplescalar compatible display functions.
    -  Use functors for the stats printing instead of functions.  This
    gets rid of the very long argument lists and improves clarity.
    -  Fix a bug in binning that caused an invalid allocation to occur.
base/statistics.hh:
    -  Instead of using a compile time variable to choose whether
    to print in ss compat mode, we use a runtime variable.
    This is how we'll choose python output.
    -  There are no more virtual functions in the statistics themselves.
    All virtual functions have been moved into a secondary helper class.
    Every stat has an associated helper class that knows how to access
    certain variables in that stat.
    There is a hash_map from the stat to it's helper class data.  This was
    done because the helper data is only used during setup, stats reset,
    and printing.  All of which happen rarely, and you want to avoid
    any performance hit that you can.
    -  To provide the name(), desc(), etc functions to classes so that the
    user can set various parameters to the stats class, a single class
    containing all of those functions was created.  An odd trick was
    done to actually make this class derive from the stat class because
    a base class with no data actually does end up taking up space.
    -  The detail namespace was removed for now.  I'll put it back when the
    package is not in so much flux.
    -  Standard deviation, and mean were added to all distribution stats.
    -  There are several bugfixes and changes that aren't mentioned
test/Makefile:
    Don't test sim_stats foo.
test/stattest.cc:
    Don't test sim_stats foo.
    Fix bin usage so that it corresponds to the current usage.

--HG--
extra : convert_revision : ce8d9a8d485a84d55799f253d851e83650684170

base/statistics.cc
base/statistics.hh
test/Makefile
test/stattest.cc

index 737f8f73b44746f0d3704df33c6f03cdfe7a04d8..afe613455351b5db76bdc588906d1ffe81601306 100644 (file)
@@ -63,108 +63,45 @@ using namespace std;
 // This is a hack to get this parameter from the old stats package.
 namespace Statistics {
 bool PrintDescriptions = true;
+DisplayMode default_mode = mode_simplescalar;
 
-namespace Detail {
-/**
- * Struct to contain a name and description of statistic subfield.
- */
-struct SubData
-{
-    /** Subfield name. */
-    string name;
-    /** Subfield desc. */
-    string desc;
-};
-
-/**
- * Struct to contain print data of a Stat.
- */
-struct StatData
-{
-    /**
-     * Create this struct.
-     */
-    StatData();
-    /**
-     * Destructor.
-     */
-    ~StatData();
-
-    /** True if the stat has been initialized. */
-    bool init;
-    /** True if the stat should be printed. */
-    bool print;
-    /** The name of the stat. */
-    string name;
-    /** Names and descriptions of subfields. */
-    vector<SubData> *subdata;
-    /** The description of the stat. */
-    string desc;
-    /** The display precision. */
-    int precision;
-    /** The formatting flags. */
-    FormatFlags flags;
-    /** A pointer to a prerequisite Stat. */
-    const Stat *prereq;
-};
-
-StatData::StatData()
-    : init(false), print(false), subdata(NULL), precision(-1), flags(none),
-      prereq(NULL)
-{
-}
-
-StatData::~StatData()
-{
-    if (subdata)
-        delete subdata;
-}
-
-class Database
+namespace Database
 {
-  private:
-    Database(const Database &) {}
-
-  private:
-    typedef list<Stat *> list_t;
-    typedef map<const Stat *, StatData *> map_t;
-
-    list<MainBin *> bins;
-    map<const MainBin *, std::string > bin_names;
-    list_t binnedStats;
+    class Data
+    {
+      private:
+        typedef list<StatData *> list_t;
+        typedef map<void *, StatData *> map_t;
 
-    list_t allStats;
-    list_t printStats;
-    map_t statMap;
+        list<MainBin *> bins;
+        map<const MainBin *, string > bin_names;
+        list_t binnedStats;
 
-  public:
-    Database();
-    ~Database();
+        list_t allStats;
+        list_t printStats;
+        map_t statMap;
 
-    void dump(ostream &stream);
+      public:
+        void dump(ostream &stream);
 
-    StatData *find(const Stat *stat);
-    void check();
-    void reset();
-    void regStat(Stat *stat);
-    StatData *print(Stat *stat);
-    void regBin(MainBin *bin, std::string name);
-};
+        StatData *find(void *stat);
+        void mapStat(void *stat, StatData *data);
 
-Database::Database()
-{}
+        void check();
+        void reset();
+        void regBin(MainBin *bin, string name);
+        void regPrint(void *stat);
+    };
 
-Database::~Database()
-{}
 
 void
-Database::dump(ostream &stream)
+Data::dump(ostream &stream)
 {
 #ifndef FS_MEASURE
     list_t::iterator i = printStats.begin();
     list_t::iterator end = printStats.end();
     while (i != end) {
-        Stat *stat = *i;
+        StatData *stat = *i;
         if (stat->binned())
             binnedStats.push_back(stat);
         ++i;
@@ -178,7 +115,7 @@ Database::dump(ostream &stream)
         ccprintf(stream, "PRINTING BINNED STATS\n");
         while (j != bins_end) {
             (*j)->activate();
-            map<const MainBin  *, std::string>::const_iterator iter;
+            map<const MainBin  *, string>::const_iterator iter;
             iter = bin_names.find(*j);
             if (iter == bin_names.end())
                 panic("a binned stat not found in names map!");
@@ -192,7 +129,7 @@ Database::dump(ostream &stream)
             list_t::iterator end = binnedStats.end();
 #endif
             while (i != end) {
-                Stat *stat = *i;
+                StatData *stat = *i;
                 if (stat->dodisplay())
                     stat->display(stream);
                 ++i;
@@ -213,8 +150,8 @@ Database::dump(ostream &stream)
     list_t::iterator k = printStats.begin();
     list_t::iterator endprint = printStats.end();
     while (k != endprint) {
-        Stat *stat = *k;
-        if (stat->dodisplay() && !stat->binned())
+        StatData *stat = *k;
+        if (stat->dodisplay() /*&& !stat->binned()*/)
             stat->display(stream);
         ++k;
     }
@@ -222,7 +159,7 @@ Database::dump(ostream &stream)
 }
 
 StatData *
-Database::find(const Stat *stat)
+Data::find(void *stat)
 {
     map_t::const_iterator i = statMap.find(stat);
 
@@ -233,41 +170,26 @@ Database::find(const Stat *stat)
 }
 
 void
-Database::check()
+Data::check()
 {
     list_t::iterator i = allStats.begin();
     list_t::iterator end = allStats.end();
 
     while (i != end) {
-        Stat *stat = *i;
-        StatData *data = find(stat);
-        if (!data || !data->init) {
-#ifdef STAT_DEBUG
-            cprintf("this is stat number %d\n",(*i)->number);
-#endif
-            panic("Not all stats have been initialized");
-        }
-
-        if (data->print) {
-            if (data->name.empty())
-                panic("all printable stats must be named");
-
-            list_t::iterator j = printStats.insert(printStats.end(), *i);
-            inplace_merge(printStats.begin(), j,
-                          printStats.end(), Stat::less);
-        }
-
+        StatData *stat = *i;
+        assert(stat);
+        stat->check();
         ++i;
     }
 }
 
 void
-Database::reset()
+Data::reset()
 {
     list_t::iterator i = allStats.begin();
     list_t::iterator end = allStats.end();
     while (i != end) {
-        Stat *stat = *i;
+        StatData *stat = *i;
         stat->reset();
         ++i;
     }
@@ -282,7 +204,7 @@ Database::reset()
 
         i = allStats.begin();
         while (i != end) {
-            Stat *stat = *i;
+            StatData *stat = *i;
             stat->reset();
             ++i;
         }
@@ -294,21 +216,20 @@ Database::reset()
 }
 
 void
-Database::regStat(Stat *stat)
+Data::mapStat(void *stat, StatData *data)
 {
     if (statMap.find(stat) != statMap.end())
         panic("shouldn't register stat twice!");
 
-    allStats.push_back(stat);
+    allStats.push_back(data);
 
-    StatData *data = new StatData;
     bool success = (statMap.insert(make_pair(stat, data))).second;
     assert(statMap.find(stat) != statMap.end());
     assert(success && "this should never fail");
 }
 
 void
-Database::regBin(MainBin *bin, std::string name)
+Data::regBin(MainBin *bin, string name)
 {
     if (bin_names.find(bin) != bin_names.end())
         panic("shouldn't register bin twice");
@@ -322,235 +243,121 @@ Database::regBin(MainBin *bin, std::string name)
     cprintf("registering %s\n", name);
 }
 
-bool
-Stat::less(Stat *stat1, Stat *stat2)
-{
-    const string &name1 = stat1->myname();
-    const string &name2 = stat2->myname();
-
-    vector<string> v1;
-    vector<string> v2;
-
-    tokenize(v1, name1, '.');
-    tokenize(v2, name2, '.');
-
-    int last = min(v1.size(), v2.size()) - 1;
-    for (int i = 0; i < last; ++i)
-        if (v1[i] != v2[i])
-            return v1[i] < v2[i];
-
-    // Special compare for last element.
-    if (v1[last] == v2[last])
-        return v1.size() < v2.size();
-    else
-        return v1[last] < v2[last];
-
-    return false;
-}
-
-StatData *
-Database::print(Stat *stat)
+void
+Data::regPrint(void *stat)
 {
     StatData *data = find(stat);
-    assert(data);
 
-    data->print = true;
+    if (!data->print) {
+        data->print = true;
+
+        list_t::iterator j = printStats.insert(printStats.end(), data);
+        inplace_merge(printStats.begin(), j,
+                      printStats.end(), StatData::less);
+    }
 
-    return data;
 }
 
-Database &
+Data &
 StatDB()
 {
-    static Database db;
+    static Data db;
     return db;
 }
 
-Stat::Stat(bool reg)
-{
-#if 0
-    // This assert can help you find that pesky stat.
-    assert(this != (void *)0xbffff5c0);
-#endif
-
-    if (reg)
-        StatDB().regStat(this);
-
-#ifdef STAT_DEBUG
-    number = ++total_stats;
-    cprintf("I'm stat number %d\n",number);
-#endif
 }
 
-void
-Stat::setInit()
-{ mydata()->init = true; }
-
 StatData *
-Stat::mydata()
+DataAccess::find() const
 {
-    StatData *data = StatDB().find(this);
-    assert(data);
-
-    return data;
-}
-
-const StatData *
-Stat::mydata() const
-{
-    StatData *data = StatDB().find(this);
-    assert(data);
-
-    return data;
+    return Database::StatDB().find(const_cast<void *>((const void *)this));
 }
 
-const SubData *
-Stat::mysubdata(int index) const
+void
+DataAccess::map(StatData *data)
 {
-    assert(index >= 0);
-    if (index >= size())
-        return NULL;
-
-    const StatData *data = this->mydata();
-    if (!data->subdata || data->subdata->size() <= index)
-        return NULL;
-
-    return &(*data->subdata)[index];
+    Database::StatDB().mapStat(this, data);
 }
 
-SubData *
-Stat::mysubdata_create(int index)
+StatData *
+DataAccess::statData()
 {
-    int size = this->size();
-    assert(index >= 0 && (size == 0 || size > 0 && index < size));
-
-    StatData *data = this->mydata();
-    if (!data->subdata) {
-        if (!data->subdata) {
-            if (size == 0)
-                size = index + 1;
-
-            data->subdata = new vector<SubData>(size);
-        }
-    } else if (data->subdata->size() <= index)
-            data->subdata->resize(index + 1);
-
-    SubData *sd = &(*data->subdata)[index];
-    assert(sd);
-
-    return sd;
+    StatData *ptr = find();
+    assert(ptr);
+    return ptr;
 }
 
-string
-Stat::myname() const
-{ return mydata()->name; }
-
-string
-Stat::mysubname(int index) const
+const StatData *
+DataAccess::statData() const
 {
-    const SubData *sd = mysubdata(index);
-    return sd ? sd->name : "";
+    const StatData *ptr = find();
+    assert(ptr);
+    return ptr;
 }
 
-string
-Stat::mydesc() const
-{ return mydata()->desc; }
-
-string
-Stat::mysubdesc(int index) const
+void
+DataAccess::setInit()
 {
-    const SubData *sd = mysubdata(index);
-    return sd ? sd->desc : "";
+    statData()->init = true;
 }
 
-int
-Stat::myprecision() const
-{ return mydata()->precision; }
-
-FormatFlags
-Stat::myflags() const
-{ return mydata()->flags; }
-
-bool
-Stat::dodisplay() const
-{ return !mydata()->prereq || !mydata()->prereq->zero(); }
-
-StatData *
-Stat::print()
+void
+DataAccess::setPrint()
 {
-    StatData *data = StatDB().print(this);
-    assert(data && data->init);
-
-    return data;
+    Database::StatDB().regPrint(this);
 }
 
-Stat &
-Stat::name(const string &name)
+StatData::~StatData()
 {
-    print()->name = name;
-    return *this;
 }
 
-Stat &
-Stat::desc(const string &desc)
+bool
+StatData::less(StatData *stat1, StatData *stat2)
 {
-    print()->desc = desc;
-    return *this;
-}
+    const string &name1 = stat1->name;
+    const string &name2 = stat2->name;
 
-Stat &
-Stat::precision(int precision)
-{
-    print()->precision = precision;
-    return *this;
-}
+    vector<string> v1;
+    vector<string> v2;
 
-Stat &
-Stat::flags(FormatFlags flags)
-{
-    if (flags & __reserved)
-        panic("Cannot set reserved flags!\n");
+    tokenize(v1, name1, '.');
+    tokenize(v2, name2, '.');
 
-    print()->flags |= flags;
-    return *this;
-}
+    int last = min(v1.size(), v2.size()) - 1;
+    for (int i = 0; i < last; ++i)
+        if (v1[i] != v2[i])
+            return v1[i] < v2[i];
 
-Stat &
-Stat::prereq(const Stat &prereq)
-{
-    print()->prereq = &prereq;
-    return *this;
-}
+    // Special compare for last element.
+    if (v1[last] == v2[last])
+        return v1.size() < v2.size();
+    else
+        return v1[last] < v2[last];
 
-Stat &
-Stat::subname(int index, const string &name)
-{
-    print();
-    mysubdata_create(index)->name = name;
-    return *this;
-}
-Stat &
-Stat::subdesc(int index, const string &desc)
-{
-    print();
-    mysubdata_create(index)->desc = desc;
-    return *this;
+    return false;
 }
 
 bool
-ScalarStat::zero() const
+StatData::check() const
 {
-    return val() == 0.0;
-}
+    if (!init) {
+#ifdef STAT_DEBUG
+        cprintf("this is stat number %d\n",(*i)->number);
+#endif
+        panic("Not all stats have been initialized");
+        return false;
+    }
 
-bool
-VectorStat::zero() const
-{
-    return val()[0] == 0.0;
+    if (print && name.empty()) {
+        panic("all printable stats must be named");
+        return false;
+    }
+
+    return true;
 }
 
 string
-ValueToString(result_t value, int precision)
+ValueToString(result_t value, DisplayMode mode, int precision)
 {
     stringstream val;
 
@@ -564,20 +371,33 @@ ValueToString(result_t value, int precision)
         val.setf(ios::fixed);
         val << value;
     } else {
-#ifndef STAT_DISPLAY_COMPAT
-        val << "no value";
-#else
-        val << "<err: div-0>";
-#endif
+        val << (mode == mode_m5 ? "no value" : "<err: div-0>");
     }
 
     return val.str();
 }
 
+struct ScalarPrint
+{
+    result_t value;
+    string name;
+    string desc;
+    int precision;
+    DisplayMode mode;
+    FormatFlags flags;
+    result_t pdf;
+    result_t cdf;
+
+    ScalarPrint()
+        : value(0.0), precision(0), mode(default_mode), flags(0),
+          pdf(NAN), cdf(NAN)
+    {}
+
+    void operator()(ostream &stream) const;
+};
+
 void
-PrintOne(ostream &stream, result_t value,
-         const string &name, const string &desc, int precision,
-         FormatFlags flags, result_t pdf = NAN, result_t cdf = NAN)
+ScalarPrint::operator()(ostream &stream) const
 {
     if (flags & nozero && value == 0.0 ||
         flags & nonan && isnan(value))
@@ -591,16 +411,13 @@ PrintOne(ostream &stream, result_t value,
     if (!isnan(cdf))
         ccprintf(cdfstr, "%.2f%%", cdf * 100.0);
 
-#ifdef STAT_DISPLAY_COMPAT
-    if (flags & __substat) {
+    if (mode == mode_simplescalar && flags & __substat) {
         ccprintf(stream, "%32s %12s %10s %10s", name,
-                 ValueToString(value, precision),
+                 ValueToString(value, mode, precision),
                  pdfstr, cdfstr);
-    } else
-#endif
-    {
+    } else {
         ccprintf(stream, "%-40s %12s %10s %10s", name,
-                 ValueToString(value, precision), pdfstr, cdfstr);
+                 ValueToString(value, mode, precision), pdfstr, cdfstr);
     }
 
     if (PrintDescriptions) {
@@ -610,312 +427,563 @@ PrintOne(ostream &stream, result_t value,
     stream << endl;
 }
 
-void
-ScalarStat::display(ostream &stream) const
+struct VectorPrint
 {
-    PrintOne(stream, val(), myname(), mydesc(), myprecision(), myflags());
-}
-
-void
-VectorStat::display(ostream &stream) const
-{
-    bool have_subname = false;
-    bool have_subdesc = false;
-    int size = this->size();
-    for (int i = 0; i < size; ++i) {
-        if (!mysubname(i).empty())
-            have_subname = true;
-        if (!mysubdesc(i).empty())
-            have_subdesc = true;
-    }
-
-    vector<string> *subnames = 0;
-    vector<string> *subdescs = 0;
-    if (have_subname) {
-        subnames = new vector<string>(size);
-        for (int i = 0; i < size; ++i)
-            (*subnames)[i] = mysubname(i);
-    }
-    if (have_subdesc) {
-        subdescs = new vector<string>(size);
-        for (int i = 0; i < size; ++i)
-            (*subdescs)[i] = mysubdesc(i);
-    }
+    string name;
+    string desc;
+    vector<string> subnames;
+    vector<string> subdescs;
+    int precision;
+    DisplayMode mode;
+    FormatFlags flags;
+    rvec_t vec;
+    result_t total;
 
-    VectorDisplay(stream, myname(), subnames, mydesc(), subdescs,
-                  myprecision(), myflags(), val(), total());
-}
+    VectorPrint()
+        : subnames(0), subdescs(0), precision(-1), mode(default_mode),
+          flags(0), total(NAN)
+    {}
 
-#ifndef STAT_DISPLAY_COMPAT
-#define NAMESEP "::"
-#else
-#define NAMESEP "_"
-#endif
+    void operator()(ostream &stream) const;
+};
 
-#ifndef STAT_DISPLAY_COMPAT
 void
-VectorDisplay(std::ostream &stream,
-              const std::string &myname,
-              const std::vector<std::string> *mysubnames,
-              const std::string &mydesc,
-              const std::vector<std::string> *mysubdescs,
-              int myprecision, FormatFlags myflags,
-              const rvec_t &vec, result_t mytotal)
+VectorPrint::operator()(std::ostream &stream) const
 {
     int _size = vec.size();
     result_t _total = 0.0;
-    result_t _pdf, _cdf = 0.0;
 
-    if (myflags & (pdf | cdf)) {
+    if (flags & (pdf | cdf)) {
         for (int i = 0; i < _size; ++i) {
             _total += vec[i];
         }
     }
 
+    string base = name + ((mode == mode_simplescalar) ? "_" : "::");
+
+    ScalarPrint print;
+    print.name = name;
+    print.desc = desc;
+    print.precision = precision;
+    print.flags = flags;
+
+    bool havesub = !subnames.empty();
+
     if (_size == 1) {
-        PrintOne(stream, vec[0], myname, mydesc, myprecision, myflags);
-    } else {
+        print.value = vec[0];
+        print(stream);
+    } else if (mode == mode_m5) {
         for (int i = 0; i < _size; ++i) {
-            string subname;
-            if (mysubnames) {
-                subname = (*mysubnames)[i];
-                if (subname.empty())
-                    continue;
-            } else {
-                subname = to_string(i);
-            }
+            if (havesub && (i >= subnames.size() || subnames[i].empty()))
+                continue;
 
-            string name = myname + NAMESEP + subname;
-            if (!(myflags & pdf))
-                PrintOne(stream, vec[i], name, mydesc, myprecision, myflags);
-            else {
-                _pdf = vec[i] / _total;
-                _cdf += _pdf;
-                PrintOne(stream, vec[i], name, mydesc, myprecision, myflags,
-                         _pdf, _cdf);
-            }
-        }
+            print.name = base + (havesub ? subnames[i] : to_string(i));
+            print.desc = subdescs.empty() ? desc : subdescs[i];
+            print.value = vec[i];
 
-        if (myflags & total)
-            PrintOne(stream, mytotal, myname + NAMESEP + "total",
-                     mydesc, myprecision, myflags);
-    }
-}
-#else
-void
-VectorDisplay(std::ostream &stream,
-              const std::string &myname,
-              const std::vector<std::string> *mysubnames,
-              const std::string &mydesc,
-              const std::vector<std::string> *mysubdescs,
-              int myprecision, FormatFlags myflags,
-              const rvec_t &vec, result_t mytotal)
-{
-    int _size = vec.size();
-    result_t _total = 0.0;
-    result_t _pdf, _cdf = 0.0;
+            if (_total && (flags & pdf)) {
+                print.pdf = vec[i] / _total;
+                print.cdf += print.pdf;
+            }
 
-    if (myflags & (pdf | cdf)) {
-        for (int i = 0; i < _size; ++i) {
-            _total += vec[i];
+            print(stream);
         }
-    }
 
-    if (_size == 1) {
-        PrintOne(stream, vec[0], myname, mydesc, myprecision, myflags);
+        if (flags & ::Statistics::total) {
+            print.name = base + "total";
+            print.desc = desc;
+            print.value = total;
+            print(stream);
+        }
     } else {
-        if (myflags & total)
-            PrintOne(stream, mytotal, myname, mydesc, myprecision, myflags);
+        if (flags & ::Statistics::total) {
+            print.value = total;
+            print(stream);
+        }
 
-        if (myflags & dist) {
-            ccprintf(stream, "%s.start_dist\n", myname);
+        result_t _pdf = 0.0;
+        result_t _cdf = 0.0;
+        if (flags & dist) {
+            ccprintf(stream, "%s.start_dist\n", name);
             for (int i = 0; i < _size; ++i) {
-                string subname, subdesc;
-                subname = to_string(i);
-                if (mysubnames) {
-                    if (!subname.empty()) {
-                        subname = (*mysubnames)[i];
-                    }
-                }
-                if (mysubdescs) {
-                    subdesc = (*mysubdescs)[i];
-                }
-                if (!(myflags & (pdf | cdf))) {
-                    PrintOne(stream, vec[i], subname, subdesc, myprecision,
-                             myflags | __substat);
-                } else {
-                    if (_total) {
-                        _pdf = vec[i] / _total;
-                        _cdf += _pdf;
-                    } else {
-                        _pdf = _cdf = 0.0;
-                    }
-                    if (!(myflags & cdf)) {
-                        PrintOne(stream, vec[i], subname, subdesc, myprecision,
-                                 myflags | __substat, _pdf);
-                    } else {
-                        PrintOne(stream, vec[i], subname, subdesc, myprecision,
-                                 myflags | __substat, _pdf, _cdf);
-                    }
+                print.name = havesub ? subnames[i] : to_string(i);
+                print.desc = subdescs.empty() ? desc : subdescs[i];
+                print.flags |= __substat;
+                print.value = vec[i];
+
+                if (_total) {
+                    _pdf = vec[i] / _total;
+                    _cdf += _pdf;
                 }
+
+                if (flags & pdf)
+                    print.pdf = _pdf;
+                if (flags & cdf)
+                    print.cdf = _cdf;
+
+                print(stream);
             }
-            ccprintf(stream, "%s.end_dist\n", myname);
+            ccprintf(stream, "%s.end_dist\n", name);
         } else {
             for (int i = 0; i < _size; ++i) {
-                string subname;
-                if (mysubnames) {
-                    subname = (*mysubnames)[i];
-                    if (subname.empty())
-                        continue;
+                if (havesub && subnames[i].empty())
+                    continue;
+
+                print.name = base;
+                print.name += havesub ? subnames[i] : to_string(i);
+                print.desc = subdescs.empty() ? desc : subdescs[i];
+                print.value = vec[i];
+
+                if (_total) {
+                    _pdf = vec[i] / _total;
+                    _cdf += _pdf;
                 } else {
-                    subname = to_string(i);
+                    _pdf = _cdf = NAN;
                 }
 
-                string name = myname + NAMESEP + subname;
-                if (!(myflags & pdf)) {
-                    PrintOne(stream, vec[i], name, mydesc, myprecision,
-                             myflags);
-                } else {
-                    if (_total) {
-                        _pdf = vec[i] / _total;
-                        _cdf += _pdf;
-                    } else {
-                        _pdf = _cdf = NAN;
-                    }
-                    PrintOne(stream, vec[i], name, mydesc, myprecision,
-                             myflags, _pdf, _cdf);
+                if (flags & pdf) {
+                    print.pdf = _pdf;
+                    print.cdf = _cdf;
                 }
+
+                print(stream);
             }
         }
     }
 }
-#endif
 
-#ifndef STAT_DISPLAY_COMPAT
+struct DistPrint
+{
+    string name;
+    string desc;
+    int precision;
+    DisplayMode mode;
+    FormatFlags flags;
+
+    result_t min_val;
+    result_t max_val;
+    result_t underflow;
+    result_t overflow;
+    rvec_t vec;
+    result_t sum;
+    result_t squares;
+    result_t samples;
+
+    int min;
+    int max;
+    int bucket_size;
+    int size;
+    bool fancy;
+
+    void operator()(ostream &stream) const;
+};
+
 void
-DistDisplay(ostream &stream, const string &name, const string &desc,
-            int precision, FormatFlags flags,
-            result_t min_val, result_t max_val,
-            result_t underflow, result_t overflow,
-            const rvec_t &vec, int min, int max, int bucket_size, int size);
+DistPrint::operator()(ostream &stream) const
 {
+    if (fancy) {
+        ScalarPrint print;
+        string base = name + ((mode == mode_m5) ? "::" : "_");
+
+        print.precision = precision;
+        print.flags = flags;
+        print.desc = desc;
+
+        print.name = base + "mean";
+        print.value = samples ? sum / samples : NAN;
+        print(stream);
+
+        print.name = base + "stdev";
+        print.value = samples ? sqrt((samples * squares - sum * sum) /
+                                     (samples * (samples - 1.0))) : NAN;
+        print(stream);
+
+        print.name = "**Ignore: " + base + "TOT";
+        print.value = samples;
+        print(stream);
+        return;
+    }
+
     assert(size == vec.size());
 
     result_t total = 0.0;
-    result_t pdf, cdf = 0.0;
 
     total += underflow;
     for (int i = 0; i < size; ++i)
         total += vec[i];
     total += overflow;
 
-    pdf = underflow / total;
-    cdf += pdf;
+    string base = name + (mode == mode_m5 ? "::" : ".");
 
-    PrintOne(stream, underflow, name + NAMESEP + "underflow", desc,
-             precision, myflags, pdf, cdf);
+    ScalarPrint print;
+    print.desc = (mode == mode_m5) ? desc : "";
+    print.precision = precision;
+    print.mode = mode;
+    print.flags = flags;
 
-    for (int i = 0; i < size; ++i) {
-        stringstream namestr;
-        namestr << name;
-
-        int low = i * bucket_size + min;
-        int high = ::std::min((i + 1) * bucket_size + min - 1, max);
-        namestr << low;
-        if (low < high)
-            namestr << "-" << high;
-
-        pdf = vec[i] / total;
-        cdf += pdf;
-        PrintOne(stream, vec[i], namestr.str(), desc, precision, myflags,
-                 pdf, cdf);
+    if (mode == mode_simplescalar) {
+        ccprintf(stream, "%-42s", base + "start_dist");
+        if (PrintDescriptions && !desc.empty())
+            ccprintf(stream, "                     # %s", desc);
+        stream << endl;
+    }
+
+    print.name = base + "samples";
+    print.value = samples;
+    print(stream);
+
+    print.name = base + "min_value";
+    print.value = min_val;
+    print(stream);
+
+    if (mode == mode_m5 || underflow > 0.0) {
+        print.name = base + "underflows";
+        print.value = underflow;
+        if (mode == mode_m5 && total) {
+            print.pdf = underflow / total;
+            print.cdf += print.pdf;
+        }
+        print(stream);
+    }
+
+
+    if (mode == mode_m5) {
+        for (int i = 0; i < size; ++i) {
+            stringstream namestr;
+            namestr << name;
+
+            int low = i * bucket_size + min;
+            int high = ::min((i + 1) * bucket_size + min - 1, max);
+            namestr << low;
+            if (low < high)
+                namestr << "-" << high;
+
+            print.name = namestr.str();
+            print.value = vec[i];
+            if (total) {
+                print.pdf = vec[i] / total;
+                print.cdf += print.pdf;
+            }
+            print(stream);
+        }
+
+    } else {
+        int _min;
+        result_t _pdf;
+        result_t _cdf = 0.0;
+
+        print.flags = flags | __substat;
+
+        for (int i = 0; i < size; ++i) {
+            if (flags & nozero && vec[i] == 0.0 ||
+                flags & nonan && isnan(vec[i]))
+                continue;
+
+            _min = i * bucket_size + min;
+            _pdf = vec[i] / total * 100.0;
+            _cdf += _pdf;
+
+
+            print.name = ValueToString(_min, mode, 0);
+            print.value = vec[i];
+            print.pdf = (flags & pdf) ? _pdf : NAN;
+            print.cdf = (flags & cdf) ? _cdf : NAN;
+            print(stream);
+        }
+
+        print.flags = flags;
+        if (flags & (pdf || cdf)) {
+            print.pdf = NAN;
+            print.cdf = NAN;
+        }
+    }
+
+    if (mode == mode_m5 || overflow > 0.0) {
+        print.name = base + "overflows";
+        print.value = overflow;
+        if (mode == mode_m5 && total) {
+            print.pdf = overflow / total;
+            print.cdf += print.pdf;
+        }
+        print(stream);
+    }
+
+    print.pdf = NAN;
+    print.cdf = NAN;
+
+    if (mode != mode_simplescalar) {
+        print.name = base + "total";
+        print.value = total;
+        print(stream);
+    }
+
+    print.name = base + "max_value";
+    print.value = max_val;
+    print(stream);
+
+    if (mode != mode_simplescalar && samples != 0) {
+        print.name = base + "mean";
+        print.value = sum / samples;
+        print(stream);
+
+        print.name = base + "stdev";
+        print.value = sqrt((samples * squares - sum * sum) /
+                           (samples * (samples - 1.0)));
+        print(stream);
     }
 
-    pdf = overflow / total;
-    cdf += pdf;
-    PrintOne(stream, overflow, name + NAMESEP + "overflow", desc,
-             precision, myflags, pdf, cdf);
-    PrintOne(stream, total, name + NAMESEP + "total", desc,
-             precision, myflags);
+    if (mode == mode_simplescalar)
+        ccprintf(stream, "%send_dist\n\n", base);
 }
-#else
+
 void
-DistDisplay(ostream &stream, const string &name, const string &desc,
-            int precision, FormatFlags flags,
-            result_t min_val, result_t max_val,
-            result_t underflow, result_t overflow,
-            const rvec_t &vec, int min, int max, int bucket_size, int size)
+ScalarDataBase::display(ostream &stream) const
 {
-    assert(size == vec.size());
-    string blank;
+    ScalarPrint print;
+    print.value = val();
+    print.name = name;
+    print.desc = desc;
+    print.precision = precision;
+    print.flags = flags;
+
+    print(stream);
+}
 
-    result_t total = 0.0;
+void
+VectorDataBase::display(ostream &stream) const
+{
+    int size = this->size();
+    const_cast<VectorDataBase *>(this)->update();
 
-    total += underflow;
-    for (int i = 0; i < size; ++i)
-        total += vec[i];
-    total += overflow;
+    VectorPrint print;
 
-    ccprintf(stream, "%-42s", name + ".start_dist");
-    if (PrintDescriptions && !desc.empty())
-        ccprintf(stream, "                     # %s", desc);
-    stream << endl;
+    print.name = name;
+    print.desc = desc;
+    print.mode = mode;
+    print.flags = flags;
+    print.precision = precision;
+    print.vec = val();
+    print.total = total();
 
-    PrintOne(stream, total, name + ".samples", blank, precision, flags);
-    PrintOne(stream, min_val, name + ".min_value", blank, precision, flags);
+    for (int i = 0; i < size; ++i) {
+        if (!subnames[i].empty()) {
+            print.subnames = subnames;
+            print.subnames.resize(size);
+            for (int i = 0; i < size; ++i) {
+                if (!subnames[i].empty() && !subdescs[i].empty()) {
+                    print.subdescs = subdescs;
+                    print.subdescs.resize(size);
+                    break;
+                }
+            }
+            break;
+        }
+    }
 
-    if (underflow > 0)
-        PrintOne(stream, min_val, name + ".underflows", blank, precision,
-                 flags);
 
-    int _min;
-    result_t _pdf, _cdf, mypdf, mycdf;
+    print(stream);
+}
 
-    _cdf = 0.0;
-    for (int i = 0; i < size; ++i) {
-        if (flags & nozero && vec[i] == 0.0 ||
-            flags & nonan && isnan(vec[i]))
+void
+Vector2dDataBase::display(ostream &stream) const
+{
+    const_cast<Vector2dDataBase *>(this)->update();
+
+    bool havesub = false;
+    VectorPrint print;
+
+    print.subnames = y_subnames;
+    print.mode = mode;
+    print.flags = flags;
+    print.precision = precision;
+
+    if (!subnames.empty()) {
+        for (int i = 0; i < x; ++i)
+            if (!subnames[i].empty())
+                havesub = true;
+    }
+
+    rvec_t tot_vec(y);
+    result_t super_total = 0.0;
+    for (int i = 0; i < x; ++i) {
+        if (havesub && (i >= subnames.size() || subnames[i].empty()))
             continue;
 
-        _min = i * bucket_size + min;
-        _pdf = vec[i] / total * 100.0;
-        _cdf += _pdf;
+        int iy = i * y;
+        rvec_t yvec(y);
 
-        mypdf = (flags & pdf) ? _pdf : NAN;
-        mycdf = (flags & cdf) ? _cdf : NAN;
+        result_t total = 0.0;
+        for (int j = 0; j < y; ++j) {
+            yvec[j] = vec[iy + j];
+            tot_vec[j] += yvec[j];
+            total += yvec[j];
+            super_total += yvec[j];
+        }
 
-        PrintOne(stream, vec[i], ValueToString(_min, 0), blank, precision,
-                 flags | __substat, mypdf, mycdf);
+        print.name = name + "_" + (havesub ? subnames[i] : to_string(i));
+        print.desc = desc;
+        print.vec = yvec;
+        print.total = total;
+        print(stream);
     }
 
-    if (overflow > 0)
-        PrintOne(stream, overflow, name + ".overflows", blank, precision,
-                 flags);
-    PrintOne(stream, max_val, name + ".max_value", blank, precision, flags);
-    ccprintf(stream, "%s.end_dist\n\n", name);
+    if ((flags & ::Statistics::total) && (x > 1)) {
+        print.name = name;
+        print.desc = desc;
+        print.vec = tot_vec;
+        print.total = super_total;
+        print(stream);
+    }
+}
+
+void
+DistDataBase::display(ostream &stream) const
+{
+    const_cast<DistDataBase *>(this)->update();
+
+    DistPrint print;
+
+    print.name = name;
+    print.desc = desc;
+    print.precision = precision;
+    print.mode = mode;
+    print.flags = flags;
+
+    print.min_val = data.min_val;
+    print.max_val = data.max_val;
+    print.underflow = data.underflow;
+    print.overflow = data.overflow;
+    print.vec = data.vec;
+    print.sum = data.sum;
+    print.squares = data.squares;
+    print.samples = data.samples;
+
+    print.min = data.min;
+    print.max = data.max;
+    print.bucket_size = data.bucket_size;
+    print.size = data.size;
+    print.fancy = data.fancy;
+
+    print(stream);
+}
+
+void
+VectorDistDataBase::display(ostream &stream) const
+{
+    const_cast<VectorDistDataBase *>(this)->update();
+
+    for (int i = 0; i < size(); ++i) {
+        DistPrint print;
+
+        print.name = name +
+            (subnames[i].empty() ? ("_" + to_string(i)) : subnames[i]);
+        print.desc = subdescs[i].empty() ? desc : subdescs[i];
+        print.precision = precision;
+        print.mode = mode;
+        print.flags = flags;
+
+        print.min_val = data[i].min_val;
+        print.max_val = data[i].max_val;
+        print.underflow = data[i].underflow;
+        print.overflow = data[i].overflow;
+        print.vec = data[i].vec;
+        print.sum = data[i].sum;
+        print.squares = data[i].squares;
+        print.samples = data[i].samples;
+
+        print.min = data[i].min;
+        print.max = data[i].max;
+        print.bucket_size = data[i].bucket_size;
+        print.size = data[i].size;
+        print.fancy = data[i].fancy;
+
+        print(stream);
+    }
+}
+
+void
+FormulaBase::val(rvec_t &vec) const
+{
+    vec = root->val();
+}
+
+result_t
+FormulaBase::total() const
+{
+    return root->total();
+}
+
+size_t
+FormulaBase::size() const
+{
+    if (!root)
+        return 0;
+    else
+        return root->size();
+}
+
+bool
+FormulaBase::binned() const
+{
+    return root->binned();
+}
+
+void
+FormulaBase::reset()
+{
+}
+
+bool
+FormulaBase::zero() const
+{
+    rvec_t vec;
+    val(vec);
+    for (int i = 0; i < vec.size(); ++i)
+        if (vec[i] != 0.0)
+            return false;
+    return true;
 }
-#endif
 
-/**
- * @todo  get rid of the ugly hack **Ignore for total
- */
 void
-FancyDisplay(ostream &stream, const string &name, const string &desc,
-             int precision, FormatFlags flags, result_t mean,
-             result_t variance, result_t total)
+FormulaBase::update(StatData *)
+{
+}
+
+Formula::Formula()
 {
-    result_t stdev = isnan(variance) ? NAN : sqrt(variance);
-    PrintOne(stream, mean, name + NAMESEP + "mean", desc, precision, flags);
-    PrintOne(stream, stdev, name + NAMESEP + "stdev", desc, precision, flags);
-    PrintOne(stream, total, "**Ignore: " + name + NAMESEP + "TOT", desc, precision, flags);
+    setInit();
 }
 
-} // namespace Detail
+Formula::Formula(Temp r)
+{
+    root = r;
+    assert(size());
+}
 
-MainBin::MainBin(const std::string &name)
+const Formula &
+Formula::operator=(Temp r)
+{
+    assert(!root && "Can't change formulas");
+    root = r;
+    assert(size());
+    return *this;
+}
+
+const Formula &
+Formula::operator+=(Temp r)
+{
+    if (root)
+        root = NodePtr(new BinaryNode<std::plus<result_t> >(root, r));
+    else
+        root = r;
+    assert(size());
+    return *this;
+}
+
+MainBin::MainBin(const string &name)
     : _name(name), mem(NULL), memsize(-1)
 {
-    Detail::StatDB().regBin(this, name);
+    Database::StatDB().regBin(this, name);
 }
 
 MainBin::~MainBin()
@@ -927,14 +995,14 @@ MainBin::~MainBin()
 char *
 MainBin::memory(off_t off)
 {
+    if (memsize == -1)
+        memsize = CeilPow2((size_t) offset());
+
     if (!mem) {
         mem = new char[memsize];
         memset(mem, 0, memsize);
     }
 
-    if (memsize == -1)
-        memsize = CeilPow2((size_t) offset());
-
     assert(offset() <= size());
     return mem + off;
 }
@@ -942,13 +1010,13 @@ MainBin::memory(off_t off)
 void
 check()
 {
-    Detail::StatDB().check();
+    Database::StatDB().check();
 }
 
 void
 dump(ostream &stream)
 {
-    Detail::StatDB().dump(stream);
+    Database::StatDB().dump(stream);
 }
 
 CallbackQueue resetQueue;
@@ -962,7 +1030,7 @@ RegResetCallback(Callback *cb)
 void
 reset()
 {
-    Detail::StatDB().reset();
+    Database::StatDB().reset();
     resetQueue.process();
 }
 
index ded1470f42195db2d8fc3138fec8023927d62734..7d2cdf869d4e88138f348ed414756b3356a8f4a2 100644 (file)
@@ -77,9 +77,6 @@ float __nan();
 #define __M5_NAN
 #endif
 
-/** Print stats out in SS format. */
-#define STAT_DISPLAY_COMPAT
-
 class Callback;
 
 /** The current simulated cycle. */
@@ -103,177 +100,415 @@ const FormatFlags none =        0x0000;
 const FormatFlags total =      0x0001;
 /** Print the percent of the total that this entry represents. */
 const FormatFlags pdf =                0x0002;
+/** Print the cumulative percentage of total upto this entry. */
+const FormatFlags cdf =                0x0004;
 /** Don't print if this is zero. */
-const FormatFlags nozero =     0x0004;
+const FormatFlags nozero =     0x0010;
 /** Don't print if this is NAN */
-const FormatFlags nonan =      0x0008;
-/** Print the cumulative percentage of total upto this entry. */
-const FormatFlags cdf =                0x0010;
+const FormatFlags nonan =      0x0020;
 /** Print the distribution. */
-const FormatFlags dist =       0x0020;
+const FormatFlags dist =       0x0100;
 /** Used for SS compatability. */
 const FormatFlags __substat =  0x8000;
 /** Mask of flags that can't be set directly */
 const FormatFlags __reserved =  __substat;
 
+enum DisplayMode
+{
+    mode_m5,
+    mode_simplescalar,
+    mode_python
+};
+
+extern DisplayMode default_mode;
+
 /* Contains the statistic implementation details */
-namespace Detail {
 //////////////////////////////////////////////////////////////////////
 //
 // Statistics Framework Base classes
 //
 //////////////////////////////////////////////////////////////////////
-struct StatData;
-struct SubData;
-
-/**
- * Common base class for all statistics, used to maintain a list and print.
- * This class holds no data itself but is used to find the associated
- * StatData in the stat database @sa Statistics::Database.
- */
-class Stat
+struct StatData
 {
-  protected:
-    /** Mark this statistics as initialized. */
-    void setInit();
-    /**
-     * Finds and returns the associated StatData from the database.
-     * @return The formatting and output data of this statistic.
-     */
-    StatData *mydata();
-    /**
-     * Finds and returns a const pointer to the associated StatData.
-     * @return The formatting and output data of this statistic.
-     */
-    const StatData *mydata() const;
-    /**
-     * Mark this stat for output at the end of simulation.
-     * @return The formatting and output data of this statistic.
-     */
-    StatData *print();
-    /**
-     * Finds and returns the SubData at the given index.
-     * @param index The index of the SubData to find.
-     * @return The name and description of the given index.
-     */
-    const SubData *mysubdata(int index) const;
-    /**
-     * Create and return a new SubData field for the given index.
-     * @param index The index to create a SubData for.
-     * @return A pointer to the created SubData.
-     */
-    SubData *mysubdata_create(int index);
+    /** True if the stat has been initialized. */
+    bool init;
+    /** True if the stat should be printed. */
+    bool print;
+    /** The name of the stat. */
+    std::string name;
+    /** The description of the stat. */
+    std::string desc;
+    /** The display precision. */
+    int precision;
+    /** Display Mode */
+    DisplayMode mode;
+    /** The formatting flags. */
+    FormatFlags flags;
 
-  public:
-    /**
-     * Return the name of this stat.
-     * @return the name of the stat.
-     */
-    virtual std::string myname() const;
-    /**
-     * Return the name of the sub field at the given index.
-     * @param index the subfield index.
-     * @return the name of the subfield.
-     */
-    virtual std::string mysubname(int index) const;
-    /**
-     * Return the description of this stat.
-     * @return the description of this stat.
-     */
-    virtual std::string mydesc() const;
-    /**
-     * Return the description of the subfield at the given index.
-     * @param index The subfield index.
-     * @return the description of the subfield.
-     */
-    virtual std::string mysubdesc(int index) const;
-    /**
-     * Return the format flags of this stat.
-     * @return the format flags.
-     */
-    virtual FormatFlags myflags() const;
-    /**
-     * Return true if this stat's prereqs have been satisfied (they are non
-     * zero).
-     * @return true if the prerequisite stats aren't zero.
-     */
-    virtual bool dodisplay() const;
-    /**
-     * Return the display percision.
-     * @return The display precision.
-     */
-    virtual int myprecision() const;
 
-  public:
-    /**
-     * Create this stat and perhaps register it with the stat database. To be
-     * printed a stat must be registered with the database.
-     * @param reg If true, register this stat in the database.
-     */
-    Stat(bool reg);
+    /** A pointer to a prerequisite Stat. */
+    const StatData *prereq;
+
+    StatData()
+        : init(false), print(false), precision(-1), mode(default_mode),
+          flags(0), prereq(0)
+    {}
+
+    virtual ~StatData();
+
     /**
-     * Destructor
+     * @return true if the stat is binned.
      */
-    virtual ~Stat() {}
+    virtual bool binned() const = 0;
 
     /**
      * Print this stat to the given ostream.
      * @param stream The stream to print to.
      */
     virtual void display(std::ostream &stream) const = 0;
+    bool dodisplay() const { return !prereq || !prereq->zero(); }
+
     /**
-     * Reset this stat to the default state.
+     * Reset the corresponding stat to the default state.
      */
     virtual void reset() = 0;
+
     /**
-     * Return the number of entries in this stat.
-     * @return The number of entries.
+     * @return true if this stat has a value and satisfies its
+     * requirement as a prereq
      */
-    virtual size_t size() const = 0;
+    virtual bool zero() const = 0;
+
     /**
-     * Return true if the stat has value zero.
-     * @return True if the stat is zero.
+     * Check that this stat has been set up properly and is ready for
+     * use
+     * @return true for success
      */
-    virtual bool zero() const = 0;
+    virtual bool check() const;
 
     /**
-     * Return true if stat is binned.
-     *@return True is stat is binned.
+     * Checks if the first stat's name is alphabetically less than the second.
+     * This function breaks names up at periods and considers each subname
+     * separately.
+     * @param stat1 The first stat.
+     * @param stat2 The second stat.
+     * @return stat1's name is alphabetically before stat2's
      */
-    virtual bool binned() const = 0;
+    static bool less(StatData *stat1, StatData *stat2);
+};
+
+struct ScalarDataBase : public StatData
+{
+    virtual result_t val() const = 0;
+    virtual result_t total() const = 0;
+
+    virtual void display(std::ostream &stream) const;
+};
+
+template <class T>
+class ScalarData : public ScalarDataBase
+{
+  protected:
+    T &s;
+
+  public:
+    ScalarData(T &stat) : s(stat) {}
+
+    virtual bool binned() const { return s.binned(); }
+    virtual result_t val() const { return s.val(); }
+    virtual result_t total() const { return s.total(); }
+    virtual void reset() { s.reset(); }
+    virtual bool zero() const { return s.zero(); }
+};
+
+struct VectorDataBase : public StatData
+{
+    /** Names and descriptions of subfields. */
+    mutable std::vector<std::string> subnames;
+    mutable std::vector<std::string> subdescs;
+
+    virtual void display(std::ostream &stream) const;
+
+    virtual size_t size() const  = 0;
+    virtual const rvec_t &val() const  = 0;
+    virtual result_t total() const  = 0;
+    virtual void update()
+    {
+        int s = size();
+        if (subnames.size() < s)
+            subnames.resize(s);
+
+        if (subdescs.size() < s)
+            subdescs.resize(s);
+    }
+};
+
+template <class T>
+class VectorData : public VectorDataBase
+{
+  protected:
+    T &s;
+    mutable rvec_t vec;
+
+  public:
+    VectorData(T &stat) : s(stat) {}
+
+    virtual bool binned() const { return s.binned(); }
+    virtual bool zero() const { return s.zero(); }
+    virtual void reset() { s.reset(); }
+
+    virtual size_t size() const { return s.size(); }
+    virtual const rvec_t &val() const
+    {
+        s.val(vec);
+        return vec;
+    }
+    virtual result_t total() const { return s.total(); }
+    virtual void update()
+    {
+        VectorDataBase::update();
+        s.update(this);
+    }
+};
+
+
+struct DistDataData
+{
+    result_t min_val;
+    result_t max_val;
+    result_t underflow;
+    result_t overflow;
+    rvec_t vec;
+    result_t sum;
+    result_t squares;
+    result_t samples;
+
+    int min;
+    int max;
+    int bucket_size;
+    int size;
+    bool fancy;
+};
+
+struct DistDataBase : public StatData
+{
+    /** Local storage for the entry values, used for printing. */
+    DistDataData data;
+
+    virtual void display(std::ostream &stream) const;
+    virtual void update() = 0;
+};
+
+template <class T>
+class DistData : public DistDataBase
+{
+  protected:
+    T &s;
+
+  public:
+    DistData(T &stat) : s(stat) {}
+
+    virtual bool binned() const { return s.binned(); }
+    virtual void reset() { s.reset(); }
+    virtual bool zero() const { return s.zero(); }
+    virtual void update() { return s.update(this); }
+};
+
+struct VectorDistDataBase : public StatData
+{
+    std::vector<DistDataData> data;
+
+   /** Names and descriptions of subfields. */
+    mutable std::vector<std::string> subnames;
+    mutable std::vector<std::string> subdescs;
+
+    /** Local storage for the entry values, used for printing. */
+    mutable rvec_t vec;
+
+    virtual size_t size() const = 0;
+    virtual void display(std::ostream &stream) const;
+    virtual void update()
+    {
+        int s = size();
+        if (subnames.size() < s)
+            subnames.resize(s);
+
+        if (subdescs.size() < s)
+            subdescs.resize(s);
+    }
+};
+
+template <class T>
+class VectorDistData : public VectorDistDataBase
+{
+  protected:
+    T &s;
+
+  public:
+    VectorDistData(T &stat) : s(stat) {}
+
+    virtual bool binned() const { return T::bin_t::binned; }
+    virtual void reset() { s.reset(); }
+    virtual size_t size() const { return s.size(); }
+    virtual bool zero() const { return s.zero(); }
+    virtual void update()
+    {
+        VectorDistDataBase::update();
+        return s.update(this);
+    }
+};
+
+struct Vector2dDataBase : public StatData
+{
+    /** Names and descriptions of subfields. */
+    std::vector<std::string> subnames;
+    std::vector<std::string> subdescs;
+    std::vector<std::string> y_subnames;
+
+    /** Local storage for the entry values, used for printing. */
+    mutable rvec_t vec;
+    mutable int x;
+    mutable int y;
+
+    virtual void display(std::ostream &stream) const;
+    virtual void update()
+    {
+        if (subnames.size() < x)
+            subnames.resize(x);
+    }
+};
+
+template <class T>
+class Vector2dData : public Vector2dDataBase
+{
+  protected:
+    T &s;
+
+  public:
+    Vector2dData(T &stat) : s(stat) {}
+
+    virtual bool binned() const { return T::bin_t::binned; }
+    virtual void reset() { s.reset(); }
+    virtual bool zero() const { return s.zero(); }
+    virtual void update()
+    {
+        Vector2dDataBase::update();
+        return s.update(this);
+    }
+};
+
+
+class DataAccess
+{
+  protected:
+    StatData *find() const;
+    void map(StatData *data);
+
+    StatData *statData();
+    const StatData *statData() const;
+
+    void setInit();
+    void setPrint();
+};
+
+template <class Parent, class Child, template <class Child> class Data>
+class Wrap : public Child
+{
+  protected:
+    Parent &self() { return *reinterpret_cast<Parent *>(this); }
+
+  protected:
+    Data<Child> *statData()
+    {
+        StatData *__data = DataAccess::statData();
+        Data<Child> *ptr = dynamic_cast<Data<Child> *>(__data);
+        assert(ptr);
+        return ptr;
+    }
+
+  public:
+    const Data<Child> *statData() const
+    {
+        const StatData *__data = DataAccess::statData();
+        const Data<Child> *ptr = dynamic_cast<const Data<Child> *>(__data);
+        assert(ptr);
+        return ptr;
+    }
+
+  public:
+    Wrap()
+    {
+        map(new Data<Child>(*this));
+    }
 
     /**
      * Set the name and marks this stat to print at the end of simulation.
      * @param name The new name.
      * @return A reference to this stat.
      */
-    Stat &name(const std::string &name);
+    Parent &name(const std::string &_name)
+    {
+        Data<Child> *data = statData();
+        data->name = _name;
+        setPrint();
+        return self();
+    }
+
     /**
      * Set the description and marks this stat to print at the end of
      * simulation.
      * @param desc The new description.
      * @return A reference to this stat.
      */
-    Stat &desc(const std::string &desc);
+    Parent &desc(const std::string &_desc)
+    {
+        statData()->desc = _desc;
+        return self();
+    }
+
     /**
      * Set the precision and marks this stat to print at the end of simulation.
      * @param p The new precision
      * @return A reference to this stat.
      */
-    Stat &precision(int p);
+    Parent &precision(int _precision)
+    {
+        statData()->precision = _precision;
+        return self();
+    }
+
     /**
      * Set the flags and marks this stat to print at the end of simulation.
      * @param f The new flags.
      * @return A reference to this stat.
      */
-    Stat &flags(FormatFlags f);
+    Parent &flags(FormatFlags _flags)
+    {
+        statData()->flags |= _flags;
+        return self();
+    }
+
     /**
      * Set the prerequisite stat and marks this stat to print at the end of
      * simulation.
      * @param prereq The prerequisite stat.
      * @return A reference to this stat.
      */
-    Stat &prereq(const Stat &prereq);
+    template <class T>
+    Parent &prereq(const T &prereq)
+    {
+        statData()->prereq = prereq.statData();
+        return self();
+    }
+};
+
+template <class Parent, class Child, template <class Child> class Data>
+class WrapVec : public Wrap<Parent, Child, Data>
+{
+  public:
+    // The following functions are specific to vectors.  If you use them
+    // in a non vector context, you will get a nice compiler error!
+
     /**
      * Set the subfield name for the given index, and marks this stat to print
      * at the end of simulation.
@@ -281,7 +516,15 @@ class Stat
      * @param name The new name of the subfield.
      * @return A reference to this stat.
      */
-    Stat &subname(int index, const std::string &name);
+    Parent &subname(int index, const std::string &name)
+    {
+        std::vector<std::string> &subn = statData()->subnames;
+        if (subn.size() <= index)
+            subn.resize(index + 1);
+        subn[index] = name;
+        return self();
+    }
+
     /**
      * Set the subfield description for the given index and marks this stat to
      * print at the end of simulation.
@@ -289,107 +532,42 @@ class Stat
      * @param desc The new description of the subfield
      * @return A reference to this stat.
      */
-    Stat &subdesc(int index, const std::string &desc);
-
-  public:
-    /**
-     * Checks if the first stat's name is alphabetically less than the second.
-     * This function breaks names up at periods and considers each subname
-     * separately.
-     * @param stat1 The first stat.
-     * @param stat2 The second stat.
-     * @return stat1's name is alphabetically before stat2's
-     */
-    static bool less(Stat *stat1, Stat *stat2);
-
-#ifdef STAT_DEBUG
-    /** A unique ID used for debugging. */
-    int number;
-#endif
-};
+    Parent &subdesc(int index, const std::string &desc)
+    {
+        std::vector<std::string> &subd = statData()->subdescs;
+        if (subd.size() <= index)
+            subd.resize(index + 1);
+        subd[index] = desc;
 
-/**
- * Base class for all scalar stats. The class provides an interface to access
- * the current value of the stat. This class can be used in formulas.
- */
-class ScalarStat : public Stat
-{
-  public:
-    /**
-     * Create and perhaps register this stat with the database.
-     * @param reg If true, register this stat with the database.
-     */
-    ScalarStat(bool reg) : Stat(reg) {}
-    /**
-     * Return the current value of this statistic as a result type.
-     * @return The current value of this statistic.
-     */
-    virtual result_t val() const = 0;
-    /**
-     * Return true if this stat has value zero.
-     * @return True if this stat is zero.
-     */
-    virtual bool zero() const;
-    /**
-     * Print this stat to the provided ostream.
-     * @param stream The output stream.
-     */
-    virtual void display(std::ostream &stream) const;
+        return self();
+    }
 
-    /**
-     * Return true if stat is binned.
-     *@return True is stat is binned.
-     */
-    virtual bool binned() const = 0;
 };
 
-void
-VectorDisplay(std::ostream &stream, const std::string &myname,
-              const std::vector<std::string> *mysubnames,
-              const std::string &mydesc,
-              const std::vector<std::string> *mysubdescs,
-              int myprecision, FormatFlags myflags, const rvec_t &vec,
-              result_t mytotal);
-
-/**
- * Base class for all vector stats. This class provides interfaces to access
- * the current values of the stats as well as the totals. This class can be
- * used in formulas.
- */
-class VectorStat : public Stat
+template <class Parent, class Child, template <class Child> class Data>
+class WrapVec2d : public WrapVec<Parent, Child, Data>
 {
   public:
     /**
-     * Create and perhaps register this stat with the database.
-     * @param reg If true, register this stat with the database.
-     */
-    VectorStat(bool reg) : Stat(reg) {}
-    /**
-     * Return a vector of result typesd of all the values in the vector.
-     * @return The values of the vector.
-     */
-    virtual const rvec_t &val() const = 0;
-    /**
-     * Return the total of all the entries in the vector.
-     * @return The total of the vector.
-     */
-    virtual result_t total() const = 0;
-    /**
-     * Return true if this stat has value zero.
-     * @return True if this stat is zero.
-     */
-    virtual bool zero() const;
-    /**
-     * Print this stat to the provided ostream.
-     * @param stream The output stream.
-     */
-    virtual void display(std::ostream &stream) const;
-
-    /**
-     * Return true if stat is binned.
-     *@return True is stat is binned.
+     * @warning This makes the assumption that if you're gonna subnames a 2d
+     * vector, you're subnaming across all y
      */
-    virtual bool binned() const = 0;
+    Parent &ysubnames(const char **names)
+    {
+        Data<Child> *data = statData();
+        data->y_subnames.resize(y);
+        for (int i = 0; i < y; ++i)
+            data->y_subnames[i] = names[i];
+        return self();
+    }
+    Parent &ysubname(int index, const std::string subname)
+    {
+        Data<Child> *data = statData();
+        assert(i < y);
+        data->y_subnames.resize(y);
+        data->y_subnames[i] = subname.c_str();
+        return self();
+    }
 };
 
 //////////////////////////////////////////////////////////////////////
@@ -411,13 +589,18 @@ struct StatStor
   private:
     /** The statistic value. */
     T data;
+    static T &Null()
+    {
+        static T __T = T();
+        return __T;
+    }
 
   public:
     /**
      * Builds this storage element and calls the base constructor of the
      * datatype.
      */
-    StatStor(const Params &) : data(T()) {}
+    StatStor(const Params &) : data(Null()) {}
 
     /**
      * The the stat to the given value.
@@ -452,7 +635,12 @@ struct StatStor
     /**
      * Reset stat value to default
      */
-    void reset() { data = T(); }
+    void reset() { data = Null(); }
+
+    /**
+     * @return true if zero value
+     */
+    bool zero() const { return data == Null(); }
 };
 
 /**
@@ -541,6 +729,11 @@ struct AvgStor
         total = 0;
         last = curTick;
     }
+
+    /**
+     * @return true if zero value
+     */
+    bool zero() const { return total == 0.0; }
 };
 
 /**
@@ -549,7 +742,7 @@ struct AvgStor
  * This allows for breaking down statistics across multiple bins easily.
  */
 template <typename T, template <typename T> class Storage, class Bin>
-class ScalarBase : public ScalarStat
+class ScalarBase : public DataAccess
 {
   protected:
     /** Define the type of the storage class. */
@@ -593,11 +786,6 @@ class ScalarBase : public ScalarStat
     const ScalarBase &operator=(const ScalarBase &);
 
   public:
-    /**
-     * Return the current value of this stat as a result type.
-     * @return The current value.
-     */
-    result_t val() const { return data()->val(params); }
     /**
      * Return the current value of this stat as its base type.
      * @return The current value.
@@ -608,9 +796,9 @@ class ScalarBase : public ScalarStat
     /**
      * Create and initialize this stat, register it with the database.
      */
-    ScalarBase() : ScalarStat(true) {
+    ScalarBase()
+    {
         bin.init(params);
-        setInit();
     }
 
   public:
@@ -659,17 +847,23 @@ class ScalarBase : public ScalarStat
      * Return the number of elements, always 1 for a scalar.
      * @return 1.
      */
-    virtual size_t size() const { return 1; }
+    size_t size() const { return 1; }
     /**
      * Return true if stat is binned.
      *@return True is stat is binned.
      */
-    virtual bool binned() const { return bin_t::binned; }
+    bool binned() const { return bin_t::binned; }
 
     /**
      * Reset stat value to default
      */
     void reset() { bin.reset(); }
+
+    result_t val() { return data()->val(params); }
+
+    result_t total() { return val(); }
+
+    bool zero() { return val() == 0.0; }
 };
 
 //////////////////////////////////////////////////////////////////////
@@ -685,7 +879,7 @@ class ScalarProxy;
  * Storage class. @sa ScalarBase
  */
 template <typename T, template <typename T> class Storage, class Bin>
-class VectorBase : public VectorStat
+class VectorBase : public DataAccess
 {
   protected:
     /** Define the type of the storage class. */
@@ -695,10 +889,6 @@ class VectorBase : public VectorStat
     /** Define the bin type. */
     typedef typename Bin::VectorBin<storage_t> bin_t;
 
-  private:
-    /** Local storage for the entry values, used for printing. */
-    mutable rvec_t *vec;
-
   protected:
     /** The bin of this stat. */
     bin_t bin;
@@ -737,18 +927,18 @@ class VectorBase : public VectorStat
      * Copy the values to a local vector and return a reference to it.
      * @return A reference to a vector of the stat values.
      */
-    const rvec_t &val() const {
-        if (vec)
-            vec->resize(size());
-        else
-            vec = new rvec_t(size());
-
+    void val(rvec_t &vec) const
+    {
+        vec.resize(size());
         for (int i = 0; i < size(); ++i)
-            (*vec)[i] = data(i)->val(params);
-
-        return *vec;
+            vec[i] = data(i)->val(params);
     }
 
+    /**
+     * @return True is stat is binned.
+     */
+    bool binned() const { return bin_t::binned; }
+
     /**
      * Return a total of all entries in this vector.
      * @return The total of all vector entries.
@@ -760,28 +950,25 @@ class VectorBase : public VectorStat
         return total;
     }
 
-  public:
-    /**
-     * Create this vector and register it with the database.
-     */
-    VectorBase() : VectorStat(true), vec(NULL) {}
     /**
-     * Destructor.
-     */
-    ~VectorBase() { if (vec) delete vec; }
-
-    /**
-     * Set this vector to have the given size.
-     * @param size The new size.
-     * @return A reference to this stat.
-     */
-    VectorBase &init(size_t size) {
-        bin.init(size, params);
-        setInit();
+     * @return the number of elements in this vector.
+     */
+    size_t size() const { return bin.size(); }
 
-        return *this;
+    bool zero() const
+    {
+        for (int i = 0; i < size(); ++i)
+            if (data(i)->zero())
+                return true;
+        return false;
     }
 
+    bool check() const { return true; }
+    void reset() { bin.reset(); }
+
+  public:
+    VectorBase() {}
+
     /** Friend this class with the associated scalar proxy. */
     friend class ScalarProxy<T, Storage, Bin>;
 
@@ -792,20 +979,7 @@ class VectorBase : public VectorStat
      */
     ScalarProxy<T, Storage, Bin> operator[](int index);
 
-    /**
-     * Return the number of elements in this vector.
-     * @return The size of the vector.
-     */
-    virtual size_t size() const { return bin.size(); }
-    /**
-     * Return true if stat is binned.
-     *@return True is stat is binned.
-     */
-    virtual bool binned() const { return bin_t::binned; }
-    /**
-     * Reset stat value to default
-     */
-    virtual void reset() { bin.reset(); }
+    void update(StatData *data) {}
 };
 
 /**
@@ -813,7 +987,7 @@ class VectorBase : public VectorStat
  * Behaves like a ScalarBase.
  */
 template <typename T, template <typename T> class Storage, class Bin>
-class ScalarProxy : public ScalarStat
+class ScalarProxy
 {
   protected:
     /** Define the type of the storage class. */
@@ -868,13 +1042,13 @@ class ScalarProxy : public ScalarStat
      * @param i The index to access.
      */
     ScalarProxy(bin_t &b, params_t &p, int i)
-        : ScalarStat(false), bin(&b), params(&p), index(i)  {}
+        : bin(&b), params(&p), index(i)  {}
     /**
      * Create a copy of the provided ScalarProxy.
      * @param sp The proxy to copy.
      */
     ScalarProxy(const ScalarProxy &sp)
-        : ScalarStat(false), bin(sp.bin), params(sp.params), index(sp.index) {}
+        : bin(sp.bin), params(sp.params), index(sp.index) {}
     /**
      * Set this proxy equal to the provided one.
      * @param sp The proxy to copy.
@@ -933,16 +1107,18 @@ class ScalarProxy : public ScalarStat
      * Return the number of elements, always 1 for a scalar.
      * @return 1.
      */
-    virtual size_t size() const { return 1; }
+    size_t size() const { return 1; }
+
     /**
      * Return true if stat is binned.
      *@return false since Proxies aren't printed/binned
      */
-    virtual bool binned() const { return false; }
+    bool binned() const { return false; }
+
     /**
      * This stat has no state.  Nothing to reset
      */
-    virtual void reset() {  }
+    void reset() {  }
 };
 
 template <typename T, template <typename T> class Storage, class Bin>
@@ -957,7 +1133,7 @@ template <typename T, template <typename T> class Storage, class Bin>
 class VectorProxy;
 
 template <typename T, template <typename T> class Storage, class Bin>
-class Vector2dBase : public Stat
+class Vector2dBase : public DataAccess
 {
   protected:
     typedef Storage<T> storage_t;
@@ -969,7 +1145,6 @@ class Vector2dBase : public Stat
     size_t y;
     bin_t bin;
     params_t params;
-    std::vector<std::string> *y_subnames;
 
   protected:
     storage_t *data(int index) { return bin.data(index, params); }
@@ -986,104 +1161,36 @@ class Vector2dBase : public Stat
     const Vector2dBase &operator=(const Vector2dBase &);
 
   public:
-    Vector2dBase() : Stat(true) {}
-    ~Vector2dBase() { }
-
-    Vector2dBase &init(size_t _x, size_t _y) {
-        x = _x;
-        y = _y;
-        bin.init(x * y, params);
-        setInit();
-        y_subnames = new std::vector<std::string>(y);
-
-        return *this;
-    }
+    Vector2dBase() {}
 
-    /**
-     * @warning This makes the assumption that if you're gonna subnames a 2d
-     * vector, you're subnaming across all y
-     */
-    Vector2dBase &ysubnames(const char **names)
-    {
-        for (int i=0; i < y; ++i) {
-            (*y_subnames)[i] = names[i];
-        }
-        return *this;
-    }
-    Vector2dBase &ysubname(int index, const std::string subname)
+    void update(Vector2dDataBase *data)
     {
-        (*y_subnames)[i] = subname.c_str();
-        return *this;
+        data->x = x;
+        data->y = y;
+        int size = this->size();
+        data->vec.resize(size);
+        for (int i = 0; i < size; ++i)
+            data->vec[i] = this->data(i)->val(params);
     }
+
     std::string ysubname(int i) const { return (*y_subnames)[i]; }
 
     friend class VectorProxy<T, Storage, Bin>;
     VectorProxy<T, Storage, Bin> operator[](int index);
 
-    virtual size_t size() const { return bin.size(); }
-    virtual bool zero() const { return data(0)->value(params) == 0.0; }
-    /**
-     * Return true if stat is binned.
-     *@return True is stat is binned.
-     */
-    virtual bool binned() const { return bin_t::binned; }
-
-    virtual void
-    display(std::ostream &out) const
-    {
-        bool have_subname = false;
-        for (int i = 0; i < x; ++i) {
-            if (!mysubname(i).empty())
-                have_subname = true;
-        }
-
-        rvec_t tot_vec(y);
-        result_t super_total = 0.0;
-        for (int i = 0; i < x; ++i) {
-            std::string subname;
-            if (have_subname) {
-                subname = mysubname(i);
-                if (subname.empty())
-                    continue;
-            } else
-                subname = to_string(i);
-
-            int iy = i * y;
-            rvec_t vec(y);
-
-            result_t total = 0.0;
-            for (int j = 0; j < y; ++j) {
-                vec[j] = data(iy + j)->val(params);
-                tot_vec[j] += vec[j];
-                total += vec[j];
-                super_total += vec[j];
-            }
-
-            std::string desc;
-            if (mysubdesc(i).empty()) {
-                desc = mydesc();
-            } else {
-                desc = mysubdesc(i);
-            }
-
-            VectorDisplay(out, myname() + "_" + subname, y_subnames, desc, 0,
-                          myprecision(), myflags(), vec, total);
+    size_t size() const { return bin.size(); }
+    bool zero() const { return data(0)->value(params) == 0.0; }
 
-        }
-        if ((myflags() & ::Statistics::total) && (x > 1)) {
-            VectorDisplay(out, myname(), y_subnames, mydesc(), 0,
-                          myprecision(), myflags(), tot_vec, super_total);
-
-        }
-    }
     /**
      * Reset stat value to default
      */
-    virtual void reset() { bin.reset(); }
+    void reset() { bin.reset(); }
+
+    bool check() { return true; }
 };
 
 template <typename T, template <typename T> class Storage, class Bin>
-class VectorProxy : public VectorStat
+class VectorProxy
 {
   protected:
     typedef Storage<T> storage_t;
@@ -1132,18 +1239,19 @@ class VectorProxy : public VectorStat
 
   public:
     VectorProxy(bin_t &b, params_t &p, int o, int l)
-        : VectorStat(false), bin(&b), params(&p), offset(o), len(l), vec(NULL)
+        : bin(&b), params(&p), offset(o), len(l), vec(NULL)
         { }
     VectorProxy(const VectorProxy &sp)
-        : VectorStat(false), bin(sp.bin), params(sp.params), offset(sp.offset),
-          len(sp.len), vec(NULL)
+        : bin(sp.bin), params(sp.params), offset(sp.offset), len(sp.len),
+          vec(NULL)
         { }
     ~VectorProxy() {
         if (vec)
             delete vec;
     }
 
-    const VectorProxy &operator=(const VectorProxy &sp) {
+    const VectorProxy &operator=(const VectorProxy &sp)
+    {
         bin = sp.bin;
         params = sp.params;
         offset = sp.offset;
@@ -1154,22 +1262,24 @@ class VectorProxy : public VectorStat
         return *this;
     }
 
-    virtual size_t size() const { return len; }
-
-    ScalarProxy<T, Storage, Bin> operator[](int index) {
+    ScalarProxy<T, Storage, Bin> operator[](int index)
+    {
         assert (index >= 0 && index < size());
         return ScalarProxy<T, Storage, Bin>(*bin, *params, offset + index);
     }
+
+    size_t size() const { return len; }
+
     /**
      * Return true if stat is binned.
      *@return false since Proxies aren't printed/binned
      */
-    virtual bool binned() const { return false; }
+    bool binned() const { return false; }
 
     /**
      * This stat has no state.  Nothing to reset.
      */
-    virtual void reset() { }
+    void reset() { }
 };
 
 template <typename T, template <typename T> class Storage, class Bin>
@@ -1187,12 +1297,6 @@ Vector2dBase<T, Storage, Bin>::operator[](int index)
 //
 //////////////////////////////////////////////////////////////////////
 
-void DistDisplay(std::ostream &stream, const std::string &name,
-                 const std::string &desc, int precision, FormatFlags flags,
-                 result_t min_val, result_t max_val,
-                 result_t underflow, result_t overflow,
-                 const rvec_t &vec, int min, int max, int bucket_size,
-                 int size);
 /**
  * Templatized storage and interface for a distrbution stat.
  */
@@ -1212,6 +1316,7 @@ struct DistStor
         /** The number of buckets. Equal to (max-min)/bucket_size. */
         int size;
     };
+    enum { fancy = false };
 
   private:
     /** The smallest value sampled. */
@@ -1222,6 +1327,12 @@ struct DistStor
     T underflow;
     /** The number of values sampled more than max. */
     T overflow;
+    /** The current sum. */
+    T sum;
+    /** The sum of squares. */
+    T squares;
+    /** The number of samples. */
+    int samples;
     /** Counter for each bucket. */
     std::vector<T> vec;
 
@@ -1232,7 +1343,7 @@ struct DistStor
      */
     DistStor(const Params &params)
         : min_val(INT_MAX), max_val(INT_MIN), underflow(0), overflow(0),
-          vec(params.size)
+          sum(T()), squares(T()), samples(0), vec(params.size)
     {
         reset();
     }
@@ -1243,7 +1354,8 @@ struct DistStor
      * @param number The number of times to add the value.
      * @param params The paramters of the distribution.
      */
-    void sample(T val, int number, const Params &params) {
+    void sample(T val, int number, const Params &params)
+    {
         if (val < params.min)
             underflow += number;
         else if (val > params.max)
@@ -1259,6 +1371,11 @@ struct DistStor
 
         if (val > max_val)
             max_val = val;
+
+        T sample = val * number;
+        sum += sample;
+        squares += sample * sample;
+        samples += number;
     }
 
     /**
@@ -1273,48 +1390,35 @@ struct DistStor
      * @param params The paramters of the distribution.
      * @return True if any values have been sampled.
      */
-    bool zero(const Params &params) const {
-        if (underflow != 0 || overflow != 0)
-            return false;
-
-        int s = size(params);
-        for (int i = 0; i < s; i++)
-            if (vec[i] != 0)
-                return false;
-
-        return true;
+    bool zero(const Params &params) const
+    {
+        return samples == 0;
     }
 
-    /**
-     * Print this distribution and the given print data to the given ostream.
-     * @param stream The output stream.
-     * @param name The name of this stat (from StatData).
-     * @param desc The description of this stat (from StatData).
-     * @param precision The print precision (from StatData).
-     * @param flags The format flags (from StatData).
-     * @param params The paramters of this distribution.
-     */
-    void display(std::ostream &stream, const std::string &name,
-                 const std::string &desc, int precision, FormatFlags flags,
-                 const Params &params) const {
+    void update(DistDataData *data, DisplayMode mode, const Params &params)
+    {
+        data->min = params.min;
+        data->max = params.max;
+        data->bucket_size = params.bucket_size;
+        data->size = params.size;
 
-#ifdef STAT_DISPLAY_COMPAT
-        result_t min = params.min;
-#else
-        result_t min = (min_val == INT_MAX) ? params.min : min_val;
-#endif
-        result_t max = (max_val == INT_MIN) ? 0 : max_val;
+        if (mode == mode_m5)
+            data->min_val = (min_val == INT_MAX) ? params.min : min_val;
+        else
+            data->min_val = params.min;
 
-        rvec_t rvec(params.size);
+        data->max_val = (max_val == INT_MIN) ? 0 : max_val;
+        data->underflow = underflow;
+        data->overflow = overflow;
+        data->vec.resize(params.size);
         for (int i = 0; i < params.size; ++i)
-            rvec[i] = vec[i];
+            data->vec[i] = vec[i];
 
-        DistDisplay(stream, name, desc, precision, flags,
-                    (result_t)min, (result_t)max,
-                    (result_t)underflow, (result_t)overflow,
-                    rvec, params.min, params.max, params.bucket_size,
-                    params.size);
+        data->sum = sum;
+        data->squares = squares;
+        data->samples = samples;
     }
+
     /**
      * Reset stat value to default
      */
@@ -1328,14 +1432,13 @@ struct DistStor
         int size = vec.size();
         for (int i = 0; i < size; ++i)
             vec[i] = T();
-    }
 
+        sum = T();
+        squares = T();
+        samples = T();
+    }
 };
 
-void FancyDisplay(std::ostream &stream, const std::string &name,
-                  const std::string &desc, int precision, FormatFlags flags,
-                  result_t mean, result_t variance, result_t total);
-
 /**
  * Templatized storage and interface for a distribution that calculates mean
  * and variance.
@@ -1348,20 +1451,21 @@ struct FancyStor
      * No paramters for this storage.
      */
     struct Params {};
+    enum { fancy = true };
 
   private:
     /** The current sum. */
     T sum;
     /** The sum of squares. */
     T squares;
-    /** The total number of samples. */
-    int total;
+    /** The number of samples. */
+    int samples;
 
   public:
     /**
      * Create and initialize this storage.
      */
-    FancyStor(const Params &) : sum(T()), squares(T()), total(0) {}
+    FancyStor(const Params &) : sum(T()), squares(T()), samples(0) {}
 
     /**
      * Add a value the given number of times to this running average.
@@ -1371,40 +1475,19 @@ struct FancyStor
      * @param number The number of times to add the value.
      * @param p The parameters of this stat.
      */
-    void sample(T val, int number, const Params &p) {
+    void sample(T val, int number, const Params &p)
+    {
         T value = val * number;
         sum += value;
         squares += value * value;
-        total += number;
+        samples += number;
     }
 
-    /**
-     * Print this distribution and the given print data to the given ostream.
-     * @param stream The output stream.
-     * @param name The name of this stat (from StatData).
-     * @param desc The description of this stat (from StatData).
-     * @param precision The print precision (from StatData).
-     * @param flags The format flags (from StatData).
-     * @param params The paramters of this distribution.
-     */
-    void display(std::ostream &stream, const std::string &name,
-                 const std::string &desc, int precision, FormatFlags flags,
-                 const Params &params) const {
-
-        result_t mean = NAN;
-        result_t variance = NAN;
-
-                result_t ftot = total;
-        if (total != 0) {
-            result_t fsum = sum;
-            result_t fsq = squares;
-
-            mean = fsum / ftot;
-            variance = (ftot * fsq - (fsum * fsum)) / (ftot * (ftot - 1.0));
-        }
-
-        FancyDisplay(stream, name, desc, precision, flags, mean,
-                     variance, ftot);
+    void update(DistDataData *data, DisplayMode mode, const Params &params)
+    {
+        data->sum = sum;
+        data->squares = squares;
+        data->samples = samples;
     }
 
     /**
@@ -1412,19 +1495,21 @@ struct FancyStor
      * @return 1.
      */
     size_t size(const Params &) const { return 1; }
+
     /**
      * Return true if no samples have been added.
      * @return True if no samples have been added.
      */
-    bool zero(const Params &) const { return total == 0; }
+    bool zero(const Params &) const { return samples == 0; }
+
     /**
      * Reset stat value to default
      */
-    virtual void reset()
+    void reset()
     {
         sum = T();
         squares = T();
-        total = 0;
+        samples = 0;
     }
 };
 
@@ -1438,6 +1523,7 @@ struct AvgFancy
   public:
     /** No parameters for this storage. */
     struct Params {};
+    enum { fancy = true };
 
   private:
     /** Current total. */
@@ -1458,28 +1544,18 @@ struct AvgFancy
      * @param number The number of times to add the value.
      * @param p The paramters of the distribution.
      */
-    void sample(T val, int number, const Params& p) {
+    void sample(T val, int number, const Params& p)
+    {
         T value = val * number;
         sum += value;
         squares += value * value;
     }
 
-    /**
-     * Print this distribution and the given print data to the given ostream.
-     * @param stream The output stream.
-     * @param name The name of this stat (from StatData).
-     * @param desc The description of this stat (from StatData).
-     * @param precision The print precision (from StatData).
-     * @param flags The format flags (from StatData).
-     * @param params The paramters of this distribution.
-     */
-    void display(std::ostream &stream, const std::string &name,
-                 const std::string &desc, int precision, FormatFlags flags,
-                 const Params &params) const {
-        result_t mean = sum / curTick;
-        result_t variance = (squares - sum * sum) / curTick;
-
-        FancyDisplay(stream, name, desc, precision, flags, mean, variance);
+    void update(DistDataData *data, DisplayMode mode, const Params &params)
+    {
+        data->sum = sum;
+        data->squares = squares;
+        data->samples = curTick;
     }
 
     /**
@@ -1495,7 +1571,7 @@ struct AvgFancy
     /**
      * Reset stat value to default
      */
-    virtual void reset()
+    void reset()
     {
         sum = T();
         squares = T();
@@ -1507,7 +1583,7 @@ struct AvgFancy
  * determined by the Storage template. @sa ScalarBase
  */
 template <typename T, template <typename T> class Storage, class Bin>
-class DistBase : public Stat
+class DistBase : public DataAccess
 {
   protected:
     /** Define the type of the storage class. */
@@ -1548,14 +1624,7 @@ class DistBase : public Stat
     const DistBase &operator=(const DistBase &);
 
   public:
-    /**
-     * Create this distrubition and register it with the database.
-     */
-    DistBase() : Stat(true) { }
-    /**
-     * Destructor.
-     */
-    ~DistBase() { }
+    DistBase() { }
 
     /**
      * Add a value to the distribtion n times. Calls sample on the storage
@@ -1570,39 +1639,38 @@ class DistBase : public Stat
      * Return the number of entries in this stat.
      * @return The number of entries.
      */
-    virtual size_t size() const { return data()->size(params); }
+    size_t size() const { return data()->size(params); }
     /**
      * Return true if no samples have been added.
      * @return True if there haven't been any samples.
      */
-    virtual bool zero() const { return data()->zero(params); }
-    /**
-     * Print this distribution to the given ostream.
-     * @param stream The output stream.
-     */
-    virtual void display(std::ostream &stream) const {
-        data()->display(stream, myname(), mydesc(), myprecision(), myflags(),
-                        params);
+    bool zero() const { return data()->zero(params); }
+
+    void update(DistDataBase *base)
+    {
+        base->data.fancy = storage_t::fancy;
+        data()->update(&(base->data), base->mode, params);
     }
     /**
-     * Return true if stat is binned.
-     *@return True is stat is binned.
+     * @return True is stat is binned.
      */
-    virtual bool binned() const { return bin_t::binned; }
+    bool binned() const { return bin_t::binned; }
     /**
      * Reset stat value to default
      */
-    virtual void reset()
+    void reset()
     {
         bin.reset();
     }
+
+    bool check() { return true; }
 };
 
 template <typename T, template <typename T> class Storage, class Bin>
 class DistProxy;
 
 template <typename T, template <typename T> class Storage, class Bin>
-class VectorDistBase : public Stat
+class VectorDistBase : public DataAccess
 {
   protected:
     typedef Storage<T> storage_t;
@@ -1628,32 +1696,38 @@ class VectorDistBase : public Stat
     const VectorDistBase &operator=(const VectorDistBase &);
 
   public:
-    VectorDistBase() : Stat(true) { }
-    ~VectorDistBase() { }
+    VectorDistBase() {}
 
     friend class DistProxy<T, Storage, Bin>;
     DistProxy<T, Storage, Bin> operator[](int index);
     const DistProxy<T, Storage, Bin> operator[](int index) const;
 
-    virtual size_t size() const { return bin.size(); }
-    virtual bool zero() const { return false; }
-    virtual void display(std::ostream &stream) const;
+    size_t size() const { return bin.size(); }
+    bool zero() const { return false; }
     /**
      * Return true if stat is binned.
      *@return True is stat is binned.
      */
-    virtual bool binned() const { return bin_t::binned; }
+    bool binned() const { return bin_t::binned; }
     /**
      * Reset stat value to default
      */
-    virtual void reset()
+    void reset() { bin.reset(); }
+
+    bool check() { return true; }
+    void update(VectorDistDataBase *base)
     {
-        bin.reset();
+        int size = this->size();
+        base->data.resize(size);
+        for (int i = 0; i < size; ++i) {
+            base->data[i].fancy = storage_t::fancy;
+            data(i)->update(&(base->data[i]), base->mode, params);
+        }
     }
 };
 
 template <typename T, template <typename T> class Storage, class Bin>
-class DistProxy : public Stat
+class DistProxy
 {
   protected:
     typedef Storage<T> storage_t;
@@ -1674,9 +1748,9 @@ class DistProxy : public Stat
 
   public:
     DistProxy(const VectorDistBase<T, Storage, Bin> &s, int i)
-        : Stat(false), cstat(&s), index(i) {}
+        : cstat(&s), index(i) {}
     DistProxy(const DistProxy &sp)
-        : Stat(false), cstat(sp.cstat), index(sp.index) {}
+        : cstat(sp.cstat), index(sp.index) {}
     const DistProxy &operator=(const DistProxy &sp) {
         cstat = sp.cstat; index = sp.index; return *this;
     }
@@ -1685,36 +1759,17 @@ class DistProxy : public Stat
     template <typename U>
     void sample(const U& v, int n = 1) { data()->sample(v, n, cstat->params); }
 
-    virtual size_t size() const { return 1; }
-    virtual bool zero() const {
-        return data()->zero(cstat->params);
-    }
-    virtual void display(std::ostream &stream) const {
-        std::stringstream name, desc;
-
-        if (!(cstat->mysubname(index).empty())) {
-            name << cstat->myname() << cstat->mysubname(index);
-        } else {
-            name << cstat->myname() << "_" << index;
-        }
-        if (!(cstat->mysubdesc(index).empty())) {
-            desc << cstat->mysubdesc(index);
-        } else {
-            desc << cstat->mydesc();
-        }
-
-        data()->display(stream, name.str(), desc.str(),
-                        cstat->myprecision(), cstat->myflags(), cstat->params);
-    }
+    size_t size() const { return 1; }
+    bool zero() const { return data()->zero(cstat->params); }
     /**
      * Return true if stat is binned.
      *@return false since Proxies are not binned/printed.
      */
-    virtual bool binned() const { return false; }
+    bool binned() const { return false; }
     /**
      * Proxy has no state.  Nothing to reset.
      */
-    virtual void reset() { }
+    void reset() { }
 };
 
 template <typename T, template <typename T> class Storage, class Bin>
@@ -1733,20 +1788,8 @@ VectorDistBase<T, Storage, Bin>::operator[](int index) const
     return DistProxy<T, Storage, Bin>(*this, index);
 }
 
-/**
- * @todo Need a way to print Distribution totals across the Vector
- */
-template <typename T, template <typename T> class Storage, class Bin>
-void
-VectorDistBase<T, Storage, Bin>::display(std::ostream &stream) const
-{
-    for (int i = 0; i < size(); ++i) {
-        DistProxy<T, Storage, Bin> proxy(*this, i);
-        proxy.display(stream);
-    }
-}
-
 #if 0
+template <typename T, template <typename T> class Storage, class Bin>
 result_t
 VectorDistBase<T, Storage, Bin>::total(int index) const
 {
@@ -1798,20 +1841,24 @@ typedef RefCountingPtr<Node> NodePtr;
 class ScalarStatNode : public Node
 {
   private:
-    const ScalarStat &stat;
+    const ScalarDataBase *data;
     mutable rvec_t result;
 
   public:
-    ScalarStatNode(const ScalarStat &s) : stat(s), result(1) {}
-    const rvec_t &val() const { result[0] = stat.val(); return result; }
-    virtual result_t total() const { return stat.val(); };
+    ScalarStatNode(const ScalarDataBase *d) : data(d), result(1) {}
+    virtual const rvec_t &val() const
+    {
+        result[0] = data->val();
+        return result;
+    }
+    virtual result_t total() const { return data->val(); };
 
     virtual size_t size() const { return 1; }
     /**
      * Return true if stat is binned.
      *@return True is stat is binned.
      */
-    virtual bool binned() const { return stat.binned(); }
+    virtual bool binned() const { return data->binned(); }
 };
 
 template <typename T, template <typename T> class Storage, class Bin>
@@ -1824,7 +1871,11 @@ class ScalarProxyNode : public Node
   public:
     ScalarProxyNode(const ScalarProxy<T, Storage, Bin> &p)
         : proxy(p), result(1) { }
-    const rvec_t &val() const { result[0] = proxy.val(); return result; }
+    virtual const rvec_t &val() const
+    {
+        result[0] = proxy.val();
+        return result;
+    }
     virtual result_t total() const { return proxy.val(); };
 
     virtual size_t size() const { return 1; }
@@ -1838,19 +1889,19 @@ class ScalarProxyNode : public Node
 class VectorStatNode : public Node
 {
   private:
-    const VectorStat &stat;
+    const VectorDataBase *data;
 
   public:
-    VectorStatNode(const VectorStat &s) : stat(s) {}
-    const rvec_t &val() const { return stat.val(); }
-    virtual result_t total() const { return stat.total(); };
+    VectorStatNode(const VectorDataBase *d) : data(d) { }
+    virtual const rvec_t &val() const { return data->val(); }
+    virtual result_t total() const { return data->total(); };
 
-    virtual size_t size() const { return stat.size(); }
+    virtual size_t size() const { return data->size(); }
     /**
      * Return true if stat is binned.
      *@return True is stat is binned.
      */
-    virtual bool binned() const { return stat.binned(); }
+    virtual bool binned() const { return data->binned(); }
 };
 
 template <typename T>
@@ -2037,143 +2088,35 @@ class SumNode : public Node
 
         result[0] = 0.0;
 
-        Op op;
-        for (int i = 0; i < size; ++i)
-            result[0] = op(result[0], lvec[i]);
-
-        return result;
-    }
-
-    result_t total() const {
-        const rvec_t &lvec = l->val();
-        int size = lvec.size();
-        assert(size > 0);
-
-        result_t result = 0.0;
-
-        Op op;
-        for (int i = 0; i < size; ++i)
-            result = op(result, lvec[i]);
-
-        return result;
-    }
-
-    virtual size_t size() const { return 1; }
-    /**
-     * Return true if child of node is binned.
-     *@return True if child of node is binned.
-     */
-    virtual bool binned() const { return l->binned(); }
-};
-
-/**
- * Helper class to construct formula node trees.
- */
-class Temp
-{
-  private:
-    /**
-     * Pointer to a Node object.
-     */
-    NodePtr node;
-
-  public:
-    /**
-     * Copy the given pointer to this class.
-     * @param n A pointer to a Node object to copy.
-     */
-    Temp(NodePtr n) : node(n) {}
-    /**
-     * Create a new ScalarStatNode.
-     * @param s The ScalarStat to place in a node.
-     */
-    Temp(const ScalarStat &s) : node(new ScalarStatNode(s)) {}
-    /**
-     * Create a new ScalarProxyNode.
-     * @param p The ScalarProxy to place in a node.
-     */
-    template <typename T, template <typename T> class Storage, class Bin>
-    Temp(const ScalarProxy<T, Storage, Bin> &p)
-        : node(new ScalarProxyNode<T, Storage, Bin>(p)) {}
-    /**
-     * Create a new VectorStatNode.
-     * @param s The VectorStat to place in a node.
-     */
-    Temp(const VectorStat &s) : node(new VectorStatNode(s)) {}
-
-    /**
-     * Create a ConstNode
-     * @param value The value of the const node.
-     */
-    Temp(signed char value) : node(new ConstNode<signed char>(value)) {}
-    /**
-     * Create a ConstNode
-     * @param value The value of the const node.
-     */
-    Temp(unsigned char value) : node(new ConstNode<unsigned char>(value)) {}
-    /**
-     * Create a ConstNode
-     * @param value The value of the const node.
-     */
-    Temp(signed short value) : node(new ConstNode<signed short>(value)) {}
-    /**
-     * Create a ConstNode
-     * @param value The value of the const node.
-     */
-    Temp(unsigned short value) : node(new ConstNode<unsigned short>(value)) {}
-    /**
-     * Create a ConstNode
-     * @param value The value of the const node.
-     */
-    Temp(signed int value) : node(new ConstNode<signed int>(value)) {}
-    /**
-     * Create a ConstNode
-     * @param value The value of the const node.
-     */
-    Temp(unsigned int value) : node(new ConstNode<unsigned int>(value)) {}
-    /**
-     * Create a ConstNode
-     * @param value The value of the const node.
-     */
-    Temp(signed long value) : node(new ConstNode<signed long>(value)) {}
-    /**
-     * Create a ConstNode
-     * @param value The value of the const node.
-     */
-    Temp(unsigned long value) : node(new ConstNode<unsigned long>(value)) {}
-    /**
-     * Create a ConstNode
-     * @param value The value of the const node.
-     */
-    Temp(signed long long value)
-        : node(new ConstNode<signed long long>(value)) {}
-    /**
-     * Create a ConstNode
-     * @param value The value of the const node.
-     */
-    Temp(unsigned long long value)
-        : node(new ConstNode<unsigned long long>(value)) {}
-    /**
-     * Create a ConstNode
-     * @param value The value of the const node.
-     */
-    Temp(float value) : node(new ConstNode<float>(value)) {}
-    /**
-     * Create a ConstNode
-     * @param value The value of the const node.
-     */
-    Temp(double value) : node(new ConstNode<double>(value)) {}
-
+        Op op;
+        for (int i = 0; i < size; ++i)
+            result[0] = op(result[0], lvec[i]);
+
+        return result;
+    }
+
+    result_t total() const {
+        const rvec_t &lvec = l->val();
+        int size = lvec.size();
+        assert(size > 0);
+
+        result_t result = 0.0;
+
+        Op op;
+        for (int i = 0; i < size; ++i)
+            result = op(result, lvec[i]);
+
+        return result;
+    }
+
+    virtual size_t size() const { return 1; }
     /**
-     * Return the node pointer.
-     * @return the node pointer.
+     * Return true if child of node is binned.
+     *@return True if child of node is binned.
      */
-    operator NodePtr() { return node;}
+    virtual bool binned() const { return l->binned(); }
 };
 
-} // namespace Detail
-
-
 //////////////////////////////////////////////////////////////////////
 //
 // Binning Interface
@@ -2466,11 +2409,16 @@ typedef NoBin DefaultBin;
  * @sa Stat, ScalarBase, StatStor
  */
 template <typename T = Counter, class Bin = DefaultBin>
-class Scalar : public Detail::ScalarBase<T, Detail::StatStor, Bin>
+class Scalar : public Wrap<Scalar<T, Bin>, ScalarBase<T, StatStor, Bin>, ScalarData>
 {
   public:
     /** The base implementation. */
-    typedef Detail::ScalarBase<T, Detail::StatStor, Bin> Base;
+    typedef ScalarBase<T, StatStor, Bin> Base;
+
+    Scalar()
+    {
+        setInit();
+    }
 
     /**
      * Sets the stat equal to the given value. Calls the base implementation
@@ -2486,11 +2434,16 @@ class Scalar : public Detail::ScalarBase<T, Detail::StatStor, Bin>
  * @sa Stat, ScalarBase, AvgStor
  */
 template <typename T = Counter, class Bin = DefaultBin>
-class Average : public Detail::ScalarBase<T, Detail::AvgStor, Bin>
+class Average : public Wrap<Average<T, Bin>, ScalarBase<T, AvgStor, Bin>, ScalarData>
 {
   public:
     /** The base implementation. */
-    typedef Detail::ScalarBase<T, Detail::AvgStor, Bin> Base;
+    typedef ScalarBase<T, AvgStor, Bin> Base;
+
+    Average()
+    {
+        setInit();
+    }
 
     /**
      * Sets the stat equal to the given value. Calls the base implementation
@@ -2506,37 +2459,73 @@ class Average : public Detail::ScalarBase<T, Detail::AvgStor, Bin>
  * @sa Stat, VectorBase, StatStor
  */
 template <typename T = Counter, class Bin = DefaultBin>
-class Vector : public Detail::VectorBase<T, Detail::StatStor, Bin>
-{ };
+class Vector : public WrapVec<Vector<T, Bin>, VectorBase<T, StatStor, Bin>, VectorData>
+{
+  public:
+    /**
+     * Set this vector to have the given size.
+     * @param size The new size.
+     * @return A reference to this stat.
+     */
+    Vector &init(size_t size) {
+        bin.init(size, params);
+        setInit();
+
+        return *this;
+    }
+};
 
 /**
  * A vector of Average stats.
  * @sa Stat, VectorBase, AvgStor
  */
 template <typename T = Counter, class Bin = DefaultBin>
-class AverageVector : public Detail::VectorBase<T, Detail::AvgStor, Bin>
-{ };
+class AverageVector : public WrapVec<AverageVector<T, Bin>, VectorBase<T, AvgStor, Bin>, VectorData>
+{
+  public:
+    /**
+     * Set this vector to have the given size.
+     * @param size The new size.
+     * @return A reference to this stat.
+     */
+    AverageVector &init(size_t size) {
+        bin.init(size, params);
+        setInit();
+
+        return *this;
+    }
+};
 
 /**
  * A 2-Dimensional vecto of scalar stats.
  * @sa Stat, Vector2dBase, StatStor
  */
 template <typename T = Counter, class Bin = DefaultBin>
-class Vector2d : public Detail::Vector2dBase<T, Detail::StatStor, Bin>
-{ };
+class Vector2d : public WrapVec2d<Vector2d<T, Bin>, Vector2dBase<T, StatStor, Bin>, Vector2dData>
+{
+  public:
+    Vector2d &init(size_t _x, size_t _y) {
+        x = _x;
+        y = _y;
+        bin.init(x * y, params);
+        setInit();
+
+        return *this;
+    }
+};
 
 /**
  * A simple distribution stat.
  * @sa Stat, DistBase, DistStor
  */
 template <typename T = Counter, class Bin = DefaultBin>
-class Distribution : public Detail::DistBase<T, Detail::DistStor, Bin>
+class Distribution : public Wrap<Distribution<T, Bin>, DistBase<T, DistStor, Bin>, DistData>
 {
   private:
     /** Base implementation. */
-    typedef Detail::DistBase<T, Detail::DistStor, Bin> Base;
+    typedef DistBase<T, DistStor, Bin> Base;
     /** The Parameter type. */
-    typedef typename Detail::DistStor<T>::Params Params;
+    typedef typename DistStor<T>::Params Params;
 
   public:
     /**
@@ -2563,13 +2552,13 @@ class Distribution : public Detail::DistBase<T, Detail::DistStor, Bin>
  * @sa Stat, DistBase, FancyStor
  */
 template <typename T = Counter, class Bin = DefaultBin>
-class StandardDeviation : public Detail::DistBase<T, Detail::FancyStor, Bin>
+class StandardDeviation : public Wrap<StandardDeviation<T, Bin>, DistBase<T, FancyStor, Bin>, DistData>
 {
   private:
     /** The base implementation */
-    typedef Detail::DistBase<T, Detail::DistStor, Bin> Base;
+    typedef DistBase<T, DistStor, Bin> Base;
     /** The parameter type. */
-    typedef typename Detail::DistStor<T>::Params Params;
+    typedef typename DistStor<T>::Params Params;
 
   public:
     /**
@@ -2586,19 +2575,20 @@ class StandardDeviation : public Detail::DistBase<T, Detail::FancyStor, Bin>
  * @sa Stat, DistBase, AvgFancy
  */
 template <typename T = Counter, class Bin = DefaultBin>
-class AverageDeviation : public Detail::DistBase<T, Detail::AvgFancy, Bin>
+class AverageDeviation : public Wrap<AverageDeviation<T, Bin>, DistBase<T, AvgFancy, Bin>, DistData>
 {
   private:
     /** The base implementation */
-    typedef Detail::DistBase<T, Detail::DistStor, Bin> Base;
+    typedef DistBase<T, DistStor, Bin> Base;
     /** The parameter type. */
-    typedef typename Detail::DistStor<T>::Params Params;
+    typedef typename DistStor<T>::Params Params;
 
   public:
     /**
      * Construct and initialize this distribution.
      */
-    AverageDeviation() {
+    AverageDeviation()
+    {
         bin.init(params);
         setInit();
     }
@@ -2609,14 +2599,13 @@ class AverageDeviation : public Detail::DistBase<T, Detail::AvgFancy, Bin>
  * @sa Stat, VectorDistBase, DistStor
  */
 template <typename T = Counter, class Bin = DefaultBin>
-class VectorDistribution
-    : public Detail::VectorDistBase<T, Detail::DistStor, Bin>
+class VectorDistribution : public WrapVec<VectorDistribution<T, Bin>, VectorDistBase<T, DistStor, Bin>, VectorDistData>
 {
   private:
     /** The base implementation */
-    typedef Detail::VectorDistBase<T, Detail::DistStor, Bin> Base;
+    typedef VectorDistBase<T, DistStor, Bin> Base;
     /** The parameter type. */
-    typedef typename Detail::DistStor<T>::Params Params;
+    typedef typename DistStor<T>::Params Params;
 
   public:
     /**
@@ -2644,14 +2633,13 @@ class VectorDistribution
  * @sa Stat, VectorDistBase, FancyStor
  */
 template <typename T = Counter, class Bin = DefaultBin>
-class VectorStandardDeviation
-    : public Detail::VectorDistBase<T, Detail::FancyStor, Bin>
+class VectorStandardDeviation : public WrapVec<VectorStandardDeviation<T, Bin>, VectorDistBase<T, FancyStor, Bin>, VectorDistData>
 {
   private:
     /** The base implementation */
-    typedef Detail::VectorDistBase<T, Detail::FancyStor, Bin> Base;
+    typedef VectorDistBase<T, FancyStor, Bin> Base;
     /** The parameter type. */
-    typedef typename Detail::DistStor<T>::Params Params;
+    typedef typename DistStor<T>::Params Params;
 
   public:
     /**
@@ -2672,14 +2660,13 @@ class VectorStandardDeviation
  * @sa Stat, VectorDistBase, AvgFancy
  */
 template <typename T = Counter, class Bin = DefaultBin>
-class VectorAverageDeviation
-    : public Detail::VectorDistBase<T, Detail::AvgFancy, Bin>
+class VectorAverageDeviation : public WrapVec<VectorAverageDeviation<T, Bin>, VectorDistBase<T, AvgFancy, Bin>, VectorDistData>
 {
   private:
     /** The base implementation */
-    typedef Detail::VectorDistBase<T, Detail::AvgFancy, Bin> Base;
+    typedef VectorDistBase<T, AvgFancy, Bin> Base;
     /** The parameter type. */
-    typedef typename Detail::DistStor<T>::Params Params;
+    typedef typename DistStor<T>::Params Params;
 
   public:
     /**
@@ -2698,99 +2685,260 @@ class VectorAverageDeviation
 /**
  * A formula for statistics that is calculated when printed. A formula is
  * stored as a tree of Nodes that represent the equation to calculate.
- * @sa Stat, ScalarStat, VectorStat, Node, Detail::Temp
+ * @sa Stat, ScalarStat, VectorStat, Node, Temp
  */
-class Formula : public Detail::VectorStat
+class FormulaBase : public DataAccess
 {
-  private:
+  protected:
     /** The root of the tree which represents the Formula */
-    Detail::NodePtr root;
-    friend class Statistics::Detail::Temp;
+    NodePtr root;
+    friend class Temp;
+
+  public:
+    /**
+     * Return the result of the Fomula in a vector.  If there were no Vector
+     * components to the Formula, then the vector is size 1.  If there were,
+     * like x/y with x being a vector of size 3, then the result returned will
+     * be x[0]/y, x[1]/y, x[2]/y, respectively.
+     * @return The result vector.
+     */
+    void val(rvec_t &vec) const;
+
+    /**
+     * Return the total Formula result.  If there is a Vector
+     * component to this Formula, then this is the result of the
+     * Formula if the formula is applied after summing all the
+     * components of the Vector.  For example, if Formula is x/y where
+     * x is size 3, then total() will return (x[1]+x[2]+x[3])/y.  If
+     * there is no Vector component, total() returns the same value as
+     * the first entry in the rvec_t val() returns.
+     * @return The total of the result vector.
+     */
+    result_t total() const;
+
+    /**
+     * Return the number of elements in the tree.
+     */
+    size_t size() const;
+
+    /**
+     * Return true if Formula is binned. i.e. any of its children
+     * nodes are binned
+     * @return True if Formula is binned.
+     */
+    bool binned() const;
+
+    /**
+     * Formulas don't need to be reset
+     */
+    void reset();
+
+    /**
+     *
+     */
+    bool zero() const;
+
+    /**
+     *
+     */
+    void update(StatData *);
+};
 
+class Temp;
+class Formula : public WrapVec<Formula, FormulaBase, VectorData>
+{
   public:
     /**
      * Create and initialize thie formula, and register it with the database.
      */
-    Formula() : VectorStat(true) { setInit(); }
+    Formula();
+
     /**
      * Create a formula with the given root node, register it with the
      * database.
      * @param r The root of the expression tree.
      */
-    Formula(Detail::Temp r) : VectorStat(true) {
-        root = r;
-        assert(size());
-    }
+    Formula(Temp r);
 
     /**
      * Set an unitialized Formula to the given root.
      * @param r The root of the expression tree.
      * @return a reference to this formula.
      */
-    const Formula &operator=(Detail::Temp r) {
-        assert(!root && "Can't change formulas");
-        root = r;
-        assert(size());
-        return *this;
-    }
+    const Formula &operator=(Temp r);
 
     /**
      * Add the given tree to the existing one.
      * @param r The root of the expression tree.
      * @return a reference to this formula.
      */
-    const Formula &operator+=(Detail::Temp r) {
-        using namespace Detail;
-        if (root)
-            root = NodePtr(new BinaryNode<std::plus<result_t> >(root, r));
-        else
-            root = r;
-        assert(size());
-        return *this;
-    }
+    const Formula &operator+=(Temp r);
+};
+
+class FormulaNode : public Node
+{
+  private:
+    const Formula &formula;
+    mutable rvec_t vec;
+
+  public:
+    FormulaNode(const Formula &f) : formula(f) {}
 
+    virtual size_t size() const { return formula.size(); }
+    virtual const rvec_t &val() const { formula.val(vec); return vec; }
+    virtual result_t total() const { return formula.total(); }
+    virtual bool binned() const { return formula.binned(); }
+};
+
+/**
+ * Helper class to construct formula node trees.
+ */
+class Temp
+{
+  protected:
     /**
-     * Return the result of the Fomula in a vector.  If there were no Vector
-     * components to the Formula, then the vector is size 1.  If there were,
-     * like x/y with x being a vector of size 3, then the result returned will
-     * be x[0]/y, x[1]/y, x[2]/y, respectively.
-     * @return The result vector.
+     * Pointer to a Node object.
      */
-    const rvec_t &val() const { return root->val(); }
+    NodePtr node;
+
+  public:
     /**
-     * Return the total Formula result.  If there is a Vector
-     * component to this Formula, then this is the result of the
-     * Formula if the formula is applied after summing all the
-     * components of the Vector.  For example, if Formula is x/y where
-     * x is size 3, then total() will return (x[1]+x[2]+x[3])/y.  If
-     * there is no Vector component, total() returns the same value as
-     * the first entry in the rvec_t val() returns.
-     * @return The total of the result vector.
+     * Copy the given pointer to this class.
+     * @param n A pointer to a Node object to copy.
      */
-    result_t total() const { return root->total(); }
+    Temp(NodePtr n) : node(n) { }
 
     /**
-     * Return the number of elements in the tree.
+     * Return the node pointer.
+     * @return the node pointer.
      */
-    size_t size() const {
-        if (!root)
-            return 0;
-        else
-            return root->size();
-    }
+    operator NodePtr() { return node;}
+
+  public:
     /**
-     * Return true if Formula is binned. i.e. any of its children
-     * nodes are binned
-     * @return True if Formula is binned.
+     * Create a new ScalarStatNode.
+     * @param s The ScalarStat to place in a node.
      */
-    virtual bool binned() const { return root->binned(); }
+    template <typename T, class Bin>
+    Temp(const Scalar<T, Bin> &s)
+        : node(new ScalarStatNode(s.statData())) { }
 
     /**
-     * Formulas don't need to be reset
+     * Create a new ScalarStatNode.
+     * @param s The ScalarStat to place in a node.
+     */
+    template <typename T, class Bin>
+    Temp(const Average<T, Bin> &s)
+        : node(new ScalarStatNode(s.statData())) { }
+
+    /**
+     * Create a new VectorStatNode.
+     * @param s The VectorStat to place in a node.
+     */
+    template <typename T, class Bin>
+    Temp(const Vector<T, Bin> &s)
+        : node(new VectorStatNode(s.statData())) { }
+
+    /**
+     *
+     */
+    Temp(const Formula &f)
+        : node(new FormulaNode(f)) { }
+
+    /**
+     * Create a new ScalarProxyNode.
+     * @param p The ScalarProxy to place in a node.
+     */
+    template <typename T, template <typename T> class Storage, class Bin>
+    Temp(const ScalarProxy<T, Storage, Bin> &p)
+        : node(new ScalarProxyNode<T, Storage, Bin>(p)) { }
+
+    /**
+     * Create a ConstNode
+     * @param value The value of the const node.
+     */
+    Temp(signed char value)
+        : node(new ConstNode<signed char>(value)) {}
+
+    /**
+     * Create a ConstNode
+     * @param value The value of the const node.
+     */
+    Temp(unsigned char value)
+        : node(new ConstNode<unsigned char>(value)) {}
+
+    /**
+     * Create a ConstNode
+     * @param value The value of the const node.
+     */
+    Temp(signed short value)
+        : node(new ConstNode<signed short>(value)) {}
+
+    /**
+     * Create a ConstNode
+     * @param value The value of the const node.
+     */
+    Temp(unsigned short value)
+        : node(new ConstNode<unsigned short>(value)) {}
+
+    /**
+     * Create a ConstNode
+     * @param value The value of the const node.
+     */
+    Temp(signed int value)
+        : node(new ConstNode<signed int>(value)) {}
+
+    /**
+     * Create a ConstNode
+     * @param value The value of the const node.
+     */
+    Temp(unsigned int value)
+        : node(new ConstNode<unsigned int>(value)) {}
+
+    /**
+     * Create a ConstNode
+     * @param value The value of the const node.
+     */
+    Temp(signed long value)
+        : node(new ConstNode<signed long>(value)) {}
+
+    /**
+     * Create a ConstNode
+     * @param value The value of the const node.
+     */
+    Temp(unsigned long value)
+        : node(new ConstNode<unsigned long>(value)) {}
+
+    /**
+     * Create a ConstNode
+     * @param value The value of the const node.
+     */
+    Temp(signed long long value)
+        : node(new ConstNode<signed long long>(value)) {}
+
+    /**
+     * Create a ConstNode
+     * @param value The value of the const node.
+     */
+    Temp(unsigned long long value)
+        : node(new ConstNode<unsigned long long>(value)) {}
+
+    /**
+     * Create a ConstNode
+     * @param value The value of the const node.
+     */
+    Temp(float value)
+        : node(new ConstNode<float>(value)) {}
+
+    /**
+     * Create a ConstNode
+     * @param value The value of the const node.
      */
-    virtual void reset() {}
+    Temp(double value)
+        : node(new ConstNode<double>(value)) {}
 };
 
+
 /**
  * @}
  */
@@ -2800,79 +2948,68 @@ void dump(std::ostream &stream);
 void reset();
 void RegResetCallback(Callback *cb);
 
-inline Detail::Temp
-operator+(Detail::Temp l, Detail::Temp r)
+inline Temp
+operator+(Temp l, Temp r)
 {
-    using namespace Detail;
     return NodePtr(new BinaryNode<std::plus<result_t> >(l, r));
 }
 
-inline Detail::Temp
-operator-(Detail::Temp l, Detail::Temp r)
+inline Temp
+operator-(Temp l, Temp r)
 {
-    using namespace Detail;
     return NodePtr(new BinaryNode<std::minus<result_t> >(l, r));
 }
 
-inline Detail::Temp
-operator*(Detail::Temp l, Detail::Temp r)
+inline Temp
+operator*(Temp l, Temp r)
 {
-    using namespace Detail;
     return NodePtr(new BinaryNode<std::multiplies<result_t> >(l, r));
 }
 
-inline Detail::Temp
-operator/(Detail::Temp l, Detail::Temp r)
+inline Temp
+operator/(Temp l, Temp r)
 {
-    using namespace Detail;
     return NodePtr(new BinaryNode<std::divides<result_t> >(l, r));
 }
 
-inline Detail::Temp
-operator%(Detail::Temp l, Detail::Temp r)
+inline Temp
+operator%(Temp l, Temp r)
 {
-    using namespace Detail;
     return NodePtr(new BinaryNode<std::modulus<result_t> >(l, r));
 }
 
-inline Detail::Temp
-operator-(Detail::Temp l)
+inline Temp
+operator-(Temp l)
 {
-    using namespace Detail;
     return NodePtr(new UnaryNode<std::negate<result_t> >(l));
 }
 
 template <typename T>
-inline Detail::Temp
+inline Temp
 constant(T val)
 {
-    using namespace Detail;
     return NodePtr(new ConstNode<T>(val));
 }
 
 template <typename T>
-inline Detail::Temp
+inline Temp
 functor(T &val)
 {
-    using namespace Detail;
     return NodePtr(new FunctorNode<T>(val));
 }
 
 template <typename T>
-inline Detail::Temp
+inline Temp
 scalar(T &val)
 {
-    using namespace Detail;
     return NodePtr(new ScalarNode<T>(val));
 }
 
-inline Detail::Temp
-sum(Detail::Temp val)
+inline Temp
+sum(Temp val)
 {
-    using namespace Detail;
     return NodePtr(new SumNode<std::plus<result_t> >(val));
 }
-
 extern bool PrintDescriptions;
 
 } // namespace statistics
index 1502bca3d02e2e28c0f53790cddcb86385c2dc3e..29d252df4d1984d940fd648078f81483f4dcd9aa 100644 (file)
@@ -52,8 +52,7 @@ offtest: offtest.o
 rangetest: rangetest.o str.o
        $(CXX) $(LFLAGS) -o $@ $^
 
-stattest: cprintf.o hostinfo.o misc.o sim_stats.o sim_time.o \
-          statistics.o stattest.o str.o
+stattest: cprintf.o hostinfo.o misc.o sim_time.o statistics.o stattest.o str.o
        $(CXX) $(LFLAGS) -o $@ $^
 
 strnumtest: strnumtest.o str.o
index 38a15900d1e06b57d6a7d36de1243fa2b64eb9b0..dea5295cc968cbf5f6b0308ffa387bbeacca1217 100644 (file)
@@ -35,7 +35,6 @@
 #include "base/misc.hh"
 #include "base/statistics.hh"
 #include "sim/host.hh"
-#include "sim/sim_stats.hh"
 
 using namespace std;
 using namespace Statistics;
@@ -67,8 +66,8 @@ Formula f4;
 Formula f5;
 Formula f6;
 
-MainBin bin1;
-MainBin bin2;
+MainBin bin1("bin1");
+MainBin bin2("bin2");
 
 double
 testfunc()
@@ -256,7 +255,7 @@ main(int argc, char *argv[])
 
     check();
 
-    MainBin::activate(bin1);
+    bin1.activate();
 
     f1 = s1 + s2;
     f2 = (-s1) / (-s2) * -s3 + ULL(100) + s4;
@@ -452,7 +451,7 @@ main(int argc, char *argv[])
     s6.sample(8);
     s6.sample(9);
 
-    MainBin::activate(bin2);
+    bin2.activate();
     s6.sample(10);
     s6.sample(10);
     s6.sample(10);
@@ -493,12 +492,12 @@ main(int argc, char *argv[])
 
     s12.sample(100);
 
-    MainBin::activate(bin1);
+    bin1.activate();
     cout << "dump 1" << endl;
     dump(cout);
     cout << endl << endl;
 
-    MainBin::activate(bin2);
+    bin2.activate();
     cout << "dump 2" << endl;
     dump(cout);
     cout << endl << endl;