Major stats package cleanup
authorNathan Binkert <binkertn@umich.edu>
Tue, 4 May 2004 21:01:00 +0000 (17:01 -0400)
committerNathan Binkert <binkertn@umich.edu>
Tue, 4 May 2004 21:01:00 +0000 (17:01 -0400)
Add support for generic visitors for stats and use them
to implement independent output functions.

Support for mysql output and some initial code for hacking
on mysql output with python

arch/alpha/pseudo_inst.cc:
base/hybrid_pred.cc:
base/hybrid_pred.hh:
base/sat_counter.cc:
base/sat_counter.hh:
cpu/simple_cpu/simple_cpu.cc:
kern/tru64/tru64_events.cc:
sim/main.cc:
sim/process.cc:
sim/process.hh:
sim/sim_events.cc:
sim/sim_object.cc:
sim/system.hh:
    update for changes in stats package
base/statistics.cc:
    move the python output code to base/stats/puthon.(cc|hh)
    and reimplement it as a visitor.

    move the text output code to base/stats/text.(cc|hh) and
    reimplement it as a visitor.

    move the database stuff into base/stats/statdb.(cc|hh) and
    get rid of the class.  Put everything as globals in the
    Statistics::Database namespace.

    allocate unique ids for all stats.

    directly implement the check routine and get rid of the
    various dumping routines since they're now in separate files.

    make sure that no two stats have the same name

    clean up some loops
base/statistics.hh:
    major changes to the statistics package again

    lots of code was factored out of statistics.hh into several
    separate files in base/stats/ (this will continue)

    There are now two Stat package types Result and Counter that
    are specified to allow the user to keep the counted type
    separate from the result type.  They are currently both doubles
    but that's an experiment.  There is no more per stat ability to
    set the type.  Statistics::Counter is not the same as Counter!

    Implement a visitor for statistics output so that new output
    types can be implemented independently from the stats package
    itself.

    Add a unique id to each stat so that it can be used to keep
    track of stats more simply.  This number can also be used in
    debugging problems with stats.

    Tweak the bucket size stuff a bit to make it work better.

    fixed VectorDist size bug
cpu/memtest/memtest.cc:
    Fix up for changes in stats package
    Don't use value() since it doesn't work with binning.  If you
    want a number as a stat, and to use it in the program itself,
    you really want two separate variables, one that's a stat,
    and one that's not.
cpu/memtest/memtest.hh:
    Fix up for changes in stats package
test/Makefile:
    Try to build stuff now that directories matter
test/stattest.cc:
    test all new output types
    choose which one with command line options

--HG--
extra : convert_revision : e3a3f5f0828c67c0e2de415d936ad240adaddc89

36 files changed:
arch/alpha/pseudo_inst.cc
base/hybrid_pred.cc
base/hybrid_pred.hh
base/mysql.cc [new file with mode: 0644]
base/mysql.hh [new file with mode: 0644]
base/sat_counter.cc
base/sat_counter.hh
base/statistics.cc
base/statistics.hh
base/stats/flags.hh [new file with mode: 0644]
base/stats/mysql.cc [new file with mode: 0644]
base/stats/mysql.hh [new file with mode: 0644]
base/stats/output.hh [new file with mode: 0644]
base/stats/statdb.cc [new file with mode: 0644]
base/stats/statdb.hh [new file with mode: 0644]
base/stats/text.cc [new file with mode: 0644]
base/stats/text.hh [new file with mode: 0644]
base/stats/types.hh [new file with mode: 0644]
base/stats/visit.cc [new file with mode: 0644]
base/stats/visit.hh [new file with mode: 0644]
base/traceflags.py [new file with mode: 0644]
cpu/memtest/memtest.cc
cpu/memtest/memtest.hh
cpu/simple_cpu/simple_cpu.cc
kern/tru64/tru64_events.cc
sim/main.cc
sim/process.cc
sim/process.hh
sim/sim_events.cc
sim/sim_object.cc
sim/stat_control.cc [new file with mode: 0644]
sim/stat_control.hh [new file with mode: 0644]
sim/stats.hh [new file with mode: 0644]
sim/system.hh
test/Makefile
test/stattest.cc

index 7f8c6b17ccf4542223ac70aa3f3cd6aa7182a655..194dc640096099269c936ba816b2a9c71b3b7316 100644 (file)
@@ -34,7 +34,8 @@
 #include "sim/param.hh"
 #include "sim/serialize.hh"
 #include "sim/sim_exit.hh"
-#include "sim/sim_stats.hh"
+#include "sim/stat_control.hh"
+#include "sim/stats.hh"
 
 using namespace std;
 using namespace Statistics;
@@ -82,6 +83,7 @@ namespace AlphaPseudo
         Tick when = curTick + NS2Ticks(delay);
         Tick repeat = NS2Ticks(period);
 
+        using namespace Statistics;
         SetupEvent(Reset, when, repeat);
     }
 
@@ -97,6 +99,7 @@ namespace AlphaPseudo
         Tick when = curTick + NS2Ticks(delay);
         Tick repeat = NS2Ticks(period);
 
+        using namespace Statistics;
         SetupEvent(Dump, when, repeat);
     }
 
@@ -112,6 +115,7 @@ namespace AlphaPseudo
         Tick when = curTick + NS2Ticks(delay);
         Tick repeat = NS2Ticks(period);
 
+        using namespace Statistics;
         SetupEvent(Dump|Reset, when, repeat);
     }
 
index 83ce7f9879e9f16f90bbb2a75929da9fd6898862..12bab975b5d881f16c14c30675a781d942b6f271 100644 (file)
@@ -31,7 +31,7 @@
 
 #include "base/hybrid_pred.hh"
 #include "base/statistics.hh"
-#include "sim/sim_stats.hh"
+#include "sim/stats.hh"
 
 using namespace std;
 
index 3fdab91534c9edc0bdd23ef4ef2917e9208c0e71..9063f3084afca4520e2c4e1d34888b05b512a893 100644 (file)
@@ -41,9 +41,7 @@
 #include <string>
 
 #include "base/sat_counter.hh"
-
 #include "base/statistics.hh"
-#include "sim/sim_stats.hh"
 
 class HybridPredictor : public GenericPredictor
 {
diff --git a/base/mysql.cc b/base/mysql.cc
new file mode 100644 (file)
index 0000000..8481e74
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2003-2004 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <iostream>
+
+#include "base/mysql.hh"
+
+using namespace std;
+
+namespace MySQL {
+
+inline const char *
+charstar(const string &string)
+{
+    return string.empty() ? NULL : string.c_str();
+}
+
+ostream &
+operator<<(ostream &stream, const Error &error)
+{
+    stream << error.string();
+    return stream;
+}
+
+/*
+ * The connection class
+ */
+Connection::Connection()
+    : valid(false)
+{
+}
+
+Connection::~Connection()
+{
+    if (valid)
+        close();
+}
+
+
+bool
+Connection::connect(const string &xhost, const string &xuser,
+                    const string &xpasswd, const string &xdatabase)
+{
+    if (connected())
+        return error.set("Already Connected");
+
+    _host = xhost;
+    _user = xuser;
+    _passwd = xpasswd;
+    _database = xdatabase;
+
+    error.clear();
+
+    mysql_init(&mysql);
+    mysql_options(&mysql, MYSQL_OPT_COMPRESS, 0); // might want to be 1
+    mysql_options(&mysql, MYSQL_READ_DEFAULT_GROUP, "odbc");
+    if (!mysql_real_connect(&mysql, charstar(_host), charstar(_user),
+                            charstar(_passwd), charstar(_database),
+                            0, NULL, 0))
+        return error.set(mysql_error(&mysql));
+
+    valid = true;
+    return false;
+}
+
+void
+Connection::close()
+{
+    mysql_close(&mysql);
+}
+
+/* namespace MySQL */ }
diff --git a/base/mysql.hh b/base/mysql.hh
new file mode 100644 (file)
index 0000000..89bec73
--- /dev/null
@@ -0,0 +1,410 @@
+/*
+ * Copyright (c) 2003-2004 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __BASE_MYQSL_HH__
+#define __BASE_MYQSL_HH__
+
+#define TO_BE_INCLUDED_LATER 0
+
+#include <cassert>
+#include <iosfwd>
+#include <mysql.h>
+#include <string>
+#include <sstream>
+
+namespace MySQL {
+
+class Error
+{
+  protected:
+    const char *error;
+
+  public:
+    Error() : error(NULL) {}
+
+    Error &clear() { error = NULL; return *this; }
+    Error &set(const char *err) { error = err; return *this; }
+
+    const char *string() const { return error; }
+
+    operator bool() const { return error != NULL; }
+    bool operator!() const { return error == NULL; }
+};
+
+std::ostream &operator<<(std::ostream &stream, const Error &error);
+
+class Result
+{
+  private:
+    MYSQL_RES *result;
+    int *refcount;
+
+    void
+    decref()
+    {
+        if (!refcount)
+            return;
+
+        *refcount -= 1;
+        if (*refcount == 0) {
+            mysql_free_result(result);
+            delete refcount;
+        }
+
+        refcount = NULL;
+    }
+
+  public:
+    Result()
+        : result(0), refcount(NULL)
+    { }
+
+    Result(MYSQL_RES *res)
+        : result(res)
+    {
+        if (result)
+            refcount = new int(1);
+    }
+
+    Result(const Result &result)
+        : result(result.result), refcount(result.refcount)
+    {
+        if (result)
+            *refcount += 1;
+    }
+
+    ~Result()
+    {
+        decref();
+    }
+
+    const Result &
+    operator=(MYSQL_RES *res)
+    {
+        decref();
+        result = res;
+        if (result)
+            refcount = new int(1);
+
+        return *this;
+    }
+
+    const Result &
+    operator=(const Result &res)
+    {
+        decref();
+        result = res.result;
+        refcount = res.refcount;
+        if (result)
+            *refcount += 1;
+
+        return *this;
+    }
+
+    operator bool() const { return result != NULL; }
+    bool operator!() const { return result == NULL; }
+
+    unsigned
+    num_fields()
+    {
+        assert(result);
+        return mysql_num_fields(result);
+    }
+
+    MYSQL_ROW
+    fetch_row()
+    {
+        return mysql_fetch_row(result);
+    }
+
+    unsigned long *
+    fetch_lengths()
+    {
+        return mysql_fetch_lengths(result);
+    }
+};
+
+typedef MYSQL_ROW Row;
+
+class Connection
+{
+  protected:
+    MYSQL mysql;
+    bool valid;
+
+  protected:
+    std::string _host;
+    std::string _user;
+    std::string _passwd;
+    std::string _database;
+
+  public:
+    Connection();
+    virtual ~Connection();
+
+    bool connected() const { return valid; }
+    bool connect(const std::string &host, const std::string &user,
+                 const std::string &passwd, const std::string &database);
+    void close();
+
+  public:
+    Error error;
+    operator MYSQL *() { return &mysql; }
+
+  public:
+    bool
+    query(const std::string &sql)
+    {
+        error.clear();
+        if (mysql_real_query(&mysql, sql.c_str(), sql.size()))
+            error.set(mysql_error(&mysql));
+
+        return error;
+    }
+
+    bool
+    query(const std::stringstream &sql)
+    {
+        return query(sql.str());
+    }
+
+    unsigned
+    field_count()
+    {
+        return mysql_field_count(&mysql);
+    }
+
+    unsigned
+    affected_rows()
+    {
+        return mysql_affected_rows(&mysql);
+    }
+
+    unsigned
+    insert_id()
+    {
+        return mysql_insert_id(&mysql);
+    }
+
+
+    Result
+    store_result()
+    {
+        error.clear();
+        Result result = mysql_store_result(&mysql);
+        if (!result)
+            error.set(mysql_error(&mysql));
+
+        return result;
+    }
+};
+
+#if 0
+class BindProxy
+{
+    MYSQL_BIND *bind;
+    BindProxy(MYSQL_BIND *b) : bind(b) {}
+
+    void operator=(bool &buffer)
+    {
+        bind->buffer_type = MYSQL_TYPE_TINY;
+        bind->buffer = (char *)&buffer;
+    }
+
+    void operator=(int8_t &buffer)
+    {
+        bind->buffer_type = MYSQL_TYPE_TINY;
+        bind->buffer = (char *)&buffer;
+    }
+
+    void operator=(int16_t &buffer)
+    {
+        bind->buffer_type = MYSQL_TYPE_SHORT;
+        bind->buffer = (char *)&buffer;
+    }
+
+    void operator=(int32_t &buffer)
+    {
+        bind->buffer_type = MYSQL_TYPE_LONG;
+        bind->buffer = (char *)&buffer;
+    }
+
+    void operator=(int64_t &buffer)
+    {
+        bind->buffer_type = MYSQL_TYPE_LONGLONG;
+        bind->buffer = (char *)&buffer;
+    }
+
+    void operator=(uint8_t &buffer)
+    {
+        bind->buffer_type = MYSQL_TYPE_TINY;
+        bind->buffer = (char *)&buffer;
+    }
+
+    void operator=(uint16_t &buffer)
+    {
+        bind->buffer_type = MYSQL_TYPE_SHORT;
+        bind->buffer = (char *)&buffer;
+    }
+
+    void operator=(uint32_t &buffer)
+    {
+        bind->buffer_type = MYSQL_TYPE_LONG;
+        bind->buffer = (char *)&buffer;
+    }
+
+    void operator=(uint64_t &buffer)
+    {
+        bind->buffer_type = MYSQL_TYPE_LONGLONG;
+        bind->buffer = (char *)&buffer;
+    }
+
+    void operator=(float &buffer)
+    {
+        bind->buffer_type = MYSQL_TYPE_FLOAT;
+        bind->buffer = (char *)&buffer;
+    }
+
+    void operator=(double &buffer)
+    {
+        bind->buffer_type = MYSQL_TYPE_DOUBLE;
+        bind->buffer = (char *)&buffer;
+    }
+
+    void operator=(Time &buffer)
+    {
+        bind->buffer_type = MYSQL_TYPE_DATE;
+        bind->buffer = (char *)&buffer;
+    }
+
+    void operator=(const char *buffer)
+    {
+        bind->buffer_type = MYSQL_TYPE_VAR_STRING;
+        bind->buffer = buffer;
+    }
+
+    void operator=(const std::string &buffer)
+    {
+        bind->buffer_type = MYSQL_TYPE_VAR_STRING;
+        bind->buffer = (char *)&buffer;
+        bind->length = buffer.length;
+    }
+
+    bool
+    set_null(bool null)
+    {
+        bind->is_null = null;
+    }
+};
+
+class Statement
+{
+  protected:
+    Error &error;
+    MYSQL_STMT *stmt;
+    MYSQL_BIND *bind;
+    int size;
+
+  public:
+    Statement(Connection &mysql)
+        : error(mysql.error), bind(NULL), size(0)
+    {
+        stmt = mysql_stmt_init(mysql);
+        assert(valid() && "mysql_stmt_init(), out of memory\n");
+    }
+
+    ~Statement()
+    {
+        assert(valid());
+        error.clear();
+        if (mysql_stmt_close(stmt))
+            error.set(mysql_stmt_error(stmt));
+
+        if (bind)
+            delete [] bind;
+    }
+
+    bool valid()
+    {
+        return stmt != NULL;
+    }
+
+    void prepare(const std::string &query)
+    {
+        assert(valid());
+        mysql.error.clear();
+        if (mysql_stmt_prepare(mysql, query, strlen(query)))
+            mysql.error.set(mysql_stmt_error(stmt));
+
+        int size = count();
+        bind = new MYSQL_BIND[size];
+    }
+
+    unsigned count()
+    {
+        assert(valid());
+        return mysql_stmt_param_count(stmt);
+    }
+
+    unsigned affected()
+    {
+        assert(valid());
+        return mysql_stmt_affected_rows(stmt);
+    }
+
+    void bind(MYSQL_BIND *bind)
+    {
+        mysql.error.clear();
+        if (mysql_stmt_bind_param(stmt, bind))
+            mysql.error.set(mysql_stmt_error(stmt));
+    }
+
+    BindProxy operator[](int index)
+    {
+        assert(index > 0 && index < N);
+        return &bind[N];
+    }
+
+    operator MYSQL_BIND *()
+    {
+        return bind;
+    }
+
+    void operator()()
+    {
+        assert(valid());
+        error.clear();
+        if (mysql_stmt_execute(stmt))
+            error.set(mysql_stmt_error(stmt));
+    }
+}
+#endif
+
+/* namespace MySQL */ }
+
+#endif // __BASE_MYQSL_HH__
index c26690a1a9b57db5e2edcc5f262779193603a864..a8367d8a0cb398d9e6eb5be36451a9f9185bbf36 100644 (file)
@@ -29,9 +29,8 @@
 #include <sstream>
 
 #include "base/sat_counter.hh"
-
 #include "base/statistics.hh"
-#include "sim/sim_stats.hh"
+#include "sim/stats.hh"
 
 
 using namespace std;
index 62c18f6b45338e839d59163e989fb757bade8f0c..a5d9c7e8aa11288e1b4cbba935532807eba961ce 100644 (file)
@@ -34,7 +34,7 @@
 #include "base/predictor.hh"
 
 #include "base/statistics.hh"
-#include "sim/sim_stats.hh"
+#include "sim/stats.hh"
 
 //
 //
index dce545f18a89e8700a7bdfe479210dc625ff0722..1a44cd34264f22b1a1b5b27364b33f1e930e2332 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * Copyright (c) 2003-2004 The Regents of The University of Michigan
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
 #include "base/str.hh"
 #include "base/time.hh"
 #include "base/trace.hh"
-
-#ifdef __M5_NAN
-float
-__nan()
-{
-    union {
-        uint32_t ui;
-        float f;
-    } nan;
-
-    nan.ui = 0x7fc00000;
-    return nan.f;
-}
-#endif
-
-#ifdef DEBUG
-static int total_stats = 0;
-#endif
+#include "base/stats/statdb.hh"
 
 using namespace std;
 
-// This is a hack to get this parameter from the old stats package.
 namespace Statistics {
-bool PrintDescriptions = true;
-DisplayMode DefaultMode = mode_simplescalar;
-
-namespace Database
-{
-    class Data
-    {
-      private:
-        typedef list<StatData *> list_t;
-        typedef map<void *, StatData *> map_t;
-
-        list<MainBin *> bins;
-
-        list_t allStats;
-        list_t printStats;
-        map_t statMap;
-
-        ofstream *stream;
-        Python *py;
-
-      public:
-        Data();
-        ~Data();
-
-        void dump(ostream &stream, DisplayMode mode);
-        void display(ostream &stream, DisplayMode mode);
-        void python_start(const string &file);
-        void python_dump(const string &name, const string &subname);
-        void python(const string &name, const string &subname,
-                    const string &bin);
-
-        StatData *find(void *stat);
-        void mapStat(void *stat, StatData *data);
-
-        void check();
-        void reset();
-        void regBin(MainBin *bin, string name);
-        void regPrint(void *stat);
-
-        static std::string name() { return "Statistics Database"; }
-    };
-
-Data::Data()
-    : stream(0), py(0)
-{
-}
-
-Data::~Data()
-{
-    if (stream) {
-        delete py;
-        ccprintf(*stream, "\n\nif __name__ == '__main__':\n");
-        ccprintf(*stream, "    program_display()\n");
-        stream->close();
-        delete stream;
-    }
-}
-
-void
-Data::dump(ostream &stream, DisplayMode mode)
-{
-    MainBin *orig = MainBin::curBin();
-
-    switch (mode) {
-      case mode_m5:
-      case mode_simplescalar:
-        display(stream, mode);
-        break;
-      default:
-        warn("invalid display mode!\n");
-        display(stream, mode_m5);
-        break;
-    }
-
-    if (orig)
-        orig->activate();
-}
-
-void
-Data::display(ostream &stream, DisplayMode mode)
-{
-    if (!bins.empty()) {
-        list<MainBin *>::iterator i = bins.begin();
-        list<MainBin *>::iterator bins_end = bins.end();
-        ccprintf(stream, "PRINTING BINNED STATS\n");
-        while (i != bins_end) {
-            (*i)->activate();
-            ccprintf(stream,"---%s Bin------------\n", (*i)->name());
-
-            list_t::iterator j = printStats.begin();
-            list_t::iterator end = printStats.end();
-            while (j != end) {
-                StatData *stat = *j;
-                if (stat->dodisplay())
-                    stat->display(stream, mode);
-                ++j;
-            }
-            ++i;
-            ccprintf(stream, "---------------------------------\n");
-        }
-    } else {
-        list_t::iterator i = printStats.begin();
-        list_t::iterator end = printStats.end();
-        while (i != end) {
-            StatData *stat = *i;
-            if (stat->dodisplay() && !stat->binned())
-                stat->display(stream, mode);
-            ++i;
-        }
-    }
-}
-
-void
-Data::python_start(const string &file)
-{
-    if (stream)
-        panic("can't start python twice!");
-
-    stream = new ofstream(file.c_str(), ios::trunc);
-    py = new Python(*stream);
-
-    ccprintf(*stream, "import sys\n");
-    ccprintf(*stream, "sys.path.append('.')\n");
-    ccprintf(*stream, "from m5stats import *\n\n");
-}
-
-void
-Data::python_dump(const string &name, const string &subname)
-{
-    if (!py)
-        panic("Can't dump python without first opening the file");
-
-    if (bins.empty()) {
-        python(name, subname, "");
-    } else {
-        list<MainBin *>::iterator i = bins.begin();
-        list<MainBin *>::iterator end = bins.end();
-
-        while (i != end) {
-            (*i)->activate();
-            python(name, subname, (*i)->name());
-            ++i;
-        }
-    }
-}
-
-void
-Data::python(const string &name, const string &subname, const string &bin)
-{
-    py->name("collections.append");
-    py->newline();
-    py->name("Collection");
-    py->newline();
-    py->qarg(name);
-    py->newline();
-    py->qarg(subname);
-    py->newline();
-    py->qarg(bin);
-    py->newline();
-    py->qarg(hostname());
-    py->newline();
-    py->qarg(Time::start.date());
-    py->newline();
-    py->list();
-    list_t::iterator i = allStats.begin();
-    list_t::iterator end = allStats.end();
-    while (i != end) {
-        StatData *stat = *i;
-        py->newline();
-        stat->python(*py);
-        ++i;
-    }
-    py->newline();
-    py->listEnd();
-    py->newline();
-    py->nameEnd();
-    py->newline();
-    py->nameEnd();
-    py->newline();
-}
-
-StatData *
-Data::find(void *stat)
-{
-    map_t::const_iterator i = statMap.find(stat);
-
-    if (i == statMap.end())
-        return NULL;
-
-    return (*i).second;
-}
-
-void
-Data::check()
-{
-    list_t::iterator i = allStats.begin();
-    list_t::iterator end = allStats.end();
-
-    while (i != end) {
-        StatData *data = *i;
-        assert(data);
-        data->check();
-        ++i;
-    }
-
-    i = allStats.begin();
-    int j = 0;
-    while (i != end) {
-        StatData *data = *i;
-        if (!(data->flags & print))
-            data->name = "__Stat" + to_string(j++);
-        ++i;
-    }
-}
-
-void
-Data::reset()
-{
-    // reset non-binned stats
-    list_t::iterator i = allStats.begin();
-    list_t::iterator end = allStats.end();
-    while (i != end) {
-        StatData *data = *i;
-        if (!data->binned())
-            data->reset();
-        ++i;
-    }
-
-    // save the bin so we can go back to where we were
-    MainBin *orig = MainBin::curBin();
-
-    // reset binned stats
-    list<MainBin *>::iterator bi = bins.begin();
-    list<MainBin *>::iterator be = bins.end();
-    while (bi != be) {
-        MainBin *bin = *bi;
-        bin->activate();
-
-        i = allStats.begin();
-        while (i != end) {
-            StatData *data = *i;
-            if (data->binned())
-                data->reset();
-            ++i;
-        }
-        ++bi;
-    }
-
-    // restore bin
-    MainBin::curBin() = orig;
-}
-
-void
-Data::mapStat(void *stat, StatData *data)
-{
-    if (statMap.find(stat) != statMap.end())
-        panic("shouldn't register stat twice!");
-
-    allStats.push_back(data);
-
-#ifndef NDEBUG
-    bool success =
-#endif
-        (statMap.insert(make_pair(stat, data))).second;
-    assert(statMap.find(stat) != statMap.end());
-    assert(success && "this should never fail");
-}
-
-void
-Data::regBin(MainBin *bin, string _name)
-{
-    bins.push_back(bin);
-    DPRINTF(Stats, "registering %s\n", _name);
-}
-
-void
-Data::regPrint(void *stat)
-{
-    StatData *data = find(stat);
-
-    if (data->flags & print)
-        return;
-
-    data->flags |= print;
-
-    list_t::iterator j = printStats.insert(printStats.end(), data);
-    inplace_merge(printStats.begin(), j, printStats.end(), StatData::less);
-}
-
-Data &
-StatDB()
-{
-    static Data db;
-    return db;
-}
-
-}
 
 StatData *
 DataAccess::find() const
 {
-    return Database::StatDB().find(const_cast<void *>((const void *)this));
+    return Database::find(const_cast<void *>((const void *)this));
 }
 
 const StatData *
 getStatData(const void *stat)
 {
-    return Database::StatDB().find(const_cast<void *>(stat));
+    return Database::find(const_cast<void *>(stat));
 }
 
 void
 DataAccess::map(StatData *data)
 {
-    Database::StatDB().mapStat(this, data);
+    Database::regStat(this, data);
 }
 
 StatData *
@@ -406,15 +91,14 @@ DataAccess::setInit()
 void
 DataAccess::setPrint()
 {
-    Database::StatDB().regPrint(this);
+    Database::regPrint(this);
 }
 
 StatData::StatData()
     : flags(none), precision(-1), prereq(0)
 {
-#ifdef DEBUG
-    number = total_stats++;
-#endif
+    static int count = 0;
+    id = count++;
 }
 
 StatData::~StatData()
@@ -452,7 +136,7 @@ StatData::baseCheck() const
 {
     if (!(flags & init)) {
 #ifdef DEBUG
-        cprintf("this is stat number %d\n", number);
+        cprintf("this is stat number %d\n", id);
 #endif
         panic("Not all stats have been initialized");
         return false;
@@ -466,719 +150,15 @@ StatData::baseCheck() const
     return true;
 }
 
-string
-ValueToString(result_t value, DisplayMode mode, int precision)
-{
-    stringstream val;
-
-    if (!isnan(value)) {
-        if (precision != -1)
-            val.precision(precision);
-        else if (value == rint(value))
-            val.precision(0);
-
-        val.unsetf(ios::showpoint);
-        val.setf(ios::fixed);
-        val << value;
-    } else {
-        val << (mode == mode_m5 ? "no value" : "<err: div-0>");
-    }
-
-    return val.str();
-}
-
-struct ScalarPrint
-{
-    result_t value;
-    string name;
-    string desc;
-    StatFlags flags;
-    DisplayMode mode;
-    int precision;
-    result_t pdf;
-    result_t cdf;
-
-    ScalarPrint()
-        : value(0.0), flags(0), mode(DefaultMode), precision(0),
-          pdf(NAN), cdf(NAN)
-    {}
-
-    void operator()(ostream &stream) const;
-};
-
-void
-ScalarPrint::operator()(ostream &stream) const
-{
-    if (flags & nozero && value == 0.0 ||
-        flags & nonan && isnan(value))
-        return;
-
-    stringstream pdfstr, cdfstr;
-
-    if (!isnan(pdf))
-        ccprintf(pdfstr, "%.2f%%", pdf * 100.0);
-
-    if (!isnan(cdf))
-        ccprintf(cdfstr, "%.2f%%", cdf * 100.0);
-
-    if (mode == mode_simplescalar && flags & __substat) {
-        ccprintf(stream, "%32s %12s %10s %10s", name,
-                 ValueToString(value, mode, precision), pdfstr, cdfstr);
-    } else {
-        ccprintf(stream, "%-40s %12s %10s %10s", name,
-                 ValueToString(value, mode, precision), pdfstr, cdfstr);
-    }
-
-    if (PrintDescriptions) {
-        if (!desc.empty())
-            ccprintf(stream, " # %s", desc);
-    }
-    stream << endl;
-}
-
-struct VectorPrint
-{
-    string name;
-    string desc;
-    vector<string> subnames;
-    vector<string> subdescs;
-    StatFlags flags;
-    DisplayMode mode;
-    int precision;
-    rvec_t vec;
-    result_t total;
-
-    VectorPrint()
-        : subnames(0), subdescs(0), flags(0), mode(DefaultMode),
-          precision(-1), total(NAN)
-    {}
-
-    void operator()(ostream &stream) const;
-};
-
-void
-VectorPrint::operator()(std::ostream &stream) const
-{
-    int _size = vec.size();
-    result_t _total = 0.0;
-
-    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) {
-        print.value = vec[0];
-        print(stream);
-    } else if (mode == mode_m5) {
-        for (int i = 0; i < _size; ++i) {
-            if (havesub && (i >= subnames.size() || subnames[i].empty()))
-                continue;
-
-            print.name = base + (havesub ? subnames[i] : to_string(i));
-            print.desc = subdescs.empty() ? desc : subdescs[i];
-            print.value = vec[i];
-
-            if (_total && (flags & pdf)) {
-                print.pdf = vec[i] / _total;
-                print.cdf += print.pdf;
-            }
-
-            print(stream);
-        }
-
-        if (flags & ::Statistics::total) {
-            print.name = base + "total";
-            print.desc = desc;
-            print.value = total;
-            print(stream);
-        }
-    } else {
-        if (flags & ::Statistics::total) {
-            print.value = total;
-            print(stream);
-        }
-
-        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) {
-                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", name);
-        } else {
-            for (int i = 0; i < _size; ++i) {
-                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 {
-                    _pdf = _cdf = NAN;
-                }
-
-                if (flags & pdf) {
-                    print.pdf = _pdf;
-                    print.cdf = _cdf;
-                }
-
-                print(stream);
-            }
-        }
-    }
-}
-
-struct DistPrint
-{
-    string name;
-    string desc;
-    StatFlags flags;
-    DisplayMode mode;
-    int precision;
-
-    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
-DistPrint::operator()(ostream &stream) const
-{
-    if (fancy) {
-        ScalarPrint print;
-        string base = name + ((mode == mode_m5) ? "::" : "_");
-
-        print.precision = precision;
-        print.flags = flags;
-        print.mode = mode;
-        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;
-
-    total += underflow;
-    for (int i = 0; i < size; ++i)
-        total += vec[i];
-    total += overflow;
-
-    string base = name + (mode == mode_m5 ? "::" : ".");
-
-    ScalarPrint print;
-    print.desc = (mode == mode_m5) ? desc : "";
-    print.flags = flags;
-    print.mode = mode;
-    print.precision = precision;
-
-    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 (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;
-        } else {
-            print.pdf = NAN;
-            print.cdf = NAN;
-        }
-        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);
-    }
-
-    if (mode == mode_simplescalar)
-        ccprintf(stream, "%send_dist\n\n", base);
-}
 
 void
-ScalarDataBase::display(ostream &stream, DisplayMode mode) const
-{
-    ScalarPrint print;
-    print.value = val();
-    print.name = name;
-    print.desc = desc;
-    print.flags = flags;
-    print.mode = mode;
-    print.precision = precision;
-
-    print(stream);
-}
-
-void
-VectorDataBase::display(ostream &stream, DisplayMode mode) const
-{
-    int size = this->size();
-    const_cast<VectorDataBase *>(this)->update();
-
-    VectorPrint print;
-
-    print.name = name;
-    print.desc = desc;
-    print.flags = flags;
-    print.mode = mode;
-    print.precision = precision;
-    print.vec = val();
-    print.total = total();
-
-    if (!subnames.empty()) {
-        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;
-            }
-        }
-    }
-
-    print(stream);
-}
-
-void
-Vector2dDataBase::display(ostream &stream, DisplayMode mode) const
-{
-    const_cast<Vector2dDataBase *>(this)->update();
-
-    bool havesub = false;
-    VectorPrint print;
-
-    print.subnames = y_subnames;
-    print.flags = flags;
-    print.mode = mode;
-    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;
-
-        int iy = i * y;
-        rvec_t yvec(y);
-
-        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];
-        }
-
-        print.name = name + "_" + (havesub ? subnames[i] : to_string(i));
-        print.desc = desc;
-        print.vec = yvec;
-        print.total = total;
-        print(stream);
-    }
-
-    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, DisplayMode mode) const
-{
-    const_cast<DistDataBase *>(this)->update();
-
-    DistPrint print;
-
-    print.name = name;
-    print.desc = desc;
-    print.flags = flags;
-    print.mode = mode;
-    print.precision = precision;
-
-    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, DisplayMode mode) 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.flags = flags;
-        print.mode = mode;
-        print.precision = precision;
-
-        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
-ScalarDataBase::python(Python &py) const
-{
-    py.name("Scalar");
-    py.qarg(name);
-    py.qqqarg(desc);
-    py.kwarg("binned", binned());
-    py.kwarg("precision", precision);
-    py.kwarg("flags", flags);
-    if (prereq)
-        py.qkwarg("prereq", prereq->name);
-    py.kwarg("value", val());
-    py.nameEnd();
-}
-
-void
-VectorDataBase::python(Python &py) const
-{
-    const_cast<VectorDataBase *>(this)->update();
-
-    py.name("Vector");
-    py.qarg(name);
-    py.qqqarg(desc);
-    py.kwarg("binned", binned());
-    py.kwarg("precision", precision);
-    py.kwarg("flags", flags);
-    if (prereq)
-        py.qkwarg("prereq", prereq->name);
-    py.kwarg("value", val());
-    if (!subnames.empty())
-        py.qkwarg("subnames", subnames);
-    if (!subdescs.empty())
-        py.qkwarg("subdescs", subdescs);
-    py.nameEnd();
-}
-
-void
-DistDataData::python(Python &py, const string &name) const
-{
-    string s = name.empty() ? "" : name + "=";
-
-    if (samples == 0 || fancy)
-        s += "SimpleDist";
-    else
-        s += "FullDist";
-
-    py.name(s);
-    py.arg(sum);
-    py.arg(squares);
-    py.arg(samples);
-    if (samples && !fancy) {
-        py.arg(min_val);
-        py.arg(min_val);
-        py.arg(underflow);
-        py.arg(vec);
-        py.arg(overflow);
-        py.arg(min);
-        py.arg(max);
-        py.arg(bucket_size);
-        py.arg(size);
-    }
-    py.nameEnd();
-}
-
-void
-FormulaDataBase::python(Python &py) const
-{
-    const_cast<FormulaDataBase *>(this)->update();
-
-    py.name("Formula");
-    py.qarg(name);
-    py.qqqarg(desc);
-    py.kwarg("binned", binned());
-    py.kwarg("precision", precision);
-    py.kwarg("flags", flags);
-    if (prereq)
-        py.qkwarg("prereq", prereq->name);
-    py.qkwarg("formula", str());
-    if (!subnames.empty())
-        py.qkwarg("subnames", subnames);
-    if (!subdescs.empty())
-        py.qkwarg("subdescs", subdescs);
-    py.nameEnd();
-}
-
-void
-DistDataBase::python(Python &py) const
-{
-    const_cast<DistDataBase *>(this)->update();
-
-    py.name("Dist");
-    py.qarg(name);
-    py.qqqarg(desc);
-    py.kwarg("binned", binned());
-    py.kwarg("precision", precision);
-    py.kwarg("flags", flags);
-    if (prereq)
-        py.qkwarg("prereq", prereq->name);
-    data.python(py, "dist");
-    py.nameEnd();
-}
-
-void
-VectorDistDataBase::python(Python &py) const
-{
-    const_cast<VectorDistDataBase *>(this)->update();
-
-    py.name("VectorDist");
-    py.qarg(name);
-    py.qqqarg(desc);
-    py.kwarg("binned", binned());
-    py.kwarg("precision", precision);
-    py.kwarg("flags", flags);
-    if (prereq)
-        py.qkwarg("prereq", prereq->name);
-    if (!subnames.empty())
-        py.qkwarg("subnames", subnames);
-    if (!subdescs.empty())
-        py.qkwarg("subdescs", subdescs);
-
-    py.tuple("dist");
-    typedef std::vector<DistDataData>::const_iterator iter;
-    iter i = data.begin();
-    iter end = data.end();
-    while (i != end) {
-        i->python(py, "");
-        ++i;
-    }
-    py.tupleEnd();
-    py.nameEnd();
-}
-
-void
-Vector2dDataBase::python(Python &py) const
-{
-    const_cast<Vector2dDataBase *>(this)->update();
-
-    py.name("Vector2d");
-    py.qarg(name);
-    py.qqqarg(desc);
-    py.kwarg("binned", binned());
-    py.kwarg("precision", precision);
-    py.kwarg("flags", flags);
-    if (prereq)
-        py.qkwarg("prereq", prereq->name);
-
-    py.kwarg("value", vec);
-    if (!subnames.empty())
-        py.qkwarg("subnames", subnames);
-    if (!subdescs.empty())
-        py.qkwarg("subdescs", subdescs);
-    if (!y_subnames.empty())
-        py.qkwarg("ysubnames", y_subnames);
-
-    py.kwarg("x", x);
-    py.kwarg("y", y);
-    py.nameEnd();
-}
-
-void
-FormulaBase::val(rvec_t &vec) const
+FormulaBase::result(VResult &vec) const
 {
     if (root)
-        vec = root->val();
+        vec = root->result();
 }
 
-result_t
+Result
 FormulaBase::total() const
 {
     return root ? root->total() : 0.0;
@@ -1207,8 +187,8 @@ FormulaBase::reset()
 bool
 FormulaBase::zero() const
 {
-    rvec_t vec;
-    val(vec);
+    VResult vec;
+    result(vec);
     for (int i = 0; i < vec.size(); ++i)
         if (vec[i] != 0.0)
             return false;
@@ -1250,7 +230,7 @@ const Formula &
 Formula::operator+=(Temp r)
 {
     if (root)
-        root = NodePtr(new BinaryNode<std::plus<result_t> >(root, r));
+        root = NodePtr(new BinaryNode<std::plus<Result> >(root, r));
     else
         root = r;
     assert(size());
@@ -1260,7 +240,7 @@ Formula::operator+=(Temp r)
 MainBin::MainBin(const string &name)
     : _name(name), mem(NULL), memsize(-1)
 {
-    Database::StatDB().regBin(this, name);
+    Database::regBin(this, name);
 }
 
 MainBin::~MainBin()
@@ -1287,41 +267,83 @@ MainBin::memory(off_t off)
 void
 check()
 {
-    Database::StatDB().check();
-}
+    typedef Database::stat_list_t::iterator iter_t;
 
-void
-dump(ostream &stream, DisplayMode mode)
-{
-    Database::StatDB().dump(stream, mode);
-}
+    iter_t i, end = Database::stats().end();
+    for (i = Database::stats().begin(); i != end; ++i) {
+        StatData *data = *i;
+        assert(data);
+        data->check();
+    }
 
-void
-python_start(const string &file)
-{
-    Database::StatDB().python_start(file);
-}
+    int j = 0;
+    for (i = Database::stats().begin(); i != end; ++i) {
+        StatData *data = *i;
+        if (!(data->flags & print))
+            data->name = "__Stat" + to_string(j++);
+    }
 
-void
-python_dump(const string &name, const string &subname)
-{
-    Database::StatDB().python_dump(name, subname);
-}
+    Database::stats().sort(StatData::less);
+
+    if (i == end)
+        return;
+
+    iter_t last = i;
+    ++i;
+
+    for (i = Database::stats().begin(); i != end; ++i) {
+        if ((*i)->name == (*last)->name)
+            panic("same name used twice! name=%s\n", (*i)->name);
 
+        last = i;
+    }
+}
 
 CallbackQueue resetQueue;
 
 void
-registerResetCallback(Callback *cb)
+reset()
 {
-    resetQueue.add(cb);
+    // reset non-binned stats
+    Database::stat_list_t::iterator i = Database::stats().begin();
+    Database::stat_list_t::iterator end = Database::stats().end();
+    while (i != end) {
+        StatData *data = *i;
+        if (!data->binned())
+            data->reset();
+        ++i;
+    }
+
+    // save the bin so we can go back to where we were
+    MainBin *orig = MainBin::curBin();
+
+    // reset binned stats
+    Database::bin_list_t::iterator bi = Database::bins().begin();
+    Database::bin_list_t::iterator be = Database::bins().end();
+    while (bi != be) {
+        MainBin *bin = *bi;
+        bin->activate();
+
+        i = Database::stats().begin();
+        while (i != end) {
+            StatData *data = *i;
+            if (data->binned())
+                data->reset();
+            ++i;
+        }
+        ++bi;
+    }
+
+    // restore bin
+    MainBin::curBin() = orig;
+
+    resetQueue.process();
 }
 
 void
-reset()
+registerResetCallback(Callback *cb)
 {
-    Database::StatDB().reset();
-    resetQueue.process();
+    resetQueue.add(cb);
 }
 
-} // namespace Statistics
+/* namespace Statistics */ }
index 0dad31a5a9cb69a86d1b4558a36755c39840b42f..e7fc18d74ecf2b1034094388fb2863586164ddc9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * Copyright (c) 2003-2004 The Regents of The University of Michigan
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -42,8 +42,8 @@
 * VectorStandardDeviation totals
 * Document Namespaces
 */
-#ifndef __STATISTICS_HH__
-#define __STATISTICS_HH__
+#ifndef __BASE_STATISTICS_HH__
+#define __BASE_STATISTICS_HH__
 
 #include <algorithm>
 #include <cassert>
 #include "base/intmath.hh"
 #include "base/refcnt.hh"
 #include "base/str.hh"
+#include "base/stats/bin.hh"
+#include "base/stats/flags.hh"
+#include "base/stats/visit.hh"
+#include "base/stats/types.hh"
 #include "sim/host.hh"
 
-#ifndef NAN
-float __nan();
-/** Define Not a number. */
-#define NAN (__nan())
-/** Need to define __nan() */
-#define __M5_NAN
-#endif
-
 class Callback;
-class Python;
 
 /** The current simulated cycle. */
 extern Tick curTick;
 
 /* A namespace for all of the Statistics */
 namespace Statistics {
-/** All results are doubles. */
-typedef double result_t;
-/** A vector to hold results. */
-typedef std::vector<result_t> rvec_t;
-
-/**
- * Define the storage for format flags.
- * @todo Can probably shrink this.
- */
-typedef u_int32_t StatFlags;
-
-/** Nothing extra to print. */
-const StatFlags none =         0x00000000;
-/** This Stat is Initialized */
-const StatFlags init =         0x00000001;
-/** Print this stat. */
-const StatFlags print =                0x00000002;
-/** Print the total. */
-const StatFlags total =                0x00000010;
-/** Print the percent of the total that this entry represents. */
-const StatFlags pdf =          0x00000020;
-/** Print the cumulative percentage of total upto this entry. */
-const StatFlags cdf =          0x00000040;
-/** Print the distribution. */
-const StatFlags dist =                 0x00000080;
-/** Don't print if this is zero. */
-const StatFlags nozero =       0x00000100;
-/** Don't print if this is NAN */
-const StatFlags nonan =                0x00000200;
-/** Used for SS compatability. */
-const StatFlags __substat =    0x80000000;
-
-/** Mask of flags that can't be set directly */
-const StatFlags __reserved =   init | print | __substat;
-
-enum DisplayMode
-{
-    mode_m5,
-    mode_simplescalar
-};
-
-extern DisplayMode DefaultMode;
 
 /* Contains the statistic implementation details */
 //////////////////////////////////////////////////////////////////////
@@ -135,10 +88,13 @@ struct StatData
     StatFlags flags;
     /** The display precision. */
     int precision;
-
-
     /** A pointer to a prerequisite Stat. */
     const StatData *prereq;
+    /**
+     * A unique stat ID for each stat in the simulator.
+     * Can be used externally for lookups as well as for debugging.
+     */
+    int id;
 
     StatData();
     virtual ~StatData();
@@ -148,14 +104,6 @@ struct StatData
      */
     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, DisplayMode mode) const = 0;
-    virtual void python(Python &py) const = 0;
-    bool dodisplay() const { return !prereq || !prereq->zero(); }
-
     /**
      * Reset the corresponding stat to the default state.
      */
@@ -175,6 +123,11 @@ struct StatData
     virtual bool check() const = 0;
     bool baseCheck() const;
 
+    /**
+     * Visitor entry for outputing statistics data
+     */
+    virtual void visit(Visit &visitor) = 0;
+
     /**
      * Checks if the first stat's name is alphabetically less than the second.
      * This function breaks names up at periods and considers each subname
@@ -184,51 +137,46 @@ struct StatData
      * @return stat1's name is alphabetically before stat2's
      */
     static bool less(StatData *stat1, StatData *stat2);
-
-#ifdef DEBUG
-    int number;
-#endif
 };
 
-struct ScalarDataBase : public StatData
+struct ScalarData : public StatData
 {
-    virtual result_t val() const = 0;
-    virtual result_t total() const = 0;
-
-    virtual void display(std::ostream &stream, DisplayMode mode) const;
-    virtual void python(Python &py) const;
+    virtual Counter value() const = 0;
+    virtual Result result() const = 0;
+    virtual Result total() const = 0;
 };
 
-template <class T>
-class ScalarData : public ScalarDataBase
+template <class Stat>
+class ScalarStatData : public ScalarData
 {
   protected:
-    T &s;
+    Stat &s;
 
   public:
-    ScalarData(T &stat) : s(stat) {}
+    ScalarStatData(Stat &stat) : s(stat) {}
 
     virtual bool binned() const { return s.binned(); }
     virtual bool check() const { return s.check(); }
-    virtual result_t val() const { return s.val(); }
-    virtual result_t total() const { return s.total(); }
+    virtual Counter value() const { return s.value(); }
+    virtual Result result() const { return s.result(); }
+    virtual Result total() const { return s.total(); }
     virtual void reset() { s.reset(); }
     virtual bool zero() const { return s.zero(); }
+
+    virtual void visit(Visit &visitor) { visitor.visit(*this); }
 };
 
-struct VectorDataBase : public StatData
+struct VectorData : 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, DisplayMode mode) const;
-    virtual void python(Python &py) const;
-
     virtual size_t size() const  = 0;
-    virtual const rvec_t &val() const  = 0;
-    virtual result_t total() const  = 0;
-    virtual void update()
+    virtual const VCounter &value() const = 0;
+    virtual const VResult &result() const = 0;
+    virtual Result total() const  = 0;
+    void update()
     {
         if (!subnames.empty()) {
             int s = size();
@@ -241,15 +189,16 @@ struct VectorDataBase : public StatData
     }
 };
 
-template <class T>
-class VectorData : public VectorDataBase
+template <class Stat>
+class VectorStatData : public VectorData
 {
   protected:
-    T &s;
-    mutable rvec_t vec;
+    Stat &s;
+    mutable VCounter cvec;
+    mutable VResult rvec;
 
   public:
-    VectorData(T &stat) : s(stat) {}
+    VectorStatData(Stat &stat) : s(stat) {}
 
     virtual bool binned() const { return s.binned(); }
     virtual bool check() const { return s.check(); }
@@ -257,66 +206,70 @@ class VectorData : public VectorDataBase
     virtual void reset() { s.reset(); }
 
     virtual size_t size() const { return s.size(); }
-    virtual const rvec_t &val() const
+    virtual VCounter &value() const
     {
-        s.val(vec);
-        return vec;
+        s.value(cvec);
+        return cvec;
+    }
+    virtual const VResult &result() const
+    {
+        s.result(rvec);
+        return rvec;
     }
-    virtual result_t total() const { return s.total(); }
-    virtual void update()
+    virtual Result total() const { return s.total(); }
+    virtual void visit(Visit &visitor)
     {
-        VectorDataBase::update();
+        update();
         s.update(this);
+        visitor.visit(*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;
+    Counter min_val;
+    Counter max_val;
+    Counter underflow;
+    Counter overflow;
+    VCounter cvec;
+    Counter sum;
+    Counter squares;
+    Counter samples;
+
+    Counter min;
+    Counter max;
+    Counter bucket_size;
     int size;
     bool fancy;
-
-    void python(Python &py, const std::string &name) const;
 };
 
-struct DistDataBase : public StatData
+struct DistData : public StatData
 {
     /** Local storage for the entry values, used for printing. */
     DistDataData data;
-
-    virtual void display(std::ostream &stream, DisplayMode mode) const;
-    virtual void python(Python &py) const;
-    virtual void update() = 0;
 };
 
-template <class T>
-class DistData : public DistDataBase
+template <class Stat>
+class DistStatData : public DistData
 {
   protected:
-    T &s;
+    Stat &s;
 
   public:
-    DistData(T &stat) : s(stat) {}
+    DistStatData(Stat &stat) : s(stat) {}
 
     virtual bool binned() const { return s.binned(); }
     virtual bool check() const { return s.check(); }
     virtual void reset() { s.reset(); }
     virtual bool zero() const { return s.zero(); }
-    virtual void update() { return s.update(this); }
+    virtual void visit(Visit &visitor)
+    {
+        s.update(this);
+        visitor.visit(*this);
+    }
 };
 
-struct VectorDistDataBase : public StatData
+struct VectorDistData : public StatData
 {
     std::vector<DistDataData> data;
 
@@ -325,12 +278,10 @@ struct VectorDistDataBase : public StatData
     mutable std::vector<std::string> subdescs;
 
     /** Local storage for the entry values, used for printing. */
-    mutable rvec_t vec;
+    mutable VResult rvec;
 
     virtual size_t size() const = 0;
-    virtual void display(std::ostream &stream, DisplayMode mode) const;
-    virtual void python(Python &py) const;
-    virtual void update()
+    void update()
     {
         int s = size();
         if (subnames.size() < s)
@@ -341,29 +292,30 @@ struct VectorDistDataBase : public StatData
     }
 };
 
-template <class T>
-class VectorDistData : public VectorDistDataBase
+template <class Stat>
+class VectorDistStatData : public VectorDistData
 {
   protected:
-    T &s;
-    typedef typename T::bin_t bin_t;
+    Stat &s;
+    typedef typename Stat::bin_t bin_t;
 
   public:
-    VectorDistData(T &stat) : s(stat) {}
+    VectorDistStatData(Stat &stat) : s(stat) {}
 
     virtual bool binned() const { return bin_t::binned; }
     virtual bool check() const { return s.check(); }
     virtual void reset() { s.reset(); }
     virtual size_t size() const { return s.size(); }
     virtual bool zero() const { return s.zero(); }
-    virtual void update()
+    virtual void visit(Visit &visitor)
     {
-        VectorDistDataBase::update();
-        return s.update(this);
+        update();
+        s.update(this);
+        visitor.visit(*this);
     }
 };
 
-struct Vector2dDataBase : public StatData
+struct Vector2dData : public StatData
 {
     /** Names and descriptions of subfields. */
     std::vector<std::string> subnames;
@@ -371,37 +323,36 @@ struct Vector2dDataBase : public StatData
     std::vector<std::string> y_subnames;
 
     /** Local storage for the entry values, used for printing. */
-    mutable rvec_t vec;
+    mutable VCounter cvec;
     mutable int x;
     mutable int y;
 
-    virtual void display(std::ostream &stream, DisplayMode mode) const;
-    virtual void python(Python &py) const;
-    virtual void update()
+    void update()
     {
         if (subnames.size() < x)
             subnames.resize(x);
     }
 };
 
-template <class T>
-class Vector2dData : public Vector2dDataBase
+template <class Stat>
+class Vector2dStatData : public Vector2dData
 {
   protected:
-    T &s;
-    typedef typename T::bin_t bin_t;
+    Stat &s;
+    typedef typename Stat::bin_t bin_t;
 
   public:
-    Vector2dData(T &stat) : s(stat) {}
+    Vector2dStatData(Stat &stat) : s(stat) {}
 
     virtual bool binned() const { return bin_t::binned; }
     virtual bool check() const { return s.check(); }
     virtual void reset() { s.reset(); }
     virtual bool zero() const { return s.zero(); }
-    virtual void update()
+    virtual void visit(Visit &visitor)
     {
-        Vector2dDataBase::update();
+        update();
         s.update(this);
+        visitor.visit(*this);
     }
 };
 
@@ -502,8 +453,8 @@ class Wrap : public Child
      * @param prereq The prerequisite stat.
      * @return A reference to this stat.
      */
-    template <class T>
-    Parent &prereq(const T &prereq)
+    template <class Stat>
+    Parent &prereq(const Stat &prereq)
     {
         statData()->prereq = prereq.statData();
         return self();
@@ -571,9 +522,9 @@ class WrapVec2d : public WrapVec<Parent, Child, Data>
     Parent &ysubname(int index, const std::string subname)
     {
         Data<Child> *data = statData();
-        assert(i < y);
+        assert(index < y);
         data->y_subnames.resize(y);
-        data->y_subnames[i] = subname.c_str();
+        data->y_subnames[index] = subname.c_str();
         return self();
     }
 };
@@ -587,7 +538,6 @@ class WrapVec2d : public WrapVec<Parent, Child, Data>
 /**
  * Templatized storage and interface for a simple scalar stat.
  */
-template <typename T>
 struct StatStor
 {
   public:
@@ -596,59 +546,54 @@ struct StatStor
 
   private:
     /** The statistic value. */
-    T data;
-    static T &Null()
-    {
-        static T __T = T();
-        return __T;
-    }
+    Counter data;
 
   public:
     /**
      * Builds this storage element and calls the base constructor of the
      * datatype.
      */
-    StatStor(const Params &) : data(Null()) {}
+    StatStor(const Params &) : data(Counter()) {}
 
     /**
      * The the stat to the given value.
      * @param val The new value.
      * @param p The paramters of this storage type.
      */
-    void set(T val, const Params &p) { data = val; }
+    void set(Counter val, const Params &p) { data = val; }
     /**
      * Increment the stat by the given value.
      * @param val The new value.
      * @param p The paramters of this storage type.
      */
-    void inc(T val, const Params &p) { data += val; }
+    void inc(Counter val, const Params &p) { data += val; }
     /**
      * Decrement the stat by the given value.
      * @param val The new value.
      * @param p The paramters of this storage type.
      */
-    void dec(T val, const Params &p) { data -= val; }
+    void dec(Counter val, const Params &p) { data -= val; }
     /**
-     * Return the value of this stat as a result type.
-     * @param p The parameters of this storage type.
+     * Return the value of this stat as its base type.
+     * @param p The params of this storage type.
      * @return The value of this stat.
      */
-    result_t val(const Params &p) const { return (result_t)data; }
+    Counter value(const Params &p) const { return data; }
     /**
-     * Return the value of this stat as its base type.
-     * @param p The params of this storage type.
+     * Return the value of this stat as a result type.
+     * @param p The parameters of this storage type.
      * @return The value of this stat.
      */
-    T value(const Params &p) const { return data; }
+    Result result(const Params &p) const { return (Result)data; }
     /**
      * Reset stat value to default
      */
-    void reset() { data = Null(); }
+    void reset() { data = Counter(); }
 
     /**
      * @return true if zero value
      */
-    bool zero() const { return data == Null(); }
+    bool zero() const { return data == Counter(); }
 };
 
 /**
@@ -659,7 +604,6 @@ struct StatStor
  * among other things.
  * @todo add lateny to the stat and fix binning.
  */
-template <typename T>
 struct AvgStor
 {
   public:
@@ -670,12 +614,12 @@ struct AvgStor
          * The current count.  We stash this here because the current
          * value is not a binned value.
          */
-        T current;
+        Counter current;
     };
 
   private:
     /** The total count for all cycles. */
-    mutable result_t total;
+    mutable Result total;
     /** The cycle that current last changed. */
     mutable Tick last;
 
@@ -683,7 +627,7 @@ struct AvgStor
     /**
      * Build and initializes this stat storage.
      */
-    AvgStor(Params &p) : total(0), last(0) { p.current = T(); }
+    AvgStor(Params &p) : total(0), last(0) { p.current = Counter(); }
 
     /**
      * Set the current count to the one provided, update the total and last
@@ -691,7 +635,7 @@ struct AvgStor
      * @param val The new count.
      * @param p The parameters for this storage.
      */
-    void set(T val, Params &p) {
+    void set(Counter val, Params &p) {
         total += p.current * (curTick - last);
         last = curTick;
         p.current = val;
@@ -702,33 +646,34 @@ struct AvgStor
      * @param val The amount to increment.
      * @param p The parameters for this storage.
      */
-    void inc(T val, Params &p) { set(p.current + val, p); }
+    void inc(Counter val, Params &p) { set(p.current + val, p); }
 
     /**
      * Deccrement the current count by the provided value, calls set.
      * @param val The amount to decrement.
      * @param p The parameters for this storage.
      */
-    void dec(T val, Params &p) { set(p.current - val, p); }
+    void dec(Counter val, Params &p) { set(p.current - val, p); }
+
+    /**
+     * Return the current count.
+     * @param p The parameters for this storage.
+     * @return The current count.
+     */
+    Counter value(const Params &p) const { return p.current; }
 
     /**
      * Return the current average.
      * @param p The parameters for this storage.
      * @return The current average.
      */
-    result_t val(const Params &p) const {
+    Result result(const Params &p) const
+    {
         total += p.current * (curTick - last);
         last = curTick;
-        return (result_t)(total + p.current) / (result_t)(curTick + 1);
+        return (Result)(total + p.current) / (Result)(curTick + 1);
     }
 
-    /**
-     * Return the current count.
-     * @param p The parameters for this storage.
-     * @return The current count.
-     */
-    T value(const Params &p) const { return p.current; }
-
     /**
      * Reset stat value to default
      */
@@ -749,16 +694,14 @@ struct AvgStor
  * Storage template. The storage for this stat is held within the Bin class.
  * This allows for breaking down statistics across multiple bins easily.
  */
-template <typename T, template <typename T> class Storage, class Bin>
+template <class Storage, class Bin>
 class ScalarBase : public DataAccess
 {
   public:
-    /** Define the type of the storage class. */
-    typedef Storage<T> storage_t;
     /** Define the params of the storage class. */
-    typedef typename storage_t::Params params_t;
+    typedef typename Storage::Params params_t;
     /** Define the bin type. */
-    typedef typename Bin::Bin<storage_t> bin_t;
+    typedef typename Bin::Bin<Storage> bin_t;
 
   protected:
     /** The bin of this stat. */
@@ -771,12 +714,12 @@ class ScalarBase : public DataAccess
      * Retrieve the storage from the bin.
      * @return The storage object for this stat.
      */
-    storage_t *data() { return bin.data(params); }
+    Storage *data() { return bin.data(params); }
     /**
      * Retrieve a const pointer to the storage from the bin.
      * @return A const pointer to the storage object for this stat.
      */
-    const storage_t *data() const
+    const Storage *data() const
     {
         bin_t *_bin = const_cast<bin_t *>(&bin);
         params_t *_params = const_cast<params_t *>(&params);
@@ -798,7 +741,7 @@ class ScalarBase : public DataAccess
      * Return the current value of this stat as its base type.
      * @return The current value.
      */
-    T value() const { return data()->value(params); }
+    Counter value() const { return data()->value(params); }
 
   public:
     /**
@@ -869,11 +812,14 @@ class ScalarBase : public DataAccess
      */
     void reset() { bin.reset(); }
 
-    result_t val() { return data()->val(params); }
+    Counter value() { return data()->value(params); }
+
+    Result result() { return data()->result(params); }
 
-    result_t total() { return val(); }
+    Result total() { return result(); }
+
+    bool zero() { return result() == 0.0; }
 
-    bool zero() { return val() == 0.0; }
 };
 
 //////////////////////////////////////////////////////////////////////
@@ -881,23 +827,21 @@ class ScalarBase : public DataAccess
 // Vector Statistics
 //
 //////////////////////////////////////////////////////////////////////
-template <typename T, template <typename T> class Storage, class Bin>
+template <class Storage, class Bin>
 class ScalarProxy;
 
 /**
  * Implementation of a vector of stats. The type of stat is determined by the
  * Storage class. @sa ScalarBase
  */
-template <typename T, template <typename T> class Storage, class Bin>
+template <class Storage, class Bin>
 class VectorBase : public DataAccess
 {
   public:
-    /** Define the type of the storage class. */
-    typedef Storage<T> storage_t;
     /** Define the params of the storage class. */
-    typedef typename storage_t::Params params_t;
+    typedef typename Storage::Params params_t;
     /** Define the bin type. */
-    typedef typename Bin::VectorBin<storage_t> bin_t;
+    typedef typename Bin::VectorBin<Storage> bin_t;
 
   protected:
     /** The bin of this stat. */
@@ -911,14 +855,14 @@ class VectorBase : public DataAccess
      * @param index The vector index to access.
      * @return The storage object at the given index.
      */
-    storage_t *data(int index) { return bin.data(index, params); }
+    Storage *data(int index) { return bin.data(index, params); }
     /**
      * Retrieve a const pointer to the storage from the bin
      * for the given index.
      * @param index The vector index to access.
      * @return A const pointer to the storage object at the given index.
      */
-    const storage_t *data(int index) const
+    const Storage *data(int index) const
     {
         bin_t *_bin = const_cast<bin_t *>(&bin);
         params_t *_params = const_cast<params_t *>(&params);
@@ -933,15 +877,22 @@ class VectorBase : public DataAccess
     const VectorBase &operator=(const VectorBase &);
 
   public:
+    void value(VCounter &vec) const
+    {
+        vec.resize(size());
+        for (int i = 0; i < size(); ++i)
+            vec[i] = data(i)->value(params);
+    }
+
     /**
      * Copy the values to a local vector and return a reference to it.
      * @return A reference to a vector of the stat values.
      */
-    void val(rvec_t &vec) const
+    void result(VResult &vec) const
     {
         vec.resize(size());
         for (int i = 0; i < size(); ++i)
-            vec[i] = data(i)->val(params);
+            vec[i] = data(i)->result(params);
     }
 
     /**
@@ -953,10 +904,10 @@ class VectorBase : public DataAccess
      * Return a total of all entries in this vector.
      * @return The total of all vector entries.
      */
-    result_t total() const {
-        result_t total = 0.0;
+    Result total() const {
+        Result total = 0.0;
         for (int i = 0; i < size(); ++i)
-            total += data(i)->val(params);
+            total += data(i)->result(params);
         return total;
     }
 
@@ -980,14 +931,14 @@ class VectorBase : public DataAccess
     VectorBase() {}
 
     /** Friend this class with the associated scalar proxy. */
-    friend class ScalarProxy<T, Storage, Bin>;
+    friend class ScalarProxy<Storage, Bin>;
 
     /**
      * Return a reference (ScalarProxy) to the stat at the given index.
      * @param index The vector index to access.
      * @return A reference of the stat.
      */
-    ScalarProxy<T, Storage, Bin> operator[](int index);
+    ScalarProxy<Storage, Bin> operator[](int index);
 
     void update(StatData *data) {}
 };
@@ -998,16 +949,14 @@ const StatData * getStatData(const void *stat);
  * A proxy class to access the stat at a given index in a VectorBase stat.
  * Behaves like a ScalarBase.
  */
-template <typename T, template <typename T> class Storage, class Bin>
+template <class Storage, class Bin>
 class ScalarProxy
 {
   public:
-    /** Define the type of the storage class. */
-    typedef Storage<T> storage_t;
     /** Define the params of the storage class. */
-    typedef typename storage_t::Params params_t;
+    typedef typename Storage::Params params_t;
     /** Define the bin type. */
-    typedef typename Bin::VectorBin<storage_t> bin_t;
+    typedef typename Bin::VectorBin<Storage> bin_t;
 
   private:
     /** Pointer to the bin in the parent VectorBase. */
@@ -1024,12 +973,12 @@ class ScalarProxy
      * Retrieve the storage from the bin.
      * @return The storage from the bin for this stat.
      */
-    storage_t *data() { return bin->data(index, *params); }
+    Storage *data() { return bin->data(index, *params); }
     /**
      * Retrieve a const pointer to the storage from the bin.
      * @return A const pointer to the storage for this stat.
      */
-    const storage_t *data() const
+    const Storage *data() const
     {
         bin_t *_bin = const_cast<bin_t *>(bin);
         params_t *_params = const_cast<params_t *>(params);
@@ -1038,15 +987,16 @@ class ScalarProxy
 
   public:
     /**
-     * Return the current value of this statas a result type.
+     * Return the current value of this stat as its base type.
      * @return The current value.
      */
-    result_t val() const { return data()->val(*params); }
+    Counter value() const { return data()->value(*params); }
+
     /**
-     * Return the current value of this stat as its base type.
+     * Return the current value of this statas a result type.
      * @return The current value.
      */
-    T value() const { return data()->value(*params); }
+    Result result() const { return data()->result(*params); }
 
   public:
     /**
@@ -1144,24 +1094,23 @@ class ScalarProxy
     }
 };
 
-template <typename T, template <typename T> class Storage, class Bin>
-inline ScalarProxy<T, Storage, Bin>
-VectorBase<T, Storage, Bin>::operator[](int index)
+template <class Storage, class Bin>
+inline ScalarProxy<Storage, Bin>
+VectorBase<Storage, Bin>::operator[](int index)
 {
     assert (index >= 0 && index < size());
-    return ScalarProxy<T, Storage, Bin>(bin, params, index, this);
+    return ScalarProxy<Storage, Bin>(bin, params, index, this);
 }
 
-template <typename T, template <typename T> class Storage, class Bin>
+template <class Storage, class Bin>
 class VectorProxy;
 
-template <typename T, template <typename T> class Storage, class Bin>
+template <class Storage, class Bin>
 class Vector2dBase : public DataAccess
 {
   public:
-    typedef Storage<T> storage_t;
-    typedef typename storage_t::Params params_t;
-    typedef typename Bin::VectorBin<storage_t> bin_t;
+    typedef typename Storage::Params params_t;
+    typedef typename Bin::VectorBin<Storage> bin_t;
 
   protected:
     size_t x;
@@ -1170,8 +1119,8 @@ class Vector2dBase : public DataAccess
     params_t params;
 
   protected:
-    storage_t *data(int index) { return bin.data(index, params); }
-    const storage_t *data(int index) const
+    Storage *data(int index) { return bin.data(index, params); }
+    const Storage *data(int index) const
     {
         bin_t *_bin = const_cast<bin_t *>(&bin);
         params_t *_params = const_cast<params_t *>(&params);
@@ -1186,18 +1135,18 @@ class Vector2dBase : public DataAccess
   public:
     Vector2dBase() {}
 
-    void update(Vector2dDataBase *data)
+    void update(Vector2dData *data)
     {
         int size = this->size();
-        data->vec.resize(size);
+        data->cvec.resize(size);
         for (int i = 0; i < size; ++i)
-            data->vec[i] = this->data(i)->val(params);
+            data->cvec[i] = this->data(i)->value(params);
     }
 
     std::string ysubname(int i) const { return (*y_subnames)[i]; }
 
-    friend class VectorProxy<T, Storage, Bin>;
-    VectorProxy<T, Storage, Bin> operator[](int index);
+    friend class VectorProxy<Storage, Bin>;
+    VectorProxy<Storage, Bin> operator[](int index);
 
     size_t size() const { return bin.size(); }
     bool zero() const { return data(0)->value(params) == 0.0; }
@@ -1210,13 +1159,12 @@ class Vector2dBase : public DataAccess
     bool check() { return bin.initialized(); }
 };
 
-template <typename T, template <typename T> class Storage, class Bin>
+template <class Storage, class Bin>
 class VectorProxy
 {
   public:
-    typedef Storage<T> storage_t;
-    typedef typename storage_t::Params params_t;
-    typedef typename Bin::VectorBin<storage_t> bin_t;
+    typedef typename Storage::Params params_t;
+    typedef typename Bin::VectorBin<Storage> bin_t;
 
   private:
     bin_t *bin;
@@ -1226,36 +1174,36 @@ class VectorProxy
     void *stat;
 
   private:
-    mutable rvec_t *vec;
+    mutable VResult *vec;
 
-    storage_t *data(int index) {
+    Storage *data(int index) {
         assert(index < len);
         return bin->data(offset + index, *params);
     }
 
-    const storage_t *data(int index) const {
+    const Storage *data(int index) const {
         bin_t *_bin = const_cast<bin_t *>(bin);
         params_t *_params = const_cast<params_t *>(params);
         return _bin->data(offset + index, *_params);
     }
 
   public:
-    const rvec_t &val() const {
+    const VResult &result() const {
         if (vec)
             vec->resize(size());
         else
-            vec = new rvec_t(size());
+            vec = new VResult(size());
 
         for (int i = 0; i < size(); ++i)
-            (*vec)[i] = data(i)->val(*params);
+            (*vec)[i] = data(i)->result(*params);
 
         return *vec;
     }
 
-    result_t total() const {
-        result_t total = 0.0;
+    Result total() const {
+        Result total = 0.0;
         for (int i = 0; i < size(); ++i)
-            total += data(i)->val(*params);
+            total += data(i)->result(*params);
         return total;
     }
 
@@ -1290,11 +1238,10 @@ class VectorProxy
         return *this;
     }
 
-    ScalarProxy<T, Storage, Bin> operator[](int index)
+    ScalarProxy<Storage, Bin> operator[](int index)
     {
         assert (index >= 0 && index < size());
-        return ScalarProxy<T, Storage, Bin>(*bin, *params, offset + index,
-                                            stat);
+        return ScalarProxy<Storage, Bin>(*bin, *params, offset + index, stat);
     }
 
     size_t size() const { return len; }
@@ -1311,13 +1258,13 @@ class VectorProxy
     void reset() { }
 };
 
-template <typename T, template <typename T> class Storage, class Bin>
-inline VectorProxy<T, Storage, Bin>
-Vector2dBase<T, Storage, Bin>::operator[](int index)
+template <class Storage, class Bin>
+inline VectorProxy<Storage, Bin>
+Vector2dBase<Storage, Bin>::operator[](int index)
 {
     int offset = index * y;
     assert (index >= 0 && offset < size());
-    return VectorProxy<T, Storage, Bin>(bin, params, offset, y, this);
+    return VectorProxy<Storage, Bin>(bin, params, offset, y, this);
 }
 
 //////////////////////////////////////////////////////////////////////
@@ -1329,7 +1276,6 @@ Vector2dBase<T, Storage, Bin>::operator[](int index)
 /**
  * Templatized storage and interface for a distrbution stat.
  */
-template <typename T>
 struct DistStor
 {
   public:
@@ -1337,11 +1283,11 @@ struct DistStor
     struct Params
     {
         /** The minimum value to track. */
-        int min;
+        Counter min;
         /** The maximum value to track. */
-        int max;
+        Counter max;
         /** The number of entries in each bucket. */
-        int bucket_size;
+        Counter bucket_size;
         /** The number of buckets. Equal to (max-min)/bucket_size. */
         int size;
     };
@@ -1349,21 +1295,21 @@ struct DistStor
 
   private:
     /** The smallest value sampled. */
-    T min_val;
+    Counter min_val;
     /** The largest value sampled. */
-    T max_val;
+    Counter max_val;
     /** The number of values sampled less than min. */
-    T underflow;
+    Counter underflow;
     /** The number of values sampled more than max. */
-    T overflow;
+    Counter overflow;
     /** The current sum. */
-    T sum;
+    Counter sum;
     /** The sum of squares. */
-    T squares;
+    Counter squares;
     /** The number of samples. */
-    int samples;
+    Counter samples;
     /** Counter for each bucket. */
-    std::vector<T> vec;
+    VCounter cvec;
 
   public:
     /**
@@ -1371,8 +1317,9 @@ struct DistStor
      * @param params The parameters.
      */
     DistStor(const Params &params)
-        : min_val(INT_MAX), max_val(INT_MIN), underflow(0), overflow(0),
-          sum(T()), squares(T()), samples(0), vec(params.size)
+        : min_val(INT_MAX), max_val(INT_MIN), underflow(Counter()),
+          overflow(Counter()), sum(Counter()), squares(Counter()),
+          samples(Counter()), cvec(params.size)
     {
         reset();
     }
@@ -1383,16 +1330,16 @@ 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(Counter val, int number, const Params &params)
     {
         if (val < params.min)
             underflow += number;
         else if (val > params.max)
             overflow += number;
         else {
-            int index = (val - params.min) / params.bucket_size;
+            int index = (int)floor((val - params.min) / params.bucket_size);
             assert(index < size(params));
-            vec[index] += number;
+            cvec[index] += number;
         }
 
         if (val < min_val)
@@ -1401,7 +1348,7 @@ struct DistStor
         if (val > max_val)
             max_val = val;
 
-        T sample = val * number;
+        Counter sample = val * number;
         sum += sample;
         squares += sample * sample;
         samples += number;
@@ -1412,7 +1359,7 @@ struct DistStor
      * @return the number of buckets.
      * @todo Is it faster to return the size from the parameters?
      */
-    size_t size(const Params &) const { return vec.size(); }
+    size_t size(const Params &) const { return cvec.size(); }
 
     /**
      * Returns true if any calls to sample have been made.
@@ -1421,7 +1368,7 @@ struct DistStor
      */
     bool zero(const Params &params) const
     {
-        return samples == 0;
+        return samples == Counter();
     }
 
     void update(DistDataData *data, const Params &params)
@@ -1435,9 +1382,9 @@ struct DistStor
         data->max_val = (max_val == INT_MIN) ? 0 : max_val;
         data->underflow = underflow;
         data->overflow = overflow;
-        data->vec.resize(params.size);
+        data->cvec.resize(params.size);
         for (int i = 0; i < params.size; ++i)
-            data->vec[i] = vec[i];
+            data->cvec[i] = cvec[i];
 
         data->sum = sum;
         data->squares = squares;
@@ -1454,13 +1401,13 @@ struct DistStor
         underflow = 0;
         overflow = 0;
 
-        int size = vec.size();
+        int size = cvec.size();
         for (int i = 0; i < size; ++i)
-            vec[i] = T();
+            cvec[i] = Counter();
 
-        sum = T();
-        squares = T();
-        samples = T();
+        sum = Counter();
+        squares = Counter();
+        samples = Counter();
     }
 };
 
@@ -1468,7 +1415,6 @@ struct DistStor
  * Templatized storage and interface for a distribution that calculates mean
  * and variance.
  */
-template <typename T>
 struct FancyStor
 {
   public:
@@ -1480,17 +1426,19 @@ struct FancyStor
 
   private:
     /** The current sum. */
-    T sum;
+    Counter sum;
     /** The sum of squares. */
-    T squares;
+    Counter squares;
     /** The number of samples. */
-    int samples;
+    Counter samples;
 
   public:
     /**
      * Create and initialize this storage.
      */
-    FancyStor(const Params &) : sum(T()), squares(T()), samples(0) {}
+    FancyStor(const Params &)
+        : sum(Counter()), squares(Counter()), samples(Counter())
+    { }
 
     /**
      * Add a value the given number of times to this running average.
@@ -1500,9 +1448,9 @@ 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(Counter val, int number, const Params &p)
     {
-        T value = val * number;
+        Counter value = val * number;
         sum += value;
         squares += value * value;
         samples += number;
@@ -1525,16 +1473,16 @@ struct FancyStor
      * Return true if no samples have been added.
      * @return True if no samples have been added.
      */
-    bool zero(const Params &) const { return samples == 0; }
+    bool zero(const Params &) const { return samples == Counter(); }
 
     /**
      * Reset stat value to default
      */
     void reset()
     {
-        sum = T();
-        squares = T();
-        samples = 0;
+        sum = Counter();
+        squares = Counter();
+        samples = Counter();
     }
 };
 
@@ -1542,7 +1490,6 @@ struct FancyStor
  * Templatized storage for distribution that calculates per cycle mean and
  * variance.
  */
-template <typename T>
 struct AvgFancy
 {
   public:
@@ -1552,15 +1499,15 @@ struct AvgFancy
 
   private:
     /** Current total. */
-    T sum;
+    Counter sum;
     /** Current sum of squares. */
-    T squares;
+    Counter squares;
 
   public:
     /**
      * Create and initialize this storage.
      */
-    AvgFancy(const Params &) : sum(T()), squares(T()) {}
+    AvgFancy(const Params &) : sum(Counter()), squares(Counter()) {}
 
     /**
      * Add a value to the distribution for the given number of times.
@@ -1569,9 +1516,9 @@ 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(Counter val, int number, const Params &p)
     {
-        T value = val * number;
+        Counter value = val * number;
         sum += value;
         squares += value * value;
     }
@@ -1592,14 +1539,14 @@ struct AvgFancy
      * Return true if no samples have been added.
      * @return True if the sum is zero.
      */
-    bool zero(const Params &params) const { return sum == 0; }
+    bool zero(const Params &params) const { return sum == Counter(); }
     /**
      * Reset stat value to default
      */
     void reset()
     {
-        sum = T();
-        squares = T();
+        sum = Counter();
+        squares = Counter();
     }
 };
 
@@ -1607,16 +1554,14 @@ struct AvgFancy
  * Implementation of a distribution stat. The type of distribution is
  * determined by the Storage template. @sa ScalarBase
  */
-template <typename T, template <typename T> class Storage, class Bin>
+template <class Storage, class Bin>
 class DistBase : public DataAccess
 {
   public:
-    /** Define the type of the storage class. */
-    typedef Storage<T> storage_t;
     /** Define the params of the storage class. */
-    typedef typename storage_t::Params params_t;
+    typedef typename Storage::Params params_t;
     /** Define the bin type. */
-    typedef typename Bin::Bin<storage_t> bin_t;
+    typedef typename Bin::Bin<Storage> bin_t;
 
   protected:
     /** The bin of this stat. */
@@ -1629,12 +1574,12 @@ class DistBase : public DataAccess
      * Retrieve the storage from the bin.
      * @return The storage object for this stat.
      */
-    storage_t *data() { return bin.data(params); }
+    Storage *data() { return bin.data(params); }
     /**
      * Retrieve a const pointer to the storage from the bin.
      * @return A const pointer to the storage object for this stat.
      */
-    const storage_t *data() const
+    const Storage *data() const
     {
         bin_t *_bin = const_cast<bin_t *>(&bin);
         params_t *_params = const_cast<params_t *>(&params);
@@ -1671,9 +1616,9 @@ class DistBase : public DataAccess
      */
     bool zero() const { return data()->zero(params); }
 
-    void update(DistDataBase *base)
+    void update(DistData *base)
     {
-        base->data.fancy = storage_t::fancy;
+        base->data.fancy = Storage::fancy;
         data()->update(&(base->data), params);
     }
     /**
@@ -1691,24 +1636,23 @@ class DistBase : public DataAccess
     bool check() { return bin.initialized(); }
 };
 
-template <typename T, template <typename T> class Storage, class Bin>
+template <class Storage, class Bin>
 class DistProxy;
 
-template <typename T, template <typename T> class Storage, class Bin>
+template <class Storage, class Bin>
 class VectorDistBase : public DataAccess
 {
   public:
-    typedef Storage<T> storage_t;
-    typedef typename storage_t::Params params_t;
-    typedef typename Bin::VectorBin<storage_t> bin_t;
+    typedef typename Storage::Params params_t;
+    typedef typename Bin::VectorBin<Storage> bin_t;
 
   protected:
     bin_t bin;
     params_t params;
 
   protected:
-    storage_t *data(int index) { return bin.data(index, params); }
-    const storage_t *data(int index) const
+    Storage *data(int index) { return bin.data(index, params); }
+    const Storage *data(int index) const
     {
         bin_t *_bin = const_cast<bin_t *>(&bin);
         params_t *_params = const_cast<params_t *>(&params);
@@ -1723,9 +1667,9 @@ class VectorDistBase : public DataAccess
   public:
     VectorDistBase() {}
 
-    friend class DistProxy<T, Storage, Bin>;
-    DistProxy<T, Storage, Bin> operator[](int index);
-    const DistProxy<T, Storage, Bin> operator[](int index) const;
+    friend class DistProxy<Storage, Bin>;
+    DistProxy<Storage, Bin> operator[](int index);
+    const DistProxy<Storage, Bin> operator[](int index) const;
 
     size_t size() const { return bin.size(); }
     bool zero() const { return false; }
@@ -1740,25 +1684,24 @@ class VectorDistBase : public DataAccess
     void reset() { bin.reset(); }
 
     bool check() { return bin.initialized(); }
-    void update(VectorDistDataBase *base)
+    void update(VectorDistData *base)
     {
         int size = this->size();
         base->data.resize(size);
         for (int i = 0; i < size; ++i) {
-            base->data[i].fancy = storage_t::fancy;
+            base->data[i].fancy = Storage::fancy;
             data(i)->update(&(base->data[i]), params);
         }
     }
 };
 
-template <typename T, template <typename T> class Storage, class Bin>
+template <class Storage, class Bin>
 class DistProxy
 {
   public:
-    typedef Storage<T> storage_t;
-    typedef typename storage_t::Params params_t;
-    typedef typename Bin::Bin<storage_t> bin_t;
-    typedef VectorDistBase<T, Storage, Bin> base_t;
+    typedef typename Storage::Params params_t;
+    typedef typename Bin::Bin<Storage> bin_t;
+    typedef VectorDistBase<Storage, Bin> base_t;
 
   private:
     union {
@@ -1768,11 +1711,11 @@ class DistProxy
     int index;
 
   protected:
-    storage_t *data() { return stat->data(index); }
-    const storage_t *data() const { return cstat->data(index); }
+    Storage *data() { return stat->data(index); }
+    const Storage *data() const { return cstat->data(index); }
 
   public:
-    DistProxy(const VectorDistBase<T, Storage, Bin> &s, int i)
+    DistProxy(const VectorDistBase<Storage, Bin> &s, int i)
         : cstat(&s), index(i) {}
     DistProxy(const DistProxy &sp)
         : cstat(sp.cstat), index(sp.index) {}
@@ -1797,30 +1740,30 @@ class DistProxy
     void reset() { }
 };
 
-template <typename T, template <typename T> class Storage, class Bin>
-inline DistProxy<T, Storage, Bin>
-VectorDistBase<T, Storage, Bin>::operator[](int index)
+template <class Storage, class Bin>
+inline DistProxy<Storage, Bin>
+VectorDistBase<Storage, Bin>::operator[](int index)
 {
     assert (index >= 0 && index < size());
-    return DistProxy<T, Storage, Bin>(*this, index);
+    return DistProxy<Storage, Bin>(*this, index);
 }
 
-template <typename T, template <typename T> class Storage, class Bin>
-inline const DistProxy<T, Storage, Bin>
-VectorDistBase<T, Storage, Bin>::operator[](int index) const
+template <class Storage, class Bin>
+inline const DistProxy<Storage, Bin>
+VectorDistBase<Storage, Bin>::operator[](int index) const
 {
     assert (index >= 0 && index < size());
-    return DistProxy<T, Storage, Bin>(*this, index);
+    return DistProxy<Storage, Bin>(*this, index);
 }
 
 #if 0
-template <typename T, template <typename T> class Storage, class Bin>
-result_t
-VectorDistBase<T, Storage, Bin>::total(int index) const
+template <class Storage, class Bin>
+Result
+VectorDistBase<Storage, Bin>::total(int index) const
 {
     int total = 0;
     for (int i=0; i < x_size(); ++i) {
-        total += data(i)->val(*params);
+        total += data(i)->result(*params);
     }
 }
 #endif
@@ -1847,12 +1790,12 @@ class Node : public RefCounted
      * Return the result vector of this subtree.
      * @return The result vector of this subtree.
      */
-    virtual const rvec_t &val() const = 0;
+    virtual const VResult &result() const = 0;
     /**
      * Return the total of the result vector.
      * @return The total of the result vector.
      */
-    virtual result_t total() const = 0;
+    virtual Result total() const = 0;
     /**
      * Return true if stat is binned.
      *@return True is stat is binned.
@@ -1871,17 +1814,17 @@ typedef RefCountingPtr<Node> NodePtr;
 class ScalarStatNode : public Node
 {
   private:
-    const ScalarDataBase *data;
-    mutable rvec_t result;
+    const ScalarData *data;
+    mutable VResult vresult;
 
   public:
-    ScalarStatNode(const ScalarDataBase *d) : data(d), result(1) {}
-    virtual const rvec_t &val() const
+    ScalarStatNode(const ScalarData *d) : data(d), vresult(1) {}
+    virtual const VResult &result() const
     {
-        result[0] = data->val();
-        return result;
+        vresult[0] = data->result();
+        return vresult;
     }
-    virtual result_t total() const { return data->val(); };
+    virtual Result total() const { return data->result(); };
 
     virtual size_t size() const { return 1; }
     /**
@@ -1896,22 +1839,22 @@ class ScalarStatNode : public Node
     virtual std::string str() const { return data->name; }
 };
 
-template <typename T, template <typename T> class Storage, class Bin>
+template <class Storage, class Bin>
 class ScalarProxyNode : public Node
 {
   private:
-    const ScalarProxy<T, Storage, Bin> proxy;
-    mutable rvec_t result;
+    const ScalarProxy<Storage, Bin> proxy;
+    mutable VResult vresult;
 
   public:
-    ScalarProxyNode(const ScalarProxy<T, Storage, Bin> &p)
-        : proxy(p), result(1) { }
-    virtual const rvec_t &val() const
+    ScalarProxyNode(const ScalarProxy<Storage, Bin> &p)
+        : proxy(p), vresult(1) { }
+    virtual const VResult &result() const
     {
-        result[0] = proxy.val();
-        return result;
+        vresult[0] = proxy.result();
+        return vresult;
     }
-    virtual result_t total() const { return proxy.val(); };
+    virtual Result total() const { return proxy.result(); };
 
     virtual size_t size() const { return 1; }
     /**
@@ -1929,12 +1872,12 @@ class ScalarProxyNode : public Node
 class VectorStatNode : public Node
 {
   private:
-    const VectorDataBase *data;
+    const VectorData *data;
 
   public:
-    VectorStatNode(const VectorDataBase *d) : data(d) { }
-    virtual const rvec_t &val() const { return data->val(); }
-    virtual result_t total() const { return data->total(); };
+    VectorStatNode(const VectorData *d) : data(d) { }
+    virtual const VResult &result() const { return data->result(); }
+    virtual Result total() const { return data->total(); };
 
     virtual size_t size() const { return data->size(); }
     /**
@@ -1946,41 +1889,42 @@ class VectorStatNode : public Node
     virtual std::string str() const { return data->name; }
 };
 
-template <typename T>
+template <class T>
 class ConstNode : public Node
 {
   private:
-    rvec_t data;
+    VResult vresult;
 
   public:
-    ConstNode(T s) : data(1, (result_t)s) {}
-    const rvec_t &val() const { return data; }
-    virtual result_t total() const { return data[0]; };
-
+    ConstNode(T s) : vresult(1, (Result)s) {}
+    const VResult &result() const { return vresult; }
+    virtual Result total() const { return vresult[0]; };
     virtual size_t size() const { return 1; }
+
     /**
      * Return true if stat is binned.
      *@return False since constants aren't binned.
      */
     virtual bool binned() const { return false; }
 
-    virtual std::string str() const { return to_string(data[0]); }
+    virtual std::string str() const { return to_string(vresult[0]); }
 };
 
-template <typename T>
+template <class T>
 class FunctorNode : public Node
 {
   private:
     T &functor;
-    mutable rvec_t result;
+    mutable VResult vresult;
 
   public:
-    FunctorNode(T &f) : functor(f) { result.resize(1); }
-    const rvec_t &val() const {
-        result[0] = (result_t)functor();
-        return result;
+    FunctorNode(T &f) : functor(f) { vresult.resize(1); }
+    const VResult &result() const
+    {
+        vresult[0] = (Result)functor();
+        return vresult;
     }
-    virtual result_t total() const { return (result_t)functor(); };
+    virtual Result total() const { return (Result)functor(); };
 
     virtual size_t size() const { return 1; }
     /**
@@ -1991,20 +1935,21 @@ class FunctorNode : public Node
     virtual std::string str() const { return to_string(functor()); }
 };
 
-template <typename T>
+template <class T>
 class ScalarNode : public Node
 {
   private:
     T &scalar;
-    mutable rvec_t result;
+    mutable VResult vresult;
 
   public:
-    ScalarNode(T &s) : scalar(s) { result.resize(1); }
-    const rvec_t &val() const {
-        result[0] = (result_t)scalar;
-        return result;
+    ScalarNode(T &s) : scalar(s) { vresult.resize(1); }
+    const VResult &result() const
+    {
+        vresult[0] = (Result)scalar;
+        return vresult;
     }
-    virtual result_t total() const { return (result_t)scalar; };
+    virtual Result total() const { return (Result)scalar; };
 
     virtual size_t size() const { return 1; }
     /**
@@ -2019,37 +1964,37 @@ template <class Op>
 struct OpString;
 
 template<>
-struct OpString<std::plus<result_t> >
+struct OpString<std::plus<Result> >
 {
     static std::string str() { return "+"; }
 };
 
 template<>
-struct OpString<std::minus<result_t> >
+struct OpString<std::minus<Result> >
 {
     static std::string str() { return "-"; }
 };
 
 template<>
-struct OpString<std::multiplies<result_t> >
+struct OpString<std::multiplies<Result> >
 {
     static std::string str() { return "*"; }
 };
 
 template<>
-struct OpString<std::divides<result_t> >
+struct OpString<std::divides<Result> >
 {
     static std::string str() { return "/"; }
 };
 
 template<>
-struct OpString<std::modulus<result_t> >
+struct OpString<std::modulus<Result> >
 {
     static std::string str() { return "%"; }
 };
 
 template<>
-struct OpString<std::negate<result_t> >
+struct OpString<std::negate<Result> >
 {
     static std::string str() { return "-"; }
 };
@@ -2059,26 +2004,27 @@ class UnaryNode : public Node
 {
   public:
     NodePtr l;
-    mutable rvec_t result;
+    mutable VResult vresult;
 
   public:
     UnaryNode(NodePtr &p) : l(p) {}
 
-    const rvec_t &val() const {
-        const rvec_t &lvec = l->val();
+    const VResult &result() const
+    {
+        const VResult &lvec = l->result();
         int size = lvec.size();
 
         assert(size > 0);
 
-        result.resize(size);
+        vresult.resize(size);
         Op op;
         for (int i = 0; i < size; ++i)
-            result[i] = op(lvec[i]);
+            vresult[i] = op(lvec[i]);
 
-        return result;
+        return vresult;
     }
 
-    result_t total() const {
+    Result total() const {
         Op op;
         return op(l->total());
     }
@@ -2102,42 +2048,43 @@ class BinaryNode : public Node
   public:
     NodePtr l;
     NodePtr r;
-    mutable rvec_t result;
+    mutable VResult vresult;
 
   public:
     BinaryNode(NodePtr &a, NodePtr &b) : l(a), r(b) {}
 
-    const rvec_t &val() const {
+    const VResult &result() const
+    {
         Op op;
-        const rvec_t &lvec = l->val();
-        const rvec_t &rvec = r->val();
+        const VResult &lvec = l->result();
+        const VResult &rvec = r->result();
 
         assert(lvec.size() > 0 && rvec.size() > 0);
 
         if (lvec.size() == 1 && rvec.size() == 1) {
-            result.resize(1);
-            result[0] = op(lvec[0], rvec[0]);
+            vresult.resize(1);
+            vresult[0] = op(lvec[0], rvec[0]);
         } else if (lvec.size() == 1) {
             int size = rvec.size();
-            result.resize(size);
+            vresult.resize(size);
             for (int i = 0; i < size; ++i)
-                result[i] = op(lvec[0], rvec[i]);
+                vresult[i] = op(lvec[0], rvec[i]);
         } else if (rvec.size() == 1) {
             int size = lvec.size();
-            result.resize(size);
+            vresult.resize(size);
             for (int i = 0; i < size; ++i)
-                result[i] = op(lvec[i], rvec[0]);
+                vresult[i] = op(lvec[i], rvec[0]);
         } else if (rvec.size() == lvec.size()) {
             int size = rvec.size();
-            result.resize(size);
+            vresult.resize(size);
             for (int i = 0; i < size; ++i)
-                result[i] = op(lvec[i], rvec[i]);
+                vresult[i] = op(lvec[i], rvec[i]);
         }
 
-        return result;
+        return vresult;
     }
 
-    result_t total() const {
+    Result total() const {
         Op op;
         return op(l->total(), r->total());
     }
@@ -2171,37 +2118,39 @@ class SumNode : public Node
 {
   public:
     NodePtr l;
-    mutable rvec_t result;
+    mutable VResult vresult;
 
   public:
-    SumNode(NodePtr &p) : l(p), result(1) {}
+    SumNode(NodePtr &p) : l(p), vresult(1) {}
 
-    const rvec_t &val() const {
-        const rvec_t &lvec = l->val();
+    const VResult &result() const
+    {
+        const VResult &lvec = l->result();
         int size = lvec.size();
         assert(size > 0);
 
-        result[0] = 0.0;
+        vresult[0] = 0.0;
 
         Op op;
         for (int i = 0; i < size; ++i)
-            result[0] = op(result[0], lvec[i]);
+            vresult[0] = op(vresult[0], lvec[i]);
 
-        return result;
+        return vresult;
     }
 
-    result_t total() const {
-        const rvec_t &lvec = l->val();
+    Result total() const
+    {
+        const VResult &lvec = l->result();
         int size = lvec.size();
         assert(size > 0);
 
-        result_t result = 0.0;
+        Result vresult = 0.0;
 
         Op op;
         for (int i = 0; i < size; ++i)
-            result = op(result, lvec[i]);
+            vresult = op(vresult, lvec[i]);
 
-        return result;
+        return vresult;
     }
 
     virtual size_t size() const { return 1; }
@@ -2217,268 +2166,6 @@ class SumNode : public Node
     }
 };
 
-//////////////////////////////////////////////////////////////////////
-//
-// Binning Interface
-//
-//////////////////////////////////////////////////////////////////////
-struct MainBin
-{
-    class BinBase;
-    friend class MainBin::BinBase;
-
-  private:
-    std::string _name;
-    char *mem;
-
-  protected:
-    off_t memsize;
-    off_t size() const { return memsize; }
-    char *memory(off_t off);
-
-  public:
-    static MainBin *&curBin()
-    {
-        static MainBin *current = NULL;
-        return current;
-    }
-
-    static void setCurBin(MainBin *bin) { curBin() = bin; }
-    static MainBin *current() { assert(curBin()); return curBin(); }
-
-    static off_t &offset()
-    {
-        static off_t offset = 0;
-        return offset;
-    }
-
-    static off_t new_offset(size_t size)
-    {
-        size_t mask = sizeof(u_int64_t) - 1;
-        off_t off = offset();
-
-        // That one is for the last trailing flags byte.
-        offset() += (size + 1 + mask) & ~mask;
-        return off;
-    }
-
-  public:
-    MainBin(const std::string &name);
-    ~MainBin();
-
-    const std::string &
-    name() const
-    {
-        return _name;
-    }
-
-    void
-    activate()
-    {
-        setCurBin(this);
-    }
-
-    class BinBase
-    {
-      private:
-        int offset;
-
-      public:
-        BinBase() : offset(-1) {}
-        void allocate(size_t size)
-        {
-            offset = new_offset(size);
-        }
-        char *access()
-        {
-            assert(offset != -1);
-            return current()->memory(offset);
-        }
-    };
-
-    template <class Storage>
-    class Bin : public BinBase
-    {
-      public:
-        typedef typename Storage::Params Params;
-
-      public:
-        enum { binned = true };
-        Bin() { allocate(sizeof(Storage)); }
-        bool initialized() const { return true; }
-        void init(Params &params) { }
-
-        int size() const { return 1; }
-
-        Storage *
-        data(Params &params)
-        {
-            assert(initialized());
-            char *ptr = access();
-            char *flags = ptr + sizeof(Storage);
-            if (!(*flags & 0x1)) {
-                *flags |= 0x1;
-                new (ptr) Storage(params);
-            }
-            return reinterpret_cast<Storage *>(ptr);
-        }
-
-        void
-        reset()
-        {
-            char *ptr = access();
-            char *flags = ptr + size() * sizeof(Storage);
-            if (!(*flags & 0x1))
-                return;
-
-            Storage *s = reinterpret_cast<Storage *>(ptr);
-            s->reset();
-        }
-    };
-
-    template <class Storage>
-    class VectorBin : public BinBase
-    {
-      public:
-        typedef typename Storage::Params Params;
-
-      private:
-        int _size;
-
-      public:
-        enum { binned = true };
-        VectorBin() : _size(0) {}
-
-        bool initialized() const { return _size > 0; }
-        void init(int s, Params &params)
-        {
-            assert(!initialized());
-            assert(s > 0);
-            _size = s;
-            allocate(_size * sizeof(Storage));
-        }
-
-        int size() const { return _size; }
-
-        Storage *data(int index, Params &params)
-        {
-            assert(initialized());
-            assert(index >= 0 && index < size());
-            char *ptr = access();
-            char *flags = ptr + size() * sizeof(Storage);
-            if (!(*flags & 0x1)) {
-                *flags |= 0x1;
-                for (int i = 0; i < size(); ++i)
-                    new (ptr + i * sizeof(Storage)) Storage(params);
-            }
-            return reinterpret_cast<Storage *>(ptr + index * sizeof(Storage));
-        }
-        void reset()
-        {
-            char *ptr = access();
-            char *flags = ptr + size() * sizeof(Storage);
-            if (!(*flags & 0x1))
-                return;
-
-            for (int i = 0; i < _size; ++i) {
-                char *p = ptr + i * sizeof(Storage);
-                Storage *s = reinterpret_cast<Storage *>(p);
-                s->reset();
-            }
-        }
-    };
-};
-
-struct NoBin
-{
-    template <class Storage>
-    struct Bin
-    {
-      public:
-        typedef typename Storage::Params Params;
-        enum { binned = false };
-
-      private:
-        char ptr[sizeof(Storage)];
-
-      public:
-        ~Bin()
-        {
-            reinterpret_cast<Storage *>(ptr)->~Storage();
-        }
-
-        bool initialized() const { return true; }
-        void init(Params &params)
-        {
-            new (ptr) Storage(params);
-        }
-        int size() const{ return 1; }
-        Storage *data(Params &params)
-        {
-            assert(initialized());
-            return reinterpret_cast<Storage *>(ptr);
-        }
-        void reset()
-        {
-            Storage *s = reinterpret_cast<Storage *>(ptr);
-            s->reset();
-        }
-    };
-
-    template <class Storage>
-    struct VectorBin
-    {
-      public:
-        typedef typename Storage::Params Params;
-        enum { binned = false };
-
-      private:
-        char *ptr;
-        int _size;
-
-      public:
-        VectorBin() : ptr(NULL) { }
-        ~VectorBin()
-        {
-            if (!initialized())
-                return;
-
-            for (int i = 0; i < _size; ++i) {
-                char *p = ptr + i * sizeof(Storage);
-                reinterpret_cast<Storage *>(p)->~Storage();
-            }
-            delete [] ptr;
-        }
-
-        bool initialized() const { return ptr != NULL; }
-        void init(int s, Params &params)
-        {
-            assert(s > 0 && "size must be positive!");
-            assert(!initialized());
-            _size = s;
-            ptr = new char[_size * sizeof(Storage)];
-            for (int i = 0; i < _size; ++i)
-                new (ptr + i * sizeof(Storage)) Storage(params);
-        }
-
-        int size() const { return _size; }
-
-        Storage *data(int index, Params &params)
-        {
-            assert(initialized());
-            assert(index >= 0 && index < size());
-            return reinterpret_cast<Storage *>(ptr + index * sizeof(Storage));
-        }
-        void reset()
-        {
-            for (int i = 0; i < _size; ++i) {
-                char *p = ptr + i * sizeof(Storage);
-                Storage *s = reinterpret_cast<Storage *>(p);
-                s->reset();
-            }
-        }
-    };
-};
 
 //////////////////////////////////////////////////////////////////////
 //
@@ -2508,15 +2195,15 @@ typedef NoBin DefaultBin;
  * This is a simple scalar statistic, like a counter.
  * @sa Stat, ScalarBase, StatStor
  */
-template <typename T = Counter, class Bin = DefaultBin>
+template <class Bin = DefaultBin>
 class Scalar
-    : public Wrap<Scalar<T, Bin>,
-                  ScalarBase<T, StatStor, Bin>,
-                  ScalarData>
+    : public Wrap<Scalar<Bin>,
+                  ScalarBase<StatStor, Bin>,
+                  ScalarStatData>
 {
   public:
     /** The base implementation. */
-    typedef ScalarBase<T, StatStor, Bin> Base;
+    typedef ScalarBase<StatStor, Bin> Base;
 
     Scalar()
     {
@@ -2536,15 +2223,15 @@ class Scalar
  * A stat that calculates the per cycle average of a value.
  * @sa Stat, ScalarBase, AvgStor
  */
-template <typename T = Counter, class Bin = DefaultBin>
+template <class Bin = DefaultBin>
 class Average
-    : public Wrap<Average<T, Bin>,
-                  ScalarBase<T, AvgStor, Bin>,
-                  ScalarData>
+    : public Wrap<Average<Bin>,
+                  ScalarBase<AvgStor, Bin>,
+                  ScalarStatData>
 {
   public:
     /** The base implementation. */
-    typedef ScalarBase<T, AvgStor, Bin> Base;
+    typedef ScalarBase<AvgStor, Bin> Base;
 
     Average()
     {
@@ -2564,15 +2251,15 @@ class Average
  * A vector of scalar stats.
  * @sa Stat, VectorBase, StatStor
  */
-template <typename T = Counter, class Bin = DefaultBin>
+template <class Bin = DefaultBin>
 class Vector
-    : public WrapVec<Vector<T, Bin>,
-                     VectorBase<T, StatStor, Bin>,
-                     VectorData>
+    : public WrapVec<Vector<Bin>,
+                     VectorBase<StatStor, Bin>,
+                     VectorStatData>
 {
   public:
     /** The base implementation. */
-    typedef ScalarBase<T, StatStor, Bin> Base;
+    typedef ScalarBase<StatStor, Bin> Base;
 
     /**
      * Set this vector to have the given size.
@@ -2591,11 +2278,11 @@ class Vector
  * A vector of Average stats.
  * @sa Stat, VectorBase, AvgStor
  */
-template <typename T = Counter, class Bin = DefaultBin>
+template <class Bin = DefaultBin>
 class AverageVector
-    : public WrapVec<AverageVector<T, Bin>,
-                     VectorBase<T, AvgStor, Bin>,
-                     VectorData>
+    : public WrapVec<AverageVector<Bin>,
+                     VectorBase<AvgStor, Bin>,
+                     VectorStatData>
 {
   public:
     /**
@@ -2615,11 +2302,11 @@ class AverageVector
  * A 2-Dimensional vecto of scalar stats.
  * @sa Stat, Vector2dBase, StatStor
  */
-template <typename T = Counter, class Bin = DefaultBin>
+template <class Bin = DefaultBin>
 class Vector2d
-    : public WrapVec2d<Vector2d<T, Bin>,
-                       Vector2dBase<T, StatStor, Bin>,
-                       Vector2dData>
+    : public WrapVec2d<Vector2d<Bin>,
+                       Vector2dBase<StatStor, Bin>,
+                       Vector2dStatData>
 {
   public:
     Vector2d &init(size_t _x, size_t _y) {
@@ -2636,17 +2323,17 @@ class Vector2d
  * A simple distribution stat.
  * @sa Stat, DistBase, DistStor
  */
-template <typename T = Counter, class Bin = DefaultBin>
+template <class Bin = DefaultBin>
 class Distribution
-    : public Wrap<Distribution<T, Bin>,
-                  DistBase<T, DistStor, Bin>,
-                  DistData>
+    : public Wrap<Distribution<Bin>,
+                  DistBase<DistStor, Bin>,
+                  DistStatData>
 {
   public:
     /** Base implementation. */
-    typedef DistBase<T, DistStor, Bin> Base;
+    typedef DistBase<DistStor, Bin> Base;
     /** The Parameter type. */
-    typedef typename DistStor<T>::Params Params;
+    typedef typename DistStor::Params Params;
 
   public:
     /**
@@ -2656,11 +2343,11 @@ class Distribution
      * @param bkt The number of values in each bucket.
      * @return A reference to this distribution.
      */
-    Distribution &init(T min, T max, int bkt) {
+    Distribution &init(Counter min, Counter max, Counter bkt) {
         params.min = min;
         params.max = max;
         params.bucket_size = bkt;
-        params.size = (max - min) / bkt + 1;
+        params.size = (int)rint((max - min) / bkt + 1.0);
         bin.init(params);
         setInit();
 
@@ -2672,17 +2359,17 @@ class Distribution
  * Calculates the mean and variance of all the samples.
  * @sa Stat, DistBase, FancyStor
  */
-template <typename T = Counter, class Bin = DefaultBin>
+template <class Bin = DefaultBin>
 class StandardDeviation
-    : public Wrap<StandardDeviation<T, Bin>,
-                  DistBase<T, FancyStor, Bin>,
-                  DistData>
+    : public Wrap<StandardDeviation<Bin>,
+                  DistBase<FancyStor, Bin>,
+                  DistStatData>
 {
   public:
     /** The base implementation */
-    typedef DistBase<T, DistStor, Bin> Base;
+    typedef DistBase<DistStor, Bin> Base;
     /** The parameter type. */
-    typedef typename DistStor<T>::Params Params;
+    typedef typename DistStor::Params Params;
 
   public:
     /**
@@ -2698,17 +2385,17 @@ class StandardDeviation
  * Calculates the per cycle mean and variance of the samples.
  * @sa Stat, DistBase, AvgFancy
  */
-template <typename T = Counter, class Bin = DefaultBin>
+template <class Bin = DefaultBin>
 class AverageDeviation
-    : public Wrap<AverageDeviation<T, Bin>,
-                  DistBase<T, AvgFancy, Bin>,
-                  DistData>
+    : public Wrap<AverageDeviation<Bin>,
+                  DistBase<AvgFancy, Bin>,
+                  DistStatData>
 {
   public:
     /** The base implementation */
-    typedef DistBase<T, DistStor, Bin> Base;
+    typedef DistBase<DistStor, Bin> Base;
     /** The parameter type. */
-    typedef typename DistStor<T>::Params Params;
+    typedef typename DistStor::Params Params;
 
   public:
     /**
@@ -2725,17 +2412,17 @@ class AverageDeviation
  * A vector of distributions.
  * @sa Stat, VectorDistBase, DistStor
  */
-template <typename T = Counter, class Bin = DefaultBin>
+template <class Bin = DefaultBin>
 class VectorDistribution
-    : public WrapVec<VectorDistribution<T, Bin>,
-                     VectorDistBase<T, DistStor, Bin>,
-                     VectorDistData>
+    : public WrapVec<VectorDistribution<Bin>,
+                     VectorDistBase<DistStor, Bin>,
+                     VectorDistStatData>
 {
   public:
     /** The base implementation */
-    typedef VectorDistBase<T, DistStor, Bin> Base;
+    typedef VectorDistBase<DistStor, Bin> Base;
     /** The parameter type. */
-    typedef typename DistStor<T>::Params Params;
+    typedef typename DistStor::Params Params;
 
   public:
     /**
@@ -2746,11 +2433,11 @@ class VectorDistribution
      * @param bkt The number of values in each bucket.
      * @return A reference to this distribution.
      */
-    VectorDistribution &init(int size, T min, T max, int bkt) {
+    VectorDistribution &init(int size, Counter min, Counter max, Counter bkt) {
         params.min = min;
         params.max = max;
         params.bucket_size = bkt;
-        params.size = (max - min) / bkt + 1;
+        params.size = (int)rint((max - min) / bkt + 1.0);
         bin.init(size, params);
         setInit();
 
@@ -2762,17 +2449,17 @@ class VectorDistribution
  * This is a vector of StandardDeviation stats.
  * @sa Stat, VectorDistBase, FancyStor
  */
-template <typename T = Counter, class Bin = DefaultBin>
+template <class Bin = DefaultBin>
 class VectorStandardDeviation
-    : public WrapVec<VectorStandardDeviation<T, Bin>,
-                     VectorDistBase<T, FancyStor, Bin>,
-                     VectorDistData>
+    : public WrapVec<VectorStandardDeviation<Bin>,
+                     VectorDistBase<FancyStor, Bin>,
+                     VectorDistStatData>
 {
   public:
     /** The base implementation */
-    typedef VectorDistBase<T, FancyStor, Bin> Base;
+    typedef VectorDistBase<FancyStor, Bin> Base;
     /** The parameter type. */
-    typedef typename DistStor<T>::Params Params;
+    typedef typename DistStor::Params Params;
 
   public:
     /**
@@ -2792,17 +2479,17 @@ class VectorStandardDeviation
  * This is a vector of AverageDeviation stats.
  * @sa Stat, VectorDistBase, AvgFancy
  */
-template <typename T = Counter, class Bin = DefaultBin>
+template <class Bin = DefaultBin>
 class VectorAverageDeviation
-    : public WrapVec<VectorAverageDeviation<T, Bin>,
-                     VectorDistBase<T, AvgFancy, Bin>,
-                     VectorDistData>
+    : public WrapVec<VectorAverageDeviation<Bin>,
+                     VectorDistBase<AvgFancy, Bin>,
+                     VectorDistStatData>
 {
   public:
     /** The base implementation */
-    typedef VectorDistBase<T, AvgFancy, Bin> Base;
+    typedef VectorDistBase<AvgFancy, Bin> Base;
     /** The parameter type. */
-    typedef typename DistStor<T>::Params Params;
+    typedef typename DistStor::Params Params;
 
   public:
     /**
@@ -2838,7 +2525,7 @@ class FormulaBase : public DataAccess
      * be x[0]/y, x[1]/y, x[2]/y, respectively.
      * @return The result vector.
      */
-    void val(rvec_t &vec) const;
+    void result(VResult &vec) const;
 
     /**
      * Return the total Formula result.  If there is a Vector
@@ -2847,10 +2534,10 @@ class FormulaBase : public DataAccess
      * 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.
+     * the first entry in the VResult val() returns.
      * @return The total of the result vector.
      */
-    result_t total() const;
+    Result total() const;
 
     /**
      * Return the number of elements in the tree.
@@ -2884,39 +2571,41 @@ class FormulaBase : public DataAccess
     std::string str() const;
 };
 
-class FormulaDataBase : public VectorDataBase
+class FormulaData : public VectorData
 {
   public:
     virtual std::string str() const = 0;
     virtual bool check() const { return true; }
-    virtual void python(Python &py) const;
 };
 
-template <class T>
-class FormulaData : public FormulaDataBase
+template <class Stat>
+class FormulaStatData : public FormulaData
 {
   protected:
-    T &s;
-    mutable rvec_t vec;
+    Stat &s;
+    mutable VResult vec;
+    mutable VCounter cvec;
 
   public:
-    FormulaData(T &stat) : s(stat) {}
+    FormulaStatData(Stat &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
+    virtual const VResult &result() const
     {
-        s.val(vec);
+        s.result(vec);
         return vec;
     }
-    virtual result_t total() const { return s.total(); }
-    virtual void update()
+    virtual Result total() const { return s.total(); }
+    virtual VCounter &value() const { return cvec; }
+    virtual void visit(Visit &visitor)
     {
-        VectorDataBase::update();
+        update();
         s.update(this);
+        visitor.visit(*this);
     }
     virtual std::string str() const { return s.str(); }
 };
@@ -2925,7 +2614,7 @@ class Temp;
 class Formula
     : public WrapVec<Formula,
                      FormulaBase,
-                     FormulaData>
+                     FormulaStatData>
 {
   public:
     /**
@@ -2959,14 +2648,14 @@ class FormulaNode : public Node
 {
   private:
     const Formula &formula;
-    mutable rvec_t vec;
+    mutable VResult 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 const VResult &result() const { formula.result(vec); return vec; }
+    virtual Result total() const { return formula.total(); }
     virtual bool binned() const { return formula.binned(); }
 
     virtual std::string str() const { return formula.str(); }
@@ -3001,24 +2690,24 @@ class Temp
      * Create a new ScalarStatNode.
      * @param s The ScalarStat to place in a node.
      */
-    template <typename T, class Bin>
-    Temp(const Scalar<T, Bin> &s)
+    template <class Bin>
+    Temp(const Scalar<Bin> &s)
         : node(new ScalarStatNode(s.statData())) { }
 
     /**
      * Create a new ScalarStatNode.
      * @param s The ScalarStat to place in a node.
      */
-    template <typename T, class Bin>
-    Temp(const Average<T, Bin> &s)
+    template <class Bin>
+    Temp(const Average<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)
+    template <class Bin>
+    Temp(const Vector<Bin> &s)
         : node(new VectorStatNode(s.statData())) { }
 
     /**
@@ -3031,9 +2720,9 @@ class Temp
      * 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)) { }
+    template <class Storage, class Bin>
+    Temp(const ScalarProxy<Storage, Bin> &p)
+        : node(new ScalarProxyNode<Storage, Bin>(p)) { }
 
     /**
      * Create a ConstNode
@@ -3126,46 +2815,43 @@ class Temp
  */
 
 void check();
-void dump(std::ostream &stream, DisplayMode mode = DefaultMode);
-void python_start(const std::string &file);
-void python_dump(const std::string &name, const std::string &subname);
 void reset();
 void registerResetCallback(Callback *cb);
 
 inline Temp
 operator+(Temp l, Temp r)
 {
-    return NodePtr(new BinaryNode<std::plus<result_t> >(l, r));
+    return NodePtr(new BinaryNode<std::plus<Result> >(l, r));
 }
 
 inline Temp
 operator-(Temp l, Temp r)
 {
-    return NodePtr(new BinaryNode<std::minus<result_t> >(l, r));
+    return NodePtr(new BinaryNode<std::minus<Result> >(l, r));
 }
 
 inline Temp
 operator*(Temp l, Temp r)
 {
-    return NodePtr(new BinaryNode<std::multiplies<result_t> >(l, r));
+    return NodePtr(new BinaryNode<std::multiplies<Result> >(l, r));
 }
 
 inline Temp
 operator/(Temp l, Temp r)
 {
-    return NodePtr(new BinaryNode<std::divides<result_t> >(l, r));
+    return NodePtr(new BinaryNode<std::divides<Result> >(l, r));
 }
 
 inline Temp
 operator%(Temp l, Temp r)
 {
-    return NodePtr(new BinaryNode<std::modulus<result_t> >(l, r));
+    return NodePtr(new BinaryNode<std::modulus<Result> >(l, r));
 }
 
 inline Temp
 operator-(Temp l)
 {
-    return NodePtr(new UnaryNode<std::negate<result_t> >(l));
+    return NodePtr(new UnaryNode<std::negate<Result> >(l));
 }
 
 template <typename T>
@@ -3192,10 +2878,9 @@ scalar(T &val)
 inline Temp
 sum(Temp val)
 {
-    return NodePtr(new SumNode<std::plus<result_t> >(val));
+    return NodePtr(new SumNode<std::plus<Result> >(val));
 }
-extern bool PrintDescriptions;
 
-} // namespace statistics
+/* namespace Statistics */ }
 
-#endif // __STATISTICS_HH__
+#endif // __BASE_STATISTICS_HH__
diff --git a/base/stats/flags.hh b/base/stats/flags.hh
new file mode 100644 (file)
index 0000000..2303de1
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2003-2004 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __BASE_STATS_FLAGS_HH__
+#define __BASE_STATS_FLAGS_HH__
+namespace Statistics {
+
+/**
+ * Define the storage for format flags.
+ * @todo Can probably shrink this.
+ */
+typedef u_int32_t StatFlags;
+
+/** Nothing extra to print. */
+const StatFlags none =         0x00000000;
+/** This Stat is Initialized */
+const StatFlags init =         0x00000001;
+/** Print this stat. */
+const StatFlags print =                0x00000002;
+/** Print the total. */
+const StatFlags total =                0x00000010;
+/** Print the percent of the total that this entry represents. */
+const StatFlags pdf =          0x00000020;
+/** Print the cumulative percentage of total upto this entry. */
+const StatFlags cdf =          0x00000040;
+/** Print the distribution. */
+const StatFlags dist =                 0x00000080;
+/** Don't print if this is zero. */
+const StatFlags nozero =       0x00000100;
+/** Don't print if this is NAN */
+const StatFlags nonan =                0x00000200;
+/** Used for SS compatability. */
+const StatFlags __substat =    0x80000000;
+
+/** Mask of flags that can't be set directly */
+const StatFlags __reserved =   init | print | __substat;
+
+enum DisplayMode
+{
+    mode_m5,
+    mode_simplescalar
+};
+
+extern DisplayMode DefaultMode;
+
+/* namespace Statistics */ }
+
+#endif //  __BASE_STATS_FLAGS_HH__
diff --git a/base/stats/mysql.cc b/base/stats/mysql.cc
new file mode 100644 (file)
index 0000000..676bc55
--- /dev/null
@@ -0,0 +1,844 @@
+/*
+ * Copyright (c) 2003-2004 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <cassert>
+#include <map>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "base/misc.hh"
+#include "base/mysql.hh"
+#include "base/statistics.hh"
+#include "base/stats/flags.hh"
+#include "base/stats/mysql.hh"
+#include "base/stats/statdb.hh"
+#include "base/stats/types.hh"
+#include "base/str.hh"
+#include "sim/host.hh"
+
+using namespace std;
+
+namespace Statistics {
+
+struct MySqlData
+{
+    map<int, int> idmap;
+    MySQL::Connection conn;
+};
+
+int
+SetupRun(MySqlData *data, const string &name, const string &user,
+         const string &project)
+{
+    MySQL::Connection &mysql = data->conn;
+    assert(mysql.connected());
+
+    stringstream insert;
+    ccprintf(insert,
+             "INSERT INTO "
+             "runs(rn_name, rn_user, rn_project, rn_date, rn_expire)"
+             "values(\"%s\", \"%s\", \"%s\", NOW(),"
+             "DATE_ADD(CURDATE(), INTERVAL 31 DAY))",
+             name, user, project);
+
+    mysql.query(insert);
+    if (mysql.error)
+        panic("could not get a run\n%s\n", mysql.error);
+
+    return mysql.insert_id();
+}
+
+void
+DeleteRun(MySqlData *data, const string &name)
+{
+    MySQL::Connection &mysql = data->conn;
+    assert(mysql.connected());
+    stringstream sql;
+    ccprintf(sql, "DELETE FROM runs WHERE rn_name=\"%s\"", name);
+    mysql.query(sql);
+}
+
+void
+Cleanup(MySqlData *data)
+{
+    MySQL::Connection &mysql = data->conn;
+    assert(mysql.connected());
+
+    mysql.query("DELETE data "
+                "FROM data "
+                "LEFT JOIN runs ON dt_run=rn_id "
+                "WHERE rn_id IS NULL");
+
+    mysql.query("DELETE formula_ref "
+                "FROM formula_ref "
+                "LEFT JOIN runs ON fr_run=rn_id "
+                "WHERE rn_id IS NULL");
+
+    mysql.query("DELETE formulas "
+                "FROM formulas "
+                "LEFT JOIN formula_ref ON fm_stat=fr_stat "
+                "WHERE fr_stat IS NULL");
+
+    mysql.query("DELETE stats "
+                "FROM stats "
+                "LEFT JOIN data ON st_id=dt_stat "
+                "WHERE dt_stat IS NULL");
+
+    mysql.query("DELETE subdata "
+                "FROM subdata "
+                "LEFT JOIN data ON sd_stat=dt_stat "
+                "WHERE dt_stat IS NULL");
+
+    mysql.query("DELETE bins "
+                "FROM bins "
+                "LEFT JOIN data ON bn_id=dt_bin "
+                "WHERE dt_bin IS NULL");
+}
+
+void
+SetupStat::init()
+{
+    name = "";
+    descr = "";
+    type = "";
+    print = false;
+    prereq = 0;
+    prec = -1;
+    nozero = false;
+    nonan = false;
+    total = false;
+    pdf = false;
+    cdf = false;
+    min = 0;
+    max = 0;
+    bktsize = 0;
+    size = 0;
+}
+
+unsigned
+SetupStat::operator()(MySqlData *data)
+{
+    MySQL::Connection &mysql = data->conn;
+
+    stringstream insert;
+    ccprintf(insert,
+             "INSERT INTO "
+             "stats(st_name, st_descr, st_type, st_print, st_prereq, "
+             "st_prec, st_nozero, st_nonan, st_total, st_pdf, st_cdf, "
+             "st_min, st_max, st_bktsize, st_size)"
+             "values(\"%s\",\"%s\",\"%s\","
+             "        %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)",
+             name, descr, type, print, prereq, (int)prec, nozero, nonan,
+             total, pdf, cdf,
+             min, max, bktsize, size);
+
+    mysql.query(insert);
+    if (!mysql.error)
+        return mysql.insert_id();
+
+    stringstream select;
+    ccprintf(select, "SELECT * FROM stats WHERE st_name=\"%s\"", name);
+
+    mysql.query(select);
+    MySQL::Result result = mysql.store_result();
+    if (!result)
+        panic("could not get a run\n%s\n", mysql.error);
+
+
+    assert(result.num_fields() == 16);
+    MySQL::Row row = result.fetch_row();
+    if (!row)
+        panic("could not get a run\n%s\n", mysql.error);
+
+    bool tb;
+    int8_t ti8;
+    uint16_t tu16;
+    int64_t ti64;
+    uint64_t tu64;
+
+    if (name != (char *)row[1])
+        panic("failed stat check on %s:name. %s != %s\n",
+              name, name, row[1]);
+
+    if (descr != (char *)row[2])
+        panic("failed stat check on %s:descr. %s != %s\n",
+              name, descr, row[2]);
+
+    if (type != (char *)row[3])
+        panic("failed stat check on %s:type. %s != %s\n",
+              name, type, row[3]);
+
+    if (!to_number(row[4], tb) || print != tb)
+        panic("failed stat check on %s:print. %d != %d\n",
+              name, print, tb);
+
+    if (!to_number(row[6], ti8) || prec != ti8)
+        panic("failed stat check on %s:prec. %d != %d\n",
+              name, prec, ti8);
+
+    if (!to_number(row[7], tb) || nozero != tb)
+        panic("failed stat check on %s:nozero. %d != %d\n",
+              name, nozero, tb);
+
+    if (!to_number(row[8], tb) || nonan != tb)
+        panic("failed stat check on %s:nonan. %d != %d\n",
+              name, nonan, tb);
+
+    if (!to_number(row[9], tb) || total != tb)
+        panic("failed stat check on %s:total. %d != %d\n",
+              name, total, tb);
+
+    if (!to_number(row[10], tb) || pdf != tb)
+        panic("failed stat check on %s:pdf. %d != %d\n",
+              name, pdf, tb);
+
+    if (!to_number(row[11], tb) || cdf != tb)
+        panic("failed stat check on %s:cdf. %d != %d\n",
+              name, cdf, tb);
+
+    if (!to_number(row[12], ti64) || min != ti64)
+        panic("failed stat check on %s:min. %d != %d\n",
+              name, min, ti64);
+
+    if (!to_number(row[13], ti64) || max != ti64)
+        panic("failed stat check on %s:max. %d != %d\n",
+              name, max, ti64);
+
+    if (!to_number(row[14], tu64) || bktsize != tu64)
+        panic("failed stat check on %s:bktsize. %d != %d\n",
+              name, bktsize, tu64);
+
+    if (!to_number(row[15], tu16) || size != tu16)
+        panic("failed stat check on %s:size. %d != %d\n",
+              name, size, tu16);
+
+    to_number(row[5], prereq);
+    uint16_t statid;
+    to_number(row[0], statid);
+    return statid;
+}
+
+unsigned
+SetupBin(MySqlData *data, const string &bin)
+{
+    MySQL::Connection &mysql = data->conn;
+    assert(mysql.connected());
+
+    using namespace MySQL;
+    stringstream select;
+    ccprintf(select, "SELECT bn_id FROM bins WHERE bn_name=\"%s\"", bin);
+
+    mysql.query(select);
+    MySQL::Result result = mysql.store_result();
+    if (result) {
+        assert(result.num_fields() == 1);
+        Row row = result.fetch_row();
+        if (row) {
+            uint16_t bin_id;
+            to_number(row[0], bin_id);
+            return bin_id;
+        }
+    }
+
+    stringstream insert;
+    ccprintf(insert, "INSERT INTO bins(bn_name) values(\"%s\")", bin);
+
+    mysql.query(insert);
+    if (mysql.error)
+        panic("could not get a run\n%s\n", mysql.error);
+
+    return mysql.insert_id();
+}
+
+InsertData::InsertData()
+{
+    query = new char[maxsize + 1];
+    size = 0;
+    flush();
+}
+
+InsertData::~InsertData()
+{
+    delete [] query;
+}
+
+void
+InsertData::flush()
+{
+    if (size) {
+        assert(mysql && mysql->connected());
+        mysql->query(query);
+    }
+
+    query[0] = '\0';
+    size = 0;
+    first = true;
+    strcpy(query, "INSERT INTO "
+           "data(dt_stat,dt_x,dt_y,dt_run,dt_sample,dt_bin,dt_data) "
+           "values");
+    size = strlen(query);
+}
+
+void
+InsertData::insert()
+{
+    if (size + 1024 > maxsize)
+        flush();
+
+    if (!first) {
+        query[size++] = ',';
+        query[size] = '\0';
+    }
+
+    first = false;
+
+    size += sprintf(query + size, "(%u,%d,%d,%u,%llu,%u,\"%f\")",
+                    stat, x, y, run, (unsigned long long)sample, bin, data);
+}
+
+struct InsertSubData
+{
+    uint16_t stat;
+    int16_t x;
+    int16_t y;
+    string name;
+    string descr;
+
+    void operator()(MySqlData *data);
+};
+
+void
+InsertSubData::operator()(MySqlData *data)
+{
+    MySQL::Connection &mysql = data->conn;
+    assert(mysql.connected());
+    stringstream insert;
+    ccprintf(insert,
+             "INSERT INTO subdata(sd_stat,sd_x,sd_y,sd_name,sd_descr) "
+             "values(%d,%d,%d,\"%s\",\"%s\")",
+             stat, x, y, name, descr);
+
+    mysql.query(insert);
+}
+
+void
+InsertFormula(MySqlData *data, uint16_t stat, uint16_t run,
+              const string &formula)
+{
+    MySQL::Connection &mysql = data->conn;
+    assert(mysql.connected());
+    stringstream insert_formula;
+    ccprintf(insert_formula,
+             "INSERT INTO formulas(fm_stat,fm_formula) values(%d, \"%s\")",
+             stat, formula);
+
+    mysql.query(insert_formula);
+
+    stringstream insert_ref;
+    ccprintf(insert_ref,
+             "INSERT INTO formula_ref(fr_stat,fr_run) values(%d, %d)",
+             stat, run);
+
+        mysql.query(insert_ref);
+}
+
+void
+UpdatePrereq(MySqlData *data, uint16_t stat, uint16_t prereq)
+{
+    MySQL::Connection &mysql = data->conn;
+    assert(mysql.connected());
+    stringstream update;
+    ccprintf(update, "UPDATE stats SET st_prereq=%d WHERE st_id=%d",
+             prereq, stat);
+    mysql.query(update);
+}
+
+#if 0
+class InsertData
+{
+  private:
+    MySQL::Connection &mysql;
+    MySQL::Statement stmt;
+
+  public:
+    InsertData(MySqlData *data)
+        : mysql(data->conn)
+    {
+        stmt.prepare("INSERT INTO "
+                     "data(dt_stat,dt_x,dt_y,dt_run,dt_sample,dt_bin,dt_data) "
+                     "values(?,?,?,?,?,?,?)");
+        assert(stmt.count() == 7 && "param count invalid");
+
+        stmt[0].buffer = stat;
+        stmt[1].buffer = x;
+        stmt[2].buffer = y;
+        stmt[3].buffer = run;
+        stmt[4].buffer = sample;
+        stmt[5].buffer = bin;
+        stmt[6].buffer = data;
+
+        stmt.bind(bind);
+        if (stmt.error)
+            panic("bind param failed\n%s\n", stmt.error);
+    }
+
+  public:
+    uint64_t sample;
+    uint64_t data;
+    uint16_t stat;
+    uint16_t bin;
+    int16_t x;
+    int16_t y;
+
+    void operator()(MySQL::Connection &mysql)
+    {
+        assert(mysql.connected())
+        stmt();
+    }
+};
+#endif
+
+
+MySql::MySql()
+    : mysql(NULL), configured(false)
+{
+}
+
+MySql::~MySql()
+{
+    if (mysql)
+        delete mysql;
+}
+
+void
+MySql::insert(int sim_id, int db_id)
+{
+    mysql->idmap.insert(make_pair(sim_id, db_id));
+}
+
+int
+MySql::find(int sim_id)
+{
+    map<int,int>::const_iterator i = mysql->idmap.find(sim_id);
+    assert(i != mysql->idmap.end());
+    return (*i).second;
+}
+
+bool
+MySql::valid() const
+{
+    return mysql && mysql->conn.connected();
+}
+
+void
+MySql::connect(const string &host, const string &user, const string &passwd,
+               const string &db, const string &name, const string &project)
+{
+    mysql = new MySqlData;
+    newdata.mysql = &mysql->conn;
+    mysql->conn.connect(host, user, passwd, db);
+    if (mysql->conn.error)
+        panic("could not connect to database server\n%s\n", mysql->conn.error);
+
+    DeleteRun(mysql, name);
+    Cleanup(mysql);
+    run_id = SetupRun(mysql, name, user, project);
+}
+
+void
+MySql::configure()
+{
+    /*
+     * set up all stats!
+     */
+    using namespace Database;
+    stat_list_t::const_iterator i, end = stats().end();
+    for (i = stats().begin(); i != end; ++i)
+        (*i)->visit(*this);
+
+    for (i = stats().begin(); i != end; ++i) {
+        StatData *data = *i;
+        if (data->prereq) {
+            uint16_t stat_id = find(data->id);
+            uint16_t prereq_id = find(data->prereq->id);
+            assert(stat_id && prereq_id);
+
+            UpdatePrereq(mysql, stat_id, prereq_id);
+        }
+    }
+
+    configured = true;
+}
+
+
+void
+MySql::configure(const StatData &data, string type)
+{
+    stat.init();
+    stat.name = data.name;
+    stat.descr = data.desc;
+    stat.type = type;
+    stat.print = data.flags & print;
+    stat.prec = data.precision;
+    stat.nozero = data.flags & nozero;
+    stat.nonan = data.flags & nonan;
+    stat.total = data.flags & total;
+    stat.pdf = data.flags & pdf;
+    stat.cdf = data.flags & cdf;
+}
+
+void
+MySql::configure(const ScalarData &data)
+{
+    configure(data, "SCALAR");
+    insert(data.id, stat(mysql));
+}
+
+void
+MySql::configure(const VectorData &data)
+{
+    configure(data, "VECTOR");
+    uint16_t statid = stat(mysql);
+
+    if (!data.subnames.empty()) {
+        InsertSubData subdata;
+        subdata.stat = statid;
+        subdata.y = 0;
+        for (int i = 0; i < data.subnames.size(); ++i) {
+            subdata.x = i;
+            subdata.name = data.subnames[i];
+            subdata.descr = data.subdescs.empty() ? "" : data.subdescs[i];
+
+            if (!subdata.name.empty() || !subdata.descr.empty())
+                subdata(mysql);
+        }
+    }
+
+    insert(data.id, statid);
+}
+
+void
+MySql::configure(const DistData &data)
+{
+    configure(data, "DIST");
+    if (!data.data.fancy) {
+        stat.size = data.data.size;
+        stat.min = data.data.min;
+        stat.max = data.data.max;
+        stat.bktsize = data.data.bucket_size;
+    }
+    insert(data.id, stat(mysql));
+}
+
+void
+MySql::configure(const VectorDistData &data)
+{
+    configure(data, "VECTORDIST");
+
+    if (!data.data[0].fancy) {
+        stat.size = data.data[0].size;
+        stat.min = data.data[0].min;
+        stat.max = data.data[0].max;
+        stat.bktsize = data.data[0].bucket_size;
+    }
+
+    uint16_t statid = stat(mysql);
+
+    if (!data.subnames.empty()) {
+        InsertSubData subdata;
+        subdata.stat = statid;
+        subdata.y = 0;
+        for (int i = 0; i < data.subnames.size(); ++i) {
+            subdata.x = i;
+            subdata.name = data.subnames[i];
+            subdata.descr = data.subdescs.empty() ? "" : data.subdescs[i];
+            if (!subdata.name.empty() || !subdata.descr.empty())
+                subdata(mysql);
+        }
+    }
+
+    insert(data.id, statid);
+}
+
+void
+MySql::configure(const Vector2dData &data)
+{
+    configure(data, "VECTOR2D");
+    uint16_t statid = stat(mysql);
+
+    if (!data.subnames.empty()) {
+        InsertSubData subdata;
+        subdata.stat = statid;
+        subdata.y = 0;
+        for (int i = 0; i < data.subnames.size(); ++i) {
+            subdata.x = i;
+            subdata.name = data.subnames[i];
+            subdata.descr = data.subdescs.empty() ? "" : data.subdescs[i];
+            if (!subdata.name.empty() || !subdata.descr.empty())
+                subdata(mysql);
+        }
+    }
+
+    if (!data.y_subnames.empty()) {
+        InsertSubData subdata;
+        subdata.stat = statid;
+        subdata.x = 0;
+        subdata.descr = "";
+        for (int i = 0; i < data.y_subnames.size(); ++i) {
+            subdata.y = i;
+            subdata.name = data.y_subnames[i];
+            if (!subdata.name.empty())
+                subdata(mysql);
+        }
+    }
+
+    insert(data.id, statid);
+}
+
+void
+MySql::configure(const FormulaData &data)
+{
+    configure(data, "FORMULA");
+    insert(data.id, stat(mysql));
+}
+
+void
+MySql::output(const string &bin)
+{
+    // set up new bin in database if there is a bin name
+    newdata.bin = bin.empty() ? 0 : SetupBin(mysql, bin);
+
+    Database::stat_list_t::const_iterator i, end = Database::stats().end();
+    for (i = Database::stats().begin(); i != end; ++i)
+        (*i)->visit(*this);
+}
+
+void
+MySql::output()
+{
+    using namespace Database;
+    assert(valid());
+
+    if (!configured)
+        configure();
+
+    // store sample #
+    newdata.run = run_id;
+    newdata.sample = curTick;
+
+    if (bins().empty()) {
+        output(string(""));
+    } else {
+        bin_list_t::iterator i, end = bins().end();
+        for (i = bins().begin(); i != end; ++i) {
+            MainBin *bin = *i;
+            bin->activate();
+            output(bin->name());
+        }
+    }
+
+    newdata.flush();
+}
+
+void
+MySql::output(const ScalarData &data)
+{
+    newdata.stat = find(data.id);
+    newdata.x = 0;
+    newdata.y = 0;
+    newdata.data = data.value();
+
+    newdata.insert();
+}
+
+void
+MySql::output(const VectorData &data)
+{
+    newdata.stat = find(data.id);
+    newdata.y = 0;
+
+    const VCounter &cvec = data.value();
+    int size = data.size();
+    for (int x = 0; x < size; x++) {
+        newdata.x = x;
+        newdata.data = cvec[x];
+        newdata.insert();
+    }
+}
+
+void
+MySql::output(const DistDataData &data)
+{
+    const int db_sum = -1;
+    const int db_squares = -2;
+    const int db_samples = -3;
+    const int db_min_val = -4;
+    const int db_max_val = -5;
+    const int db_underflow = -6;
+    const int db_overflow = -7;
+
+    newdata.x = db_sum;
+    newdata.data = data.sum;
+    newdata.insert();
+
+    newdata.x = db_squares;
+    newdata.data = data.squares;
+    newdata.insert();
+
+    newdata.x = db_samples;
+    newdata.data = data.samples;
+    newdata.insert();
+
+    if (data.samples && !data.fancy) {
+        newdata.x = db_min_val;
+        newdata.data = data.min_val;
+        newdata.insert();
+
+        newdata.x = db_max_val;
+        newdata.data = data.max_val;
+        newdata.insert();
+
+        newdata.x = db_underflow;
+        newdata.data = data.underflow;
+        newdata.insert();
+
+        newdata.x = db_overflow;
+        newdata.data = data.overflow;
+        newdata.insert();
+
+        int size = data.cvec.size();
+        for (int x = 0; x < size; x++) {
+            newdata.x = x;
+            newdata.data = data.cvec[x];
+            newdata.insert();
+        }
+    }
+}
+
+
+void
+MySql::output(const DistData &data)
+{
+    newdata.stat = find(data.id);
+    newdata.y = 0;
+    output(data.data);
+}
+
+void
+MySql::output(const VectorDistData &data)
+{
+    newdata.stat = find(data.id);
+
+    int size = data.data.size();
+    for (int y = 0; y < size; ++y) {
+        newdata.y = y;
+        output(data.data[y]);
+    }
+}
+
+void
+MySql::output(const Vector2dData &data)
+{
+    newdata.stat = find(data.id);
+
+    int index = 0;
+    for (int x = 0; x < data.x; x++) {
+        newdata.x = x;
+        for (int y = 0; y < data.y; y++) {
+            newdata.y = y;
+            newdata.data = data.cvec[index++];
+            newdata.insert();
+        }
+    }
+}
+
+void
+MySql::output(const FormulaData &data)
+{
+    InsertFormula(mysql, find(data.id), run_id, data.str());
+}
+
+/*
+ * Implement the visitor
+ */
+void
+MySql::visit(const ScalarData &data)
+{
+    if (!configured)
+        configure(data);
+    else
+        output(data);
+}
+
+void
+MySql::visit(const VectorData &data)
+{
+    if (!configured)
+        configure(data);
+    else
+        output(data);
+}
+
+void
+MySql::visit(const DistData &data)
+{
+    if (!configured)
+        configure(data);
+    else
+        output(data);
+}
+
+void
+MySql::visit(const VectorDistData &data)
+{
+    if (!configured)
+        configure(data);
+    else
+        output(data);
+}
+
+void
+MySql::visit(const Vector2dData &data)
+{
+    if (!configured)
+        configure(data);
+    else
+        output(data);
+}
+
+void
+MySql::visit(const FormulaData &data)
+{
+    if (!configured)
+        configure(data);
+    else
+        output(data);
+}
+
+/* namespace Statistics */ }
diff --git a/base/stats/mysql.hh b/base/stats/mysql.hh
new file mode 100644 (file)
index 0000000..4ff4747
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2003-2004 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __BASE_STATS_MYSQL_HH__
+#define __BASE_STATS_MYSQL_HH__
+
+#include <string>
+
+#include "base/stats/output.hh"
+
+namespace MySQL { class Connection; }
+namespace Statistics {
+
+class DistDataData;
+class MySqlData;
+
+struct SetupStat
+{
+    std::string name;
+    std::string descr;
+    std::string type;
+    bool print;
+    uint16_t prereq;
+    int8_t prec;
+    bool nozero;
+    bool nonan;
+    bool total;
+    bool pdf;
+    bool cdf;
+    double min;
+    double max;
+    double bktsize;
+    uint16_t size;
+
+    void init();
+    unsigned operator()(MySqlData *data);
+};
+
+class InsertData
+{
+  private:
+    char *query;
+    int size;
+    bool first;
+    static const int maxsize = 1024*1024;
+
+  public:
+    MySQL::Connection *mysql;
+
+  public:
+    uint64_t sample;
+    double data;
+    uint16_t stat;
+    uint16_t bin;
+    uint16_t run;
+    int16_t x;
+    int16_t y;
+
+  public:
+    InsertData();
+    ~InsertData();
+
+    void flush();
+    void insert();
+};
+
+class MySql : public Output
+{
+  protected:
+    std::list<FormulaData *> formulas;
+    MySqlData *mysql;
+    bool configured;
+    uint16_t run_id;
+
+    SetupStat stat;
+    InsertData newdata;
+
+    void insert(int sim_id, int db_id);
+    int find(int sim_id);
+
+  public:
+    MySql();
+    ~MySql();
+
+    void connect(const std::string &host, const std::string &user,
+                 const std::string &passwd, const std::string &db,
+                 const std::string &name, const std::string &project);
+
+    // Implement Visit
+    virtual void visit(const ScalarData &data);
+    virtual void visit(const VectorData &data);
+    virtual void visit(const DistData &data);
+    virtual void visit(const VectorDistData &data);
+    virtual void visit(const Vector2dData &data);
+    virtual void visit(const FormulaData &data);
+
+    // Implement Output
+    virtual bool valid() const;
+    virtual void output();
+
+  protected:
+    // Output helper
+    void output(const std::string &bin);
+    void output(const DistDataData &data);
+    void output(const ScalarData &data);
+    void output(const VectorData &data);
+    void output(const DistData &data);
+    void output(const VectorDistData &data);
+    void output(const Vector2dData &data);
+    void output(const FormulaData &data);
+
+    void configure();
+    void configure(const StatData &data, std::string type);
+    void configure(const ScalarData &data);
+    void configure(const VectorData &data);
+    void configure(const DistData &data);
+    void configure(const VectorDistData &data);
+    void configure(const Vector2dData &data);
+    void configure(const FormulaData &data);
+};
+
+/* namespace Statistics */ }
+
+#endif // __BASE_STATS_MYSQL_HH__
diff --git a/base/stats/output.hh b/base/stats/output.hh
new file mode 100644 (file)
index 0000000..9f1fbf4
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2003-2004 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __BASE_STATS_OUTPUT_HH__
+#define __BASE_STATS_OUTPUT_HH__
+
+#include <string>
+
+#include "base/stats/visit.hh"
+
+namespace Statistics {
+
+struct Output : public Visit
+{
+    inline void operator()() { output(); }
+    virtual void output() = 0;
+    virtual bool valid() const = 0;
+};
+
+/* namespace Statistics */ }
+
+#endif // __BASE_STATS_OUTPUT_HH__
diff --git a/base/stats/statdb.cc b/base/stats/statdb.cc
new file mode 100644 (file)
index 0000000..f54272a
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2003-2004 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "base/misc.hh"
+#include "base/trace.hh"
+#include "base/statistics.hh"
+#include "base/stats/bin.hh"
+#include "base/stats/statdb.hh"
+
+using namespace std;
+
+namespace Statistics {
+namespace Database {
+
+StatData *
+find(void *stat)
+{
+    stat_map_t::const_iterator i = map().find(stat);
+
+    if (i == map().end())
+        return NULL;
+
+    return (*i).second;
+}
+
+void
+regBin(MainBin *bin, const std::string &_name)
+{
+    bins().push_back(bin);
+    DPRINTF(Stats, "registering %s\n", _name);
+}
+
+void
+regStat(void *stat, StatData *data)
+{
+    if (map().find(stat) != map().end())
+        panic("shouldn't register stat twice!");
+
+    stats().push_back(data);
+
+#ifndef NDEBUG
+    pair<stat_map_t::iterator, bool> result =
+#endif
+        map().insert(make_pair(stat, data));
+    assert(result.second && "this should never fail");
+    assert(map().find(stat) != map().end());
+}
+
+void
+regPrint(void *stat)
+{
+    StatData *data = find(stat);
+    assert(data);
+    data->flags |= print;
+}
+
+TheDatabase &db()
+{
+    static TheDatabase db;
+    return db;
+}
+
+/* namespace Database */ }
+/* namespace Statistics */ }
diff --git a/base/stats/statdb.hh b/base/stats/statdb.hh
new file mode 100644 (file)
index 0000000..fb672e1
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2003-2004 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __BASE_STATS_STATDB_HH__
+#define __BASE_STATS_STATDB_HH__
+
+#include <iosfwd>
+#include <list>
+#include <map>
+#include <string>
+
+class Python;
+
+namespace Statistics {
+
+class MainBin;
+class StatData;
+
+namespace Database {
+
+typedef std::map<void *, StatData *> stat_map_t;
+typedef std::list<StatData *> stat_list_t;
+typedef std::list<MainBin *> bin_list_t;
+
+// We wrap the database in a struct to make sure it is built in time.
+struct TheDatabase
+{
+    stat_map_t map;
+    stat_list_t stats;
+    bin_list_t bins;
+
+};
+
+TheDatabase &db();
+inline stat_map_t &map() { return db().map; }
+inline stat_list_t &stats() { return db().stats; }
+inline bin_list_t &bins() { return db().bins; }
+
+StatData *find(void *stat);
+void regBin(MainBin *bin, const std::string &name);
+void regStat(void *stat, StatData *data);
+void regPrint(void *stat);
+
+inline std::string name() { return "Statistics Database"; }
+
+/* namespace Database */ }
+/* namespace Statistics */ }
+
+#endif // __BASE_STATS_STATDB_HH__
diff --git a/base/stats/text.cc b/base/stats/text.cc
new file mode 100644 (file)
index 0000000..0f43a17
--- /dev/null
@@ -0,0 +1,731 @@
+/*
+ * Copyright (c) 2003-2004 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <iostream>
+#include <fstream>
+#include <string>
+
+#include "base/misc.hh"
+#include "base/statistics.hh"
+#include "base/stats/statdb.hh"
+#include "base/stats/text.hh"
+#include "base/stats/visit.hh"
+
+using namespace std;
+
+#ifndef NAN
+float __nan();
+/** Define Not a number. */
+#define NAN (__nan())
+/** Need to define __nan() */
+#define __M5_NAN
+#endif
+
+#ifdef __M5_NAN
+float
+__nan()
+{
+    union {
+        uint32_t ui;
+        float f;
+    } nan;
+
+    nan.ui = 0x7fc00000;
+    return nan.f;
+}
+#endif
+
+namespace Statistics {
+
+Text::Text()
+    : mystream(false), stream(NULL), compat(false), descriptions(false)
+{
+}
+
+Text::Text(std::ostream &stream)
+    : mystream(false), stream(NULL), compat(false), descriptions(false)
+{
+    open(stream);
+}
+
+Text::Text(const std::string &file)
+    : mystream(false), stream(NULL), compat(false), descriptions(false)
+{
+    open(file);
+}
+
+
+Text::~Text()
+{
+    if (mystream) {
+        assert(stream);
+        delete stream;
+    }
+}
+
+void
+Text::open(std::ostream &_stream)
+{
+    if (stream)
+        panic("stream already set!");
+
+    mystream = false;
+    stream = &_stream;
+    assert(valid());
+}
+
+void
+Text::open(const std::string &file)
+{
+    if (stream)
+        panic("stream already set!");
+
+    mystream = true;
+    stream = new ofstream(file.c_str(), ios::trunc);
+    assert(valid());
+}
+
+bool
+Text::valid() const
+{
+    return stream != NULL;
+}
+
+void
+Text::output()
+{
+    using namespace Database;
+
+    ccprintf(*stream, "\n---------- Begin Simulation Statistics ----------\n");
+    if (bins().empty()) {
+        stat_list_t::const_iterator i, end = stats().end();
+        for (i = stats().begin(); i != end; ++i)
+            (*i)->visit(*this);
+    } else {
+        ccprintf(*stream, "PRINTING BINNED STATS\n");
+        bin_list_t::iterator i, end = bins().end();
+        for (i = bins().begin(); i != end; ++i) {
+            MainBin *bin = *i;
+            bin->activate();
+            ccprintf(*stream,"---%s Bin------------\n", bin);
+            stat_list_t::const_iterator i, end = stats().end();
+            for (i = stats().begin(); i != end; ++i)
+                (*i)->visit(*this);
+            ccprintf(*stream, "---------------------------------\n");
+        }
+    }
+    ccprintf(*stream, "\n---------- End Simulation Statistics   ----------\n");
+    stream->flush();
+}
+
+bool
+Text::noOutput(const StatData &data)
+{
+    if (!(data.flags & print))
+        return true;
+
+    if (data.prereq && data.prereq->zero())
+        return true;
+
+    return false;
+}
+
+string
+ValueToString(Result value, int precision, bool compat)
+{
+    stringstream val;
+
+    if (!isnan(value)) {
+        if (precision != -1)
+            val.precision(precision);
+        else if (value == rint(value))
+            val.precision(0);
+
+        val.unsetf(ios::showpoint);
+        val.setf(ios::fixed);
+        val << value;
+    } else {
+        val << (compat ? "<err: div-0>" : "no value");
+    }
+
+    return val.str();
+}
+
+struct ScalarPrint
+{
+    Result value;
+    string name;
+    string desc;
+    StatFlags flags;
+    bool compat;
+    bool descriptions;
+    int precision;
+    Result pdf;
+    Result cdf;
+
+    void operator()(ostream &stream) const;
+};
+
+void
+ScalarPrint::operator()(ostream &stream) const
+{
+    if (flags & nozero && value == 0.0 ||
+        flags & nonan && isnan(value))
+        return;
+
+    stringstream pdfstr, cdfstr;
+
+    if (!isnan(pdf))
+        ccprintf(pdfstr, "%.2f%%", pdf * 100.0);
+
+    if (!isnan(cdf))
+        ccprintf(cdfstr, "%.2f%%", cdf * 100.0);
+
+    if (compat && flags & __substat) {
+        ccprintf(stream, "%32s %12s %10s %10s", name,
+                 ValueToString(value, precision, compat), pdfstr, cdfstr);
+    } else {
+        ccprintf(stream, "%-40s %12s %10s %10s", name,
+                 ValueToString(value, precision, compat), pdfstr, cdfstr);
+    }
+
+    if (descriptions) {
+        if (!desc.empty())
+            ccprintf(stream, " # %s", desc);
+    }
+    stream << endl;
+}
+
+struct VectorPrint
+{
+    string name;
+    string desc;
+    vector<string> subnames;
+    vector<string> subdescs;
+    StatFlags flags;
+    bool compat;
+    bool descriptions;
+    int precision;
+    VResult vec;
+    Result total;
+
+    void operator()(ostream &stream) const;
+};
+
+void
+VectorPrint::operator()(std::ostream &stream) const
+{
+    int _size = vec.size();
+    Result _total = 0.0;
+
+    if (flags & (pdf | cdf)) {
+        for (int i = 0; i < _size; ++i) {
+            _total += vec[i];
+        }
+    }
+
+    string base = name + (compat ? "_" : "::");
+
+    ScalarPrint print;
+    print.name = name;
+    print.desc = desc;
+    print.precision = precision;
+    print.descriptions = descriptions;
+    print.flags = flags;
+    print.pdf = NAN;
+    print.cdf = NAN;
+
+    bool havesub = !subnames.empty();
+
+    if (_size == 1) {
+        print.value = vec[0];
+        print(stream);
+    } else if (!compat) {
+        for (int i = 0; i < _size; ++i) {
+            if (havesub && (i >= subnames.size() || subnames[i].empty()))
+                continue;
+
+            print.name = base + (havesub ? subnames[i] : to_string(i));
+            print.desc = subdescs.empty() ? desc : subdescs[i];
+            print.value = vec[i];
+
+            if (_total && (flags & pdf)) {
+                print.pdf = vec[i] / _total;
+                print.cdf += print.pdf;
+            }
+
+            print(stream);
+        }
+
+        if (flags & ::Statistics::total) {
+            print.name = base + "total";
+            print.desc = desc;
+            print.value = total;
+            print(stream);
+        }
+    } else {
+        if (flags & ::Statistics::total) {
+            print.value = total;
+            print(stream);
+        }
+
+        Result _pdf = 0.0;
+        Result _cdf = 0.0;
+        if (flags & dist) {
+            ccprintf(stream, "%s.start_dist\n", name);
+            for (int i = 0; i < _size; ++i) {
+                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", name);
+        } else {
+            for (int i = 0; i < _size; ++i) {
+                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 {
+                    _pdf = _cdf = NAN;
+                }
+
+                if (flags & pdf) {
+                    print.pdf = _pdf;
+                    print.cdf = _cdf;
+                }
+
+                print(stream);
+            }
+        }
+    }
+}
+
+struct DistPrint
+{
+    string name;
+    string desc;
+    StatFlags flags;
+    bool compat;
+    bool descriptions;
+    int precision;
+
+    Result min_val;
+    Result max_val;
+    Result underflow;
+    Result overflow;
+    VResult vec;
+    Result sum;
+    Result squares;
+    Result samples;
+
+    Counter min;
+    Counter max;
+    Counter bucket_size;
+    int size;
+    bool fancy;
+
+    void operator()(ostream &stream) const;
+};
+
+void
+DistPrint::operator()(ostream &stream) const
+{
+    if (fancy) {
+        ScalarPrint print;
+        string base = name + (compat ? "_" : "::");
+
+        print.precision = precision;
+        print.flags = flags;
+        print.compat = compat;
+        print.descriptions = descriptions;
+        print.desc = desc;
+        print.pdf = NAN;
+        print.cdf = NAN;
+
+        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 total = 0.0;
+
+    total += underflow;
+    for (int i = 0; i < size; ++i)
+        total += vec[i];
+    total += overflow;
+
+    string base = name + (compat ? "." : "::");
+
+    ScalarPrint print;
+    print.desc = compat ? "" : desc;
+    print.flags = flags;
+    print.compat = compat;
+    print.descriptions = descriptions;
+    print.precision = precision;
+    print.pdf = NAN;
+    print.cdf = NAN;
+
+    if (compat) {
+        ccprintf(stream, "%-42s", base + "start_dist");
+        if (descriptions && !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 (!compat || underflow > 0.0) {
+        print.name = base + "underflows";
+        print.value = underflow;
+        if (!compat && total) {
+            print.pdf = underflow / total;
+            print.cdf += print.pdf;
+        }
+        print(stream);
+    }
+
+
+    if (!compat) {
+        for (int i = 0; i < size; ++i) {
+            stringstream namestr;
+            namestr << name;
+
+            Counter low = i * bucket_size + min;
+            Counter high = ::min(low + bucket_size, 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 {
+        Counter _min;
+        Result _pdf;
+        Result _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, 0, compat);
+            print.value = vec[i];
+            print.pdf = (flags & pdf) ? _pdf : NAN;
+            print.cdf = (flags & cdf) ? _cdf : NAN;
+            print(stream);
+        }
+
+        print.flags = flags;
+    }
+
+    if (!compat || overflow > 0.0) {
+        print.name = base + "overflows";
+        print.value = overflow;
+        if (!compat && total) {
+            print.pdf = overflow / total;
+            print.cdf += print.pdf;
+        } else {
+            print.pdf = NAN;
+            print.cdf = NAN;
+        }
+        print(stream);
+    }
+
+    print.pdf = NAN;
+    print.cdf = NAN;
+
+    if (!compat) {
+        print.name = base + "total";
+        print.value = total;
+        print(stream);
+    }
+
+    print.name = base + "max_value";
+    print.value = max_val;
+    print(stream);
+
+    if (!compat && 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);
+    }
+
+    if (compat)
+        ccprintf(stream, "%send_dist\n\n", base);
+}
+
+void
+Text::visit(const ScalarData &data)
+{
+    if (noOutput(data))
+        return;
+
+    ScalarPrint print;
+    print.value = data.result();
+    print.name = data.name;
+    print.desc = data.desc;
+    print.flags = data.flags;
+    print.compat = compat;
+    print.descriptions = descriptions;
+    print.precision = data.precision;
+    print.pdf = NAN;
+    print.cdf = NAN;
+
+    print(*stream);
+}
+
+void
+Text::visit(const VectorData &data)
+{
+    if (noOutput(data))
+        return;
+
+    int size = data.size();
+    VectorPrint print;
+
+    print.name = data.name;
+    print.desc = data.desc;
+    print.flags = data.flags;
+    print.compat = compat;
+    print.descriptions = descriptions;
+    print.precision = data.precision;
+    print.vec = data.result();
+    print.total = data.total();
+
+    if (!data.subnames.empty()) {
+        for (int i = 0; i < size; ++i) {
+            if (!data.subnames[i].empty()) {
+                print.subnames = data.subnames;
+                print.subnames.resize(size);
+                for (int i = 0; i < size; ++i) {
+                    if (!data.subnames[i].empty() &&
+                        !data.subdescs[i].empty()) {
+                        print.subdescs = data.subdescs;
+                        print.subdescs.resize(size);
+                        break;
+                    }
+                }
+                break;
+            }
+        }
+    }
+
+    print(*stream);
+}
+
+void
+Text::visit(const Vector2dData &data)
+{
+    if (noOutput(data))
+        return;
+
+    bool havesub = false;
+    VectorPrint print;
+
+    print.subnames = data.y_subnames;
+    print.flags = data.flags;
+    print.compat = compat;
+    print.descriptions = descriptions;
+    print.precision = data.precision;
+
+    if (!data.subnames.empty()) {
+        for (int i = 0; i < data.x; ++i)
+            if (!data.subnames[i].empty())
+                havesub = true;
+    }
+
+    VResult tot_vec(data.y);
+    Result super_total = 0.0;
+    for (int i = 0; i < data.x; ++i) {
+        if (havesub && (i >= data.subnames.size() || data.subnames[i].empty()))
+            continue;
+
+        int iy = i * data.y;
+        VResult yvec(data.y);
+
+        Result total = 0.0;
+        for (int j = 0; j < data.y; ++j) {
+            yvec[j] = data.cvec[iy + j];
+            tot_vec[j] += yvec[j];
+            total += yvec[j];
+            super_total += yvec[j];
+        }
+
+        print.name = data.name + "_" + (havesub ? data.subnames[i] : to_string(i));
+        print.desc = data.desc;
+        print.vec = yvec;
+        print.total = total;
+        print(*stream);
+    }
+
+    if ((data.flags & ::Statistics::total) && (data.x > 1)) {
+        print.name = data.name;
+        print.desc = data.desc;
+        print.vec = tot_vec;
+        print.total = super_total;
+        print(*stream);
+    }
+}
+
+void
+Text::visit(const DistData &data)
+{
+    if (noOutput(data))
+        return;
+
+    DistPrint print;
+
+    print.name = data.name;
+    print.desc = data.desc;
+    print.flags = data.flags;
+    print.compat = compat;
+    print.descriptions = descriptions;
+    print.precision = data.precision;
+
+    print.min_val = data.data.min_val;
+    print.max_val = data.data.max_val;
+    print.underflow = data.data.underflow;
+    print.overflow = data.data.overflow;
+    print.vec.resize(data.data.cvec.size());
+    for (int i = 0; i < print.vec.size(); ++i)
+        print.vec[i] = (Result)data.data.cvec[i];
+    print.sum = data.data.sum;
+    print.squares = data.data.squares;
+    print.samples = data.data.samples;
+
+    print.min = data.data.min;
+    print.max = data.data.max;
+    print.bucket_size = data.data.bucket_size;
+    print.size = data.data.size;
+    print.fancy = data.data.fancy;
+
+    print(*stream);
+}
+
+void
+Text::visit(const VectorDistData &data)
+{
+    if (noOutput(data))
+        return;
+
+    for (int i = 0; i < data.size(); ++i) {
+        DistPrint print;
+
+        print.name = data.name +
+            (data.subnames[i].empty() ? ("_" + to_string(i)) : data.subnames[i]);
+        print.desc = data.subdescs[i].empty() ? data.desc : data.subdescs[i];
+        print.flags = data.flags;
+        print.compat = compat;
+        print.descriptions = descriptions;
+        print.precision = data.precision;
+
+        print.min_val = data.data[i].min_val;
+        print.max_val = data.data[i].max_val;
+        print.underflow = data.data[i].underflow;
+        print.overflow = data.data[i].overflow;
+        print.vec.resize(data.data[i].cvec.size());
+        for (int j = 0; j < print.vec.size(); ++j)
+            print.vec[j] = (Result)data.data[i].cvec[j];
+        print.sum = data.data[i].sum;
+        print.squares = data.data[i].squares;
+        print.samples = data.data[i].samples;
+
+        print.min = data.data[i].min;
+        print.max = data.data[i].max;
+        print.bucket_size = data.data[i].bucket_size;
+        print.size = data.data[i].size;
+        print.fancy = data.data[i].fancy;
+
+        print(*stream);
+    }
+}
+
+void
+Text::visit(const FormulaData &data)
+{
+    visit((const VectorData &)data);
+}
+
+/* namespace Statistics */ }
diff --git a/base/stats/text.hh b/base/stats/text.hh
new file mode 100644 (file)
index 0000000..89bddf0
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2003-2004 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __BASE_STATS_TEXT_HH__
+#define __BASE_STATS_TEXT_HH__
+
+#include <iosfwd>
+#include <string>
+
+#include "base/stats/output.hh"
+
+namespace Statistics {
+
+class Text : public Output
+{
+  protected:
+    bool mystream;
+    std::ostream *stream;
+
+  protected:
+    bool noOutput(const StatData &data);
+    void binout();
+
+  public:
+    bool compat;
+    bool descriptions;
+
+  public:
+    Text();
+    Text(std::ostream &stream);
+    Text(const std::string &file);
+    ~Text();
+
+    void open(std::ostream &stream);
+    void open(const std::string &file);
+
+    // Implement Visit
+    virtual void visit(const ScalarData &data);
+    virtual void visit(const VectorData &data);
+    virtual void visit(const DistData &data);
+    virtual void visit(const VectorDistData &data);
+    virtual void visit(const Vector2dData &data);
+    virtual void visit(const FormulaData &data);
+
+    // Implement Output
+    virtual bool valid() const;
+    virtual void output();
+};
+
+/* namespace Statistics */ }
+
+#endif // __BASE_STATS_TEXT_HH__
diff --git a/base/stats/types.hh b/base/stats/types.hh
new file mode 100644 (file)
index 0000000..4451c4e
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2003-2004 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __BASE_STATS_TYPES_HH__
+#define __BASE_STATS_TYPES_HH__
+
+#include <vector>
+#include <inttypes.h>
+
+namespace Statistics {
+
+/** All counters are of 64-bit values. */
+typedef double Counter;
+/** vector of counters. */
+typedef std::vector<Counter> VCounter;
+
+/** All results are doubles. */
+typedef double Result;
+/** vector of results. */
+typedef std::vector<Result> VResult;
+
+/* namespace Statistics */ }
+
+#endif // __BASE_STATS_TYPES_HH__
diff --git a/base/stats/visit.cc b/base/stats/visit.cc
new file mode 100644 (file)
index 0000000..fec11b2
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2003-2004 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "base/stats/visit.hh"
+
+namespace Statistics {
+namespace Detail {
+
+Visit::Visit()
+{}
+
+Visit::~Visit()
+{}
+
+/* namespace Detail */ }
+/* namespace Statistics */ }
diff --git a/base/stats/visit.hh b/base/stats/visit.hh
new file mode 100644 (file)
index 0000000..a03842c
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2003-2004 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __BASE_STATS_VISIT_HH__
+#define __BASE_STATS_VISIT_HH__
+
+#include <string>
+
+#include "base/time.hh"
+#include "sim/host.hh"
+
+namespace Statistics {
+
+class StatData;
+class ScalarData;
+class VectorData;
+class DistDataData;
+class DistData;
+class VectorDistData;
+class Vector2dData;
+class FormulaData;
+
+struct Visit
+{
+    Visit();
+    virtual ~Visit();
+
+    virtual void visit(const ScalarData &data) = 0;
+    virtual void visit(const VectorData &data) = 0;
+    virtual void visit(const DistData &data) = 0;
+    virtual void visit(const VectorDistData &data) = 0;
+    virtual void visit(const Vector2dData &data) = 0;
+    virtual void visit(const FormulaData &data) = 0;
+};
+
+/* namespace Statistics */ }
+
+#endif // __BASE_STATS_VISIT_HH__
diff --git a/base/traceflags.py b/base/traceflags.py
new file mode 100644 (file)
index 0000000..79a5444
--- /dev/null
@@ -0,0 +1,340 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2004 The Regents of The University of Michigan
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met: redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer;
+# redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution;
+# neither the name of the copyright holders nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#
+# This file generates the header and source files for the flags
+# that control the tracing facility.
+#
+hhfilename="traceflags.hh"
+ccfilename="traceflags.cc"
+
+#
+# The list of trace flags that can be used to condition DPRINTFs etc.
+# To define a new flag, simply add it to this list.
+#
+baseFlags = [
+    'TCPIP',
+    'Bus',
+    'ScsiDisk',
+    'ScsiCtrl',
+    'ScsiNone',
+    'DMA',
+    'DMAReadVerbose',
+    'DMAWriteVerbose',
+    'TLB',
+    'SimpleDisk',
+    'SimpleDiskData',
+    'Clock',
+    'Regs',
+    'MC146818',
+    'IPI',
+    'Timer',
+    'Mbox',
+    'PCIA',
+    'PCIDEV',
+    'ISP',
+    'BADADDR',
+    'Console',
+    'ConsolePoll',
+    'ConsoleVerbose',
+    'TlaserUart',
+    'AlphaConsole',
+    'Flow',
+    'Interrupt',
+    'Cycle',
+    'Loader',
+    'MMU',
+    'Ethernet',
+    'EthernetPIO',
+    'EthernetDMA',
+    'EthernetData',
+    'GDBMisc',
+    'GDBAcc',
+    'GDBRead',
+    'GDBWrite',
+    'GDBSend',
+    'GDBRecv',
+    'GDBExtra',
+    'VtoPhys',
+    'Printf',
+    'DebugPrintf',
+    'Serialize',
+    'Event',
+    'PCEvent',
+    'SyscallWarnings',
+    'SyscallVerbose',
+    'DiskImage',
+    'DiskImageRead',
+    'DiskImageWrite',
+    'InstExec',
+    'BPredRAS',
+    'Cache',
+    'IIC',
+    'IICMore',
+    'MSHR',
+    'Chains',
+    'Dispatch',
+    'Stats',
+    'Context',
+    'Config',
+    'Sampler',
+    'WriteBarrier'
+    ]
+
+#
+# "Compound" flags correspond to a set of base flags.  These exist
+# solely for convenience in setting them via the command line: if a
+# compound flag is specified, all of the corresponding base flags are
+# set.  Compound flags cannot be used directly in DPRINTFs etc.
+# To define a new compound flag, add a new entry to this hash
+# following the existing examples.
+#
+compoundFlagMap = {
+    'GDBAll' : [ 'GDBMisc', 'GDBAcc', 'GDBRead', 'GDBWrite', 'GDBSend', 'GDBRecv', 'GDBExtra' ],
+    'ScsiAll' : [ 'ScsiDisk', 'ScsiCtrl', 'ScsiNone' ],
+    'DiskImageAll' : [ 'DiskImage', 'DiskImageRead', 'DiskImageWrite' ],
+    'EthernetAll' : [ 'Ethernet', 'EthernetPIO', 'EthernetDMA', 'EthernetData' ]
+}
+
+#############################################################
+#
+# Everything below this point generates the appropriate C++
+# declarations and definitions for the trace flags.  If you are simply
+# adding or modifying flag definitions, you should not have to change
+# anything below.
+#
+
+import sys
+
+# extract just the compound flag names into a list
+compoundFlags = []
+compoundFlags.extend(compoundFlagMap.keys())
+#for flags in compoundFlagMap.keys():
+#    compoundFlags.append(flags)
+print 'compound', compoundFlags
+compoundFlags.sort()
+print 'compound', compoundFlags
+
+#
+# First generate the header file.  This defines the Flag enum
+# and some extern declarations for the .cc file.
+#
+try:
+    hhfile = file(hhfilename, 'w')
+except IOError, e:
+    sys.exit("can't open %s: %s" % (hhfilename, e))
+
+# file header boilerplate
+print >>hhfile, '''/* $Id $ */
+
+/*
+ * Copyright (c) 2004
+ * The Regents of The University of Michigan
+ * All Rights Reserved
+ *
+ * This code is part of the M5 simulator, developed by Nathan Binkert,
+ * Erik Hallnor, Steve Raasch, and Steve Reinhardt, with contributions
+ * from Ron Dreslinski, Dave Greene, and Lisa Hsu.
+ *
+ * Permission is granted to use, copy, create derivative works and
+ * redistribute this software and such derivative works for any
+ * purpose, so long as the copyright notice above, this grant of
+ * permission, and the disclaimer below appear in all copies made; and
+ * so long as the name of The University of Michigan is not used in
+ * any advertising or publicity pertaining to the use or distribution
+ * of this software without specific, written prior authorization.
+ *
+ * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE
+ * UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND
+ * WITHOUT WARRANTY BY THE UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE. THE REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE
+ * LIABLE FOR ANY DAMAGES, INCLUDING DIRECT, SPECIAL, INDIRECT,
+ * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM
+ * ARISING OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
+ * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGES.
+ */
+
+/*
+ * DO NOT EDIT THIS FILE!
+ *
+ * Automatically generated from traceflags.py
+ */
+
+#ifndef __BASE_TRACE_FLAGS_HH__
+#define __BASE_TRACE_FLAGS_HH__
+
+namespace Trace {
+
+enum Flags {
+''',
+
+# Generate the enum.  Base flags come first, then compound flags.
+idx = 0
+for flag in baseFlags:
+    print >>hhfile, '    %s = %d,' % (flag, idx)
+    idx += 1
+
+numBaseFlags = idx
+print >>hhfile, '    NumFlags = %d,' % idx
+
+# put a comment in here to separate base from compound flags
+print >>hhfile, '''
+    // The remaining enum values are *not* valid indices for Trace::flags.
+    // They are "compound" flags, which correspond to sets of base
+    // flags, and are used only by TraceParamContext::setFlags().
+''',
+
+for flag in compoundFlags:
+    print >>hhfile, '    %s = %d,' % (flag, idx)
+    idx += 1
+
+numCompoundFlags = idx - numBaseFlags
+print >>hhfile, '    NumCompoundFlags = %d' % numCompoundFlags
+
+# trailer boilerplate
+print >>hhfile, '''\
+}; // enum Flags
+
+// Array of strings for SimpleEnumParam
+extern const char *flagStrings[];
+extern const int numFlagStrings;
+
+// Array of arraay pointers: for each compound flag, gives the list of
+// base flags to set.  Inidividual flag arrays are terminated by -1.
+extern const Flags *compoundFlags[];
+
+/* namespace Trace */ }
+
+#endif // __BASE_TRACE_FLAGS_HH__
+''',
+
+hhfile.close()
+
+#
+#
+# Print out .cc file with array definitions.
+#
+#
+try:
+    ccfile = file(ccfilename, 'w')
+except OSError, e:
+    sys.exit("can't open %s: %s" % (ccfilename, e))
+
+# file header
+print >>ccfile, '''\
+/* $Id $ */
+
+/*
+ * Copyright (c) 2004
+ * The Regents of The University of Michigan
+ * All Rights Reserved
+ *
+ * This code is part of the M5 simulator, developed by Nathan Binkert,
+ * Erik Hallnor, Steve Raasch, and Steve Reinhardt, with contributions
+ * from Ron Dreslinski, Dave Greene, and Lisa Hsu.
+ *
+ * Permission is granted to use, copy, create derivative works and
+ * redistribute this software and such derivative works for any
+ * purpose, so long as the copyright notice above, this grant of
+ * permission, and the disclaimer below appear in all copies made; and
+ * so long as the name of The University of Michigan is not used in
+ * any advertising or publicity pertaining to the use or distribution
+ * of this software without specific, written prior authorization.
+ *
+ * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE
+ * UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND
+ * WITHOUT WARRANTY BY THE UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE. THE REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE
+ * LIABLE FOR ANY DAMAGES, INCLUDING DIRECT, SPECIAL, INDIRECT,
+ * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM
+ * ARISING OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
+ * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGES.
+ */
+
+/*
+ * DO NOT EDIT THIS FILE!
+ *
+ * Automatically generated from traceflags.pl.
+ */
+
+#include "base/trace_flags.hh"
+
+using namespace Trace;
+
+const char *Trace::flagStrings[] =
+{
+''',
+
+# The string array is used by SimpleEnumParam to map the strings
+# provided by the user to enum values.
+for flag in baseFlags:
+    print >>ccfile, '    "%s",' % flag
+
+for flag in compoundFlags:
+    print >>ccfile, '    "%s",' % flag
+
+print >>ccfile, '};\n'
+
+numFlagStrings = len(baseFlags) + len(compoundFlags);
+
+print >>ccfile, 'const int Trace::numFlagStrings = %d;' % numFlagStrings
+print >>ccfile
+
+#
+# Now define the individual compound flag arrays.  There is an array
+# for each compound flag listing the component base flags.
+#
+
+for flag in compoundFlags:
+    flags = compoundFlagMap[flag]
+    flags.append('(Flags)-1')
+    print >>ccfile, 'static const Flags %sMap[] =' % flag
+    print >>ccfile, '{ %s };' % (', '.join(flags))
+    print >>ccfile
+
+#
+# Finally the compoundFlags[] array maps the compound flags
+# to their individual arrays/
+#
+print >>ccfile, 'const Flags *Trace::compoundFlags[] ='
+print >>ccfile, '{'
+
+for flag in compoundFlags:
+    print >>ccfile, '    %sMap,' % flag
+
+# file trailer
+print >>ccfile, '};'
+
+ccfile.close()
+
index 051d9623a59ac5f49e72e673c879b213048e60e6..5d608976dad4cb597fe3f689ac1369c6f9e13153 100644 (file)
@@ -40,7 +40,7 @@
 #include "mem/functional_mem/main_memory.hh"
 #include "sim/builder.hh"
 #include "sim/sim_events.hh"
-#include "sim/sim_stats.hh"
+#include "sim/stats.hh"
 
 using namespace std;
 
@@ -109,7 +109,6 @@ MemTest::MemTest(const string &name,
     // set up counters
     noResponseCycles = 0;
     numReads = 0;
-    numWrites = 0;
     tickEvent.schedule(0);
 }
 
@@ -142,21 +141,23 @@ MemTest::completeRequest(MemReqPtr &req, uint8_t *data)
         }
 
         numReads++;
+        numReadsStat++;
 
-        if (numReads.value() == nextProgressMessage) {
-            cerr << name() << ": completed " << numReads.value()
-                 << " read accesses @ " << curTick << endl;
+        if (numReads == nextProgressMessage) {
+            ccprintf(cerr, "%s: completed %d read accesses @%d\n",
+                     name(), numReads, curTick);
             nextProgressMessage += progressInterval;
         }
 
-        comLoadEventQueue[0]->serviceEvents(numReads.value());
+        comLoadEventQueue[0]->serviceEvents(numReads);
         break;
 
       case Write:
-        numWrites++;
+        numWritesStat++;
         break;
 
       case Copy:
+        numCopiesStat++;
         break;
 
       default:
@@ -187,17 +188,18 @@ MemTest::regStats()
 {
     using namespace Statistics;
 
-    numReads
+
+    numReadsStat
         .name(name() + ".num_reads")
         .desc("number of read accesses completed")
         ;
 
-    numWrites
+    numWritesStat
         .name(name() + ".num_writes")
         .desc("number of write accesses completed")
         ;
 
-    numCopies
+    numCopiesStat
         .name(name() + ".num_copies")
         .desc("number of copy accesses completed")
         ;
index da6e180a084fb41bd06caeee26d639c4eb2b755c..f2409d54c04bbc40b38185ac9a3941017097e550 100644 (file)
@@ -36,7 +36,7 @@
 #include "cpu/exec_context.hh"
 
 #include "base/statistics.hh"
-#include "sim/sim_stats.hh"
+#include "sim/stats.hh"
 
 class MemTest : public BaseCPU
 {
@@ -110,9 +110,10 @@ class MemTest : public BaseCPU
 
     Tick noResponseCycles;
 
-    Statistics::Scalar<> numReads;
-    Statistics::Scalar<> numWrites;
-    Statistics::Scalar<> numCopies;
+    uint64_t numReads;
+    Statistics::Scalar<> numReadsStat;
+    Statistics::Scalar<> numWritesStat;
+    Statistics::Scalar<> numCopiesStat;
 
     // called by MemCompleteEvent::process()
     void completeRequest(MemReqPtr &req, uint8_t *data);
index 711c81c519385604f1df96b7707c7d2eba1e13ad..f29d9d60e459273812e08320f0079bf818e136c2 100644 (file)
@@ -56,7 +56,7 @@
 #include "sim/host.hh"
 #include "sim/sim_events.hh"
 #include "sim/sim_object.hh"
-#include "sim/sim_stats.hh"
+#include "sim/stats.hh"
 
 #ifdef FULL_SYSTEM
 #include "base/remote_gdb.hh"
index a57c01841d5b6c2314020870a54787633dc5353f..17a5e406afa4690f5856ff257be6e87cfa3160ba 100644 (file)
@@ -159,6 +159,6 @@ FnEvent::process(ExecContext *xc)
     myBin->activate();
     xc->system->fnCalls++;
     DPRINTF(TCPIP, "fnCalls for %s is %d\n", description,
-            xc->system->fnCalls.val());
+            xc->system->fnCalls.value());
     xc->system->dumpState(xc);
 }
index 48d64d4cd51e57a8c31e38f59378fc197f69fa39..8861f3ef0b9ef98be7a1ffc33cfd1694dafcd366 100644 (file)
@@ -53,7 +53,8 @@
 #include "sim/sim_exit.hh"
 #include "sim/sim_init.hh"
 #include "sim/sim_object.hh"
-#include "sim/sim_stats.hh"
+#include "sim/stat_control.hh"
+#include "sim/stats.hh"
 #include "sim/universe.hh"
 
 using namespace std;
@@ -235,7 +236,7 @@ main(int argc, char **argv)
     sayHello(cerr);
 
     // Initialize statistics database
-    initBaseStats();
+    Statistics::InitSimStats();
 
     vector<char *> cppArgs;
 
index 1523c093e1b35ce415ed7612ad46f56ecd421874..c6b497343e99c7798bb49f278c14a674d0fd55fa 100644 (file)
@@ -43,7 +43,7 @@
 #include "sim/builder.hh"
 #include "sim/fake_syscall.hh"
 #include "sim/process.hh"
-#include "sim/sim_stats.hh"
+#include "sim/stats.hh"
 
 #ifdef TARGET_ALPHA
 #include "arch/alpha/alpha_tru64_process.hh"
index 5df5736ff7e68fd94fb7d596fb9984b5bae15e7e..b23302b8f68a31c325e2e1d0339067f78054cf98 100644 (file)
@@ -40,7 +40,7 @@
 
 #include "targetarch/isa_traits.hh"
 #include "sim/sim_object.hh"
-#include "sim/sim_stats.hh"
+#include "sim/stats.hh"
 #include "base/statistics.hh"
 
 class ExecContext;
index f7b07359c0598079dc918ddc194979e89bdad274..3530adedceb7bebb86df252ae73860ec09f91bd3 100644 (file)
@@ -35,7 +35,7 @@
 #include "sim/sim_events.hh"
 #include "sim/sim_exit.hh"
 #include "sim/sim_init.hh"
-#include "sim/sim_stats.hh"
+#include "sim/stats.hh"
 
 using namespace std;
 
index 5534ea8409a914d05753ea7da73606fc3476c269..9626c54ea7299533430e7962a7b0b7016a83dd3c 100644 (file)
@@ -35,7 +35,7 @@
 #include "sim/configfile.hh"
 #include "sim/host.hh"
 #include "sim/sim_object.hh"
-#include "sim/sim_stats.hh"
+#include "sim/stats.hh"
 
 using namespace std;
 
diff --git a/sim/stat_control.cc b/sim/stat_control.cc
new file mode 100644 (file)
index 0000000..d6d7e2c
--- /dev/null
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2003 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// This file will contain default statistics for the simulator that
+// don't really belong to a specific simulator object
+
+#include <fstream>
+#include <iostream>
+#include <list>
+
+#include "base/callback.hh"
+#include "base/hostinfo.hh"
+#include "base/statistics.hh"
+#include "base/str.hh"
+#include "base/time.hh"
+#include "base/stats/output.hh"
+#include "sim/eventq.hh"
+#include "sim/sim_object.hh"
+#include "sim/stat_control.hh"
+#include "sim/universe.hh"
+
+using namespace std;
+
+Statistics::Formula hostInstRate;
+Statistics::Formula hostMemory;
+Statistics::Formula hostSeconds;
+Statistics::Formula hostTickRate;
+
+Statistics::Formula simInsts;
+Statistics::Formula simSeconds;
+Statistics::Formula simTicks;
+
+namespace Statistics {
+
+Time statTime(true);
+Tick startTick;
+
+class SimTicksReset : public Callback
+{
+  public:
+    void process()
+    {
+        statTime.set();
+        startTick = curTick;
+    }
+};
+
+double
+statElapsedTime()
+{
+    Time now(true);
+    Time elapsed = now - statTime;
+    return elapsed();
+}
+
+SimTicksReset simTicksReset;
+
+void
+InitSimStats()
+{
+    simInsts
+        .name("sim_insts")
+        .desc("Number of instructions simulated")
+        .precision(0)
+        .prereq(simInsts)
+        ;
+
+    simSeconds
+        .name("sim_seconds")
+        .desc("Number of seconds simulated")
+        ;
+
+    simTicks
+        .name("sim_ticks")
+        .desc("Number of ticks simulated")
+        ;
+
+    hostInstRate
+        .name("host_inst_rate")
+        .desc("Simulator instruction rate (inst/s)")
+        .precision(0)
+        .prereq(simInsts)
+        ;
+
+    hostMemory
+        .name("host_mem_usage")
+        .desc("Number of bytes of host memory used")
+        .prereq(hostMemory)
+        ;
+
+    hostSeconds
+        .name("host_seconds")
+        .desc("Real time elapsed on the host")
+        .precision(2)
+        ;
+
+    hostTickRate
+        .name("host_tick_rate")
+        .desc("Simulator tick rate (ticks/s)")
+        .precision(0)
+        ;
+
+    simInsts = constant(0);
+    simTicks = scalar(curTick) - scalar(startTick);
+    simSeconds = simTicks / scalar(ticksPerSecond);
+    hostMemory = functor(memUsage);
+    hostSeconds = functor(statElapsedTime);
+    hostInstRate = simInsts / hostSeconds;
+    hostTickRate = simTicks / hostSeconds;
+
+    registerResetCallback(&simTicksReset);
+}
+
+class StatEvent : public Event
+{
+  protected:
+    int flags;
+    Tick repeat;
+
+  public:
+    StatEvent(int _flags, Tick _when, Tick _repeat);
+    virtual void process();
+    virtual const char *description();
+};
+
+StatEvent::StatEvent(int _flags, Tick _when, Tick _repeat)
+    : Event(&mainEventQueue, Stat_Event_Pri),
+      flags(_flags), repeat(_repeat)
+{
+    setFlags(AutoDelete);
+    schedule(_when);
+}
+
+const char *
+StatEvent::description()
+{
+    return "Statistics dump and/or reset";
+}
+
+void
+StatEvent::process()
+{
+    if (flags & Statistics::Dump)
+        DumpNow();
+
+    if (flags & Statistics::Reset)
+        reset();
+
+    if (repeat)
+        schedule(curTick + repeat);
+}
+
+list<Output *> OutputList;
+
+void
+DumpNow()
+{
+    list<Output *>::iterator i = OutputList.begin();
+    list<Output *>::iterator end = OutputList.end();
+    for (; i != end; ++i) {
+        Output *output = *i;
+        if (!output->valid())
+            continue;
+
+        output->output();
+    }
+}
+
+void
+SetupEvent(int flags, Tick when, Tick repeat)
+{
+    new StatEvent(flags, when, repeat);
+}
+
+/* namespace Statistics */ }
+
+extern "C" void
+debugDumpStats()
+{
+    Statistics::DumpNow();
+}
+
diff --git a/sim/stat_control.hh b/sim/stat_control.hh
new file mode 100644 (file)
index 0000000..9a5e269
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2003 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __SIM_STAT_CONTROL_HH__
+#define __SIM_STAT_CONTROL_HH__
+
+#include <fstream>
+#include <list>
+
+namespace Statistics {
+
+enum {
+    Reset = 0x1,
+    Dump = 0x2
+};
+
+class Output;
+extern std::list<Output *> OutputList;
+
+void DumpNow();
+void SetupEvent(int flags, Tick when, Tick repeat = 0);
+
+void InitSimStats();
+
+/* namespace Statistics */ }
+
+#endif // __SIM_STAT_CONTROL_HH__
diff --git a/sim/stats.hh b/sim/stats.hh
new file mode 100644 (file)
index 0000000..b736850
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2003 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __SIM_STATS_HH__
+#define __SIM_STATS_HH__
+
+#include "base/statistics.hh"
+
+extern Statistics::Formula simTicks;
+extern Statistics::Formula simSeconds;
+extern Statistics::Formula simInsts;
+extern Statistics::Formula hostSeconds;
+extern Statistics::Formula hostTickRate;
+extern Statistics::Formula hostInstRate;
+
+#endif // __SIM_SIM_STATS_HH__
index e5bf9cdac12feb3c34044936d1e4feebfbcfecce..050d1dd112d0d8a8a6f37ada946ed4a64b87da25 100644 (file)
@@ -53,7 +53,7 @@ class System : public SimObject
     std::map<const Addr, SWContext *> swCtxMap;
 
   public:
-    Statistics::Scalar<Counter> fnCalls;
+    Statistics::Scalar<> fnCalls;
     Statistics::MainBin *Kernel;
     Statistics::MainBin *User;
 
index d62dba64aa7d6104fa87a0f13461dd96cb57c4f7..bf4200ba3d2360da20beeb852acb309a6ae71f21 100644 (file)
@@ -5,81 +5,61 @@ CXX?= g++
 
 CURDIR?= $(shell /bin/pwd)
 SRCDIR?= ..
-TARGET?= alpha
-
-TEST_SRCDIR?= $(SRCDIR)/test
-ARCH_SRCDIR?= $(SRCDIR)/arch/$(TARGET)
-BASE_SRCDIR?= $(SRCDIR)/base
-SIM_SRCDIR?= $(SRCDIR)/sim
-CACHE_SRCDIR?= $(SRCDIR)/sim/cache
-OLD_SRCDIR= $(SRCDIR)/old
-
-vpath % $(TEST_SRCDIR)
-vpath % $(BASE_SRCDIR)
-vpath % $(SIM_SRCDIR)
-vpath % $(CACHE_SRCDIR)
-vpath % $(OLD_SRCDIR)
 
 CCFLAGS= -g -O0 -MMD -I. -I$(SRCDIR) -I- -DTRACING_ON=0
+MYSQL= -I/usr/include/mysql -L/usr/lib/mysql -lmysqlclient
+
+VPATH=$(SRCDIR)
 
 default:
        @echo "You must specify a target"
 
-targetarch:
-       ln -s ../arch/$(TARGET) targetarch
-
-bitvectest: bitvectest.o
-       $(CXX) $(LFLAGS) -o $@ $^
+bitvectest: test/bitvectest.cc
+       $(CXX) $(CCFLAGS) -o $@ $^
 
-circletest: circletest.o circlebuf.o
-       $(CXX) $(LFLAGS) -o $@ $^
+circletest: test/circletest.cc base/circlebuf.cc
+       $(CXX) $(CCFLAGS) -o $@ $^
 
-cprintftest: cprintftest.o cprintf.o
-       $(CXX) $(LFLAGS) -o $@ $^
+cprintftest: test/cprintftest.cc base/cprintf.cc
+       $(CXX) $(CCFLAGS) -o $@ $^
 
-initest: initest.o str.o inifile.o cprintf.o
-       $(CXX) $(LFLAGS) -o $@ $^
+initest: test/initest.cc base/str.cc base/inifile.cc base/cprintf.cc
+       $(CXX) $(CCFLAGS) -o $@ $^
 
-lrutest: lru_test.o
-       $(CXX) $(LFLAGS) -o $@ $^
+lrutest: test/lru_test.cc
+       $(CXX) $(CCFLAGS) -o $@ $^
 
-nmtest: nmtest.o object_file.o symtab.o misc.o str.o
-       $(CXX) $(LFLAGS) -o $@ $^
+nmtest: test/nmtest.cc base/object_file.cc base/symtab.cc base/misc.cc base/str.cc
+       $(CXX) $(CCFLAGS) -o $@ $^
 
-offtest: offtest.o
-       $(CXX) $(LFLAGS) -o $@ $^
+offtest: test/offtest.cc
+       $(CXX) $(CCFLAGS) -o $@ $^
 
-rangetest: rangetest.o range.o str.o
-       $(CXX) $(LFLAGS) -o $@ $^
+rangetest: test/rangetest.cc base/range.cc base/str.cc
+       $(CXX) $(CCFLAGS) -o $@ $^
 
-stattest: cprintf.o hostinfo.o misc.o python.o statistics.o stattest.o \
-       str.o time.o
-       $(CXX) $(LFLAGS) -o $@ $^
+STATTEST+= base/cprintf.cc base/hostinfo.cc base/misc.cc base/mysql.cc
+STATTEST+= base/python.cc base/str.cc base/time.cc 
+STATTEST+= base/statistics.cc base/stats/mysql.cc base/stats/python.cc
+STATTEST+= base/stats/statdb.cc base/stats/text.cc base/stats/visit.cc
+STATTEST+= test/stattest.cc 
+stattest: $(STATTEST)
+       $(CXX) $(CCFLAGS) $(MYSQL) -o $@ $^ 
 
-strnumtest: strnumtest.o str.o
-       $(CXX) $(LFLAGS) -o $@ $^
+strnumtest: test/strnumtest.cc base/str.cc
+       $(CXX) $(CCFLAGS) -o $@ $^
 
-symtest: misc.o symtest.o symtab.o str.o
-       $(CXX) $(LFLAGS) -o $@ $^
+symtest: test/symtest.cc base/misc.cc base/symtab.cc base/str.cc
+       $(CXX) $(CCFLAGS) -o $@ $^
 
-tokentest: tokentest.o str.o
-       $(CXX) $(LFLAGS) -o $@ $^
+tokentest: test/tokentest.cc base/str.cc
+       $(CXX) $(CCFLAGS) -o $@ $^
 
-tracetest: tracetest.o trace.o trace_flags.o cprintf.o str.o misc.o
-       $(CXX) $(LFLAGS) -o $@ $^
+TRACE+=test/tracetest.cc base/trace.cc base/trace_flags.cc base/cprintf.cc
+TRACE+=base/str.cc base/misc.cc
+tracetest: $(TRACE)
+       $(CXX) $(CCFLAGS) -o $@ $^
 
 clean:
-       @rm -f *.o *.d *test *~ .#* *.core core
+       @rm -f *test *~ .#* *.core core
 .PHONY: clean
-
-# C++ Compilation
-%.o: %.cc
-       @echo '$(CXX) $(CCFLAGS) -c $(notdir $<) -o $@'
-       @$(CXX) $(CCFLAGS) -c $< -o $@
-
-# C Compilation
-%.o: %.c
-       @echo '$(CC) $(CCFLAGS) -c $(notdir $<) -o $@'
-       @$(CC) $(CCFLAGS) -c $< -o $@
-
--include *.d
index 8dd8eeb8e4a3b9937228f5a939036da0c5cd3129..7bf355c0eb57c021cb36e76c3d0a571108f0d028 100644 (file)
@@ -35,6 +35,9 @@
 #include "base/cprintf.hh"
 #include "base/misc.hh"
 #include "base/statistics.hh"
+#include "base/stats/text.hh"
+#include "base/stats/python.hh"
+#include "base/stats/mysql.hh"
 #include "sim/host.hh"
 
 using namespace std;
@@ -46,14 +49,14 @@ Tick ticksPerSecond = ULL(2000000000);
 Scalar<> s1;
 Scalar<> s2;
 Average<> s3;
-Scalar<Counter, MainBin> s4;
-Vector<Counter, MainBin> s5;
-Distribution<Counter, MainBin> s6;
-Vector<Counter, MainBin> s7;
+Scalar<MainBin> s4;
+Vector<MainBin> s5;
+Distribution<MainBin> s6;
+Vector<MainBin> s7;
 AverageVector<> s8;
 StandardDeviation<> s9;
 AverageDeviation<> s10;
-Scalar<Counter> s11;
+Scalar<> s11;
 Distribution<> s12;
 VectorDistribution<> s13;
 VectorStandardDeviation<> s14;
@@ -71,6 +74,8 @@ Formula f7;
 MainBin bin1("bin1");
 MainBin bin2("bin2");
 
+ostream *outputStream = &cout;
+
 double
 testfunc()
 {
@@ -89,26 +94,57 @@ usage()
 {
     panic("incorrect usage.\n"
           "usage:\n"
-          "\t%s [-v]\n", progname);
+          "\t%s [-p <python file>] [-t [-c] [-d]]\n", progname);
 }
 
 int
 main(int argc, char *argv[])
 {
+    bool descriptions = false;
+    bool compat = false;
+    bool text = false;
+    string pyfile;
+    string mysql_name;
+    string mysql_host;
+    string mysql_user = "binkertn";
+    string mysql_passwd;
+
     char c;
     progname = argv[0];
-    PrintDescriptions = false;
-    while ((c = getopt(argc, argv, "v")) != -1) {
-        cprintf("c == %c\n", c);
+    while ((c = getopt(argc, argv, "cdh:P:p:s:tu:")) != -1) {
         switch (c) {
-          case 'v':
-            PrintDescriptions = true;
+          case 'c':
+            compat = true;
+            break;
+          case 'd':
+            descriptions = true;
+            break;
+          case 'h':
+            mysql_host = optarg;
+            break;
+          case 'P':
+            mysql_passwd = optarg;
+            break;
+          case 'p':
+            pyfile = optarg;
+            break;
+          case 's':
+            mysql_name = optarg;
+            break;
+          case 't':
+            text = true;
+            break;
+          case 'u':
+            mysql_user = optarg;
             break;
           default:
             usage();
         }
     }
 
+    if (!text && (compat || descriptions))
+        usage();
+
     s5.init(5);
     s6.init(1, 100, 13);
     s7.init(7);
@@ -214,6 +250,8 @@ main(int argc, char *argv[])
         .flags(total)
         .subname(0, "sub0")
         .subname(1, "sub1")
+        .ysubname(0, "y0")
+        .ysubname(1, "y1")
         ;
 
     f1
@@ -509,9 +547,24 @@ main(int argc, char *argv[])
 
     s12.sample(100);
 
-//    dump(cout, mode_simplescalar);
-    python_start("/tmp/stats.py");
-    python_dump("stattest", "all");
+    if (text) {
+        Text out(cout);
+        out.descriptions = descriptions;
+        out.compat = compat;
+        out();
+    }
+
+    if (!pyfile.empty()) {
+        Python out(pyfile);
+        out();
+    }
+
+    if (!mysql_name.empty()) {
+        MySql out;
+        out.connect(mysql_host, mysql_user, mysql_passwd, "m5stats",
+                    mysql_name, "test");
+        out();
+    }
 
     return 0;
 }