diff options
Diffstat (limited to 'base/stats')
-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 |
11 files changed, 2237 insertions, 0 deletions
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__ |