2f52314b9e1695c08dc902c105bf403e770fd90a
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.
38 #include "base/callback.hh"
39 #include "base/cprintf.hh"
40 #include "base/intmath.hh"
41 #include "base/misc.hh"
42 #include "base/statistics.hh"
43 #include "base/str.hh"
44 #include "sim/universe.hh"
61 static int total_stats
= 0;
66 // This is a hack to get this parameter from the old stats package.
67 namespace Statistics
{
68 bool PrintDescriptions
= true;
72 * Struct to contain a name and description of statistic subfield.
83 * Struct to contain print data of a Stat.
96 /** True if the stat has been initialized. */
98 /** True if the stat should be printed. */
100 /** The name of the stat. */
102 /** Names and descriptions of subfields. */
103 vector
<SubData
> *subdata
;
104 /** The description of the stat. */
106 /** The display precision. */
108 /** The formatting flags. */
110 /** A pointer to a prerequisite Stat. */
115 : init(false), print(false), subdata(NULL
), precision(-1), flags(none
),
120 StatData::~StatData()
129 Database(const Database
&) {}
132 typedef list
<Stat
*> list_t
;
133 typedef map
<const Stat
*, StatData
*> map_t
;
143 void dump(ostream
&stream
);
145 StatData
*find(const Stat
*stat
);
148 void regStat(Stat
*stat
);
149 StatData
*print(Stat
*stat
);
155 Database::~Database()
159 Database::dump(ostream
&stream
)
161 list_t::iterator i
= printStats
.begin();
162 list_t::iterator end
= printStats
.end();
166 if (stat
->dodisplay())
167 stat
->display(stream
);
173 Database::find(const Stat
*stat
)
175 map_t::const_iterator i
= map
.find(stat
);
186 list_t::iterator i
= allStats
.begin();
187 list_t::iterator end
= allStats
.end();
191 StatData
*data
= find(stat
);
192 if (!data
|| !data
->init
) {
194 cprintf("this is stat number %d\n",(*i
)->number
);
196 panic("Not all stats have been initialized");
200 if (data
->name
.empty())
201 panic("all printable stats must be named");
203 list_t::iterator j
= printStats
.insert(printStats
.end(), *i
);
204 inplace_merge(printStats
.begin(), j
,
205 printStats
.end(), Stat::less
);
215 list_t::iterator i
= allStats
.begin();
216 list_t::iterator end
= allStats
.end();
225 Database::regStat(Stat
*stat
)
227 if (map
.find(stat
) != map
.end())
228 panic("shouldn't register stat twice!");
230 allStats
.push_back(stat
);
232 StatData
*data
= new StatData
;
233 bool success
= (map
.insert(make_pair(stat
, data
))).second
;
234 assert(map
.find(stat
) != map
.end());
235 assert(success
&& "this should never fail");
239 Stat::less(Stat
*stat1
, Stat
*stat2
)
241 const string
&name1
= stat1
->myname();
242 const string
&name2
= stat2
->myname();
247 tokenize(v1
, name1
, '.');
248 tokenize(v2
, name2
, '.');
250 int last
= min(v1
.size(), v2
.size()) - 1;
251 for (int i
= 0; i
< last
; ++i
)
253 return v1
[i
] < v2
[i
];
255 // Special compare for last element.
256 if (v1
[last
] == v2
[last
])
257 return v1
.size() < v2
.size();
259 return v1
[last
] < v2
[last
];
265 Database::print(Stat
*stat
)
267 StatData
*data
= find(stat
);
285 // This assert can help you find that pesky stat.
286 assert(this != (void *)0xbffff5c0);
290 StatDB().regStat(this);
292 number
= ++total_stats
;
293 cprintf("I'm stat number %d\n",number
);
299 { mydata()->init
= true; }
304 StatData
*data
= StatDB().find(this);
313 StatData
*data
= StatDB().find(this);
320 Stat::mysubdata(int index
) const
326 const StatData
*data
= this->mydata();
327 if (!data
->subdata
|| data
->subdata
->size() <= index
)
330 return &(*data
->subdata
)[index
];
334 Stat::mysubdata_create(int index
)
336 int size
= this->size();
337 assert(index
>= 0 && (size
== 0 || size
> 0 && index
< size
));
339 StatData
*data
= this->mydata();
340 if (!data
->subdata
) {
341 if (!data
->subdata
) {
345 data
->subdata
= new vector
<SubData
>(size
);
347 } else if (data
->subdata
->size() <= index
)
348 data
->subdata
->resize(index
+ 1);
350 SubData
*sd
= &(*data
->subdata
)[index
];
358 { return mydata()->name
; }
361 Stat::mysubname(int index
) const
363 const SubData
*sd
= mysubdata(index
);
364 return sd
? sd
->name
: "";
369 { return mydata()->desc
; }
372 Stat::mysubdesc(int index
) const
374 const SubData
*sd
= mysubdata(index
);
375 return sd
? sd
->desc
: "";
379 Stat::myprecision() const
380 { return mydata()->precision
; }
383 Stat::myflags() const
384 { return mydata()->flags
; }
387 Stat::dodisplay() const
388 { return !mydata()->prereq
|| !mydata()->prereq
->zero(); }
393 StatData
*data
= StatDB().print(this);
394 assert(data
&& data
->init
);
400 Stat::name(const string
&name
)
402 print()->name
= name
;
407 Stat::desc(const string
&desc
)
409 print()->desc
= desc
;
414 Stat::precision(int precision
)
416 print()->precision
= precision
;
421 Stat::flags(FormatFlags flags
)
423 if (flags
& __reserved
)
424 panic("Cannot set reserved flags!\n");
426 print()->flags
|= flags
;
431 Stat::prereq(const Stat
&prereq
)
433 print()->prereq
= &prereq
;
438 Stat::subname(int index
, const string
&name
)
441 mysubdata_create(index
)->name
= name
;
445 Stat::subdesc(int index
, const string
&desc
)
448 mysubdata_create(index
)->desc
= desc
;
453 ScalarStat::zero() const
459 VectorStat::zero() const
461 return val()[0] == 0.0;
465 ValueToString(result_t value
, int precision
)
471 val
.precision(precision
);
472 else if (value
== rint(value
))
475 val
.unsetf(ios::showpoint
);
476 val
.setf(ios::fixed
);
479 #ifndef STAT_DISPLAY_COMPAT
482 val
<< "<err: div-0>";
490 PrintOne(ostream
&stream
, result_t value
,
491 const string
&name
, const string
&desc
, int precision
,
492 FormatFlags flags
, result_t pdf
= NAN
, result_t cdf
= NAN
)
494 if (flags
& nozero
&& value
== 0.0 ||
495 flags
& nonan
&& isnan(value
))
498 stringstream pdfstr
, cdfstr
;
501 ccprintf(pdfstr
, "%.2f%%", pdf
* 100.0);
504 ccprintf(cdfstr
, "%.2f%%", cdf
* 100.0);
506 #ifdef STAT_DISPLAY_COMPAT
507 if (flags
& __substat
) {
508 ccprintf(stream
, "%32s%12s%10s%10s", name
,
509 ValueToString(value
, precision
),
514 ccprintf(stream
, "%-40s%12s%10s%10s", name
,
515 ValueToString(value
, precision
), pdfstr
, cdfstr
);
518 if (PrintDescriptions
) {
520 ccprintf(stream
, " # %s", desc
);
526 ScalarStat::display(ostream
&stream
) const
528 PrintOne(stream
, val(), myname(), mydesc(), myprecision(), myflags());
532 VectorStat::display(ostream
&stream
) const
534 bool have_subname
= false;
535 bool have_subdesc
= false;
536 int size
= this->size();
537 for (int i
= 0; i
< size
; ++i
) {
538 if (!mysubname(i
).empty())
540 if (!mysubdesc(i
).empty())
544 vector
<string
> *subnames
= 0;
545 vector
<string
> *subdescs
= 0;
547 subnames
= new vector
<string
>(size
);
548 for (int i
= 0; i
< size
; ++i
)
549 (*subnames
)[i
] = mysubname(i
);
552 subdescs
= new vector
<string
>(size
);
553 for (int i
= 0; i
< size
; ++i
)
554 (*subdescs
)[i
] = mysubdesc(i
);
557 VectorDisplay(stream
, myname(), subnames
, mydesc(), subdescs
,
558 myprecision(), myflags(), val(), total());
561 #ifndef STAT_DISPLAY_COMPAT
567 #ifndef STAT_DISPLAY_COMPAT
569 VectorDisplay(std::ostream
&stream
,
570 const std::string
&myname
,
571 const std::vector
<std::string
> *mysubnames
,
572 const std::string
&mydesc
,
573 const std::vector
<std::string
> *mysubdescs
,
574 int myprecision
, FormatFlags myflags
,
575 const rvec_t
&vec
, result_t mytotal
)
577 int _size
= vec
.size();
578 result_t _total
= 0.0;
579 result_t _pdf
, _cdf
= 0.0;
581 if (myflags
& (pdf
| cdf
)) {
582 for (int i
= 0; i
< _size
; ++i
) {
588 PrintOne(stream
, vec
[0], myname
, mydesc
, myprecision
, myflags
);
590 for (int i
= 0; i
< _size
; ++i
) {
593 subname
= (*mysubnames
)[i
];
597 subname
= to_string(i
);
600 string name
= myname
+ NAMESEP
+ subname
;
601 if (!(myflags
& pdf
))
602 PrintOne(stream
, vec
[i
], name
, mydesc
, myprecision
, myflags
);
604 _pdf
= vec
[i
] / _total
;
606 PrintOne(stream
, vec
[i
], name
, mydesc
, myprecision
, myflags
,
612 PrintOne(stream
, mytotal
, myname
+ NAMESEP
+ "total",
613 mydesc
, myprecision
, myflags
);
618 VectorDisplay(std::ostream
&stream
,
619 const std::string
&myname
,
620 const std::vector
<std::string
> *mysubnames
,
621 const std::string
&mydesc
,
622 const std::vector
<std::string
> *mysubdescs
,
623 int myprecision
, FormatFlags myflags
,
624 const rvec_t
&vec
, result_t mytotal
)
626 int _size
= vec
.size();
627 result_t _total
= 0.0;
628 result_t _pdf
, _cdf
= 0.0;
630 if (myflags
& (pdf
| cdf
)) {
631 for (int i
= 0; i
< _size
; ++i
) {
637 PrintOne(stream
, vec
[0], myname
, mydesc
, myprecision
, myflags
);
640 PrintOne(stream
, mytotal
, myname
, mydesc
, myprecision
, myflags
);
642 if (myflags
& dist
) {
643 ccprintf(stream
, "%s.start_dist\n", myname
);
644 for (int i
= 0; i
< _size
; ++i
) {
645 string subname
, subdesc
;
646 subname
= to_string(i
);
648 if (!subname
.empty()) {
649 subname
= (*mysubnames
)[i
];
653 subdesc
= (*mysubdescs
)[i
];
655 if (!(myflags
& (pdf
| cdf
))) {
656 PrintOne(stream
, vec
[i
], subname
, subdesc
, myprecision
,
657 myflags
| __substat
);
660 _pdf
= vec
[i
] / _total
;
665 if (!(myflags
& cdf
)) {
666 PrintOne(stream
, vec
[i
], subname
, subdesc
, myprecision
,
667 myflags
| __substat
, _pdf
);
669 PrintOne(stream
, vec
[i
], subname
, subdesc
, myprecision
,
670 myflags
| __substat
, _pdf
, _cdf
);
674 ccprintf(stream
, "%s.end_dist\n", myname
);
676 for (int i
= 0; i
< _size
; ++i
) {
679 subname
= (*mysubnames
)[i
];
683 subname
= to_string(i
);
686 string name
= myname
+ NAMESEP
+ subname
;
687 if (!(myflags
& pdf
)) {
688 PrintOne(stream
, vec
[i
], name
, mydesc
, myprecision
,
692 _pdf
= vec
[i
] / _total
;
697 _pdf
= vec
[i
] / _total
;
699 PrintOne(stream
, vec
[i
], name
, mydesc
, myprecision
,
700 myflags
, _pdf
, _cdf
);
708 #ifndef STAT_DISPLAY_COMPAT
710 DistDisplay(ostream
&stream
, const string
&name
, const string
&desc
,
711 int precision
, FormatFlags flags
,
712 result_t min_val
, result_t max_val
,
713 result_t underflow
, result_t overflow
,
714 const rvec_t
&vec
, int min
, int max
, int bucket_size
, int size
);
716 assert(size
== vec
.size());
718 result_t total
= 0.0;
719 result_t pdf
, cdf
= 0.0;
722 for (int i
= 0; i
< size
; ++i
)
726 pdf
= underflow
/ total
;
729 PrintOne(stream
, underflow
, name
+ NAMESEP
+ "underflow", desc
,
730 precision
, myflags
, pdf
, cdf
);
732 for (int i
= 0; i
< size
; ++i
) {
733 stringstream namestr
;
736 int low
= i
* bucket_size
+ min
;
737 int high
= ::std::min((i
+ 1) * bucket_size
+ min
- 1, max
);
740 namestr
<< "-" << high
;
742 pdf
= vec
[i
] / total
;
744 PrintOne(stream
, vec
[i
], namestr
.str(), desc
, precision
, myflags
,
748 pdf
= overflow
/ total
;
750 PrintOne(stream
, overflow
, name
+ NAMESEP
+ "overflow", desc
,
751 precision
, myflags
, pdf
, cdf
);
752 PrintOne(stream
, total
, name
+ NAMESEP
+ "total", desc
,
757 DistDisplay(ostream
&stream
, const string
&name
, const string
&desc
,
758 int precision
, FormatFlags flags
,
759 result_t min_val
, result_t max_val
,
760 result_t underflow
, result_t overflow
,
761 const rvec_t
&vec
, int min
, int max
, int bucket_size
, int size
)
763 assert(size
== vec
.size());
766 result_t total
= 0.0;
769 for (int i
= 0; i
< size
; ++i
)
773 ccprintf(stream
, "%-42s", name
+ ".start_dist");
774 if (PrintDescriptions
&& !desc
.empty())
775 ccprintf(stream
, " # %s", desc
);
778 PrintOne(stream
, total
, name
+ ".samples", blank
, precision
, flags
);
779 PrintOne(stream
, min_val
, name
+ ".min_value", blank
, precision
, flags
);
782 PrintOne(stream
, min_val
, name
+ ".underflows", blank
, precision
,
786 result_t _pdf
, _cdf
, mypdf
, mycdf
;
789 for (int i
= 0; i
< size
; ++i
) {
790 if (flags
& nozero
&& vec
[i
] == 0.0 ||
791 flags
& nonan
&& isnan(vec
[i
]))
794 _min
= i
* bucket_size
+ min
;
795 _pdf
= vec
[i
] / total
* 100.0;
798 mypdf
= (flags
& pdf
) ? _pdf
: NAN
;
799 mycdf
= (flags
& cdf
) ? _cdf
: NAN
;
801 PrintOne(stream
, vec
[i
], ValueToString(_min
, 0), blank
, precision
,
802 flags
| __substat
, mypdf
, mycdf
);
806 PrintOne(stream
, overflow
, name
+ ".overflows", blank
, precision
,
808 PrintOne(stream
, max_val
, name
+ ".max_value", blank
, precision
, flags
);
809 ccprintf(stream
, "%s.end_dist\n\n", name
);
814 FancyDisplay(ostream
&stream
, const string
&name
, const string
&desc
,
815 int precision
, FormatFlags flags
, result_t mean
,
818 result_t stdev
= isnan(variance
) ? NAN
: sqrt(variance
);
819 PrintOne(stream
, mean
, name
+ NAMESEP
+ "mean", desc
, precision
, flags
);
820 PrintOne(stream
, stdev
, name
+ NAMESEP
+ "stdev", desc
, precision
, flags
);
823 BinBase::BinBase(size_t size
)
824 : memsize(CeilPow2(size
)), mem(NULL
)
838 mem
= new char[memsize
];
839 memset(mem
, 0, memsize
);
845 } // namespace Detail
850 Detail::StatDB().check();
854 dump(ostream
&stream
)
856 Detail::StatDB().dump(stream
);
859 CallbackQueue resetQueue
;
862 regReset(Callback
*cb
)
870 Detail::StatDB().reset();
871 resetQueue
.process();
874 } // namespace Statistics