diff options
-rw-r--r-- | base/statistics.cc | 1164 | ||||
-rw-r--r-- | base/statistics.hh | 1669 | ||||
-rw-r--r-- | test/Makefile | 3 | ||||
-rw-r--r-- | test/stattest.cc | 13 |
4 files changed, 1526 insertions, 1323 deletions
diff --git a/base/statistics.cc b/base/statistics.cc index 737f8f73b..afe613455 100644 --- a/base/statistics.cc +++ b/base/statistics.cc @@ -63,108 +63,45 @@ using namespace std; // This is a hack to get this parameter from the old stats package. namespace Statistics { bool PrintDescriptions = true; +DisplayMode default_mode = mode_simplescalar; -namespace Detail { -/** - * Struct to contain a name and description of statistic subfield. - */ -struct SubData -{ - /** Subfield name. */ - string name; - /** Subfield desc. */ - string desc; -}; - -/** - * Struct to contain print data of a Stat. - */ -struct StatData -{ - /** - * Create this struct. - */ - StatData(); - /** - * Destructor. - */ - ~StatData(); - - /** True if the stat has been initialized. */ - bool init; - /** True if the stat should be printed. */ - bool print; - /** The name of the stat. */ - string name; - /** Names and descriptions of subfields. */ - vector<SubData> *subdata; - /** The description of the stat. */ - string desc; - /** The display precision. */ - int precision; - /** The formatting flags. */ - FormatFlags flags; - /** A pointer to a prerequisite Stat. */ - const Stat *prereq; -}; - -StatData::StatData() - : init(false), print(false), subdata(NULL), precision(-1), flags(none), - prereq(NULL) -{ -} - -StatData::~StatData() -{ - if (subdata) - delete subdata; -} - -class Database +namespace Database { - private: - Database(const Database &) {} - - private: - typedef list<Stat *> list_t; - typedef map<const Stat *, StatData *> map_t; - - list<MainBin *> bins; - map<const MainBin *, std::string > bin_names; - list_t binnedStats; + class Data + { + private: + typedef list<StatData *> list_t; + typedef map<void *, StatData *> map_t; - list_t allStats; - list_t printStats; - map_t statMap; + list<MainBin *> bins; + map<const MainBin *, string > bin_names; + list_t binnedStats; - public: - Database(); - ~Database(); + list_t allStats; + list_t printStats; + map_t statMap; - void dump(ostream &stream); + public: + void dump(ostream &stream); - StatData *find(const Stat *stat); - void check(); - void reset(); - void regStat(Stat *stat); - StatData *print(Stat *stat); - void regBin(MainBin *bin, std::string name); -}; + StatData *find(void *stat); + void mapStat(void *stat, StatData *data); -Database::Database() -{} + void check(); + void reset(); + void regBin(MainBin *bin, string name); + void regPrint(void *stat); + }; -Database::~Database() -{} void -Database::dump(ostream &stream) +Data::dump(ostream &stream) { #ifndef FS_MEASURE list_t::iterator i = printStats.begin(); list_t::iterator end = printStats.end(); while (i != end) { - Stat *stat = *i; + StatData *stat = *i; if (stat->binned()) binnedStats.push_back(stat); ++i; @@ -178,7 +115,7 @@ Database::dump(ostream &stream) ccprintf(stream, "PRINTING BINNED STATS\n"); while (j != bins_end) { (*j)->activate(); - map<const MainBin *, std::string>::const_iterator iter; + map<const MainBin *, string>::const_iterator iter; iter = bin_names.find(*j); if (iter == bin_names.end()) panic("a binned stat not found in names map!"); @@ -192,7 +129,7 @@ Database::dump(ostream &stream) list_t::iterator end = binnedStats.end(); #endif while (i != end) { - Stat *stat = *i; + StatData *stat = *i; if (stat->dodisplay()) stat->display(stream); ++i; @@ -213,8 +150,8 @@ Database::dump(ostream &stream) list_t::iterator k = printStats.begin(); list_t::iterator endprint = printStats.end(); while (k != endprint) { - Stat *stat = *k; - if (stat->dodisplay() && !stat->binned()) + StatData *stat = *k; + if (stat->dodisplay() /*&& !stat->binned()*/) stat->display(stream); ++k; } @@ -222,7 +159,7 @@ Database::dump(ostream &stream) } StatData * -Database::find(const Stat *stat) +Data::find(void *stat) { map_t::const_iterator i = statMap.find(stat); @@ -233,41 +170,26 @@ Database::find(const Stat *stat) } void -Database::check() +Data::check() { list_t::iterator i = allStats.begin(); list_t::iterator end = allStats.end(); while (i != end) { - Stat *stat = *i; - StatData *data = find(stat); - if (!data || !data->init) { -#ifdef STAT_DEBUG - cprintf("this is stat number %d\n",(*i)->number); -#endif - panic("Not all stats have been initialized"); - } - - if (data->print) { - if (data->name.empty()) - panic("all printable stats must be named"); - - list_t::iterator j = printStats.insert(printStats.end(), *i); - inplace_merge(printStats.begin(), j, - printStats.end(), Stat::less); - } - + StatData *stat = *i; + assert(stat); + stat->check(); ++i; } } void -Database::reset() +Data::reset() { list_t::iterator i = allStats.begin(); list_t::iterator end = allStats.end(); while (i != end) { - Stat *stat = *i; + StatData *stat = *i; stat->reset(); ++i; } @@ -282,7 +204,7 @@ Database::reset() i = allStats.begin(); while (i != end) { - Stat *stat = *i; + StatData *stat = *i; stat->reset(); ++i; } @@ -294,21 +216,20 @@ Database::reset() } void -Database::regStat(Stat *stat) +Data::mapStat(void *stat, StatData *data) { if (statMap.find(stat) != statMap.end()) panic("shouldn't register stat twice!"); - allStats.push_back(stat); + allStats.push_back(data); - StatData *data = new StatData; bool success = (statMap.insert(make_pair(stat, data))).second; assert(statMap.find(stat) != statMap.end()); assert(success && "this should never fail"); } void -Database::regBin(MainBin *bin, std::string name) +Data::regBin(MainBin *bin, string name) { if (bin_names.find(bin) != bin_names.end()) panic("shouldn't register bin twice"); @@ -322,235 +243,121 @@ Database::regBin(MainBin *bin, std::string name) cprintf("registering %s\n", name); } -bool -Stat::less(Stat *stat1, Stat *stat2) -{ - const string &name1 = stat1->myname(); - const string &name2 = stat2->myname(); - - vector<string> v1; - vector<string> v2; - - tokenize(v1, name1, '.'); - tokenize(v2, name2, '.'); - - int last = min(v1.size(), v2.size()) - 1; - for (int i = 0; i < last; ++i) - if (v1[i] != v2[i]) - return v1[i] < v2[i]; - - // Special compare for last element. - if (v1[last] == v2[last]) - return v1.size() < v2.size(); - else - return v1[last] < v2[last]; - - return false; -} - -StatData * -Database::print(Stat *stat) +void +Data::regPrint(void *stat) { StatData *data = find(stat); - assert(data); - data->print = true; + if (!data->print) { + data->print = true; + + list_t::iterator j = printStats.insert(printStats.end(), data); + inplace_merge(printStats.begin(), j, + printStats.end(), StatData::less); + } - return data; } -Database & +Data & StatDB() { - static Database db; + static Data db; return db; } -Stat::Stat(bool reg) -{ -#if 0 - // This assert can help you find that pesky stat. - assert(this != (void *)0xbffff5c0); -#endif - - if (reg) - StatDB().regStat(this); - -#ifdef STAT_DEBUG - number = ++total_stats; - cprintf("I'm stat number %d\n",number); -#endif } -void -Stat::setInit() -{ mydata()->init = true; } - StatData * -Stat::mydata() +DataAccess::find() const { - StatData *data = StatDB().find(this); - assert(data); - - return data; -} - -const StatData * -Stat::mydata() const -{ - StatData *data = StatDB().find(this); - assert(data); - - return data; + return Database::StatDB().find(const_cast<void *>((const void *)this)); } -const SubData * -Stat::mysubdata(int index) const +void +DataAccess::map(StatData *data) { - assert(index >= 0); - if (index >= size()) - return NULL; - - const StatData *data = this->mydata(); - if (!data->subdata || data->subdata->size() <= index) - return NULL; - - return &(*data->subdata)[index]; + Database::StatDB().mapStat(this, data); } -SubData * -Stat::mysubdata_create(int index) +StatData * +DataAccess::statData() { - int size = this->size(); - assert(index >= 0 && (size == 0 || size > 0 && index < size)); - - StatData *data = this->mydata(); - if (!data->subdata) { - if (!data->subdata) { - if (size == 0) - size = index + 1; - - data->subdata = new vector<SubData>(size); - } - } else if (data->subdata->size() <= index) - data->subdata->resize(index + 1); - - SubData *sd = &(*data->subdata)[index]; - assert(sd); - - return sd; + StatData *ptr = find(); + assert(ptr); + return ptr; } -string -Stat::myname() const -{ return mydata()->name; } - -string -Stat::mysubname(int index) const +const StatData * +DataAccess::statData() const { - const SubData *sd = mysubdata(index); - return sd ? sd->name : ""; + const StatData *ptr = find(); + assert(ptr); + return ptr; } -string -Stat::mydesc() const -{ return mydata()->desc; } - -string -Stat::mysubdesc(int index) const +void +DataAccess::setInit() { - const SubData *sd = mysubdata(index); - return sd ? sd->desc : ""; + statData()->init = true; } -int -Stat::myprecision() const -{ return mydata()->precision; } - -FormatFlags -Stat::myflags() const -{ return mydata()->flags; } - -bool -Stat::dodisplay() const -{ return !mydata()->prereq || !mydata()->prereq->zero(); } - -StatData * -Stat::print() +void +DataAccess::setPrint() { - StatData *data = StatDB().print(this); - assert(data && data->init); - - return data; + Database::StatDB().regPrint(this); } -Stat & -Stat::name(const string &name) +StatData::~StatData() { - print()->name = name; - return *this; } -Stat & -Stat::desc(const string &desc) +bool +StatData::less(StatData *stat1, StatData *stat2) { - print()->desc = desc; - return *this; -} + const string &name1 = stat1->name; + const string &name2 = stat2->name; -Stat & -Stat::precision(int precision) -{ - print()->precision = precision; - return *this; -} + vector<string> v1; + vector<string> v2; -Stat & -Stat::flags(FormatFlags flags) -{ - if (flags & __reserved) - panic("Cannot set reserved flags!\n"); + tokenize(v1, name1, '.'); + tokenize(v2, name2, '.'); - print()->flags |= flags; - return *this; -} + int last = min(v1.size(), v2.size()) - 1; + for (int i = 0; i < last; ++i) + if (v1[i] != v2[i]) + return v1[i] < v2[i]; -Stat & -Stat::prereq(const Stat &prereq) -{ - print()->prereq = &prereq; - return *this; -} + // Special compare for last element. + if (v1[last] == v2[last]) + return v1.size() < v2.size(); + else + return v1[last] < v2[last]; -Stat & -Stat::subname(int index, const string &name) -{ - print(); - mysubdata_create(index)->name = name; - return *this; -} -Stat & -Stat::subdesc(int index, const string &desc) -{ - print(); - mysubdata_create(index)->desc = desc; - return *this; + return false; } bool -ScalarStat::zero() const +StatData::check() const { - return val() == 0.0; -} + if (!init) { +#ifdef STAT_DEBUG + cprintf("this is stat number %d\n",(*i)->number); +#endif + panic("Not all stats have been initialized"); + return false; + } -bool -VectorStat::zero() const -{ - return val()[0] == 0.0; + if (print && name.empty()) { + panic("all printable stats must be named"); + return false; + } + + return true; } string -ValueToString(result_t value, int precision) +ValueToString(result_t value, DisplayMode mode, int precision) { stringstream val; @@ -564,20 +371,33 @@ ValueToString(result_t value, int precision) val.setf(ios::fixed); val << value; } else { -#ifndef STAT_DISPLAY_COMPAT - val << "no value"; -#else - val << "<err: div-0>"; -#endif + val << (mode == mode_m5 ? "no value" : "<err: div-0>"); } return val.str(); } +struct ScalarPrint +{ + result_t value; + string name; + string desc; + int precision; + DisplayMode mode; + FormatFlags flags; + result_t pdf; + result_t cdf; + + ScalarPrint() + : value(0.0), precision(0), mode(default_mode), flags(0), + pdf(NAN), cdf(NAN) + {} + + void operator()(ostream &stream) const; +}; + void -PrintOne(ostream &stream, result_t value, - const string &name, const string &desc, int precision, - FormatFlags flags, result_t pdf = NAN, result_t cdf = NAN) +ScalarPrint::operator()(ostream &stream) const { if (flags & nozero && value == 0.0 || flags & nonan && isnan(value)) @@ -591,16 +411,13 @@ PrintOne(ostream &stream, result_t value, if (!isnan(cdf)) ccprintf(cdfstr, "%.2f%%", cdf * 100.0); -#ifdef STAT_DISPLAY_COMPAT - if (flags & __substat) { + if (mode == mode_simplescalar && flags & __substat) { ccprintf(stream, "%32s %12s %10s %10s", name, - ValueToString(value, precision), + ValueToString(value, mode, precision), pdfstr, cdfstr); - } else -#endif - { + } else { ccprintf(stream, "%-40s %12s %10s %10s", name, - ValueToString(value, precision), pdfstr, cdfstr); + ValueToString(value, mode, precision), pdfstr, cdfstr); } if (PrintDescriptions) { @@ -610,312 +427,563 @@ PrintOne(ostream &stream, result_t value, stream << endl; } -void -ScalarStat::display(ostream &stream) const +struct VectorPrint { - PrintOne(stream, val(), myname(), mydesc(), myprecision(), myflags()); -} - -void -VectorStat::display(ostream &stream) const -{ - bool have_subname = false; - bool have_subdesc = false; - int size = this->size(); - for (int i = 0; i < size; ++i) { - if (!mysubname(i).empty()) - have_subname = true; - if (!mysubdesc(i).empty()) - have_subdesc = true; - } - - vector<string> *subnames = 0; - vector<string> *subdescs = 0; - if (have_subname) { - subnames = new vector<string>(size); - for (int i = 0; i < size; ++i) - (*subnames)[i] = mysubname(i); - } - if (have_subdesc) { - subdescs = new vector<string>(size); - for (int i = 0; i < size; ++i) - (*subdescs)[i] = mysubdesc(i); - } + string name; + string desc; + vector<string> subnames; + vector<string> subdescs; + int precision; + DisplayMode mode; + FormatFlags flags; + rvec_t vec; + result_t total; - VectorDisplay(stream, myname(), subnames, mydesc(), subdescs, - myprecision(), myflags(), val(), total()); -} + VectorPrint() + : subnames(0), subdescs(0), precision(-1), mode(default_mode), + flags(0), total(NAN) + {} -#ifndef STAT_DISPLAY_COMPAT -#define NAMESEP "::" -#else -#define NAMESEP "_" -#endif + void operator()(ostream &stream) const; +}; -#ifndef STAT_DISPLAY_COMPAT void -VectorDisplay(std::ostream &stream, - const std::string &myname, - const std::vector<std::string> *mysubnames, - const std::string &mydesc, - const std::vector<std::string> *mysubdescs, - int myprecision, FormatFlags myflags, - const rvec_t &vec, result_t mytotal) +VectorPrint::operator()(std::ostream &stream) const { int _size = vec.size(); result_t _total = 0.0; - result_t _pdf, _cdf = 0.0; - if (myflags & (pdf | cdf)) { + 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) { - PrintOne(stream, vec[0], myname, mydesc, myprecision, myflags); - } else { + print.value = vec[0]; + print(stream); + } else if (mode == mode_m5) { for (int i = 0; i < _size; ++i) { - string subname; - if (mysubnames) { - subname = (*mysubnames)[i]; - if (subname.empty()) - continue; - } else { - subname = to_string(i); - } + if (havesub && (i >= subnames.size() || subnames[i].empty())) + continue; - string name = myname + NAMESEP + subname; - if (!(myflags & pdf)) - PrintOne(stream, vec[i], name, mydesc, myprecision, myflags); - else { - _pdf = vec[i] / _total; - _cdf += _pdf; - PrintOne(stream, vec[i], name, mydesc, myprecision, myflags, - _pdf, _cdf); - } - } + print.name = base + (havesub ? subnames[i] : to_string(i)); + print.desc = subdescs.empty() ? desc : subdescs[i]; + print.value = vec[i]; - if (myflags & total) - PrintOne(stream, mytotal, myname + NAMESEP + "total", - mydesc, myprecision, myflags); - } -} -#else -void -VectorDisplay(std::ostream &stream, - const std::string &myname, - const std::vector<std::string> *mysubnames, - const std::string &mydesc, - const std::vector<std::string> *mysubdescs, - int myprecision, FormatFlags myflags, - const rvec_t &vec, result_t mytotal) -{ - int _size = vec.size(); - result_t _total = 0.0; - result_t _pdf, _cdf = 0.0; + if (_total && (flags & pdf)) { + print.pdf = vec[i] / _total; + print.cdf += print.pdf; + } - if (myflags & (pdf | cdf)) { - for (int i = 0; i < _size; ++i) { - _total += vec[i]; + print(stream); } - } - if (_size == 1) { - PrintOne(stream, vec[0], myname, mydesc, myprecision, myflags); + if (flags & ::Statistics::total) { + print.name = base + "total"; + print.desc = desc; + print.value = total; + print(stream); + } } else { - if (myflags & total) - PrintOne(stream, mytotal, myname, mydesc, myprecision, myflags); + if (flags & ::Statistics::total) { + print.value = total; + print(stream); + } - if (myflags & dist) { - ccprintf(stream, "%s.start_dist\n", myname); + 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) { - string subname, subdesc; - subname = to_string(i); - if (mysubnames) { - if (!subname.empty()) { - subname = (*mysubnames)[i]; - } - } - if (mysubdescs) { - subdesc = (*mysubdescs)[i]; - } - if (!(myflags & (pdf | cdf))) { - PrintOne(stream, vec[i], subname, subdesc, myprecision, - myflags | __substat); - } else { - if (_total) { - _pdf = vec[i] / _total; - _cdf += _pdf; - } else { - _pdf = _cdf = 0.0; - } - if (!(myflags & cdf)) { - PrintOne(stream, vec[i], subname, subdesc, myprecision, - myflags | __substat, _pdf); - } else { - PrintOne(stream, vec[i], subname, subdesc, myprecision, - myflags | __substat, _pdf, _cdf); - } + 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", myname); + ccprintf(stream, "%s.end_dist\n", name); } else { for (int i = 0; i < _size; ++i) { - string subname; - if (mysubnames) { - subname = (*mysubnames)[i]; - if (subname.empty()) - continue; + 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 { - subname = to_string(i); + _pdf = _cdf = NAN; } - string name = myname + NAMESEP + subname; - if (!(myflags & pdf)) { - PrintOne(stream, vec[i], name, mydesc, myprecision, - myflags); - } else { - if (_total) { - _pdf = vec[i] / _total; - _cdf += _pdf; - } else { - _pdf = _cdf = NAN; - } - PrintOne(stream, vec[i], name, mydesc, myprecision, - myflags, _pdf, _cdf); + if (flags & pdf) { + print.pdf = _pdf; + print.cdf = _cdf; } + + print(stream); } } } } -#endif -#ifndef STAT_DISPLAY_COMPAT +struct DistPrint +{ + string name; + string desc; + int precision; + DisplayMode mode; + FormatFlags flags; + + 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 -DistDisplay(ostream &stream, const string &name, const string &desc, - int precision, FormatFlags flags, - result_t min_val, result_t max_val, - result_t underflow, result_t overflow, - const rvec_t &vec, int min, int max, int bucket_size, int size); +DistPrint::operator()(ostream &stream) const { + if (fancy) { + ScalarPrint print; + string base = name + ((mode == mode_m5) ? "::" : "_"); + + print.precision = precision; + print.flags = flags; + 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; - result_t pdf, cdf = 0.0; total += underflow; for (int i = 0; i < size; ++i) total += vec[i]; total += overflow; - pdf = underflow / total; - cdf += pdf; + string base = name + (mode == mode_m5 ? "::" : "."); - PrintOne(stream, underflow, name + NAMESEP + "underflow", desc, - precision, myflags, pdf, cdf); + ScalarPrint print; + print.desc = (mode == mode_m5) ? desc : ""; + print.precision = precision; + print.mode = mode; + print.flags = flags; - for (int i = 0; i < size; ++i) { - stringstream namestr; - namestr << name; - - int low = i * bucket_size + min; - int high = ::std::min((i + 1) * bucket_size + min - 1, max); - namestr << low; - if (low < high) - namestr << "-" << high; - - pdf = vec[i] / total; - cdf += pdf; - PrintOne(stream, vec[i], namestr.str(), desc, precision, myflags, - pdf, cdf); + 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 (flags & (pdf || cdf)) { + print.pdf = NAN; + print.cdf = NAN; + } + } + + 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; + } + 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); } - pdf = overflow / total; - cdf += pdf; - PrintOne(stream, overflow, name + NAMESEP + "overflow", desc, - precision, myflags, pdf, cdf); - PrintOne(stream, total, name + NAMESEP + "total", desc, - precision, myflags); + if (mode == mode_simplescalar) + ccprintf(stream, "%send_dist\n\n", base); } -#else + void -DistDisplay(ostream &stream, const string &name, const string &desc, - int precision, FormatFlags flags, - result_t min_val, result_t max_val, - result_t underflow, result_t overflow, - const rvec_t &vec, int min, int max, int bucket_size, int size) +ScalarDataBase::display(ostream &stream) const { - assert(size == vec.size()); - string blank; + ScalarPrint print; + print.value = val(); + print.name = name; + print.desc = desc; + print.precision = precision; + print.flags = flags; + + print(stream); +} - result_t total = 0.0; +void +VectorDataBase::display(ostream &stream) const +{ + int size = this->size(); + const_cast<VectorDataBase *>(this)->update(); - total += underflow; - for (int i = 0; i < size; ++i) - total += vec[i]; - total += overflow; + VectorPrint print; - ccprintf(stream, "%-42s", name + ".start_dist"); - if (PrintDescriptions && !desc.empty()) - ccprintf(stream, " # %s", desc); - stream << endl; + print.name = name; + print.desc = desc; + print.mode = mode; + print.flags = flags; + print.precision = precision; + print.vec = val(); + print.total = total(); - PrintOne(stream, total, name + ".samples", blank, precision, flags); - PrintOne(stream, min_val, name + ".min_value", blank, precision, flags); + 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; + } + } - if (underflow > 0) - PrintOne(stream, min_val, name + ".underflows", blank, precision, - flags); - int _min; - result_t _pdf, _cdf, mypdf, mycdf; + print(stream); +} - _cdf = 0.0; - for (int i = 0; i < size; ++i) { - if (flags & nozero && vec[i] == 0.0 || - flags & nonan && isnan(vec[i])) +void +Vector2dDataBase::display(ostream &stream) const +{ + const_cast<Vector2dDataBase *>(this)->update(); + + bool havesub = false; + VectorPrint print; + + print.subnames = y_subnames; + print.mode = mode; + print.flags = flags; + 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; - _min = i * bucket_size + min; - _pdf = vec[i] / total * 100.0; - _cdf += _pdf; + int iy = i * y; + rvec_t yvec(y); - mypdf = (flags & pdf) ? _pdf : NAN; - mycdf = (flags & cdf) ? _cdf : NAN; + 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]; + } - PrintOne(stream, vec[i], ValueToString(_min, 0), blank, precision, - flags | __substat, mypdf, mycdf); + print.name = name + "_" + (havesub ? subnames[i] : to_string(i)); + print.desc = desc; + print.vec = yvec; + print.total = total; + print(stream); } - if (overflow > 0) - PrintOne(stream, overflow, name + ".overflows", blank, precision, - flags); - PrintOne(stream, max_val, name + ".max_value", blank, precision, flags); - ccprintf(stream, "%s.end_dist\n\n", name); + 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) const +{ + const_cast<DistDataBase *>(this)->update(); + + DistPrint print; + + print.name = name; + print.desc = desc; + print.precision = precision; + print.mode = mode; + print.flags = flags; + + 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) 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.precision = precision; + print.mode = mode; + print.flags = flags; + + 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 +FormulaBase::val(rvec_t &vec) const +{ + vec = root->val(); +} + +result_t +FormulaBase::total() const +{ + return root->total(); +} + +size_t +FormulaBase::size() const +{ + if (!root) + return 0; + else + return root->size(); +} + +bool +FormulaBase::binned() const +{ + return root->binned(); +} + +void +FormulaBase::reset() +{ +} + +bool +FormulaBase::zero() const +{ + rvec_t vec; + val(vec); + for (int i = 0; i < vec.size(); ++i) + if (vec[i] != 0.0) + return false; + return true; } -#endif -/** - * @todo get rid of the ugly hack **Ignore for total - */ void -FancyDisplay(ostream &stream, const string &name, const string &desc, - int precision, FormatFlags flags, result_t mean, - result_t variance, result_t total) +FormulaBase::update(StatData *) +{ +} + +Formula::Formula() { - result_t stdev = isnan(variance) ? NAN : sqrt(variance); - PrintOne(stream, mean, name + NAMESEP + "mean", desc, precision, flags); - PrintOne(stream, stdev, name + NAMESEP + "stdev", desc, precision, flags); - PrintOne(stream, total, "**Ignore: " + name + NAMESEP + "TOT", desc, precision, flags); + setInit(); } -} // namespace Detail +Formula::Formula(Temp r) +{ + root = r; + assert(size()); +} -MainBin::MainBin(const std::string &name) +const Formula & +Formula::operator=(Temp r) +{ + assert(!root && "Can't change formulas"); + root = r; + assert(size()); + return *this; +} + +const Formula & +Formula::operator+=(Temp r) +{ + if (root) + root = NodePtr(new BinaryNode<std::plus<result_t> >(root, r)); + else + root = r; + assert(size()); + return *this; +} + +MainBin::MainBin(const string &name) : _name(name), mem(NULL), memsize(-1) { - Detail::StatDB().regBin(this, name); + Database::StatDB().regBin(this, name); } MainBin::~MainBin() @@ -927,14 +995,14 @@ MainBin::~MainBin() char * MainBin::memory(off_t off) { + if (memsize == -1) + memsize = CeilPow2((size_t) offset()); + if (!mem) { mem = new char[memsize]; memset(mem, 0, memsize); } - if (memsize == -1) - memsize = CeilPow2((size_t) offset()); - assert(offset() <= size()); return mem + off; } @@ -942,13 +1010,13 @@ MainBin::memory(off_t off) void check() { - Detail::StatDB().check(); + Database::StatDB().check(); } void dump(ostream &stream) { - Detail::StatDB().dump(stream); + Database::StatDB().dump(stream); } CallbackQueue resetQueue; @@ -962,7 +1030,7 @@ RegResetCallback(Callback *cb) void reset() { - Detail::StatDB().reset(); + Database::StatDB().reset(); resetQueue.process(); } diff --git a/base/statistics.hh b/base/statistics.hh index ded1470f4..7d2cdf869 100644 --- a/base/statistics.hh +++ b/base/statistics.hh @@ -77,9 +77,6 @@ float __nan(); #define __M5_NAN #endif -/** Print stats out in SS format. */ -#define STAT_DISPLAY_COMPAT - class Callback; /** The current simulated cycle. */ @@ -103,177 +100,415 @@ const FormatFlags none = 0x0000; const FormatFlags total = 0x0001; /** Print the percent of the total that this entry represents. */ const FormatFlags pdf = 0x0002; +/** Print the cumulative percentage of total upto this entry. */ +const FormatFlags cdf = 0x0004; /** Don't print if this is zero. */ -const FormatFlags nozero = 0x0004; +const FormatFlags nozero = 0x0010; /** Don't print if this is NAN */ -const FormatFlags nonan = 0x0008; -/** Print the cumulative percentage of total upto this entry. */ -const FormatFlags cdf = 0x0010; +const FormatFlags nonan = 0x0020; /** Print the distribution. */ -const FormatFlags dist = 0x0020; +const FormatFlags dist = 0x0100; /** Used for SS compatability. */ const FormatFlags __substat = 0x8000; /** Mask of flags that can't be set directly */ const FormatFlags __reserved = __substat; +enum DisplayMode +{ + mode_m5, + mode_simplescalar, + mode_python +}; + +extern DisplayMode default_mode; + /* Contains the statistic implementation details */ -namespace Detail { ////////////////////////////////////////////////////////////////////// // // Statistics Framework Base classes // ////////////////////////////////////////////////////////////////////// -struct StatData; -struct SubData; - -/** - * Common base class for all statistics, used to maintain a list and print. - * This class holds no data itself but is used to find the associated - * StatData in the stat database @sa Statistics::Database. - */ -class Stat +struct StatData { - protected: - /** Mark this statistics as initialized. */ - void setInit(); - /** - * Finds and returns the associated StatData from the database. - * @return The formatting and output data of this statistic. - */ - StatData *mydata(); - /** - * Finds and returns a const pointer to the associated StatData. - * @return The formatting and output data of this statistic. - */ - const StatData *mydata() const; - /** - * Mark this stat for output at the end of simulation. - * @return The formatting and output data of this statistic. - */ - StatData *print(); - /** - * Finds and returns the SubData at the given index. - * @param index The index of the SubData to find. - * @return The name and description of the given index. - */ - const SubData *mysubdata(int index) const; - /** - * Create and return a new SubData field for the given index. - * @param index The index to create a SubData for. - * @return A pointer to the created SubData. - */ - SubData *mysubdata_create(int index); + /** True if the stat has been initialized. */ + bool init; + /** True if the stat should be printed. */ + bool print; + /** The name of the stat. */ + std::string name; + /** The description of the stat. */ + std::string desc; + /** The display precision. */ + int precision; + /** Display Mode */ + DisplayMode mode; + /** The formatting flags. */ + FormatFlags flags; - public: - /** - * Return the name of this stat. - * @return the name of the stat. - */ - virtual std::string myname() const; - /** - * Return the name of the sub field at the given index. - * @param index the subfield index. - * @return the name of the subfield. - */ - virtual std::string mysubname(int index) const; - /** - * Return the description of this stat. - * @return the description of this stat. - */ - virtual std::string mydesc() const; - /** - * Return the description of the subfield at the given index. - * @param index The subfield index. - * @return the description of the subfield. - */ - virtual std::string mysubdesc(int index) const; - /** - * Return the format flags of this stat. - * @return the format flags. - */ - virtual FormatFlags myflags() const; - /** - * Return true if this stat's prereqs have been satisfied (they are non - * zero). - * @return true if the prerequisite stats aren't zero. - */ - virtual bool dodisplay() const; - /** - * Return the display percision. - * @return The display precision. - */ - virtual int myprecision() const; - public: - /** - * Create this stat and perhaps register it with the stat database. To be - * printed a stat must be registered with the database. - * @param reg If true, register this stat in the database. - */ - Stat(bool reg); + /** A pointer to a prerequisite Stat. */ + const StatData *prereq; + + StatData() + : init(false), print(false), precision(-1), mode(default_mode), + flags(0), prereq(0) + {} + + virtual ~StatData(); + /** - * Destructor + * @return true if the stat is binned. */ - virtual ~Stat() {} + 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) const = 0; + bool dodisplay() const { return !prereq || !prereq->zero(); } + /** - * Reset this stat to the default state. + * Reset the corresponding stat to the default state. */ virtual void reset() = 0; + /** - * Return the number of entries in this stat. - * @return The number of entries. + * @return true if this stat has a value and satisfies its + * requirement as a prereq */ - virtual size_t size() const = 0; + virtual bool zero() const = 0; + /** - * Return true if the stat has value zero. - * @return True if the stat is zero. + * Check that this stat has been set up properly and is ready for + * use + * @return true for success */ - virtual bool zero() const = 0; + virtual bool check() const; /** - * Return true if stat is binned. - *@return True is stat is binned. + * 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. + * @param stat1 The first stat. + * @param stat2 The second stat. + * @return stat1's name is alphabetically before stat2's */ - virtual bool binned() const = 0; + static bool less(StatData *stat1, StatData *stat2); +}; + +struct ScalarDataBase : public StatData +{ + virtual result_t val() const = 0; + virtual result_t total() const = 0; + + virtual void display(std::ostream &stream) const; +}; + +template <class T> +class ScalarData : public ScalarDataBase +{ + protected: + T &s; + + public: + ScalarData(T &stat) : s(stat) {} + + virtual bool binned() const { return s.binned(); } + virtual result_t val() const { return s.val(); } + virtual result_t total() const { return s.total(); } + virtual void reset() { s.reset(); } + virtual bool zero() const { return s.zero(); } +}; + +struct VectorDataBase : 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) const; + + virtual size_t size() const = 0; + virtual const rvec_t &val() const = 0; + virtual result_t total() const = 0; + virtual void update() + { + int s = size(); + if (subnames.size() < s) + subnames.resize(s); + + if (subdescs.size() < s) + subdescs.resize(s); + } +}; + +template <class T> +class VectorData : public VectorDataBase +{ + protected: + T &s; + mutable rvec_t vec; + + public: + VectorData(T &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 + { + s.val(vec); + return vec; + } + virtual result_t total() const { return s.total(); } + virtual void update() + { + VectorDataBase::update(); + s.update(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; + int size; + bool fancy; +}; + +struct DistDataBase : public StatData +{ + /** Local storage for the entry values, used for printing. */ + DistDataData data; + + virtual void display(std::ostream &stream) const; + virtual void update() = 0; +}; + +template <class T> +class DistData : public DistDataBase +{ + protected: + T &s; + + public: + DistData(T &stat) : s(stat) {} + + virtual bool binned() const { return s.binned(); } + virtual void reset() { s.reset(); } + virtual bool zero() const { return s.zero(); } + virtual void update() { return s.update(this); } +}; + +struct VectorDistDataBase : public StatData +{ + std::vector<DistDataData> data; + + /** Names and descriptions of subfields. */ + mutable std::vector<std::string> subnames; + mutable std::vector<std::string> subdescs; + + /** Local storage for the entry values, used for printing. */ + mutable rvec_t vec; + + virtual size_t size() const = 0; + virtual void display(std::ostream &stream) const; + virtual void update() + { + int s = size(); + if (subnames.size() < s) + subnames.resize(s); + + if (subdescs.size() < s) + subdescs.resize(s); + } +}; + +template <class T> +class VectorDistData : public VectorDistDataBase +{ + protected: + T &s; + + public: + VectorDistData(T &stat) : s(stat) {} + + virtual bool binned() const { return T::bin_t::binned; } + virtual void reset() { s.reset(); } + virtual size_t size() const { return s.size(); } + virtual bool zero() const { return s.zero(); } + virtual void update() + { + VectorDistDataBase::update(); + return s.update(this); + } +}; + +struct Vector2dDataBase : public StatData +{ + /** Names and descriptions of subfields. */ + std::vector<std::string> subnames; + std::vector<std::string> subdescs; + std::vector<std::string> y_subnames; + + /** Local storage for the entry values, used for printing. */ + mutable rvec_t vec; + mutable int x; + mutable int y; + + virtual void display(std::ostream &stream) const; + virtual void update() + { + if (subnames.size() < x) + subnames.resize(x); + } +}; + +template <class T> +class Vector2dData : public Vector2dDataBase +{ + protected: + T &s; + + public: + Vector2dData(T &stat) : s(stat) {} + + virtual bool binned() const { return T::bin_t::binned; } + virtual void reset() { s.reset(); } + virtual bool zero() const { return s.zero(); } + virtual void update() + { + Vector2dDataBase::update(); + return s.update(this); + } +}; + + +class DataAccess +{ + protected: + StatData *find() const; + void map(StatData *data); + + StatData *statData(); + const StatData *statData() const; + + void setInit(); + void setPrint(); +}; + +template <class Parent, class Child, template <class Child> class Data> +class Wrap : public Child +{ + protected: + Parent &self() { return *reinterpret_cast<Parent *>(this); } + + protected: + Data<Child> *statData() + { + StatData *__data = DataAccess::statData(); + Data<Child> *ptr = dynamic_cast<Data<Child> *>(__data); + assert(ptr); + return ptr; + } + + public: + const Data<Child> *statData() const + { + const StatData *__data = DataAccess::statData(); + const Data<Child> *ptr = dynamic_cast<const Data<Child> *>(__data); + assert(ptr); + return ptr; + } + + public: + Wrap() + { + map(new Data<Child>(*this)); + } /** * Set the name and marks this stat to print at the end of simulation. * @param name The new name. * @return A reference to this stat. */ - Stat &name(const std::string &name); + Parent &name(const std::string &_name) + { + Data<Child> *data = statData(); + data->name = _name; + setPrint(); + return self(); + } + /** * Set the description and marks this stat to print at the end of * simulation. * @param desc The new description. * @return A reference to this stat. */ - Stat &desc(const std::string &desc); + Parent &desc(const std::string &_desc) + { + statData()->desc = _desc; + return self(); + } + /** * Set the precision and marks this stat to print at the end of simulation. * @param p The new precision * @return A reference to this stat. */ - Stat &precision(int p); + Parent &precision(int _precision) + { + statData()->precision = _precision; + return self(); + } + /** * Set the flags and marks this stat to print at the end of simulation. * @param f The new flags. * @return A reference to this stat. */ - Stat &flags(FormatFlags f); + Parent &flags(FormatFlags _flags) + { + statData()->flags |= _flags; + return self(); + } + /** * Set the prerequisite stat and marks this stat to print at the end of * simulation. * @param prereq The prerequisite stat. * @return A reference to this stat. */ - Stat &prereq(const Stat &prereq); + template <class T> + Parent &prereq(const T &prereq) + { + statData()->prereq = prereq.statData(); + return self(); + } +}; + +template <class Parent, class Child, template <class Child> class Data> +class WrapVec : public Wrap<Parent, Child, Data> +{ + public: + // The following functions are specific to vectors. If you use them + // in a non vector context, you will get a nice compiler error! + /** * Set the subfield name for the given index, and marks this stat to print * at the end of simulation. @@ -281,7 +516,15 @@ class Stat * @param name The new name of the subfield. * @return A reference to this stat. */ - Stat &subname(int index, const std::string &name); + Parent &subname(int index, const std::string &name) + { + std::vector<std::string> &subn = statData()->subnames; + if (subn.size() <= index) + subn.resize(index + 1); + subn[index] = name; + return self(); + } + /** * Set the subfield description for the given index and marks this stat to * print at the end of simulation. @@ -289,107 +532,42 @@ class Stat * @param desc The new description of the subfield * @return A reference to this stat. */ - Stat &subdesc(int index, const std::string &desc); - - public: - /** - * 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. - * @param stat1 The first stat. - * @param stat2 The second stat. - * @return stat1's name is alphabetically before stat2's - */ - static bool less(Stat *stat1, Stat *stat2); - -#ifdef STAT_DEBUG - /** A unique ID used for debugging. */ - int number; -#endif -}; + Parent &subdesc(int index, const std::string &desc) + { + std::vector<std::string> &subd = statData()->subdescs; + if (subd.size() <= index) + subd.resize(index + 1); + subd[index] = desc; -/** - * Base class for all scalar stats. The class provides an interface to access - * the current value of the stat. This class can be used in formulas. - */ -class ScalarStat : public Stat -{ - public: - /** - * Create and perhaps register this stat with the database. - * @param reg If true, register this stat with the database. - */ - ScalarStat(bool reg) : Stat(reg) {} - /** - * Return the current value of this statistic as a result type. - * @return The current value of this statistic. - */ - virtual result_t val() const = 0; - /** - * Return true if this stat has value zero. - * @return True if this stat is zero. - */ - virtual bool zero() const; - /** - * Print this stat to the provided ostream. - * @param stream The output stream. - */ - virtual void display(std::ostream &stream) const; + return self(); + } - /** - * Return true if stat is binned. - *@return True is stat is binned. - */ - virtual bool binned() const = 0; }; -void -VectorDisplay(std::ostream &stream, const std::string &myname, - const std::vector<std::string> *mysubnames, - const std::string &mydesc, - const std::vector<std::string> *mysubdescs, - int myprecision, FormatFlags myflags, const rvec_t &vec, - result_t mytotal); - -/** - * Base class for all vector stats. This class provides interfaces to access - * the current values of the stats as well as the totals. This class can be - * used in formulas. - */ -class VectorStat : public Stat +template <class Parent, class Child, template <class Child> class Data> +class WrapVec2d : public WrapVec<Parent, Child, Data> { public: /** - * Create and perhaps register this stat with the database. - * @param reg If true, register this stat with the database. - */ - VectorStat(bool reg) : Stat(reg) {} - /** - * Return a vector of result typesd of all the values in the vector. - * @return The values of the vector. - */ - virtual const rvec_t &val() const = 0; - /** - * Return the total of all the entries in the vector. - * @return The total of the vector. - */ - virtual result_t total() const = 0; - /** - * Return true if this stat has value zero. - * @return True if this stat is zero. - */ - virtual bool zero() const; - /** - * Print this stat to the provided ostream. - * @param stream The output stream. - */ - virtual void display(std::ostream &stream) const; - - /** - * Return true if stat is binned. - *@return True is stat is binned. + * @warning This makes the assumption that if you're gonna subnames a 2d + * vector, you're subnaming across all y */ - virtual bool binned() const = 0; + Parent &ysubnames(const char **names) + { + Data<Child> *data = statData(); + data->y_subnames.resize(y); + for (int i = 0; i < y; ++i) + data->y_subnames[i] = names[i]; + return self(); + } + Parent &ysubname(int index, const std::string subname) + { + Data<Child> *data = statData(); + assert(i < y); + data->y_subnames.resize(y); + data->y_subnames[i] = subname.c_str(); + return self(); + } }; ////////////////////////////////////////////////////////////////////// @@ -411,13 +589,18 @@ struct StatStor private: /** The statistic value. */ T data; + static T &Null() + { + static T __T = T(); + return __T; + } public: /** * Builds this storage element and calls the base constructor of the * datatype. */ - StatStor(const Params &) : data(T()) {} + StatStor(const Params &) : data(Null()) {} /** * The the stat to the given value. @@ -452,7 +635,12 @@ struct StatStor /** * Reset stat value to default */ - void reset() { data = T(); } + void reset() { data = Null(); } + + /** + * @return true if zero value + */ + bool zero() const { return data == Null(); } }; /** @@ -541,6 +729,11 @@ struct AvgStor total = 0; last = curTick; } + + /** + * @return true if zero value + */ + bool zero() const { return total == 0.0; } }; /** @@ -549,7 +742,7 @@ struct AvgStor * This allows for breaking down statistics across multiple bins easily. */ template <typename T, template <typename T> class Storage, class Bin> -class ScalarBase : public ScalarStat +class ScalarBase : public DataAccess { protected: /** Define the type of the storage class. */ @@ -594,11 +787,6 @@ class ScalarBase : public ScalarStat public: /** - * Return the current value of this stat as a result type. - * @return The current value. - */ - result_t val() const { return data()->val(params); } - /** * Return the current value of this stat as its base type. * @return The current value. */ @@ -608,9 +796,9 @@ class ScalarBase : public ScalarStat /** * Create and initialize this stat, register it with the database. */ - ScalarBase() : ScalarStat(true) { + ScalarBase() + { bin.init(params); - setInit(); } public: @@ -659,17 +847,23 @@ class ScalarBase : public ScalarStat * Return the number of elements, always 1 for a scalar. * @return 1. */ - virtual size_t size() const { return 1; } + size_t size() const { return 1; } /** * Return true if stat is binned. *@return True is stat is binned. */ - virtual bool binned() const { return bin_t::binned; } + bool binned() const { return bin_t::binned; } /** * Reset stat value to default */ void reset() { bin.reset(); } + + result_t val() { return data()->val(params); } + + result_t total() { return val(); } + + bool zero() { return val() == 0.0; } }; ////////////////////////////////////////////////////////////////////// @@ -685,7 +879,7 @@ class ScalarProxy; * Storage class. @sa ScalarBase */ template <typename T, template <typename T> class Storage, class Bin> -class VectorBase : public VectorStat +class VectorBase : public DataAccess { protected: /** Define the type of the storage class. */ @@ -695,10 +889,6 @@ class VectorBase : public VectorStat /** Define the bin type. */ typedef typename Bin::VectorBin<storage_t> bin_t; - private: - /** Local storage for the entry values, used for printing. */ - mutable rvec_t *vec; - protected: /** The bin of this stat. */ bin_t bin; @@ -737,19 +927,19 @@ class VectorBase : public VectorStat * Copy the values to a local vector and return a reference to it. * @return A reference to a vector of the stat values. */ - const rvec_t &val() const { - if (vec) - vec->resize(size()); - else - vec = new rvec_t(size()); - + void val(rvec_t &vec) const + { + vec.resize(size()); for (int i = 0; i < size(); ++i) - (*vec)[i] = data(i)->val(params); - - return *vec; + vec[i] = data(i)->val(params); } /** + * @return True is stat is binned. + */ + bool binned() const { return bin_t::binned; } + + /** * Return a total of all entries in this vector. * @return The total of all vector entries. */ @@ -760,28 +950,25 @@ class VectorBase : public VectorStat return total; } - public: - /** - * Create this vector and register it with the database. - */ - VectorBase() : VectorStat(true), vec(NULL) {} - /** - * Destructor. - */ - ~VectorBase() { if (vec) delete vec; } - /** - * Set this vector to have the given size. - * @param size The new size. - * @return A reference to this stat. + * @return the number of elements in this vector. */ - VectorBase &init(size_t size) { - bin.init(size, params); - setInit(); + size_t size() const { return bin.size(); } - return *this; + bool zero() const + { + for (int i = 0; i < size(); ++i) + if (data(i)->zero()) + return true; + return false; } + bool check() const { return true; } + void reset() { bin.reset(); } + + public: + VectorBase() {} + /** Friend this class with the associated scalar proxy. */ friend class ScalarProxy<T, Storage, Bin>; @@ -792,20 +979,7 @@ class VectorBase : public VectorStat */ ScalarProxy<T, Storage, Bin> operator[](int index); - /** - * Return the number of elements in this vector. - * @return The size of the vector. - */ - virtual size_t size() const { return bin.size(); } - /** - * Return true if stat is binned. - *@return True is stat is binned. - */ - virtual bool binned() const { return bin_t::binned; } - /** - * Reset stat value to default - */ - virtual void reset() { bin.reset(); } + void update(StatData *data) {} }; /** @@ -813,7 +987,7 @@ class VectorBase : public VectorStat * Behaves like a ScalarBase. */ template <typename T, template <typename T> class Storage, class Bin> -class ScalarProxy : public ScalarStat +class ScalarProxy { protected: /** Define the type of the storage class. */ @@ -868,13 +1042,13 @@ class ScalarProxy : public ScalarStat * @param i The index to access. */ ScalarProxy(bin_t &b, params_t &p, int i) - : ScalarStat(false), bin(&b), params(&p), index(i) {} + : bin(&b), params(&p), index(i) {} /** * Create a copy of the provided ScalarProxy. * @param sp The proxy to copy. */ ScalarProxy(const ScalarProxy &sp) - : ScalarStat(false), bin(sp.bin), params(sp.params), index(sp.index) {} + : bin(sp.bin), params(sp.params), index(sp.index) {} /** * Set this proxy equal to the provided one. * @param sp The proxy to copy. @@ -933,16 +1107,18 @@ class ScalarProxy : public ScalarStat * Return the number of elements, always 1 for a scalar. * @return 1. */ - virtual size_t size() const { return 1; } + size_t size() const { return 1; } + /** * Return true if stat is binned. *@return false since Proxies aren't printed/binned */ - virtual bool binned() const { return false; } + bool binned() const { return false; } + /** * This stat has no state. Nothing to reset */ - virtual void reset() { } + void reset() { } }; template <typename T, template <typename T> class Storage, class Bin> @@ -957,7 +1133,7 @@ template <typename T, template <typename T> class Storage, class Bin> class VectorProxy; template <typename T, template <typename T> class Storage, class Bin> -class Vector2dBase : public Stat +class Vector2dBase : public DataAccess { protected: typedef Storage<T> storage_t; @@ -969,7 +1145,6 @@ class Vector2dBase : public Stat size_t y; bin_t bin; params_t params; - std::vector<std::string> *y_subnames; protected: storage_t *data(int index) { return bin.data(index, params); } @@ -986,104 +1161,36 @@ class Vector2dBase : public Stat const Vector2dBase &operator=(const Vector2dBase &); public: - Vector2dBase() : Stat(true) {} - ~Vector2dBase() { } + Vector2dBase() {} - Vector2dBase &init(size_t _x, size_t _y) { - x = _x; - y = _y; - bin.init(x * y, params); - setInit(); - y_subnames = new std::vector<std::string>(y); - - return *this; - } - - /** - * @warning This makes the assumption that if you're gonna subnames a 2d - * vector, you're subnaming across all y - */ - Vector2dBase &ysubnames(const char **names) + void update(Vector2dDataBase *data) { - for (int i=0; i < y; ++i) { - (*y_subnames)[i] = names[i]; - } - return *this; - } - Vector2dBase &ysubname(int index, const std::string subname) - { - (*y_subnames)[i] = subname.c_str(); - return *this; + data->x = x; + data->y = y; + int size = this->size(); + data->vec.resize(size); + for (int i = 0; i < size; ++i) + data->vec[i] = this->data(i)->val(params); } + std::string ysubname(int i) const { return (*y_subnames)[i]; } friend class VectorProxy<T, Storage, Bin>; VectorProxy<T, Storage, Bin> operator[](int index); - virtual size_t size() const { return bin.size(); } - virtual bool zero() const { return data(0)->value(params) == 0.0; } - /** - * Return true if stat is binned. - *@return True is stat is binned. - */ - virtual bool binned() const { return bin_t::binned; } - - virtual void - display(std::ostream &out) const - { - bool have_subname = false; - for (int i = 0; i < x; ++i) { - if (!mysubname(i).empty()) - have_subname = true; - } - - rvec_t tot_vec(y); - result_t super_total = 0.0; - for (int i = 0; i < x; ++i) { - std::string subname; - if (have_subname) { - subname = mysubname(i); - if (subname.empty()) - continue; - } else - subname = to_string(i); - - int iy = i * y; - rvec_t vec(y); - - result_t total = 0.0; - for (int j = 0; j < y; ++j) { - vec[j] = data(iy + j)->val(params); - tot_vec[j] += vec[j]; - total += vec[j]; - super_total += vec[j]; - } - - std::string desc; - if (mysubdesc(i).empty()) { - desc = mydesc(); - } else { - desc = mysubdesc(i); - } + size_t size() const { return bin.size(); } + bool zero() const { return data(0)->value(params) == 0.0; } - VectorDisplay(out, myname() + "_" + subname, y_subnames, desc, 0, - myprecision(), myflags(), vec, total); - - } - if ((myflags() & ::Statistics::total) && (x > 1)) { - VectorDisplay(out, myname(), y_subnames, mydesc(), 0, - myprecision(), myflags(), tot_vec, super_total); - - } - } /** * Reset stat value to default */ - virtual void reset() { bin.reset(); } + void reset() { bin.reset(); } + + bool check() { return true; } }; template <typename T, template <typename T> class Storage, class Bin> -class VectorProxy : public VectorStat +class VectorProxy { protected: typedef Storage<T> storage_t; @@ -1132,18 +1239,19 @@ class VectorProxy : public VectorStat public: VectorProxy(bin_t &b, params_t &p, int o, int l) - : VectorStat(false), bin(&b), params(&p), offset(o), len(l), vec(NULL) + : bin(&b), params(&p), offset(o), len(l), vec(NULL) { } VectorProxy(const VectorProxy &sp) - : VectorStat(false), bin(sp.bin), params(sp.params), offset(sp.offset), - len(sp.len), vec(NULL) + : bin(sp.bin), params(sp.params), offset(sp.offset), len(sp.len), + vec(NULL) { } ~VectorProxy() { if (vec) delete vec; } - const VectorProxy &operator=(const VectorProxy &sp) { + const VectorProxy &operator=(const VectorProxy &sp) + { bin = sp.bin; params = sp.params; offset = sp.offset; @@ -1154,22 +1262,24 @@ class VectorProxy : public VectorStat return *this; } - virtual size_t size() const { return len; } - - ScalarProxy<T, Storage, Bin> operator[](int index) { + ScalarProxy<T, Storage, Bin> operator[](int index) + { assert (index >= 0 && index < size()); return ScalarProxy<T, Storage, Bin>(*bin, *params, offset + index); } + + size_t size() const { return len; } + /** * Return true if stat is binned. *@return false since Proxies aren't printed/binned */ - virtual bool binned() const { return false; } + bool binned() const { return false; } /** * This stat has no state. Nothing to reset. */ - virtual void reset() { } + void reset() { } }; template <typename T, template <typename T> class Storage, class Bin> @@ -1187,12 +1297,6 @@ Vector2dBase<T, Storage, Bin>::operator[](int index) // ////////////////////////////////////////////////////////////////////// -void DistDisplay(std::ostream &stream, const std::string &name, - const std::string &desc, int precision, FormatFlags flags, - result_t min_val, result_t max_val, - result_t underflow, result_t overflow, - const rvec_t &vec, int min, int max, int bucket_size, - int size); /** * Templatized storage and interface for a distrbution stat. */ @@ -1212,6 +1316,7 @@ struct DistStor /** The number of buckets. Equal to (max-min)/bucket_size. */ int size; }; + enum { fancy = false }; private: /** The smallest value sampled. */ @@ -1222,6 +1327,12 @@ struct DistStor T underflow; /** The number of values sampled more than max. */ T overflow; + /** The current sum. */ + T sum; + /** The sum of squares. */ + T squares; + /** The number of samples. */ + int samples; /** Counter for each bucket. */ std::vector<T> vec; @@ -1232,7 +1343,7 @@ struct DistStor */ DistStor(const Params ¶ms) : min_val(INT_MAX), max_val(INT_MIN), underflow(0), overflow(0), - vec(params.size) + sum(T()), squares(T()), samples(0), vec(params.size) { reset(); } @@ -1243,7 +1354,8 @@ 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(T val, int number, const Params ¶ms) + { if (val < params.min) underflow += number; else if (val > params.max) @@ -1259,6 +1371,11 @@ struct DistStor if (val > max_val) max_val = val; + + T sample = val * number; + sum += sample; + squares += sample * sample; + samples += number; } /** @@ -1273,48 +1390,35 @@ struct DistStor * @param params The paramters of the distribution. * @return True if any values have been sampled. */ - bool zero(const Params ¶ms) const { - if (underflow != 0 || overflow != 0) - return false; - - int s = size(params); - for (int i = 0; i < s; i++) - if (vec[i] != 0) - return false; - - return true; + bool zero(const Params ¶ms) const + { + return samples == 0; } - /** - * Print this distribution and the given print data to the given ostream. - * @param stream The output stream. - * @param name The name of this stat (from StatData). - * @param desc The description of this stat (from StatData). - * @param precision The print precision (from StatData). - * @param flags The format flags (from StatData). - * @param params The paramters of this distribution. - */ - void display(std::ostream &stream, const std::string &name, - const std::string &desc, int precision, FormatFlags flags, - const Params ¶ms) const { + void update(DistDataData *data, DisplayMode mode, const Params ¶ms) + { + data->min = params.min; + data->max = params.max; + data->bucket_size = params.bucket_size; + data->size = params.size; -#ifdef STAT_DISPLAY_COMPAT - result_t min = params.min; -#else - result_t min = (min_val == INT_MAX) ? params.min : min_val; -#endif - result_t max = (max_val == INT_MIN) ? 0 : max_val; + if (mode == mode_m5) + data->min_val = (min_val == INT_MAX) ? params.min : min_val; + else + data->min_val = params.min; - rvec_t rvec(params.size); + data->max_val = (max_val == INT_MIN) ? 0 : max_val; + data->underflow = underflow; + data->overflow = overflow; + data->vec.resize(params.size); for (int i = 0; i < params.size; ++i) - rvec[i] = vec[i]; + data->vec[i] = vec[i]; - DistDisplay(stream, name, desc, precision, flags, - (result_t)min, (result_t)max, - (result_t)underflow, (result_t)overflow, - rvec, params.min, params.max, params.bucket_size, - params.size); + data->sum = sum; + data->squares = squares; + data->samples = samples; } + /** * Reset stat value to default */ @@ -1328,14 +1432,13 @@ struct DistStor int size = vec.size(); for (int i = 0; i < size; ++i) vec[i] = T(); - } + sum = T(); + squares = T(); + samples = T(); + } }; -void FancyDisplay(std::ostream &stream, const std::string &name, - const std::string &desc, int precision, FormatFlags flags, - result_t mean, result_t variance, result_t total); - /** * Templatized storage and interface for a distribution that calculates mean * and variance. @@ -1348,20 +1451,21 @@ struct FancyStor * No paramters for this storage. */ struct Params {}; + enum { fancy = true }; private: /** The current sum. */ T sum; /** The sum of squares. */ T squares; - /** The total number of samples. */ - int total; + /** The number of samples. */ + int samples; public: /** * Create and initialize this storage. */ - FancyStor(const Params &) : sum(T()), squares(T()), total(0) {} + FancyStor(const Params &) : sum(T()), squares(T()), samples(0) {} /** * Add a value the given number of times to this running average. @@ -1371,40 +1475,19 @@ 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(T val, int number, const Params &p) + { T value = val * number; sum += value; squares += value * value; - total += number; + samples += number; } - /** - * Print this distribution and the given print data to the given ostream. - * @param stream The output stream. - * @param name The name of this stat (from StatData). - * @param desc The description of this stat (from StatData). - * @param precision The print precision (from StatData). - * @param flags The format flags (from StatData). - * @param params The paramters of this distribution. - */ - void display(std::ostream &stream, const std::string &name, - const std::string &desc, int precision, FormatFlags flags, - const Params ¶ms) const { - - result_t mean = NAN; - result_t variance = NAN; - - result_t ftot = total; - if (total != 0) { - result_t fsum = sum; - result_t fsq = squares; - - mean = fsum / ftot; - variance = (ftot * fsq - (fsum * fsum)) / (ftot * (ftot - 1.0)); - } - - FancyDisplay(stream, name, desc, precision, flags, mean, - variance, ftot); + void update(DistDataData *data, DisplayMode mode, const Params ¶ms) + { + data->sum = sum; + data->squares = squares; + data->samples = samples; } /** @@ -1412,19 +1495,21 @@ struct FancyStor * @return 1. */ size_t size(const Params &) const { return 1; } + /** * Return true if no samples have been added. * @return True if no samples have been added. */ - bool zero(const Params &) const { return total == 0; } + bool zero(const Params &) const { return samples == 0; } + /** * Reset stat value to default */ - virtual void reset() + void reset() { sum = T(); squares = T(); - total = 0; + samples = 0; } }; @@ -1438,6 +1523,7 @@ struct AvgFancy public: /** No parameters for this storage. */ struct Params {}; + enum { fancy = true }; private: /** Current total. */ @@ -1458,28 +1544,18 @@ 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(T val, int number, const Params& p) + { T value = val * number; sum += value; squares += value * value; } - /** - * Print this distribution and the given print data to the given ostream. - * @param stream The output stream. - * @param name The name of this stat (from StatData). - * @param desc The description of this stat (from StatData). - * @param precision The print precision (from StatData). - * @param flags The format flags (from StatData). - * @param params The paramters of this distribution. - */ - void display(std::ostream &stream, const std::string &name, - const std::string &desc, int precision, FormatFlags flags, - const Params ¶ms) const { - result_t mean = sum / curTick; - result_t variance = (squares - sum * sum) / curTick; - - FancyDisplay(stream, name, desc, precision, flags, mean, variance); + void update(DistDataData *data, DisplayMode mode, const Params ¶ms) + { + data->sum = sum; + data->squares = squares; + data->samples = curTick; } /** @@ -1495,7 +1571,7 @@ struct AvgFancy /** * Reset stat value to default */ - virtual void reset() + void reset() { sum = T(); squares = T(); @@ -1507,7 +1583,7 @@ struct AvgFancy * determined by the Storage template. @sa ScalarBase */ template <typename T, template <typename T> class Storage, class Bin> -class DistBase : public Stat +class DistBase : public DataAccess { protected: /** Define the type of the storage class. */ @@ -1548,14 +1624,7 @@ class DistBase : public Stat const DistBase &operator=(const DistBase &); public: - /** - * Create this distrubition and register it with the database. - */ - DistBase() : Stat(true) { } - /** - * Destructor. - */ - ~DistBase() { } + DistBase() { } /** * Add a value to the distribtion n times. Calls sample on the storage @@ -1570,39 +1639,38 @@ class DistBase : public Stat * Return the number of entries in this stat. * @return The number of entries. */ - virtual size_t size() const { return data()->size(params); } + size_t size() const { return data()->size(params); } /** * Return true if no samples have been added. * @return True if there haven't been any samples. */ - virtual bool zero() const { return data()->zero(params); } - /** - * Print this distribution to the given ostream. - * @param stream The output stream. - */ - virtual void display(std::ostream &stream) const { - data()->display(stream, myname(), mydesc(), myprecision(), myflags(), - params); + bool zero() const { return data()->zero(params); } + + void update(DistDataBase *base) + { + base->data.fancy = storage_t::fancy; + data()->update(&(base->data), base->mode, params); } /** - * Return true if stat is binned. - *@return True is stat is binned. + * @return True is stat is binned. */ - virtual bool binned() const { return bin_t::binned; } + bool binned() const { return bin_t::binned; } /** * Reset stat value to default */ - virtual void reset() + void reset() { bin.reset(); } + + bool check() { return true; } }; template <typename T, template <typename T> class Storage, class Bin> class DistProxy; template <typename T, template <typename T> class Storage, class Bin> -class VectorDistBase : public Stat +class VectorDistBase : public DataAccess { protected: typedef Storage<T> storage_t; @@ -1628,32 +1696,38 @@ class VectorDistBase : public Stat const VectorDistBase &operator=(const VectorDistBase &); public: - VectorDistBase() : Stat(true) { } - ~VectorDistBase() { } + VectorDistBase() {} friend class DistProxy<T, Storage, Bin>; DistProxy<T, Storage, Bin> operator[](int index); const DistProxy<T, Storage, Bin> operator[](int index) const; - virtual size_t size() const { return bin.size(); } - virtual bool zero() const { return false; } - virtual void display(std::ostream &stream) const; + size_t size() const { return bin.size(); } + bool zero() const { return false; } /** * Return true if stat is binned. *@return True is stat is binned. */ - virtual bool binned() const { return bin_t::binned; } + bool binned() const { return bin_t::binned; } /** * Reset stat value to default */ - virtual void reset() + void reset() { bin.reset(); } + + bool check() { return true; } + void update(VectorDistDataBase *base) { - bin.reset(); + int size = this->size(); + base->data.resize(size); + for (int i = 0; i < size; ++i) { + base->data[i].fancy = storage_t::fancy; + data(i)->update(&(base->data[i]), base->mode, params); + } } }; template <typename T, template <typename T> class Storage, class Bin> -class DistProxy : public Stat +class DistProxy { protected: typedef Storage<T> storage_t; @@ -1674,9 +1748,9 @@ class DistProxy : public Stat public: DistProxy(const VectorDistBase<T, Storage, Bin> &s, int i) - : Stat(false), cstat(&s), index(i) {} + : cstat(&s), index(i) {} DistProxy(const DistProxy &sp) - : Stat(false), cstat(sp.cstat), index(sp.index) {} + : cstat(sp.cstat), index(sp.index) {} const DistProxy &operator=(const DistProxy &sp) { cstat = sp.cstat; index = sp.index; return *this; } @@ -1685,36 +1759,17 @@ class DistProxy : public Stat template <typename U> void sample(const U& v, int n = 1) { data()->sample(v, n, cstat->params); } - virtual size_t size() const { return 1; } - virtual bool zero() const { - return data()->zero(cstat->params); - } - virtual void display(std::ostream &stream) const { - std::stringstream name, desc; - - if (!(cstat->mysubname(index).empty())) { - name << cstat->myname() << cstat->mysubname(index); - } else { - name << cstat->myname() << "_" << index; - } - if (!(cstat->mysubdesc(index).empty())) { - desc << cstat->mysubdesc(index); - } else { - desc << cstat->mydesc(); - } - - data()->display(stream, name.str(), desc.str(), - cstat->myprecision(), cstat->myflags(), cstat->params); - } + size_t size() const { return 1; } + bool zero() const { return data()->zero(cstat->params); } /** * Return true if stat is binned. *@return false since Proxies are not binned/printed. */ - virtual bool binned() const { return false; } + bool binned() const { return false; } /** * Proxy has no state. Nothing to reset. */ - virtual void reset() { } + void reset() { } }; template <typename T, template <typename T> class Storage, class Bin> @@ -1733,20 +1788,8 @@ VectorDistBase<T, Storage, Bin>::operator[](int index) const return DistProxy<T, Storage, Bin>(*this, index); } -/** - * @todo Need a way to print Distribution totals across the Vector - */ -template <typename T, template <typename T> class Storage, class Bin> -void -VectorDistBase<T, Storage, Bin>::display(std::ostream &stream) const -{ - for (int i = 0; i < size(); ++i) { - DistProxy<T, Storage, Bin> proxy(*this, i); - proxy.display(stream); - } -} - #if 0 +template <typename T, template <typename T> class Storage, class Bin> result_t VectorDistBase<T, Storage, Bin>::total(int index) const { @@ -1798,20 +1841,24 @@ typedef RefCountingPtr<Node> NodePtr; class ScalarStatNode : public Node { private: - const ScalarStat &stat; + const ScalarDataBase *data; mutable rvec_t result; public: - ScalarStatNode(const ScalarStat &s) : stat(s), result(1) {} - const rvec_t &val() const { result[0] = stat.val(); return result; } - virtual result_t total() const { return stat.val(); }; + ScalarStatNode(const ScalarDataBase *d) : data(d), result(1) {} + virtual const rvec_t &val() const + { + result[0] = data->val(); + return result; + } + virtual result_t total() const { return data->val(); }; virtual size_t size() const { return 1; } /** * Return true if stat is binned. *@return True is stat is binned. */ - virtual bool binned() const { return stat.binned(); } + virtual bool binned() const { return data->binned(); } }; template <typename T, template <typename T> class Storage, class Bin> @@ -1824,7 +1871,11 @@ class ScalarProxyNode : public Node public: ScalarProxyNode(const ScalarProxy<T, Storage, Bin> &p) : proxy(p), result(1) { } - const rvec_t &val() const { result[0] = proxy.val(); return result; } + virtual const rvec_t &val() const + { + result[0] = proxy.val(); + return result; + } virtual result_t total() const { return proxy.val(); }; virtual size_t size() const { return 1; } @@ -1838,19 +1889,19 @@ class ScalarProxyNode : public Node class VectorStatNode : public Node { private: - const VectorStat &stat; + const VectorDataBase *data; public: - VectorStatNode(const VectorStat &s) : stat(s) {} - const rvec_t &val() const { return stat.val(); } - virtual result_t total() const { return stat.total(); }; + VectorStatNode(const VectorDataBase *d) : data(d) { } + virtual const rvec_t &val() const { return data->val(); } + virtual result_t total() const { return data->total(); }; - virtual size_t size() const { return stat.size(); } + virtual size_t size() const { return data->size(); } /** * Return true if stat is binned. *@return True is stat is binned. */ - virtual bool binned() const { return stat.binned(); } + virtual bool binned() const { return data->binned(); } }; template <typename T> @@ -2066,114 +2117,6 @@ class SumNode : public Node virtual bool binned() const { return l->binned(); } }; -/** - * Helper class to construct formula node trees. - */ -class Temp -{ - private: - /** - * Pointer to a Node object. - */ - NodePtr node; - - public: - /** - * Copy the given pointer to this class. - * @param n A pointer to a Node object to copy. - */ - Temp(NodePtr n) : node(n) {} - /** - * Create a new ScalarStatNode. - * @param s The ScalarStat to place in a node. - */ - Temp(const ScalarStat &s) : node(new ScalarStatNode(s)) {} - /** - * 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)) {} - /** - * Create a new VectorStatNode. - * @param s The VectorStat to place in a node. - */ - Temp(const VectorStat &s) : node(new VectorStatNode(s)) {} - - /** - * Create a ConstNode - * @param value The value of the const node. - */ - Temp(signed char value) : node(new ConstNode<signed char>(value)) {} - /** - * Create a ConstNode - * @param value The value of the const node. - */ - Temp(unsigned char value) : node(new ConstNode<unsigned char>(value)) {} - /** - * Create a ConstNode - * @param value The value of the const node. - */ - Temp(signed short value) : node(new ConstNode<signed short>(value)) {} - /** - * Create a ConstNode - * @param value The value of the const node. - */ - Temp(unsigned short value) : node(new ConstNode<unsigned short>(value)) {} - /** - * Create a ConstNode - * @param value The value of the const node. - */ - Temp(signed int value) : node(new ConstNode<signed int>(value)) {} - /** - * Create a ConstNode - * @param value The value of the const node. - */ - Temp(unsigned int value) : node(new ConstNode<unsigned int>(value)) {} - /** - * Create a ConstNode - * @param value The value of the const node. - */ - Temp(signed long value) : node(new ConstNode<signed long>(value)) {} - /** - * Create a ConstNode - * @param value The value of the const node. - */ - Temp(unsigned long value) : node(new ConstNode<unsigned long>(value)) {} - /** - * Create a ConstNode - * @param value The value of the const node. - */ - Temp(signed long long value) - : node(new ConstNode<signed long long>(value)) {} - /** - * Create a ConstNode - * @param value The value of the const node. - */ - Temp(unsigned long long value) - : node(new ConstNode<unsigned long long>(value)) {} - /** - * Create a ConstNode - * @param value The value of the const node. - */ - Temp(float value) : node(new ConstNode<float>(value)) {} - /** - * Create a ConstNode - * @param value The value of the const node. - */ - Temp(double value) : node(new ConstNode<double>(value)) {} - - /** - * Return the node pointer. - * @return the node pointer. - */ - operator NodePtr() { return node;} -}; - -} // namespace Detail - - ////////////////////////////////////////////////////////////////////// // // Binning Interface @@ -2466,11 +2409,16 @@ typedef NoBin DefaultBin; * @sa Stat, ScalarBase, StatStor */ template <typename T = Counter, class Bin = DefaultBin> -class Scalar : public Detail::ScalarBase<T, Detail::StatStor, Bin> +class Scalar : public Wrap<Scalar<T, Bin>, ScalarBase<T, StatStor, Bin>, ScalarData> { public: /** The base implementation. */ - typedef Detail::ScalarBase<T, Detail::StatStor, Bin> Base; + typedef ScalarBase<T, StatStor, Bin> Base; + + Scalar() + { + setInit(); + } /** * Sets the stat equal to the given value. Calls the base implementation @@ -2486,11 +2434,16 @@ class Scalar : public Detail::ScalarBase<T, Detail::StatStor, Bin> * @sa Stat, ScalarBase, AvgStor */ template <typename T = Counter, class Bin = DefaultBin> -class Average : public Detail::ScalarBase<T, Detail::AvgStor, Bin> +class Average : public Wrap<Average<T, Bin>, ScalarBase<T, AvgStor, Bin>, ScalarData> { public: /** The base implementation. */ - typedef Detail::ScalarBase<T, Detail::AvgStor, Bin> Base; + typedef ScalarBase<T, AvgStor, Bin> Base; + + Average() + { + setInit(); + } /** * Sets the stat equal to the given value. Calls the base implementation @@ -2506,37 +2459,73 @@ class Average : public Detail::ScalarBase<T, Detail::AvgStor, Bin> * @sa Stat, VectorBase, StatStor */ template <typename T = Counter, class Bin = DefaultBin> -class Vector : public Detail::VectorBase<T, Detail::StatStor, Bin> -{ }; +class Vector : public WrapVec<Vector<T, Bin>, VectorBase<T, StatStor, Bin>, VectorData> +{ + public: + /** + * Set this vector to have the given size. + * @param size The new size. + * @return A reference to this stat. + */ + Vector &init(size_t size) { + bin.init(size, params); + setInit(); + + return *this; + } +}; /** * A vector of Average stats. * @sa Stat, VectorBase, AvgStor */ template <typename T = Counter, class Bin = DefaultBin> -class AverageVector : public Detail::VectorBase<T, Detail::AvgStor, Bin> -{ }; +class AverageVector : public WrapVec<AverageVector<T, Bin>, VectorBase<T, AvgStor, Bin>, VectorData> +{ + public: + /** + * Set this vector to have the given size. + * @param size The new size. + * @return A reference to this stat. + */ + AverageVector &init(size_t size) { + bin.init(size, params); + setInit(); + + return *this; + } +}; /** * A 2-Dimensional vecto of scalar stats. * @sa Stat, Vector2dBase, StatStor */ template <typename T = Counter, class Bin = DefaultBin> -class Vector2d : public Detail::Vector2dBase<T, Detail::StatStor, Bin> -{ }; +class Vector2d : public WrapVec2d<Vector2d<T, Bin>, Vector2dBase<T, StatStor, Bin>, Vector2dData> +{ + public: + Vector2d &init(size_t _x, size_t _y) { + x = _x; + y = _y; + bin.init(x * y, params); + setInit(); + + return *this; + } +}; /** * A simple distribution stat. * @sa Stat, DistBase, DistStor */ template <typename T = Counter, class Bin = DefaultBin> -class Distribution : public Detail::DistBase<T, Detail::DistStor, Bin> +class Distribution : public Wrap<Distribution<T, Bin>, DistBase<T, DistStor, Bin>, DistData> { private: /** Base implementation. */ - typedef Detail::DistBase<T, Detail::DistStor, Bin> Base; + typedef DistBase<T, DistStor, Bin> Base; /** The Parameter type. */ - typedef typename Detail::DistStor<T>::Params Params; + typedef typename DistStor<T>::Params Params; public: /** @@ -2563,13 +2552,13 @@ class Distribution : public Detail::DistBase<T, Detail::DistStor, Bin> * @sa Stat, DistBase, FancyStor */ template <typename T = Counter, class Bin = DefaultBin> -class StandardDeviation : public Detail::DistBase<T, Detail::FancyStor, Bin> +class StandardDeviation : public Wrap<StandardDeviation<T, Bin>, DistBase<T, FancyStor, Bin>, DistData> { private: /** The base implementation */ - typedef Detail::DistBase<T, Detail::DistStor, Bin> Base; + typedef DistBase<T, DistStor, Bin> Base; /** The parameter type. */ - typedef typename Detail::DistStor<T>::Params Params; + typedef typename DistStor<T>::Params Params; public: /** @@ -2586,19 +2575,20 @@ class StandardDeviation : public Detail::DistBase<T, Detail::FancyStor, Bin> * @sa Stat, DistBase, AvgFancy */ template <typename T = Counter, class Bin = DefaultBin> -class AverageDeviation : public Detail::DistBase<T, Detail::AvgFancy, Bin> +class AverageDeviation : public Wrap<AverageDeviation<T, Bin>, DistBase<T, AvgFancy, Bin>, DistData> { private: /** The base implementation */ - typedef Detail::DistBase<T, Detail::DistStor, Bin> Base; + typedef DistBase<T, DistStor, Bin> Base; /** The parameter type. */ - typedef typename Detail::DistStor<T>::Params Params; + typedef typename DistStor<T>::Params Params; public: /** * Construct and initialize this distribution. */ - AverageDeviation() { + AverageDeviation() + { bin.init(params); setInit(); } @@ -2609,14 +2599,13 @@ class AverageDeviation : public Detail::DistBase<T, Detail::AvgFancy, Bin> * @sa Stat, VectorDistBase, DistStor */ template <typename T = Counter, class Bin = DefaultBin> -class VectorDistribution - : public Detail::VectorDistBase<T, Detail::DistStor, Bin> +class VectorDistribution : public WrapVec<VectorDistribution<T, Bin>, VectorDistBase<T, DistStor, Bin>, VectorDistData> { private: /** The base implementation */ - typedef Detail::VectorDistBase<T, Detail::DistStor, Bin> Base; + typedef VectorDistBase<T, DistStor, Bin> Base; /** The parameter type. */ - typedef typename Detail::DistStor<T>::Params Params; + typedef typename DistStor<T>::Params Params; public: /** @@ -2644,14 +2633,13 @@ class VectorDistribution * @sa Stat, VectorDistBase, FancyStor */ template <typename T = Counter, class Bin = DefaultBin> -class VectorStandardDeviation - : public Detail::VectorDistBase<T, Detail::FancyStor, Bin> +class VectorStandardDeviation : public WrapVec<VectorStandardDeviation<T, Bin>, VectorDistBase<T, FancyStor, Bin>, VectorDistData> { private: /** The base implementation */ - typedef Detail::VectorDistBase<T, Detail::FancyStor, Bin> Base; + typedef VectorDistBase<T, FancyStor, Bin> Base; /** The parameter type. */ - typedef typename Detail::DistStor<T>::Params Params; + typedef typename DistStor<T>::Params Params; public: /** @@ -2672,14 +2660,13 @@ class VectorStandardDeviation * @sa Stat, VectorDistBase, AvgFancy */ template <typename T = Counter, class Bin = DefaultBin> -class VectorAverageDeviation - : public Detail::VectorDistBase<T, Detail::AvgFancy, Bin> +class VectorAverageDeviation : public WrapVec<VectorAverageDeviation<T, Bin>, VectorDistBase<T, AvgFancy, Bin>, VectorDistData> { private: /** The base implementation */ - typedef Detail::VectorDistBase<T, Detail::AvgFancy, Bin> Base; + typedef VectorDistBase<T, AvgFancy, Bin> Base; /** The parameter type. */ - typedef typename Detail::DistStor<T>::Params Params; + typedef typename DistStor<T>::Params Params; public: /** @@ -2698,99 +2685,260 @@ class VectorAverageDeviation /** * A formula for statistics that is calculated when printed. A formula is * stored as a tree of Nodes that represent the equation to calculate. - * @sa Stat, ScalarStat, VectorStat, Node, Detail::Temp + * @sa Stat, ScalarStat, VectorStat, Node, Temp */ -class Formula : public Detail::VectorStat +class FormulaBase : public DataAccess { - private: + protected: /** The root of the tree which represents the Formula */ - Detail::NodePtr root; - friend class Statistics::Detail::Temp; + NodePtr root; + friend class Temp; + + public: + /** + * Return the result of the Fomula in a vector. If there were no Vector + * components to the Formula, then the vector is size 1. If there were, + * like x/y with x being a vector of size 3, then the result returned will + * be x[0]/y, x[1]/y, x[2]/y, respectively. + * @return The result vector. + */ + void val(rvec_t &vec) const; + + /** + * Return the total Formula result. If there is a Vector + * component to this Formula, then this is the result of the + * Formula if the formula is applied after summing all the + * 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. + * @return The total of the result vector. + */ + result_t total() const; + + /** + * Return the number of elements in the tree. + */ + size_t size() const; + + /** + * Return true if Formula is binned. i.e. any of its children + * nodes are binned + * @return True if Formula is binned. + */ + bool binned() const; + + /** + * Formulas don't need to be reset + */ + void reset(); + + /** + * + */ + bool zero() const; + + /** + * + */ + void update(StatData *); +}; +class Temp; +class Formula : public WrapVec<Formula, FormulaBase, VectorData> +{ public: /** * Create and initialize thie formula, and register it with the database. */ - Formula() : VectorStat(true) { setInit(); } + Formula(); + /** * Create a formula with the given root node, register it with the * database. * @param r The root of the expression tree. */ - Formula(Detail::Temp r) : VectorStat(true) { - root = r; - assert(size()); - } + Formula(Temp r); /** * Set an unitialized Formula to the given root. * @param r The root of the expression tree. * @return a reference to this formula. */ - const Formula &operator=(Detail::Temp r) { - assert(!root && "Can't change formulas"); - root = r; - assert(size()); - return *this; - } + const Formula &operator=(Temp r); /** * Add the given tree to the existing one. * @param r The root of the expression tree. * @return a reference to this formula. */ - const Formula &operator+=(Detail::Temp r) { - using namespace Detail; - if (root) - root = NodePtr(new BinaryNode<std::plus<result_t> >(root, r)); - else - root = r; - assert(size()); - return *this; - } + const Formula &operator+=(Temp r); +}; + +class FormulaNode : public Node +{ + private: + const Formula &formula; + mutable rvec_t 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 bool binned() const { return formula.binned(); } +}; +/** + * Helper class to construct formula node trees. + */ +class Temp +{ + protected: /** - * Return the result of the Fomula in a vector. If there were no Vector - * components to the Formula, then the vector is size 1. If there were, - * like x/y with x being a vector of size 3, then the result returned will - * be x[0]/y, x[1]/y, x[2]/y, respectively. - * @return The result vector. + * Pointer to a Node object. */ - const rvec_t &val() const { return root->val(); } + NodePtr node; + + public: /** - * Return the total Formula result. If there is a Vector - * component to this Formula, then this is the result of the - * Formula if the formula is applied after summing all the - * 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. - * @return The total of the result vector. + * Copy the given pointer to this class. + * @param n A pointer to a Node object to copy. */ - result_t total() const { return root->total(); } + Temp(NodePtr n) : node(n) { } /** - * Return the number of elements in the tree. + * Return the node pointer. + * @return the node pointer. */ - size_t size() const { - if (!root) - return 0; - else - return root->size(); - } + operator NodePtr() { return node;} + + public: /** - * Return true if Formula is binned. i.e. any of its children - * nodes are binned - * @return True if Formula is binned. + * Create a new ScalarStatNode. + * @param s The ScalarStat to place in a node. */ - virtual bool binned() const { return root->binned(); } + template <typename T, class Bin> + Temp(const Scalar<T, Bin> &s) + : node(new ScalarStatNode(s.statData())) { } /** - * Formulas don't need to be reset + * Create a new ScalarStatNode. + * @param s The ScalarStat to place in a node. + */ + template <typename T, class Bin> + Temp(const Average<T, 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) + : node(new VectorStatNode(s.statData())) { } + + /** + * + */ + Temp(const Formula &f) + : node(new FormulaNode(f)) { } + + /** + * 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)) { } + + /** + * Create a ConstNode + * @param value The value of the const node. + */ + Temp(signed char value) + : node(new ConstNode<signed char>(value)) {} + + /** + * Create a ConstNode + * @param value The value of the const node. + */ + Temp(unsigned char value) + : node(new ConstNode<unsigned char>(value)) {} + + /** + * Create a ConstNode + * @param value The value of the const node. */ - virtual void reset() {} + Temp(signed short value) + : node(new ConstNode<signed short>(value)) {} + + /** + * Create a ConstNode + * @param value The value of the const node. + */ + Temp(unsigned short value) + : node(new ConstNode<unsigned short>(value)) {} + + /** + * Create a ConstNode + * @param value The value of the const node. + */ + Temp(signed int value) + : node(new ConstNode<signed int>(value)) {} + + /** + * Create a ConstNode + * @param value The value of the const node. + */ + Temp(unsigned int value) + : node(new ConstNode<unsigned int>(value)) {} + + /** + * Create a ConstNode + * @param value The value of the const node. + */ + Temp(signed long value) + : node(new ConstNode<signed long>(value)) {} + + /** + * Create a ConstNode + * @param value The value of the const node. + */ + Temp(unsigned long value) + : node(new ConstNode<unsigned long>(value)) {} + + /** + * Create a ConstNode + * @param value The value of the const node. + */ + Temp(signed long long value) + : node(new ConstNode<signed long long>(value)) {} + + /** + * Create a ConstNode + * @param value The value of the const node. + */ + Temp(unsigned long long value) + : node(new ConstNode<unsigned long long>(value)) {} + + /** + * Create a ConstNode + * @param value The value of the const node. + */ + Temp(float value) + : node(new ConstNode<float>(value)) {} + + /** + * Create a ConstNode + * @param value The value of the const node. + */ + Temp(double value) + : node(new ConstNode<double>(value)) {} }; + /** * @} */ @@ -2800,79 +2948,68 @@ void dump(std::ostream &stream); void reset(); void RegResetCallback(Callback *cb); -inline Detail::Temp -operator+(Detail::Temp l, Detail::Temp r) +inline Temp +operator+(Temp l, Temp r) { - using namespace Detail; return NodePtr(new BinaryNode<std::plus<result_t> >(l, r)); } -inline Detail::Temp -operator-(Detail::Temp l, Detail::Temp r) +inline Temp +operator-(Temp l, Temp r) { - using namespace Detail; return NodePtr(new BinaryNode<std::minus<result_t> >(l, r)); } -inline Detail::Temp -operator*(Detail::Temp l, Detail::Temp r) +inline Temp +operator*(Temp l, Temp r) { - using namespace Detail; return NodePtr(new BinaryNode<std::multiplies<result_t> >(l, r)); } -inline Detail::Temp -operator/(Detail::Temp l, Detail::Temp r) +inline Temp +operator/(Temp l, Temp r) { - using namespace Detail; return NodePtr(new BinaryNode<std::divides<result_t> >(l, r)); } -inline Detail::Temp -operator%(Detail::Temp l, Detail::Temp r) +inline Temp +operator%(Temp l, Temp r) { - using namespace Detail; return NodePtr(new BinaryNode<std::modulus<result_t> >(l, r)); } -inline Detail::Temp -operator-(Detail::Temp l) +inline Temp +operator-(Temp l) { - using namespace Detail; return NodePtr(new UnaryNode<std::negate<result_t> >(l)); } template <typename T> -inline Detail::Temp +inline Temp constant(T val) { - using namespace Detail; return NodePtr(new ConstNode<T>(val)); } template <typename T> -inline Detail::Temp +inline Temp functor(T &val) { - using namespace Detail; return NodePtr(new FunctorNode<T>(val)); } template <typename T> -inline Detail::Temp +inline Temp scalar(T &val) { - using namespace Detail; return NodePtr(new ScalarNode<T>(val)); } -inline Detail::Temp -sum(Detail::Temp val) +inline Temp +sum(Temp val) { - using namespace Detail; return NodePtr(new SumNode<std::plus<result_t> >(val)); } - extern bool PrintDescriptions; } // namespace statistics diff --git a/test/Makefile b/test/Makefile index 1502bca3d..29d252df4 100644 --- a/test/Makefile +++ b/test/Makefile @@ -52,8 +52,7 @@ offtest: offtest.o rangetest: rangetest.o str.o $(CXX) $(LFLAGS) -o $@ $^ -stattest: cprintf.o hostinfo.o misc.o sim_stats.o sim_time.o \ - statistics.o stattest.o str.o +stattest: cprintf.o hostinfo.o misc.o sim_time.o statistics.o stattest.o str.o $(CXX) $(LFLAGS) -o $@ $^ strnumtest: strnumtest.o str.o diff --git a/test/stattest.cc b/test/stattest.cc index 38a15900d..dea5295cc 100644 --- a/test/stattest.cc +++ b/test/stattest.cc @@ -35,7 +35,6 @@ #include "base/misc.hh" #include "base/statistics.hh" #include "sim/host.hh" -#include "sim/sim_stats.hh" using namespace std; using namespace Statistics; @@ -67,8 +66,8 @@ Formula f4; Formula f5; Formula f6; -MainBin bin1; -MainBin bin2; +MainBin bin1("bin1"); +MainBin bin2("bin2"); double testfunc() @@ -256,7 +255,7 @@ main(int argc, char *argv[]) check(); - MainBin::activate(bin1); + bin1.activate(); f1 = s1 + s2; f2 = (-s1) / (-s2) * -s3 + ULL(100) + s4; @@ -452,7 +451,7 @@ main(int argc, char *argv[]) s6.sample(8); s6.sample(9); - MainBin::activate(bin2); + bin2.activate(); s6.sample(10); s6.sample(10); s6.sample(10); @@ -493,12 +492,12 @@ main(int argc, char *argv[]) s12.sample(100); - MainBin::activate(bin1); + bin1.activate(); cout << "dump 1" << endl; dump(cout); cout << endl << endl; - MainBin::activate(bin2); + bin2.activate(); cout << "dump 2" << endl; dump(cout); cout << endl << endl; |