diff options
author | Lisa Hsu <hsul@eecs.umich.edu> | 2004-05-11 01:15:18 -0400 |
---|---|---|
committer | Lisa Hsu <hsul@eecs.umich.edu> | 2004-05-11 01:15:18 -0400 |
commit | a5f90eba3bd2d96c6733a6ac9e8d03a9297fae6a (patch) | |
tree | 06662aecdd919aa0bafb0562fc646465dda5a901 /base | |
parent | 3c7071a6be21fc0c87753758fc09ff28890edc99 (diff) | |
parent | 2cc4fd87eb643c81d37954cbf4a226e78ebd34bc (diff) | |
download | gem5-a5f90eba3bd2d96c6733a6ac9e8d03a9297fae6a.tar.xz |
first pass at merging m5 with linux
--HG--
extra : convert_revision : dfe23349b80ae3b34d3cb95c5734e01ef62f700e
Diffstat (limited to 'base')
-rw-r--r-- | base/compression/lzss_compression.cc | 43 | ||||
-rw-r--r-- | base/compression/lzss_compression.hh | 9 | ||||
-rw-r--r-- | base/hashmap.hh | 2 | ||||
-rw-r--r-- | base/hybrid_pred.cc | 2 | ||||
-rw-r--r-- | base/hybrid_pred.hh | 2 | ||||
-rw-r--r-- | base/loader/elf_object.cc | 1 | ||||
-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/time.cc | 15 | ||||
-rw-r--r-- | base/time.hh | 4 | ||||
-rw-r--r-- | base/trace.hh | 2 | ||||
-rw-r--r-- | base/traceflags.py | 336 | ||||
-rw-r--r-- | base/userinfo.cc | 41 | ||||
-rw-r--r-- | base/userinfo.hh | 36 |
29 files changed, 3763 insertions, 1894 deletions
diff --git a/base/compression/lzss_compression.cc b/base/compression/lzss_compression.cc index 8f235b808..2f6c5d338 100644 --- a/base/compression/lzss_compression.cc +++ b/base/compression/lzss_compression.cc @@ -36,21 +36,32 @@ #include "base/misc.hh" //for fatal -int -LZSSCompression::findSubString(uint8_t *src, int front, int back, int size) +void +LZSSCompression::findSubString(uint8_t *src, int back, int size, uint16_t &L, + uint16_t &P) { - int subSize = 0; - int max_length = 2048; - if (size - back < max_length) { - max_length = size - back; - } - for (int i = 0; i < max_length; ++i) { - if (src[front+i] != src[back+i]) { - return subSize; + int front = 0; + int max_length = size - back; + L = 0; + P = back - 1; + while (front < back) { + while (src[front] != src[back] && front < back) ++front; + if (front >= back) { + return; + } + int i = 1; + while (src[front+i] == src[back+i] && i < max_length) ++i; + if (i >= L) { + L = i; + P = front; + } + if (src[front+i] != src[back+i-1]) { + // can't find a longer substring until past this point. + front += i; + } else { + ++front; } - ++subSize; } - return subSize; } int @@ -106,13 +117,7 @@ LZSSCompression::compress(uint8_t *dest, uint8_t *src, int size) ++i; continue; } - for (int j = 0; j < i; ++j) { - int sub_size = findSubString(src, j, i, size); - if (sub_size >= L) { - L = sub_size; - P = j; - } - } + findSubString(src, i, size, L, P); if (L > 1) { // Output the string reference emitString(&dest[dest_index], P, L); diff --git a/base/compression/lzss_compression.hh b/base/compression/lzss_compression.hh index 755a52c92..9707a8aca 100644 --- a/base/compression/lzss_compression.hh +++ b/base/compression/lzss_compression.hh @@ -41,14 +41,15 @@ class LZSSCompression { /** - * Finds the longest substrings that start at the given offsets. + * Finds the longest substring for the given offset. * @param src The source block that we search for substrings. - * @param front The smaller offset. * @param back The larger offset. * @param size The size of the source block. - * @return The size of the longest substring. + * @param L The length of the largest substring. + * @param P The starting offset of the largest substring. */ - int findSubString(uint8_t *src, int front, int back, int size); + void findSubString(uint8_t *src, int back, int size, uint16_t &L, + uint16_t &P); /** * Emit an encoded byte to the compressed data array. If the 2 high diff --git a/base/hashmap.hh b/base/hashmap.hh index 995e98a90..59c1fe3aa 100644 --- a/base/hashmap.hh +++ b/base/hashmap.hh @@ -57,7 +57,7 @@ namespace m5 { // namespace __hash_namespace { -#if !defined(__LP64__) +#if !defined(__LP64__) && !defined(__alpha__) template<> struct hash<uint64_t> { size_t operator()(uint64_t r) const { 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/loader/elf_object.cc b/base/loader/elf_object.cc index 98e3198a6..a0c0c0551 100644 --- a/base/loader/elf_object.cc +++ b/base/loader/elf_object.cc @@ -36,6 +36,7 @@ // set this now (it causes things to break on 64-bit platforms). #define __LIBELF64_LINUX 0 #define __LIBELF_NEED_LINK_H 0 +#define __LIBELF_SYMBOL_VERSIONS 0 #include <libelf/libelf.h> #include <libelf/gelf.h> 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/time.cc b/base/time.cc index d2e8f60a5..9a484a883 100644 --- a/base/time.cc +++ b/base/time.cc @@ -47,10 +47,11 @@ convert(const timeval &tv) return (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0; } -Time::Time() +Time::Time(bool set_now) { time = new _timeval; - ::gettimeofday(&time->tv, NULL); + if (set_now) + set(); } Time::Time(const timeval &val) @@ -77,15 +78,15 @@ Time::get() const } void -Time::set(const timeval &tv) +Time::set() { - memcpy(&time->tv, &tv, sizeof(timeval)); + ::gettimeofday(&time->tv, NULL); } void -Time::reset() +Time::set(const timeval &tv) { - ::gettimeofday(&time->tv, NULL); + memcpy(&time->tv, &tv, sizeof(timeval)); } double @@ -127,4 +128,4 @@ operator-(const Time &l, const Time &r) return tv; } -const Time Time::start; +const Time Time::start(true); diff --git a/base/time.hh b/base/time.hh index 64da52e1d..1f8c7e747 100644 --- a/base/time.hh +++ b/base/time.hh @@ -42,15 +42,15 @@ class Time mutable _timeval *time; public: - Time(); + explicit Time(bool set_now = false); Time(const timeval &val); Time(const Time &val); ~Time(); + void set(); const timeval &get() const; void set(const timeval &val); - void reset(); double operator()() const; std::string date(std::string format = "") const; diff --git a/base/trace.hh b/base/trace.hh index e49d7aa61..948bff548 100644 --- a/base/trace.hh +++ b/base/trace.hh @@ -43,7 +43,7 @@ #endif #endif -#include "base/trace_flags.hh" +#include "base/traceflags.hh" namespace Trace { diff --git a/base/traceflags.py b/base/traceflags.py new file mode 100644 index 000000000..b7b7fa777 --- /dev/null +++ b/base/traceflags.py @@ -0,0 +1,336 @@ +#!/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()) +compoundFlags.sort() + +# +# 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/traceflags.hh" + +using namespace Trace; + +const char *Trace::flagStrings[] = +{ +''', + +# The string array is used by SimpleEnumParam to map the strings +# provided by the user to enum values. +for flag in baseFlags: + print >>ccfile, ' "%s",' % flag + +for flag in compoundFlags: + print >>ccfile, ' "%s",' % flag + +print >>ccfile, '};\n' + +numFlagStrings = len(baseFlags) + len(compoundFlags); + +print >>ccfile, 'const int Trace::numFlagStrings = %d;' % numFlagStrings +print >>ccfile + +# +# Now define the individual compound flag arrays. There is an array +# for each compound flag listing the component base flags. +# + +for flag in compoundFlags: + flags = compoundFlagMap[flag] + flags.append('(Flags)-1') + print >>ccfile, 'static const Flags %sMap[] =' % flag + print >>ccfile, '{ %s };' % (', '.join(flags)) + print >>ccfile + +# +# Finally the compoundFlags[] array maps the compound flags +# to their individual arrays/ +# +print >>ccfile, 'const Flags *Trace::compoundFlags[] =' +print >>ccfile, '{' + +for flag in compoundFlags: + print >>ccfile, ' %sMap,' % flag + +# file trailer +print >>ccfile, '};' + +ccfile.close() + diff --git a/base/userinfo.cc b/base/userinfo.cc new file mode 100644 index 000000000..a729dfdf4 --- /dev/null +++ b/base/userinfo.cc @@ -0,0 +1,41 @@ +/* + * 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. + */ + +#include <sys/types.h> +#include <pwd.h> +#include <unistd.h> + +#include <string> + +std::string +username() +{ + struct passwd *pwd = getpwuid(getuid()); + + return pwd->pw_name; +} diff --git a/base/userinfo.hh b/base/userinfo.hh new file mode 100644 index 000000000..14e704ec4 --- /dev/null +++ b/base/userinfo.hh @@ -0,0 +1,36 @@ +/* + * 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. + */ + +#ifndef __BASE_USERINFO_HH__ +#define __BASE_USERINFO_HH__ + +#include <string> + +std::string username(); + +#endif // __BASE_USERINFO_HH__ |