69b663dbb9d403033eaa07ec802f3412ec605298
2 * Copyright (c) 2003 The Regents of The University of Michigan
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 #include "base/callback.hh"
37 #include "base/cprintf.hh"
38 #include "base/misc.hh"
39 #include "base/statistics.hh"
40 #include "base/str.hh"
41 #include "sim/universe.hh"
58 static int total_stats
= 0;
63 // This is a hack to get this parameter from the old stats package.
64 namespace Statistics
{
65 bool PrintDescriptions
= true;
69 * Struct to contain a name and description of statistic subfield.
80 * Struct to contain print data of a Stat.
93 /** True if the stat has been initialized. */
95 /** True if the stat should be printed. */
97 /** The name of the stat. */
99 /** Names and descriptions of subfields. */
100 vector
<SubData
> *subdata
;
101 /** The description of the stat. */
103 /** The display precision. */
105 /** The formatting flags. */
107 /** A pointer to a prerequisite Stat. */
112 : init(false), print(false), subdata(NULL
), precision(-1), flags(none
),
117 StatData::~StatData()
126 Database(const Database
&) {}
129 typedef list
<Stat
*> list_t
;
130 typedef map
<const Stat
*, StatData
*> map_t
;
133 map
<const GenBin
*, std::string
> bin_names
;
144 void dump(ostream
&stream
);
146 StatData
*find(const Stat
*stat
);
149 void regStat(Stat
*stat
);
150 StatData
*print(Stat
*stat
);
151 void regBin(GenBin
*bin
, std::string name
);
157 Database::~Database()
161 Database::dump(ostream
&stream
)
164 list_t::iterator i
= printStats
.begin();
165 list_t::iterator end
= printStats
.end();
169 binnedStats
.push_back(stat
);
174 list
<GenBin
*>::iterator j
= bins
.begin();
175 list
<GenBin
*>::iterator bins_end
=bins
.end();
178 ccprintf(stream
, "PRINTING BINNED STATS\n");
179 while (j
!= bins_end
) {
181 map
<const GenBin
*, std::string
>::const_iterator iter
;
182 iter
= bin_names
.find(*j
);
183 if (iter
== bin_names
.end())
184 panic("a binned stat not found in names map!");
185 ccprintf(stream
,"---%s Bin------------\n", (*iter
).second
);
188 list_t::iterator i
= printStats
.begin();
189 list_t::iterator end
= printStats
.end();
191 list_t::iterator i
= binnedStats
.begin();
192 list_t::iterator end
= binnedStats
.end();
196 if (stat
->dodisplay())
197 stat
->display(stream
);
201 ccprintf(stream
, "---------------------------------\n");
204 ccprintf(stream
, "**************ALL STATS************\n");
209 * get bin totals working, then print the stat here (as total), even if
210 * its' binned. (this is only for the case you selectively bin a few stats
213 list_t::iterator k
= printStats
.begin();
214 list_t::iterator endprint
= printStats
.end();
215 while (k
!= endprint
) {
217 if (stat
->dodisplay() && !stat
->binned())
218 stat
->display(stream
);
225 Database::find(const Stat
*stat
)
227 map_t::const_iterator i
= statMap
.find(stat
);
229 if (i
== statMap
.end())
238 list_t::iterator i
= allStats
.begin();
239 list_t::iterator end
= allStats
.end();
243 StatData
*data
= find(stat
);
244 if (!data
|| !data
->init
) {
246 cprintf("this is stat number %d\n",(*i
)->number
);
248 panic("Not all stats have been initialized");
252 if (data
->name
.empty())
253 panic("all printable stats must be named");
255 list_t::iterator j
= printStats
.insert(printStats
.end(), *i
);
256 inplace_merge(printStats
.begin(), j
,
257 printStats
.end(), Stat::less
);
267 list_t::iterator i
= allStats
.begin();
268 list_t::iterator end
= allStats
.end();
275 MainBin
*orig
= MainBin::current();
277 list
<GenBin
*>::iterator bi
= bins
.begin();
278 list
<GenBin
*>::iterator be
= bins
.end();
283 i
= allStats
.begin();
296 Database::regStat(Stat
*stat
)
298 if (statMap
.find(stat
) != statMap
.end())
299 panic("shouldn't register stat twice!");
301 allStats
.push_back(stat
);
303 StatData
*data
= new StatData
;
304 bool success
= (statMap
.insert(make_pair(stat
, data
))).second
;
305 assert(statMap
.find(stat
) != statMap
.end());
306 assert(success
&& "this should never fail");
310 Database::regBin(GenBin
*bin
, std::string name
)
312 if (bin_names
.find(bin
) != bin_names
.end())
313 panic("shouldn't register bin twice");
317 bool success
= (bin_names
.insert(make_pair(bin
,name
))).second
;
318 assert(bin_names
.find(bin
) != bin_names
.end());
319 assert(success
&& "this should not fail");
321 cprintf("registering %s\n", name
);
325 Stat::less(Stat
*stat1
, Stat
*stat2
)
327 const string
&name1
= stat1
->myname();
328 const string
&name2
= stat2
->myname();
333 tokenize(v1
, name1
, '.');
334 tokenize(v2
, name2
, '.');
336 int last
= min(v1
.size(), v2
.size()) - 1;
337 for (int i
= 0; i
< last
; ++i
)
339 return v1
[i
] < v2
[i
];
341 // Special compare for last element.
342 if (v1
[last
] == v2
[last
])
343 return v1
.size() < v2
.size();
345 return v1
[last
] < v2
[last
];
351 Database::print(Stat
*stat
)
353 StatData
*data
= find(stat
);
371 // This assert can help you find that pesky stat.
372 assert(this != (void *)0xbffff5c0);
376 StatDB().regStat(this);
379 number
= ++total_stats
;
380 cprintf("I'm stat number %d\n",number
);
386 { mydata()->init
= true; }
391 StatData
*data
= StatDB().find(this);
400 StatData
*data
= StatDB().find(this);
407 Stat::mysubdata(int index
) const
413 const StatData
*data
= this->mydata();
414 if (!data
->subdata
|| data
->subdata
->size() <= index
)
417 return &(*data
->subdata
)[index
];
421 Stat::mysubdata_create(int index
)
423 int size
= this->size();
424 assert(index
>= 0 && (size
== 0 || size
> 0 && index
< size
));
426 StatData
*data
= this->mydata();
427 if (!data
->subdata
) {
428 if (!data
->subdata
) {
432 data
->subdata
= new vector
<SubData
>(size
);
434 } else if (data
->subdata
->size() <= index
)
435 data
->subdata
->resize(index
+ 1);
437 SubData
*sd
= &(*data
->subdata
)[index
];
445 { return mydata()->name
; }
448 Stat::mysubname(int index
) const
450 const SubData
*sd
= mysubdata(index
);
451 return sd
? sd
->name
: "";
456 { return mydata()->desc
; }
459 Stat::mysubdesc(int index
) const
461 const SubData
*sd
= mysubdata(index
);
462 return sd
? sd
->desc
: "";
466 Stat::myprecision() const
467 { return mydata()->precision
; }
470 Stat::myflags() const
471 { return mydata()->flags
; }
474 Stat::dodisplay() const
475 { return !mydata()->prereq
|| !mydata()->prereq
->zero(); }
480 StatData
*data
= StatDB().print(this);
481 assert(data
&& data
->init
);
487 Stat::name(const string
&name
)
489 print()->name
= name
;
494 Stat::desc(const string
&desc
)
496 print()->desc
= desc
;
501 Stat::precision(int precision
)
503 print()->precision
= precision
;
508 Stat::flags(FormatFlags flags
)
510 if (flags
& __reserved
)
511 panic("Cannot set reserved flags!\n");
513 print()->flags
|= flags
;
518 Stat::prereq(const Stat
&prereq
)
520 print()->prereq
= &prereq
;
525 Stat::subname(int index
, const string
&name
)
528 mysubdata_create(index
)->name
= name
;
532 Stat::subdesc(int index
, const string
&desc
)
535 mysubdata_create(index
)->desc
= desc
;
540 ScalarStat::zero() const
546 VectorStat::zero() const
548 return val()[0] == 0.0;
552 ValueToString(result_t value
, int precision
)
558 val
.precision(precision
);
559 else if (value
== rint(value
))
562 val
.unsetf(ios::showpoint
);
563 val
.setf(ios::fixed
);
566 #ifndef STAT_DISPLAY_COMPAT
569 val
<< "<err: div-0>";
577 PrintOne(ostream
&stream
, result_t value
,
578 const string
&name
, const string
&desc
, int precision
,
579 FormatFlags flags
, result_t pdf
= NAN
, result_t cdf
= NAN
)
581 if (flags
& nozero
&& value
== 0.0 ||
582 flags
& nonan
&& isnan(value
))
585 stringstream pdfstr
, cdfstr
;
588 ccprintf(pdfstr
, "%.2f%%", pdf
* 100.0);
591 ccprintf(cdfstr
, "%.2f%%", cdf
* 100.0);
593 #ifdef STAT_DISPLAY_COMPAT
594 if (flags
& __substat
) {
595 ccprintf(stream
, "%32s %12s %10s %10s", name
,
596 ValueToString(value
, precision
),
601 ccprintf(stream
, "%-40s %12s %10s %10s", name
,
602 ValueToString(value
, precision
), pdfstr
, cdfstr
);
605 if (PrintDescriptions
) {
607 ccprintf(stream
, " # %s", desc
);
613 ScalarStat::display(ostream
&stream
) const
615 PrintOne(stream
, val(), myname(), mydesc(), myprecision(), myflags());
619 VectorStat::display(ostream
&stream
) const
621 bool have_subname
= false;
622 bool have_subdesc
= false;
623 int size
= this->size();
624 for (int i
= 0; i
< size
; ++i
) {
625 if (!mysubname(i
).empty())
627 if (!mysubdesc(i
).empty())
631 vector
<string
> *subnames
= 0;
632 vector
<string
> *subdescs
= 0;
634 subnames
= new vector
<string
>(size
);
635 for (int i
= 0; i
< size
; ++i
)
636 (*subnames
)[i
] = mysubname(i
);
639 subdescs
= new vector
<string
>(size
);
640 for (int i
= 0; i
< size
; ++i
)
641 (*subdescs
)[i
] = mysubdesc(i
);
644 VectorDisplay(stream
, myname(), subnames
, mydesc(), subdescs
,
645 myprecision(), myflags(), val(), total());
648 #ifndef STAT_DISPLAY_COMPAT
654 #ifndef STAT_DISPLAY_COMPAT
656 VectorDisplay(std::ostream
&stream
,
657 const std::string
&myname
,
658 const std::vector
<std::string
> *mysubnames
,
659 const std::string
&mydesc
,
660 const std::vector
<std::string
> *mysubdescs
,
661 int myprecision
, FormatFlags myflags
,
662 const rvec_t
&vec
, result_t mytotal
)
664 int _size
= vec
.size();
665 result_t _total
= 0.0;
666 result_t _pdf
, _cdf
= 0.0;
668 if (myflags
& (pdf
| cdf
)) {
669 for (int i
= 0; i
< _size
; ++i
) {
675 PrintOne(stream
, vec
[0], myname
, mydesc
, myprecision
, myflags
);
677 for (int i
= 0; i
< _size
; ++i
) {
680 subname
= (*mysubnames
)[i
];
684 subname
= to_string(i
);
687 string name
= myname
+ NAMESEP
+ subname
;
688 if (!(myflags
& pdf
))
689 PrintOne(stream
, vec
[i
], name
, mydesc
, myprecision
, myflags
);
691 _pdf
= vec
[i
] / _total
;
693 PrintOne(stream
, vec
[i
], name
, mydesc
, myprecision
, myflags
,
699 PrintOne(stream
, mytotal
, myname
+ NAMESEP
+ "total",
700 mydesc
, myprecision
, myflags
);
705 VectorDisplay(std::ostream
&stream
,
706 const std::string
&myname
,
707 const std::vector
<std::string
> *mysubnames
,
708 const std::string
&mydesc
,
709 const std::vector
<std::string
> *mysubdescs
,
710 int myprecision
, FormatFlags myflags
,
711 const rvec_t
&vec
, result_t mytotal
)
713 int _size
= vec
.size();
714 result_t _total
= 0.0;
715 result_t _pdf
, _cdf
= 0.0;
717 if (myflags
& (pdf
| cdf
)) {
718 for (int i
= 0; i
< _size
; ++i
) {
724 PrintOne(stream
, vec
[0], myname
, mydesc
, myprecision
, myflags
);
727 PrintOne(stream
, mytotal
, myname
, mydesc
, myprecision
, myflags
);
729 if (myflags
& dist
) {
730 ccprintf(stream
, "%s.start_dist\n", myname
);
731 for (int i
= 0; i
< _size
; ++i
) {
732 string subname
, subdesc
;
733 subname
= to_string(i
);
735 if (!subname
.empty()) {
736 subname
= (*mysubnames
)[i
];
740 subdesc
= (*mysubdescs
)[i
];
742 if (!(myflags
& (pdf
| cdf
))) {
743 PrintOne(stream
, vec
[i
], subname
, subdesc
, myprecision
,
744 myflags
| __substat
);
747 _pdf
= vec
[i
] / _total
;
752 if (!(myflags
& cdf
)) {
753 PrintOne(stream
, vec
[i
], subname
, subdesc
, myprecision
,
754 myflags
| __substat
, _pdf
);
756 PrintOne(stream
, vec
[i
], subname
, subdesc
, myprecision
,
757 myflags
| __substat
, _pdf
, _cdf
);
761 ccprintf(stream
, "%s.end_dist\n", myname
);
763 for (int i
= 0; i
< _size
; ++i
) {
766 subname
= (*mysubnames
)[i
];
770 subname
= to_string(i
);
773 string name
= myname
+ NAMESEP
+ subname
;
774 if (!(myflags
& pdf
)) {
775 PrintOne(stream
, vec
[i
], name
, mydesc
, myprecision
,
779 _pdf
= vec
[i
] / _total
;
784 PrintOne(stream
, vec
[i
], name
, mydesc
, myprecision
,
785 myflags
, _pdf
, _cdf
);
793 #ifndef STAT_DISPLAY_COMPAT
795 DistDisplay(ostream
&stream
, const string
&name
, const string
&desc
,
796 int precision
, FormatFlags flags
,
797 result_t min_val
, result_t max_val
,
798 result_t underflow
, result_t overflow
,
799 const rvec_t
&vec
, int min
, int max
, int bucket_size
, int size
);
801 assert(size
== vec
.size());
803 result_t total
= 0.0;
804 result_t pdf
, cdf
= 0.0;
807 for (int i
= 0; i
< size
; ++i
)
811 pdf
= underflow
/ total
;
814 PrintOne(stream
, underflow
, name
+ NAMESEP
+ "underflow", desc
,
815 precision
, myflags
, pdf
, cdf
);
817 for (int i
= 0; i
< size
; ++i
) {
818 stringstream namestr
;
821 int low
= i
* bucket_size
+ min
;
822 int high
= ::std::min((i
+ 1) * bucket_size
+ min
- 1, max
);
825 namestr
<< "-" << high
;
827 pdf
= vec
[i
] / total
;
829 PrintOne(stream
, vec
[i
], namestr
.str(), desc
, precision
, myflags
,
833 pdf
= overflow
/ total
;
835 PrintOne(stream
, overflow
, name
+ NAMESEP
+ "overflow", desc
,
836 precision
, myflags
, pdf
, cdf
);
837 PrintOne(stream
, total
, name
+ NAMESEP
+ "total", desc
,
842 DistDisplay(ostream
&stream
, const string
&name
, const string
&desc
,
843 int precision
, FormatFlags flags
,
844 result_t min_val
, result_t max_val
,
845 result_t underflow
, result_t overflow
,
846 const rvec_t
&vec
, int min
, int max
, int bucket_size
, int size
)
848 assert(size
== vec
.size());
851 result_t total
= 0.0;
854 for (int i
= 0; i
< size
; ++i
)
858 ccprintf(stream
, "%-42s", name
+ ".start_dist");
859 if (PrintDescriptions
&& !desc
.empty())
860 ccprintf(stream
, " # %s", desc
);
863 PrintOne(stream
, total
, name
+ ".samples", blank
, precision
, flags
);
864 PrintOne(stream
, min_val
, name
+ ".min_value", blank
, precision
, flags
);
867 PrintOne(stream
, min_val
, name
+ ".underflows", blank
, precision
,
871 result_t _pdf
, _cdf
, mypdf
, mycdf
;
874 for (int i
= 0; i
< size
; ++i
) {
875 if (flags
& nozero
&& vec
[i
] == 0.0 ||
876 flags
& nonan
&& isnan(vec
[i
]))
879 _min
= i
* bucket_size
+ min
;
880 _pdf
= vec
[i
] / total
* 100.0;
883 mypdf
= (flags
& pdf
) ? _pdf
: NAN
;
884 mycdf
= (flags
& cdf
) ? _cdf
: NAN
;
886 PrintOne(stream
, vec
[i
], ValueToString(_min
, 0), blank
, precision
,
887 flags
| __substat
, mypdf
, mycdf
);
891 PrintOne(stream
, overflow
, name
+ ".overflows", blank
, precision
,
893 PrintOne(stream
, max_val
, name
+ ".max_value", blank
, precision
, flags
);
894 ccprintf(stream
, "%s.end_dist\n\n", name
);
899 * @todo get rid of the ugly hack **Ignore for total
902 FancyDisplay(ostream
&stream
, const string
&name
, const string
&desc
,
903 int precision
, FormatFlags flags
, result_t mean
,
904 result_t variance
, result_t total
)
906 result_t stdev
= isnan(variance
) ? NAN
: sqrt(variance
);
907 PrintOne(stream
, mean
, name
+ NAMESEP
+ "mean", desc
, precision
, flags
);
908 PrintOne(stream
, stdev
, name
+ NAMESEP
+ "stdev", desc
, precision
, flags
);
909 PrintOne(stream
, total
, "**Ignore: " + name
+ NAMESEP
+ "TOT", desc
, precision
, flags
);
913 : mem(NULL
), memsize(-1)
927 mem
= new char[memsize
];
928 memset(mem
, 0, memsize
);
935 GenBin::regBin(GenBin
*bin
, std::string name
)
937 Detail::StatDB().regBin(bin
, name
);
940 } // namespace Detail
945 Detail::StatDB().check();
949 dump(ostream
&stream
)
951 Detail::StatDB().dump(stream
);
954 CallbackQueue resetQueue
;
957 RegResetCallback(Callback
*cb
)
965 Detail::StatDB().reset();
966 resetQueue
.process();
969 } // namespace Statistics