From 0ff2457bfaa223c70d431d100c5b5a92540ff6e2 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Mon, 8 Dec 2003 13:15:18 -0500 Subject: [PATCH 1/5] move setStatus into the .cc file --HG-- extra : convert_revision : 9ccf885274d72ea3151a0db76b580dd51763edab --- cpu/simple_cpu/simple_cpu.cc | 57 ++++++++++++++++++++++++++++++++++++ cpu/simple_cpu/simple_cpu.hh | 56 +---------------------------------- 2 files changed, 58 insertions(+), 55 deletions(-) diff --git a/cpu/simple_cpu/simple_cpu.cc b/cpu/simple_cpu/simple_cpu.cc index 476f28ea0..4b9a7c6bd 100644 --- a/cpu/simple_cpu/simple_cpu.cc +++ b/cpu/simple_cpu/simple_cpu.cc @@ -212,6 +212,63 @@ SimpleCPU::execCtxStatusChg(int thread_num) { setStatus(Idle); } +void +SimpleCPU::setStatus(Status new_status) +{ + Status old_status = status(); + + // We should never even get here if the CPU has been switched out. + assert(old_status != SwitchedOut); + + _status = new_status; + + switch (status()) { + case IcacheMissStall: + assert(old_status == Running); + lastIcacheStall = curTick; + if (tickEvent.scheduled()) + tickEvent.squash(); + break; + + case IcacheMissComplete: + assert(old_status == IcacheMissStall); + if (tickEvent.squashed()) + tickEvent.reschedule(curTick + 1); + else if (!tickEvent.scheduled()) + tickEvent.schedule(curTick + 1); + break; + + case DcacheMissStall: + assert(old_status == Running); + lastDcacheStall = curTick; + if (tickEvent.scheduled()) + tickEvent.squash(); + break; + + case Idle: + assert(old_status == Running); + idleFraction++; + if (tickEvent.scheduled()) + tickEvent.squash(); + break; + + case Running: + assert(old_status == Idle || + old_status == DcacheMissStall || + old_status == IcacheMissComplete); + if (old_status == Idle && curTick != 0) + idleFraction--; + + if (tickEvent.squashed()) + tickEvent.reschedule(curTick + 1); + else if (!tickEvent.scheduled()) + tickEvent.schedule(curTick + 1); + break; + + default: + panic("can't get here"); + } +} void SimpleCPU::regStats() diff --git a/cpu/simple_cpu/simple_cpu.hh b/cpu/simple_cpu/simple_cpu.hh index b0189349f..e497559ce 100644 --- a/cpu/simple_cpu/simple_cpu.hh +++ b/cpu/simple_cpu/simple_cpu.hh @@ -174,61 +174,7 @@ class SimpleCPU : public BaseCPU virtual void execCtxStatusChg(int thread_num); - void setStatus(Status new_status) { - Status old_status = status(); - - // We should never even get here if the CPU has been switched out. - assert(old_status != SwitchedOut); - - _status = new_status; - - switch (status()) { - case IcacheMissStall: - assert(old_status == Running); - lastIcacheStall = curTick; - if (tickEvent.scheduled()) - tickEvent.squash(); - break; - - case IcacheMissComplete: - assert(old_status == IcacheMissStall); - if (tickEvent.squashed()) - tickEvent.reschedule(curTick + 1); - else if (!tickEvent.scheduled()) - tickEvent.schedule(curTick + 1); - break; - - case DcacheMissStall: - assert(old_status == Running); - lastDcacheStall = curTick; - if (tickEvent.scheduled()) - tickEvent.squash(); - break; - - case Idle: - assert(old_status == Running); - idleFraction++; - if (tickEvent.scheduled()) - tickEvent.squash(); - break; - - case Running: - assert(old_status == Idle || - old_status == DcacheMissStall || - old_status == IcacheMissComplete); - if (old_status == Idle && curTick != 0) - idleFraction--; - - if (tickEvent.squashed()) - tickEvent.reschedule(curTick + 1); - else if (!tickEvent.scheduled()) - tickEvent.schedule(curTick + 1); - break; - - default: - panic("can't get here"); - } - } + void setStatus(Status new_status); // statistics virtual void regStats(); From 1d7c11af7d876e758e7afce47782563aefdcdcc7 Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Mon, 8 Dec 2003 14:01:48 -0500 Subject: [PATCH 2/5] Instead of keeping track of the fraction of time that we're idle, keep track of the fraction of time we're not idle. This works better because the default processor state is idle, and the default stat value is 0. Keep the stat as idleFraction which is a formula that is equal to 1 - notIdleFraction --HG-- extra : convert_revision : 331c2e46f45ae0abda46988567ac2c4f7c42ccad --- cpu/simple_cpu/simple_cpu.cc | 8 +++++--- cpu/simple_cpu/simple_cpu.hh | 3 ++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/cpu/simple_cpu/simple_cpu.cc b/cpu/simple_cpu/simple_cpu.cc index 4b9a7c6bd..aaf8a9dc5 100644 --- a/cpu/simple_cpu/simple_cpu.cc +++ b/cpu/simple_cpu/simple_cpu.cc @@ -247,7 +247,7 @@ SimpleCPU::setStatus(Status new_status) case Idle: assert(old_status == Running); - idleFraction++; + notIdleFraction--; if (tickEvent.scheduled()) tickEvent.squash(); break; @@ -256,8 +256,8 @@ SimpleCPU::setStatus(Status new_status) assert(old_status == Idle || old_status == DcacheMissStall || old_status == IcacheMissComplete); - if (old_status == Idle && curTick != 0) - idleFraction--; + if (old_status == Idle) + notIdleFraction++; if (tickEvent.squashed()) tickEvent.reschedule(curTick + 1); @@ -304,6 +304,7 @@ SimpleCPU::regStats() .prereq(dcacheStallCycles) ; + idleFraction = constant(1.0) - notIdleFraction; numInsts = Statistics::scalar(numInst) - Statistics::scalar(startNumInst); simInsts += numInsts; } @@ -312,6 +313,7 @@ void SimpleCPU::resetStats() { startNumInst = numInst; + notIdleFraction = (_status != Idle); } void diff --git a/cpu/simple_cpu/simple_cpu.hh b/cpu/simple_cpu/simple_cpu.hh index e497559ce..666fe490b 100644 --- a/cpu/simple_cpu/simple_cpu.hh +++ b/cpu/simple_cpu/simple_cpu.hh @@ -193,7 +193,8 @@ class SimpleCPU : public BaseCPU Counter startNumLoad; // number of idle cycles - Statistics::Average<> idleFraction; + Statistics::Average<> notIdleFraction; + Statistics::Formula idleFraction; // number of cycles stalled for I-cache misses Statistics::Scalar<> icacheStallCycles; From 368de4109f9decca72faac1a6eb0909da712f43f Mon Sep 17 00:00:00 2001 From: Nathan Binkert Date: Tue, 9 Dec 2003 13:05:43 -0500 Subject: [PATCH 5/5] Sweeping change in the stats package....again... base/statistics.cc: - Merge the m5 display and simplescalar compatible display functions. - Use functors for the stats printing instead of functions. This gets rid of the very long argument lists and improves clarity. - Fix a bug in binning that caused an invalid allocation to occur. base/statistics.hh: - Instead of using a compile time variable to choose whether to print in ss compat mode, we use a runtime variable. This is how we'll choose python output. - There are no more virtual functions in the statistics themselves. All virtual functions have been moved into a secondary helper class. Every stat has an associated helper class that knows how to access certain variables in that stat. There is a hash_map from the stat to it's helper class data. This was done because the helper data is only used during setup, stats reset, and printing. All of which happen rarely, and you want to avoid any performance hit that you can. - To provide the name(), desc(), etc functions to classes so that the user can set various parameters to the stats class, a single class containing all of those functions was created. An odd trick was done to actually make this class derive from the stat class because a base class with no data actually does end up taking up space. - The detail namespace was removed for now. I'll put it back when the package is not in so much flux. - Standard deviation, and mean were added to all distribution stats. - There are several bugfixes and changes that aren't mentioned test/Makefile: Don't test sim_stats foo. test/stattest.cc: Don't test sim_stats foo. Fix bin usage so that it corresponds to the current usage. --HG-- extra : convert_revision : ce8d9a8d485a84d55799f253d851e83650684170 --- base/statistics.cc | 1216 ++++++++++++++++--------------- base/statistics.hh | 1737 ++++++++++++++++++++++++-------------------- test/Makefile | 3 +- test/stattest.cc | 13 +- 4 files changed, 1586 insertions(+), 1383 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 +namespace Database { - /** Subfield name. */ - string name; - /** Subfield desc. */ - string desc; -}; + class Data + { + private: + typedef list list_t; + typedef map map_t; -/** - * Struct to contain print data of a Stat. - */ -struct StatData -{ - /** - * Create this struct. - */ - StatData(); - /** - * Destructor. - */ - ~StatData(); + list bins; + map bin_names; + list_t binnedStats; - /** 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; - /** 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; -}; + list_t allStats; + list_t printStats; + map_t statMap; -StatData::StatData() - : init(false), print(false), subdata(NULL), precision(-1), flags(none), - prereq(NULL) -{ -} + public: + void dump(ostream &stream); -StatData::~StatData() -{ - if (subdata) - delete subdata; -} + StatData *find(void *stat); + void mapStat(void *stat, StatData *data); -class Database -{ - private: - Database(const Database &) {} + void check(); + void reset(); + void regBin(MainBin *bin, string name); + void regPrint(void *stat); + }; - private: - typedef list list_t; - typedef map map_t; - - list bins; - map bin_names; - list_t binnedStats; - - list_t allStats; - list_t printStats; - map_t statMap; - - public: - Database(); - ~Database(); - - 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); -}; - -Database::Database() -{} - -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_iterator iter; + map::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,11 +243,79 @@ Database::regBin(MainBin *bin, std::string name) cprintf("registering %s\n", name); } -bool -Stat::less(Stat *stat1, Stat *stat2) +void +Data::regPrint(void *stat) { - const string &name1 = stat1->myname(); - const string &name2 = stat2->myname(); + StatData *data = find(stat); + + if (!data->print) { + data->print = true; + + list_t::iterator j = printStats.insert(printStats.end(), data); + inplace_merge(printStats.begin(), j, + printStats.end(), StatData::less); + } + +} + +Data & +StatDB() +{ + static Data db; + return db; +} + +} + +StatData * +DataAccess::find() const +{ + return Database::StatDB().find(const_cast((const void *)this)); +} + +void +DataAccess::map(StatData *data) +{ + Database::StatDB().mapStat(this, data); +} + +StatData * +DataAccess::statData() +{ + StatData *ptr = find(); + assert(ptr); + return ptr; +} + +const StatData * +DataAccess::statData() const +{ + const StatData *ptr = find(); + assert(ptr); + return ptr; +} + +void +DataAccess::setInit() +{ + statData()->init = true; +} + +void +DataAccess::setPrint() +{ + Database::StatDB().regPrint(this); +} + +StatData::~StatData() +{ +} + +bool +StatData::less(StatData *stat1, StatData *stat2) +{ + const string &name1 = stat1->name; + const string &name2 = stat2->name; vector v1; vector v2; @@ -348,209 +337,27 @@ Stat::less(Stat *stat1, Stat *stat2) return false; } -StatData * -Database::print(Stat *stat) +bool +StatData::check() const { - StatData *data = find(stat); - assert(data); - - data->print = true; - - return data; -} - -Database & -StatDB() -{ - static Database 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); - + if (!init) { #ifdef STAT_DEBUG - number = ++total_stats; - cprintf("I'm stat number %d\n",number); + cprintf("this is stat number %d\n",(*i)->number); #endif -} + panic("Not all stats have been initialized"); + return false; + } -void -Stat::setInit() -{ mydata()->init = true; } + if (print && name.empty()) { + panic("all printable stats must be named"); + return false; + } -StatData * -Stat::mydata() -{ - StatData *data = StatDB().find(this); - assert(data); - - return data; -} - -const StatData * -Stat::mydata() const -{ - StatData *data = StatDB().find(this); - assert(data); - - return data; -} - -const SubData * -Stat::mysubdata(int index) const -{ - 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]; -} - -SubData * -Stat::mysubdata_create(int index) -{ - 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(size); - } - } else if (data->subdata->size() <= index) - data->subdata->resize(index + 1); - - SubData *sd = &(*data->subdata)[index]; - assert(sd); - - return sd; + return true; } string -Stat::myname() const -{ return mydata()->name; } - -string -Stat::mysubname(int index) const -{ - const SubData *sd = mysubdata(index); - return sd ? sd->name : ""; -} - -string -Stat::mydesc() const -{ return mydata()->desc; } - -string -Stat::mysubdesc(int index) const -{ - const SubData *sd = mysubdata(index); - return sd ? sd->desc : ""; -} - -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() -{ - StatData *data = StatDB().print(this); - assert(data && data->init); - - return data; -} - -Stat & -Stat::name(const string &name) -{ - print()->name = name; - return *this; -} - -Stat & -Stat::desc(const string &desc) -{ - print()->desc = desc; - return *this; -} - -Stat & -Stat::precision(int precision) -{ - print()->precision = precision; - return *this; -} - -Stat & -Stat::flags(FormatFlags flags) -{ - if (flags & __reserved) - panic("Cannot set reserved flags!\n"); - - print()->flags |= flags; - return *this; -} - -Stat & -Stat::prereq(const Stat &prereq) -{ - print()->prereq = &prereq; - return *this; -} - -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; -} - -bool -ScalarStat::zero() const -{ - return val() == 0.0; -} - -bool -VectorStat::zero() const -{ - return val()[0] == 0.0; -} - -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 << ""; -#endif + val << (mode == mode_m5 ? "no value" : ""); } 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,244 +427,184 @@ PrintOne(ostream &stream, result_t value, stream << endl; } -void -ScalarStat::display(ostream &stream) const +struct VectorPrint { - PrintOne(stream, val(), myname(), mydesc(), myprecision(), myflags()); -} + string name; + string desc; + vector subnames; + vector subdescs; + int precision; + DisplayMode mode; + FormatFlags flags; + rvec_t vec; + result_t total; + + VectorPrint() + : subnames(0), subdescs(0), precision(-1), mode(default_mode), + flags(0), total(NAN) + {} + + void operator()(ostream &stream) const; +}; 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 *subnames = 0; - vector *subdescs = 0; - if (have_subname) { - subnames = new vector(size); - for (int i = 0; i < size; ++i) - (*subnames)[i] = mysubname(i); - } - if (have_subdesc) { - subdescs = new vector(size); - for (int i = 0; i < size; ++i) - (*subdescs)[i] = mysubdesc(i); - } - - VectorDisplay(stream, myname(), subnames, mydesc(), subdescs, - myprecision(), myflags(), val(), total()); -} - -#ifndef STAT_DISPLAY_COMPAT -#define NAMESEP "::" -#else -#define NAMESEP "_" -#endif - -#ifndef STAT_DISPLAY_COMPAT -void -VectorDisplay(std::ostream &stream, - const std::string &myname, - const std::vector *mysubnames, - const std::string &mydesc, - const std::vector *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]; } } - if (_size == 1) { - PrintOne(stream, vec[0], myname, mydesc, myprecision, myflags); - } else { - for (int i = 0; i < _size; ++i) { - string subname; - if (mysubnames) { - subname = (*mysubnames)[i]; - if (subname.empty()) - continue; - } else { - subname = to_string(i); - } + string base = name + ((mode == mode_simplescalar) ? "_" : "::"); - 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); - } - } + ScalarPrint print; + print.name = name; + print.desc = desc; + print.precision = precision; + print.flags = flags; - 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 *mysubnames, - const std::string &mydesc, - const std::vector *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 (myflags & (pdf | cdf)) { - for (int i = 0; i < _size; ++i) { - _total += vec[i]; - } - } + bool havesub = !subnames.empty(); if (_size == 1) { - PrintOne(stream, vec[0], myname, mydesc, myprecision, myflags); - } else { - if (myflags & total) - PrintOne(stream, mytotal, myname, mydesc, myprecision, myflags); + print.value = vec[0]; + print(stream); + } else if (mode == mode_m5) { + for (int i = 0; i < _size; ++i) { + if (havesub && (i >= subnames.size() || subnames[i].empty())) + continue; - if (myflags & dist) { - ccprintf(stream, "%s.start_dist\n", myname); + print.name = base + (havesub ? subnames[i] : to_string(i)); + print.desc = subdescs.empty() ? desc : subdescs[i]; + print.value = vec[i]; + + if (_total && (flags & pdf)) { + print.pdf = vec[i] / _total; + print.cdf += print.pdf; + } + + print(stream); + } + + if (flags & ::Statistics::total) { + print.name = base + "total"; + print.desc = desc; + print.value = total; + print(stream); + } + } else { + if (flags & ::Statistics::total) { + print.value = total; + print(stream); + } + + result_t _pdf = 0.0; + result_t _cdf = 0.0; + if (flags & dist) { + ccprintf(stream, "%s.start_dist\n", name); for (int i = 0; i < _size; ++i) { - 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 -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); +struct DistPrint { - assert(size == vec.size()); + string name; + string desc; + int precision; + DisplayMode mode; + FormatFlags flags; - result_t total = 0.0; - result_t pdf, cdf = 0.0; + 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; - total += underflow; - for (int i = 0; i < size; ++i) - total += vec[i]; - total += overflow; + int min; + int max; + int bucket_size; + int size; + bool fancy; - pdf = underflow / total; - cdf += pdf; + void operator()(ostream &stream) const; +}; - PrintOne(stream, underflow, name + NAMESEP + "underflow", desc, - precision, myflags, pdf, cdf); +void +DistPrint::operator()(ostream &stream) const +{ + if (fancy) { + ScalarPrint print; + string base = name + ((mode == mode_m5) ? "::" : "_"); - for (int i = 0; i < size; ++i) { - stringstream namestr; - namestr << name; + print.precision = precision; + print.flags = flags; + print.desc = desc; - int low = i * bucket_size + min; - int high = ::std::min((i + 1) * bucket_size + min - 1, max); - namestr << low; - if (low < high) - namestr << "-" << high; + print.name = base + "mean"; + print.value = samples ? sum / samples : NAN; + print(stream); - pdf = vec[i] / total; - cdf += pdf; - PrintOne(stream, vec[i], namestr.str(), desc, precision, myflags, - pdf, cdf); + 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; } - 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); -} -#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) -{ assert(size == vec.size()); - string blank; result_t total = 0.0; @@ -856,66 +613,377 @@ DistDisplay(ostream &stream, const string &name, const string &desc, total += vec[i]; total += overflow; - ccprintf(stream, "%-42s", name + ".start_dist"); - if (PrintDescriptions && !desc.empty()) - ccprintf(stream, " # %s", desc); - stream << endl; + string base = name + (mode == mode_m5 ? "::" : "."); - PrintOne(stream, total, name + ".samples", blank, precision, flags); - PrintOne(stream, min_val, name + ".min_value", blank, precision, flags); + ScalarPrint print; + print.desc = (mode == mode_m5) ? desc : ""; + print.precision = precision; + print.mode = mode; + print.flags = flags; - if (underflow > 0) - PrintOne(stream, min_val, name + ".underflows", blank, precision, - flags); + if (mode == mode_simplescalar) { + ccprintf(stream, "%-42s", base + "start_dist"); + if (PrintDescriptions && !desc.empty()) + ccprintf(stream, " # %s", desc); + stream << endl; + } - int _min; - result_t _pdf, _cdf, mypdf, mycdf; + 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); + } + + if (mode == mode_simplescalar) + ccprintf(stream, "%send_dist\n\n", base); +} + +void +ScalarDataBase::display(ostream &stream) const +{ + ScalarPrint print; + print.value = val(); + print.name = name; + print.desc = desc; + print.precision = precision; + print.flags = flags; + + print(stream); +} + +void +VectorDataBase::display(ostream &stream) const +{ + int size = this->size(); + const_cast(this)->update(); + + VectorPrint print; + + print.name = name; + print.desc = desc; + print.mode = mode; + print.flags = flags; + print.precision = precision; + print.vec = val(); + print.total = total(); - _cdf = 0.0; for (int i = 0; i < size; ++i) { - if (flags & nozero && vec[i] == 0.0 || - flags & nonan && isnan(vec[i])) + if (!subnames[i].empty()) { + print.subnames = subnames; + print.subnames.resize(size); + for (int i = 0; i < size; ++i) { + if (!subnames[i].empty() && !subdescs[i].empty()) { + print.subdescs = subdescs; + print.subdescs.resize(size); + break; + } + } + break; + } + } + + + print(stream); +} + +void +Vector2dDataBase::display(ostream &stream) const +{ + const_cast(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); + } } -#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) +DistDataBase::display(ostream &stream) const { - 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); + const_cast(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); } -} // namespace Detail +void +VectorDistDataBase::display(ostream &stream) const +{ + const_cast(this)->update(); -MainBin::MainBin(const std::string &name) + 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; +} + +void +FormulaBase::update(StatData *) +{ +} + +Formula::Formula() +{ + setInit(); +} + +Formula::Formula(Temp r) +{ + root = r; + assert(size()); +} + +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 >(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,195 +100,92 @@ const FormatFlags none = 0x0000; const FormatFlags total = 0x0001; /** Print the percent of the total that this entry represents. */ const FormatFlags pdf = 0x0002; -/** Don't print if this is zero. */ -const FormatFlags nozero = 0x0004; -/** 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 cdf = 0x0004; +/** Don't print if this is zero. */ +const FormatFlags nozero = 0x0010; +/** Don't print if this is NAN */ +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: + /** 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(); + /** - * 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. + * @return true if the stat is binned. */ - Stat(bool reg); - /** - * Destructor - */ - 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. - */ - virtual size_t size() const = 0; - /** - * Return true if the stat has value zero. - * @return True if the stat is zero. + * @return true if this stat has a value and satisfies its + * requirement as a prereq */ virtual bool zero() const = 0; /** - * Return true if stat is binned. - *@return True is stat is binned. + * Check that this stat has been set up properly and is ready for + * use + * @return true for success */ - virtual bool binned() const = 0; + virtual bool check() const; - /** - * 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); - /** - * 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); - /** - * 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); - /** - * 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); - /** - * 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); - /** - * Set the subfield name for the given index, and marks this stat to print - * at the end of simulation. - * @param index The subfield index. - * @param name The new name of the subfield. - * @return A reference to this stat. - */ - Stat &subname(int index, const std::string &name); - /** - * Set the subfield description for the given index and marks this stat to - * print at the end of simulation. - * @param index The subfield index. - * @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 @@ -300,96 +194,380 @@ class 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 + static bool less(StatData *stat1, StatData *stat2); }; -/** - * 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 +struct ScalarDataBase : public StatData { - 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; + virtual result_t total() const = 0; - /** - * Return true if stat is binned. - *@return True is stat is binned. - */ - virtual bool binned() const = 0; + virtual void display(std::ostream &stream) const; }; -void -VectorDisplay(std::ostream &stream, const std::string &myname, - const std::vector *mysubnames, - const std::string &mydesc, - const std::vector *mysubdescs, - int myprecision, FormatFlags myflags, const rvec_t &vec, - result_t mytotal); +template +class ScalarData : public ScalarDataBase +{ + protected: + T &s; -/** - * 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 + 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 subnames; + mutable std::vector 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 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 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 data; + + /** Names and descriptions of subfields. */ + mutable std::vector subnames; + mutable std::vector 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 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 subnames; + std::vector subdescs; + std::vector 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 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 Data> +class Wrap : public Child +{ + protected: + Parent &self() { return *reinterpret_cast(this); } + + protected: + Data *statData() + { + StatData *__data = DataAccess::statData(); + Data *ptr = dynamic_cast *>(__data); + assert(ptr); + return ptr; + } + + public: + const Data *statData() const + { + const StatData *__data = DataAccess::statData(); + const Data *ptr = dynamic_cast *>(__data); + assert(ptr); + return ptr; + } + + public: + Wrap() + { + map(new Data(*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. + */ + Parent &name(const std::string &_name) + { + Data *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. + */ + 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. + */ + 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. + */ + 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. + */ + template + Parent &prereq(const T &prereq) + { + statData()->prereq = prereq.statData(); + return self(); + } +}; + +template class Data> +class WrapVec : public Wrap +{ + 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. + * @param index The subfield index. + * @param name The new name of the subfield. + * @return A reference to this stat. + */ + Parent &subname(int index, const std::string &name) + { + std::vector &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. + * @param index The subfield index. + * @param desc The new description of the subfield + * @return A reference to this stat. + */ + Parent &subdesc(int index, const std::string &desc) + { + std::vector &subd = statData()->subdescs; + if (subd.size() <= index) + subd.resize(index + 1); + subd[index] = desc; + + return self(); + } + +}; + +template class Data> +class WrapVec2d : public WrapVec { public: /** - * Create and perhaps register this stat with the database. - * @param reg If true, register this stat with the database. + * @warning This makes the assumption that if you're gonna subnames a 2d + * vector, you're subnaming across all y */ - 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. - */ - virtual bool binned() const = 0; + Parent &ysubnames(const char **names) + { + Data *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 *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 class Storage, class Bin> -class ScalarBase : public ScalarStat +class ScalarBase : public DataAccess { protected: /** Define the type of the storage class. */ @@ -593,11 +786,6 @@ class ScalarBase : public ScalarStat const ScalarBase &operator=(const ScalarBase &); 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 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 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,18 +927,18 @@ 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. + * @return the number of elements in this vector. */ - VectorBase() : VectorStat(true), vec(NULL) {} - /** - * Destructor. - */ - ~VectorBase() { if (vec) delete vec; } + size_t size() const { return bin.size(); } - /** - * Set this vector to have the given size. - * @param size The new size. - * @return A reference to this stat. - */ - VectorBase &init(size_t size) { - bin.init(size, params); - setInit(); - - 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; @@ -792,20 +979,7 @@ class VectorBase : public VectorStat */ ScalarProxy 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 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 class Storage, class Bin> @@ -957,7 +1133,7 @@ template class Storage, class Bin> class VectorProxy; template class Storage, class Bin> -class Vector2dBase : public Stat +class Vector2dBase : public DataAccess { protected: typedef Storage storage_t; @@ -969,7 +1145,6 @@ class Vector2dBase : public Stat size_t y; bin_t bin; params_t params; - std::vector *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(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; VectorProxy 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; } + size_t size() const { return bin.size(); } + bool zero() const { return data(0)->value(params) == 0.0; } - 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); - } - - 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 class Storage, class Bin> -class VectorProxy : public VectorStat +class VectorProxy { protected: typedef Storage 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 operator[](int index) { + ScalarProxy operator[](int index) + { assert (index >= 0 && index < size()); return ScalarProxy(*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 class Storage, class Bin> @@ -1187,12 +1297,6 @@ Vector2dBase::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 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 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 class Storage, class Bin> class DistProxy; template class Storage, class Bin> -class VectorDistBase : public Stat +class VectorDistBase : public DataAccess { protected: typedef Storage storage_t; @@ -1628,32 +1696,38 @@ class VectorDistBase : public Stat const VectorDistBase &operator=(const VectorDistBase &); public: - VectorDistBase() : Stat(true) { } - ~VectorDistBase() { } + VectorDistBase() {} friend class DistProxy; DistProxy operator[](int index); const DistProxy 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 class Storage, class Bin> -class DistProxy : public Stat +class DistProxy { protected: typedef Storage storage_t; @@ -1674,9 +1748,9 @@ class DistProxy : public Stat public: DistProxy(const VectorDistBase &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 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 class Storage, class Bin> @@ -1733,20 +1788,8 @@ VectorDistBase::operator[](int index) const return DistProxy(*this, index); } -/** - * @todo Need a way to print Distribution totals across the Vector - */ -template class Storage, class Bin> -void -VectorDistBase::display(std::ostream &stream) const -{ - for (int i = 0; i < size(); ++i) { - DistProxy proxy(*this, i); - proxy.display(stream); - } -} - #if 0 +template class Storage, class Bin> result_t VectorDistBase::total(int index) const { @@ -1798,20 +1841,24 @@ typedef RefCountingPtr 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 class Storage, class Bin> @@ -1824,7 +1871,11 @@ class ScalarProxyNode : public Node public: ScalarProxyNode(const ScalarProxy &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 @@ -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 class Storage, class Bin> - Temp(const ScalarProxy &p) - : node(new ScalarProxyNode(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(value)) {} - /** - * Create a ConstNode - * @param value The value of the const node. - */ - Temp(unsigned char value) : node(new ConstNode(value)) {} - /** - * Create a ConstNode - * @param value The value of the const node. - */ - Temp(signed short value) : node(new ConstNode(value)) {} - /** - * Create a ConstNode - * @param value The value of the const node. - */ - Temp(unsigned short value) : node(new ConstNode(value)) {} - /** - * Create a ConstNode - * @param value The value of the const node. - */ - Temp(signed int value) : node(new ConstNode(value)) {} - /** - * Create a ConstNode - * @param value The value of the const node. - */ - Temp(unsigned int value) : node(new ConstNode(value)) {} - /** - * Create a ConstNode - * @param value The value of the const node. - */ - Temp(signed long value) : node(new ConstNode(value)) {} - /** - * Create a ConstNode - * @param value The value of the const node. - */ - Temp(unsigned long value) : node(new ConstNode(value)) {} - /** - * Create a ConstNode - * @param value The value of the const node. - */ - Temp(signed long long value) - : node(new ConstNode(value)) {} - /** - * Create a ConstNode - * @param value The value of the const node. - */ - Temp(unsigned long long value) - : node(new ConstNode(value)) {} - /** - * Create a ConstNode - * @param value The value of the const node. - */ - Temp(float value) : node(new ConstNode(value)) {} - /** - * Create a ConstNode - * @param value The value of the const node. - */ - Temp(double value) : node(new ConstNode(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 -class Scalar : public Detail::ScalarBase +class Scalar : public Wrap, ScalarBase, ScalarData> { public: /** The base implementation. */ - typedef Detail::ScalarBase Base; + typedef ScalarBase Base; + + Scalar() + { + setInit(); + } /** * Sets the stat equal to the given value. Calls the base implementation @@ -2486,11 +2434,16 @@ class Scalar : public Detail::ScalarBase * @sa Stat, ScalarBase, AvgStor */ template -class Average : public Detail::ScalarBase +class Average : public Wrap, ScalarBase, ScalarData> { public: /** The base implementation. */ - typedef Detail::ScalarBase Base; + typedef ScalarBase Base; + + Average() + { + setInit(); + } /** * Sets the stat equal to the given value. Calls the base implementation @@ -2506,37 +2459,73 @@ class Average : public Detail::ScalarBase * @sa Stat, VectorBase, StatStor */ template -class Vector : public Detail::VectorBase -{ }; +class Vector : public WrapVec, VectorBase, 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 -class AverageVector : public Detail::VectorBase -{ }; +class AverageVector : public WrapVec, VectorBase, 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 -class Vector2d : public Detail::Vector2dBase -{ }; +class Vector2d : public WrapVec2d, Vector2dBase, 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 -class Distribution : public Detail::DistBase +class Distribution : public Wrap, DistBase, DistData> { private: /** Base implementation. */ - typedef Detail::DistBase Base; + typedef DistBase Base; /** The Parameter type. */ - typedef typename Detail::DistStor::Params Params; + typedef typename DistStor::Params Params; public: /** @@ -2563,13 +2552,13 @@ class Distribution : public Detail::DistBase * @sa Stat, DistBase, FancyStor */ template -class StandardDeviation : public Detail::DistBase +class StandardDeviation : public Wrap, DistBase, DistData> { private: /** The base implementation */ - typedef Detail::DistBase Base; + typedef DistBase Base; /** The parameter type. */ - typedef typename Detail::DistStor::Params Params; + typedef typename DistStor::Params Params; public: /** @@ -2586,19 +2575,20 @@ class StandardDeviation : public Detail::DistBase * @sa Stat, DistBase, AvgFancy */ template -class AverageDeviation : public Detail::DistBase +class AverageDeviation : public Wrap, DistBase, DistData> { private: /** The base implementation */ - typedef Detail::DistBase Base; + typedef DistBase Base; /** The parameter type. */ - typedef typename Detail::DistStor::Params Params; + typedef typename DistStor::Params Params; public: /** * Construct and initialize this distribution. */ - AverageDeviation() { + AverageDeviation() + { bin.init(params); setInit(); } @@ -2609,14 +2599,13 @@ class AverageDeviation : public Detail::DistBase * @sa Stat, VectorDistBase, DistStor */ template -class VectorDistribution - : public Detail::VectorDistBase +class VectorDistribution : public WrapVec, VectorDistBase, VectorDistData> { private: /** The base implementation */ - typedef Detail::VectorDistBase Base; + typedef VectorDistBase Base; /** The parameter type. */ - typedef typename Detail::DistStor::Params Params; + typedef typename DistStor::Params Params; public: /** @@ -2644,14 +2633,13 @@ class VectorDistribution * @sa Stat, VectorDistBase, FancyStor */ template -class VectorStandardDeviation - : public Detail::VectorDistBase +class VectorStandardDeviation : public WrapVec, VectorDistBase, VectorDistData> { private: /** The base implementation */ - typedef Detail::VectorDistBase Base; + typedef VectorDistBase Base; /** The parameter type. */ - typedef typename Detail::DistStor::Params Params; + typedef typename DistStor::Params Params; public: /** @@ -2672,14 +2660,13 @@ class VectorStandardDeviation * @sa Stat, VectorDistBase, AvgFancy */ template -class VectorAverageDeviation - : public Detail::VectorDistBase +class VectorAverageDeviation : public WrapVec, VectorDistBase, VectorDistData> { private: /** The base implementation */ - typedef Detail::VectorDistBase Base; + typedef VectorDistBase Base; /** The parameter type. */ - typedef typename Detail::DistStor::Params Params; + typedef typename DistStor::Params Params; public: /** @@ -2698,57 +2685,16 @@ 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: - /** - * Create and initialize thie formula, and register it with the database. - */ - Formula() : VectorStat(true) { setInit(); } - /** - * 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()); - } - - /** - * 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; - } - - /** - * 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 >(root, r)); - else - root = r; - assert(size()); - return *this; - } - /** * 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, @@ -2756,7 +2702,8 @@ class Formula : public Detail::VectorStat * be x[0]/y, x[1]/y, x[2]/y, respectively. * @return The result vector. */ - const rvec_t &val() const { return root->val(); } + 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 @@ -2767,30 +2714,231 @@ class Formula : public Detail::VectorStat * the first entry in the rvec_t val() returns. * @return The total of the result vector. */ - result_t total() const { return root->total(); } + result_t total() const; /** * Return the number of elements in the tree. */ - size_t size() const { - if (!root) - return 0; - else - return root->size(); - } + 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. */ - virtual bool binned() const { return root->binned(); } + bool binned() const; /** * Formulas don't need to be reset */ - virtual void reset() {} + void reset(); + + /** + * + */ + bool zero() const; + + /** + * + */ + void update(StatData *); }; +class Temp; +class Formula : public WrapVec +{ + public: + /** + * Create and initialize thie formula, and register it with the database. + */ + Formula(); + + /** + * Create a formula with the given root node, register it with the + * database. + * @param r The root of the expression tree. + */ + 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=(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+=(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: + /** + * 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) { } + + /** + * Return the node pointer. + * @return the node pointer. + */ + operator NodePtr() { return node;} + + public: + /** + * Create a new ScalarStatNode. + * @param s The ScalarStat to place in a node. + */ + template + Temp(const Scalar &s) + : node(new ScalarStatNode(s.statData())) { } + + /** + * Create a new ScalarStatNode. + * @param s The ScalarStat to place in a node. + */ + template + Temp(const Average &s) + : node(new ScalarStatNode(s.statData())) { } + + /** + * Create a new VectorStatNode. + * @param s The VectorStat to place in a node. + */ + template + Temp(const Vector &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 class Storage, class Bin> + Temp(const ScalarProxy &p) + : node(new ScalarProxyNode(p)) { } + + /** + * Create a ConstNode + * @param value The value of the const node. + */ + Temp(signed char value) + : node(new ConstNode(value)) {} + + /** + * Create a ConstNode + * @param value The value of the const node. + */ + Temp(unsigned char value) + : node(new ConstNode(value)) {} + + /** + * Create a ConstNode + * @param value The value of the const node. + */ + Temp(signed short value) + : node(new ConstNode(value)) {} + + /** + * Create a ConstNode + * @param value The value of the const node. + */ + Temp(unsigned short value) + : node(new ConstNode(value)) {} + + /** + * Create a ConstNode + * @param value The value of the const node. + */ + Temp(signed int value) + : node(new ConstNode(value)) {} + + /** + * Create a ConstNode + * @param value The value of the const node. + */ + Temp(unsigned int value) + : node(new ConstNode(value)) {} + + /** + * Create a ConstNode + * @param value The value of the const node. + */ + Temp(signed long value) + : node(new ConstNode(value)) {} + + /** + * Create a ConstNode + * @param value The value of the const node. + */ + Temp(unsigned long value) + : node(new ConstNode(value)) {} + + /** + * Create a ConstNode + * @param value The value of the const node. + */ + Temp(signed long long value) + : node(new ConstNode(value)) {} + + /** + * Create a ConstNode + * @param value The value of the const node. + */ + Temp(unsigned long long value) + : node(new ConstNode(value)) {} + + /** + * Create a ConstNode + * @param value The value of the const node. + */ + Temp(float value) + : node(new ConstNode(value)) {} + + /** + * Create a ConstNode + * @param value The value of the const node. + */ + Temp(double value) + : node(new ConstNode(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 >(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 >(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 >(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 >(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 >(l, r)); } -inline Detail::Temp -operator-(Detail::Temp l) +inline Temp +operator-(Temp l) { - using namespace Detail; return NodePtr(new UnaryNode >(l)); } template -inline Detail::Temp +inline Temp constant(T val) { - using namespace Detail; return NodePtr(new ConstNode(val)); } template -inline Detail::Temp +inline Temp functor(T &val) { - using namespace Detail; return NodePtr(new FunctorNode(val)); } template -inline Detail::Temp +inline Temp scalar(T &val) { - using namespace Detail; return NodePtr(new ScalarNode(val)); } -inline Detail::Temp -sum(Detail::Temp val) +inline Temp +sum(Temp val) { - using namespace Detail; return NodePtr(new SumNode >(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;