diff options
author | Nathan Binkert <binkertn@umich.edu> | 2004-05-04 17:01:00 -0400 |
---|---|---|
committer | Nathan Binkert <binkertn@umich.edu> | 2004-05-04 17:01:00 -0400 |
commit | 25a358983a31167e048b19dd21bc1ec872890a74 (patch) | |
tree | fc275ade79d5237ef873131f39471b93f2732bc2 /base | |
parent | 1eb08bcf896e6973b6e0e317b483804e6639f067 (diff) | |
download | gem5-25a358983a31167e048b19dd21bc1ec872890a74.tar.xz |
Major stats package cleanup
Add support for generic visitors for stats and use them
to implement independent output functions.
Support for mysql output and some initial code for hacking
on mysql output with python
arch/alpha/pseudo_inst.cc:
base/hybrid_pred.cc:
base/hybrid_pred.hh:
base/sat_counter.cc:
base/sat_counter.hh:
cpu/simple_cpu/simple_cpu.cc:
kern/tru64/tru64_events.cc:
sim/main.cc:
sim/process.cc:
sim/process.hh:
sim/sim_events.cc:
sim/sim_object.cc:
sim/system.hh:
update for changes in stats package
base/statistics.cc:
move the python output code to base/stats/puthon.(cc|hh)
and reimplement it as a visitor.
move the text output code to base/stats/text.(cc|hh) and
reimplement it as a visitor.
move the database stuff into base/stats/statdb.(cc|hh) and
get rid of the class. Put everything as globals in the
Statistics::Database namespace.
allocate unique ids for all stats.
directly implement the check routine and get rid of the
various dumping routines since they're now in separate files.
make sure that no two stats have the same name
clean up some loops
base/statistics.hh:
major changes to the statistics package again
lots of code was factored out of statistics.hh into several
separate files in base/stats/ (this will continue)
There are now two Stat package types Result and Counter that
are specified to allow the user to keep the counted type
separate from the result type. They are currently both doubles
but that's an experiment. There is no more per stat ability to
set the type. Statistics::Counter is not the same as Counter!
Implement a visitor for statistics output so that new output
types can be implemented independently from the stats package
itself.
Add a unique id to each stat so that it can be used to keep
track of stats more simply. This number can also be used in
debugging problems with stats.
Tweak the bucket size stuff a bit to make it work better.
fixed VectorDist size bug
cpu/memtest/memtest.cc:
Fix up for changes in stats package
Don't use value() since it doesn't work with binning. If you
want a number as a stat, and to use it in the program itself,
you really want two separate variables, one that's a stat,
and one that's not.
cpu/memtest/memtest.hh:
Fix up for changes in stats package
test/Makefile:
Try to build stuff now that directories matter
test/stattest.cc:
test all new output types
choose which one with command line options
--HG--
extra : convert_revision : e3a3f5f0828c67c0e2de415d936ad240adaddc89
Diffstat (limited to 'base')
-rw-r--r-- | base/hybrid_pred.cc | 2 | ||||
-rw-r--r-- | base/hybrid_pred.hh | 2 | ||||
-rw-r--r-- | base/mysql.cc | 97 | ||||
-rw-r--r-- | base/mysql.hh | 410 | ||||
-rw-r--r-- | base/sat_counter.cc | 3 | ||||
-rw-r--r-- | base/sat_counter.hh | 2 | ||||
-rw-r--r-- | base/statistics.cc | 1140 | ||||
-rw-r--r-- | base/statistics.hh | 1275 | ||||
-rw-r--r-- | base/stats/flags.hh | 73 | ||||
-rw-r--r-- | base/stats/mysql.cc | 844 | ||||
-rw-r--r-- | base/stats/mysql.hh | 149 | ||||
-rw-r--r-- | base/stats/output.hh | 47 | ||||
-rw-r--r-- | base/stats/statdb.cc | 89 | ||||
-rw-r--r-- | base/stats/statdb.hh | 74 | ||||
-rw-r--r-- | base/stats/text.cc | 731 | ||||
-rw-r--r-- | base/stats/text.hh | 77 | ||||
-rw-r--r-- | base/stats/types.hh | 49 | ||||
-rw-r--r-- | base/stats/visit.cc | 41 | ||||
-rw-r--r-- | base/stats/visit.hh | 63 | ||||
-rw-r--r-- | base/traceflags.py | 340 |
20 files changed, 3648 insertions, 1860 deletions
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 *>(¶ms); @@ -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 *>(¶ms); @@ -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 *>(¶ms); @@ -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 ¶ms) - : 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 ¶ms) + void sample(Counter val, int number, const Params ¶ms) { 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 ¶ms) const { - return samples == 0; + return samples == Counter(); } void update(DistDataData *data, const Params ¶ms) @@ -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 ¶ms) const { return sum == 0; } + bool zero(const Params ¶ms) 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 *>(¶ms); @@ -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 *>(¶ms); @@ -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 ¶ms) { } - - int size() const { return 1; } - - Storage * - data(Params ¶ms) - { - 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 ¶ms) - { - assert(!initialized()); - assert(s > 0); - _size = s; - allocate(_size * sizeof(Storage)); - } - - int size() const { return _size; } - - Storage *data(int index, Params ¶ms) - { - 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 ¶ms) - { - new (ptr) Storage(params); - } - int size() const{ return 1; } - Storage *data(Params ¶ms) - { - 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 ¶ms) - { - 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 ¶ms) - { - 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() + |