summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/alpha/pseudo_inst.cc6
-rw-r--r--base/hybrid_pred.cc2
-rw-r--r--base/hybrid_pred.hh2
-rw-r--r--base/mysql.cc97
-rw-r--r--base/mysql.hh410
-rw-r--r--base/sat_counter.cc3
-rw-r--r--base/sat_counter.hh2
-rw-r--r--base/statistics.cc1140
-rw-r--r--base/statistics.hh1275
-rw-r--r--base/stats/flags.hh73
-rw-r--r--base/stats/mysql.cc844
-rw-r--r--base/stats/mysql.hh149
-rw-r--r--base/stats/output.hh47
-rw-r--r--base/stats/statdb.cc89
-rw-r--r--base/stats/statdb.hh74
-rw-r--r--base/stats/text.cc731
-rw-r--r--base/stats/text.hh77
-rw-r--r--base/stats/types.hh49
-rw-r--r--base/stats/visit.cc41
-rw-r--r--base/stats/visit.hh63
-rw-r--r--base/traceflags.py340
-rw-r--r--cpu/memtest/memtest.cc22
-rw-r--r--cpu/memtest/memtest.hh9
-rw-r--r--cpu/simple_cpu/simple_cpu.cc2
-rw-r--r--kern/tru64/tru64_events.cc2
-rw-r--r--sim/main.cc5
-rw-r--r--sim/process.cc2
-rw-r--r--sim/process.hh2
-rw-r--r--sim/sim_events.cc2
-rw-r--r--sim/sim_object.cc2
-rw-r--r--sim/stat_control.cc207
-rw-r--r--sim/stat_control.hh52
-rw-r--r--sim/stats.hh41
-rw-r--r--sim/system.hh2
-rw-r--r--test/Makefile94
-rw-r--r--test/stattest.cc81
36 files changed, 4084 insertions, 1955 deletions
diff --git a/arch/alpha/pseudo_inst.cc b/arch/alpha/pseudo_inst.cc
index 7f8c6b17c..194dc6400 100644
--- a/arch/alpha/pseudo_inst.cc
+++ b/arch/alpha/pseudo_inst.cc
@@ -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);
}
diff --git a/base/hybrid_pred.cc b/base/hybrid_pred.cc
index 83ce7f987..12bab975b 100644
--- a/base/hybrid_pred.cc
+++ b/base/hybrid_pred.cc
@@ -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;
diff --git a/base/hybrid_pred.hh b/base/hybrid_pred.hh
index 3fdab9153..9063f3084 100644
--- a/base/hybrid_pred.hh
+++ b/base/hybrid_pred.hh
@@ -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
index 000000000..8481e74e2
--- /dev/null
+++ b/base/mysql.cc
@@ -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
index 000000000..89bec73d0
--- /dev/null
+++ b/base/mysql.hh
@@ -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__
diff --git a/base/sat_counter.cc b/base/sat_counter.cc
index c26690a1a..a8367d8a0 100644
--- a/base/sat_counter.cc
+++ b/base/sat_counter.cc
@@ -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;
diff --git a/base/sat_counter.hh b/base/sat_counter.hh
index 62c18f6b4..a5d9c7e8a 100644
--- a/base/sat_counter.hh
+++ b/base/sat_counter.hh
@@ -34,7 +34,7 @@
#include "base/predictor.hh"
#include "base/statistics.hh"
-#include "sim/sim_stats.hh"
+#include "sim/stats.hh"
//
//
diff --git a/base/statistics.cc b/base/statistics.cc
index dce545f18..1a44cd342 100644
--- a/base/statistics.cc
+++ b/base/statistics.cc
@@ -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,343 +42,28 @@
#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 */ }
diff --git a/base/statistics.hh b/base/statistics.hh
index 0dad31a5a..e7fc18d74 100644
--- a/base/statistics.hh
+++ b/base/statistics.hh
@@ -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>
@@ -58,66 +58,19 @@
#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();
@@ -149,14 +105,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.
*/
virtual void reset() = 0;
@@ -176,6 +124,11 @@ struct StatData
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
* separately.
@@ -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,34 +646,35 @@ 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
*/
void reset()
@@ -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
index 000000000..2303de172
--- /dev/null
+++ b/base/stats/flags.hh
@@ -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
index 000000000..676bc555c
--- /dev/null
+++ b/base/stats/mysql.cc
@@ -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
index 000000000..4ff474752
--- /dev/null
+++ b/base/stats/mysql.hh
@@ -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
index 000000000..9f1fbf415
--- /dev/null
+++ b/base/stats/output.hh
@@ -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
index 000000000..f54272a50
--- /dev/null
+++ b/base/stats/statdb.cc
@@ -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
index 000000000..fb672e1dc
--- /dev/null
+++ b/base/stats/statdb.hh
@@ -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
index 000000000..0f43a1772
--- /dev/null
+++ b/base/stats/text.cc
@@ -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
index 000000000..89bddf0cb
--- /dev/null
+++ b/base/stats/text.hh
@@ -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
index 000000000..4451c4e6e
--- /dev/null
+++ b/base/stats/types.hh
@@ -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
index 000000000..fec11b262
--- /dev/null
+++ b/base/stats/visit.cc
@@ -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
index 000000000..a03842c52
--- /dev/null
+++ b/base/stats/visit.hh
@@ -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
index 000000000..79a54445e
--- /dev/null
+++ b/base/traceflags.py
@@ -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()
+
diff --git a/cpu/memtest/memtest.cc b/cpu/memtest/memtest.cc
index 051d9623a..5d608976d 100644
--- a/cpu/memtest/memtest.cc
+++ b/cpu/memtest/memtest.cc
@@ -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")
;
diff --git a/cpu/memtest/memtest.hh b/cpu/memtest/memtest.hh
index da6e180a0..f2409d54c 100644
--- a/cpu/memtest/memtest.hh
+++ b/cpu/memtest/memtest.hh
@@ -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);
diff --git a/cpu/simple_cpu/simple_cpu.cc b/cpu/simple_cpu/simple_cpu.cc
index 711c81c51..f29d9d60e 100644
--- a/cpu/simple_cpu/simple_cpu.cc
+++ b/cpu/simple_cpu/simple_cpu.cc
@@ -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"
diff --git a/kern/tru64/tru64_events.cc b/kern/tru64/tru64_events.cc
index a57c01841..17a5e406a 100644
--- a/kern/tru64/tru64_events.cc
+++ b/kern/tru64/tru64_events.cc
@@ -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);
}
diff --git a/sim/main.cc b/sim/main.cc
index 48d64d4cd..8861f3ef0 100644
--- a/sim/main.cc
+++ b/sim/main.cc
@@ -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;
diff --git a/sim/process.cc b/sim/process.cc
index 1523c093e..c6b497343 100644
--- a/sim/process.cc
+++ b/sim/process.cc
@@ -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"
diff --git a/sim/process.hh b/sim/process.hh
index 5df5736ff..b23302b8f 100644
--- a/sim/process.hh
+++ b/sim/process.hh
@@ -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;
diff --git a/sim/sim_events.cc b/sim/sim_events.cc
index f7b07359c..3530adedc 100644
--- a/sim/sim_events.cc
+++ b/sim/sim_events.cc
@@ -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;
diff --git a/sim/sim_object.cc b/sim/sim_object.cc
index 5534ea840..9626c54ea 100644
--- a/sim/sim_object.cc
+++ b/sim/sim_object.cc
@@ -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
index 000000000..d6d7e2c91
--- /dev/null
+++ b/sim/stat_control.cc
@@ -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
index 000000000..9a5e269e1
--- /dev/null
+++ b/sim/stat_control.hh
@@ -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
index 000000000..b736850e7
--- /dev/null
+++ b/sim/stats.hh
@@ -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__
diff --git a/sim/system.hh b/sim/system.hh
index e5bf9cdac..050d1dd11 100644
--- a/sim/system.hh
+++ b/sim/system.hh
@@ -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;
diff --git a/test/Makefile b/test/Makefile
index d62dba64a..bf4200ba3 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -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
diff --git a/test/stattest.cc b/test/stattest.cc
index 8dd8eeb8e..7bf355c0e 100644
--- a/test/stattest.cc
+++ b/test/stattest.cc
@@ -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;
}