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;
66 DisplayMode default_mode
= mode_simplescalar
;
73 typedef list
<StatData
*> list_t
;
74 typedef map
<void *, StatData
*> map_t
;
77 map
<const MainBin
*, string
> bin_names
;
85 void dump(ostream
&stream
);
87 StatData
*find(void *stat
);
88 void mapStat(void *stat
, StatData
*data
);
92 void regBin(MainBin
*bin
, string name
);
93 void regPrint(void *stat
);
98 Data::dump(ostream
&stream
)
101 list_t::iterator i
= printStats
.begin();
102 list_t::iterator end
= printStats
.end();
106 binnedStats
.push_back(stat
);
111 list
<MainBin
*>::iterator j
= bins
.begin();
112 list
<MainBin
*>::iterator bins_end
=bins
.end();
115 ccprintf(stream
, "PRINTING BINNED STATS\n");
116 while (j
!= bins_end
) {
118 map
<const MainBin
*, string
>::const_iterator iter
;
119 iter
= bin_names
.find(*j
);
120 if (iter
== bin_names
.end())
121 panic("a binned stat not found in names map!");
122 ccprintf(stream
,"---%s Bin------------\n", (*iter
).second
);
125 list_t::iterator i
= printStats
.begin();
126 list_t::iterator end
= printStats
.end();
128 list_t::iterator i
= binnedStats
.begin();
129 list_t::iterator end
= binnedStats
.end();
133 if (stat
->dodisplay())
134 stat
->display(stream
);
138 ccprintf(stream
, "---------------------------------\n");
141 ccprintf(stream
, "**************ALL STATS************\n");
146 * get bin totals working, then print the stat here (as total), even if
147 * its' binned. (this is only for the case you selectively bin a few stats
150 list_t::iterator k
= printStats
.begin();
151 list_t::iterator endprint
= printStats
.end();
152 while (k
!= endprint
) {
154 if (stat
->dodisplay() /*&& !stat->binned()*/)
155 stat
->display(stream
);
162 Data::find(void *stat
)
164 map_t::const_iterator i
= statMap
.find(stat
);
166 if (i
== statMap
.end())
175 list_t::iterator i
= allStats
.begin();
176 list_t::iterator end
= allStats
.end();
189 list_t::iterator i
= allStats
.begin();
190 list_t::iterator end
= allStats
.end();
197 MainBin
*orig
= MainBin::curBin();
199 list
<MainBin
*>::iterator bi
= bins
.begin();
200 list
<MainBin
*>::iterator be
= bins
.end();
205 i
= allStats
.begin();
219 Data::mapStat(void *stat
, StatData
*data
)
221 if (statMap
.find(stat
) != statMap
.end())
222 panic("shouldn't register stat twice!");
224 allStats
.push_back(data
);
226 bool success
= (statMap
.insert(make_pair(stat
, data
))).second
;
227 assert(statMap
.find(stat
) != statMap
.end());
228 assert(success
&& "this should never fail");
232 Data::regBin(MainBin
*bin
, string name
)
234 if (bin_names
.find(bin
) != bin_names
.end())
235 panic("shouldn't register bin twice");
239 bool success
= (bin_names
.insert(make_pair(bin
,name
))).second
;
240 assert(bin_names
.find(bin
) != bin_names
.end());
241 assert(success
&& "this should not fail");
243 cprintf("registering %s\n", name
);
247 Data::regPrint(void *stat
)
249 StatData
*data
= find(stat
);
254 list_t::iterator j
= printStats
.insert(printStats
.end(), data
);
255 inplace_merge(printStats
.begin(), j
,
256 printStats
.end(), StatData::less
);
271 DataAccess::find() const
273 return Database::StatDB().find(const_cast<void *>((const void *)this));
277 DataAccess::map(StatData
*data
)
279 Database::StatDB().mapStat(this, data
);
283 DataAccess::statData()
285 StatData
*ptr
= find();
291 DataAccess::statData() const
293 const StatData
*ptr
= find();
299 DataAccess::setInit()
301 statData()->init
= true;
305 DataAccess::setPrint()
307 Database::StatDB().regPrint(this);
310 StatData::~StatData()
315 StatData::less(StatData
*stat1
, StatData
*stat2
)
317 const string
&name1
= stat1
->name
;
318 const string
&name2
= stat2
->name
;
323 tokenize(v1
, name1
, '.');
324 tokenize(v2
, name2
, '.');
326 int last
= min(v1
.size(), v2
.size()) - 1;
327 for (int i
= 0; i
< last
; ++i
)
329 return v1
[i
] < v2
[i
];
331 // Special compare for last element.
332 if (v1
[last
] == v2
[last
])
333 return v1
.size() < v2
.size();
335 return v1
[last
] < v2
[last
];
341 StatData::check() const
345 cprintf("this is stat number %d\n",(*i
)->number
);
347 panic("Not all stats have been initialized");
351 if (print
&& name
.empty()) {
352 panic("all printable stats must be named");
360 ValueToString(result_t value
, DisplayMode mode
, int precision
)
366 val
.precision(precision
);
367 else if (value
== rint(value
))
370 val
.unsetf(ios::showpoint
);
371 val
.setf(ios::fixed
);
374 val
<< (mode
== mode_m5
? "no value" : "<err: div-0>");
392 : value(0.0), precision(0), mode(default_mode
), flags(0),
396 void operator()(ostream
&stream
) const;
400 ScalarPrint::operator()(ostream
&stream
) const
402 if (flags
& nozero
&& value
== 0.0 ||
403 flags
& nonan
&& isnan(value
))
406 stringstream pdfstr
, cdfstr
;
409 ccprintf(pdfstr
, "%.2f%%", pdf
* 100.0);
412 ccprintf(cdfstr
, "%.2f%%", cdf
* 100.0);
414 if (mode
== mode_simplescalar
&& flags
& __substat
) {
415 ccprintf(stream
, "%32s %12s %10s %10s", name
,
416 ValueToString(value
, mode
, precision
),
419 ccprintf(stream
, "%-40s %12s %10s %10s", name
,
420 ValueToString(value
, mode
, precision
), pdfstr
, cdfstr
);
423 if (PrintDescriptions
) {
425 ccprintf(stream
, " # %s", desc
);
434 vector
<string
> subnames
;
435 vector
<string
> subdescs
;
443 : subnames(0), subdescs(0), precision(-1), mode(default_mode
),
447 void operator()(ostream
&stream
) const;
451 VectorPrint::operator()(std::ostream
&stream
) const
453 int _size
= vec
.size();
454 result_t _total
= 0.0;
456 if (flags
& (pdf
| cdf
)) {
457 for (int i
= 0; i
< _size
; ++i
) {
462 string base
= name
+ ((mode
== mode_simplescalar
) ? "_" : "::");
467 print
.precision
= precision
;
470 bool havesub
= !subnames
.empty();
473 print
.value
= vec
[0];
475 } else if (mode
== mode_m5
) {
476 for (int i
= 0; i
< _size
; ++i
) {
477 if (havesub
&& (i
>= subnames
.size() || subnames
[i
].empty()))
480 print
.name
= base
+ (havesub
? subnames
[i
] : to_string(i
));
481 print
.desc
= subdescs
.empty() ? desc
: subdescs
[i
];
482 print
.value
= vec
[i
];
484 if (_total
&& (flags
& pdf
)) {
485 print
.pdf
= vec
[i
] / _total
;
486 print
.cdf
+= print
.pdf
;
492 if (flags
& ::Statistics::total
) {
493 print
.name
= base
+ "total";
499 if (flags
& ::Statistics::total
) {
507 ccprintf(stream
, "%s.start_dist\n", name
);
508 for (int i
= 0; i
< _size
; ++i
) {
509 print
.name
= havesub
? subnames
[i
] : to_string(i
);
510 print
.desc
= subdescs
.empty() ? desc
: subdescs
[i
];
511 print
.flags
|= __substat
;
512 print
.value
= vec
[i
];
515 _pdf
= vec
[i
] / _total
;
526 ccprintf(stream
, "%s.end_dist\n", name
);
528 for (int i
= 0; i
< _size
; ++i
) {
529 if (havesub
&& subnames
[i
].empty())
533 print
.name
+= havesub
? subnames
[i
] : to_string(i
);
534 print
.desc
= subdescs
.empty() ? desc
: subdescs
[i
];
535 print
.value
= vec
[i
];
538 _pdf
= vec
[i
] / _total
;
578 void operator()(ostream
&stream
) const;
582 DistPrint::operator()(ostream
&stream
) const
586 string base
= name
+ ((mode
== mode_m5
) ? "::" : "_");
588 print
.precision
= precision
;
592 print
.name
= base
+ "mean";
593 print
.value
= samples
? sum
/ samples
: NAN
;
596 print
.name
= base
+ "stdev";
597 print
.value
= samples
? sqrt((samples
* squares
- sum
* sum
) /
598 (samples
* (samples
- 1.0))) : NAN
;
601 print
.name
= "**Ignore: " + base
+ "TOT";
602 print
.value
= samples
;
607 assert(size
== vec
.size());
609 result_t total
= 0.0;
612 for (int i
= 0; i
< size
; ++i
)
616 string base
= name
+ (mode
== mode_m5
? "::" : ".");
619 print
.desc
= (mode
== mode_m5
) ? desc
: "";
620 print
.precision
= precision
;
624 if (mode
== mode_simplescalar
) {
625 ccprintf(stream
, "%-42s", base
+ "start_dist");
626 if (PrintDescriptions
&& !desc
.empty())
627 ccprintf(stream
, " # %s", desc
);
631 print
.name
= base
+ "samples";
632 print
.value
= samples
;
635 print
.name
= base
+ "min_value";
636 print
.value
= min_val
;
639 if (mode
== mode_m5
|| underflow
> 0.0) {
640 print
.name
= base
+ "underflows";
641 print
.value
= underflow
;
642 if (mode
== mode_m5
&& total
) {
643 print
.pdf
= underflow
/ total
;
644 print
.cdf
+= print
.pdf
;
650 if (mode
== mode_m5
) {
651 for (int i
= 0; i
< size
; ++i
) {
652 stringstream namestr
;
655 int low
= i
* bucket_size
+ min
;
656 int high
= ::min((i
+ 1) * bucket_size
+ min
- 1, max
);
659 namestr
<< "-" << high
;
661 print
.name
= namestr
.str();
662 print
.value
= vec
[i
];
664 print
.pdf
= vec
[i
] / total
;
665 print
.cdf
+= print
.pdf
;
675 print
.flags
= flags
| __substat
;
677 for (int i
= 0; i
< size
; ++i
) {
678 if (flags
& nozero
&& vec
[i
] == 0.0 ||
679 flags
& nonan
&& isnan(vec
[i
]))
682 _min
= i
* bucket_size
+ min
;
683 _pdf
= vec
[i
] / total
* 100.0;
687 print
.name
= ValueToString(_min
, mode
, 0);
688 print
.value
= vec
[i
];
689 print
.pdf
= (flags
& pdf
) ? _pdf
: NAN
;
690 print
.cdf
= (flags
& cdf
) ? _cdf
: NAN
;
695 if (flags
& (pdf
|| cdf
)) {
701 if (mode
== mode_m5
|| overflow
> 0.0) {
702 print
.name
= base
+ "overflows";
703 print
.value
= overflow
;
704 if (mode
== mode_m5
&& total
) {
705 print
.pdf
= overflow
/ total
;
706 print
.cdf
+= print
.pdf
;
714 if (mode
!= mode_simplescalar
) {
715 print
.name
= base
+ "total";
720 print
.name
= base
+ "max_value";
721 print
.value
= max_val
;
724 if (mode
!= mode_simplescalar
&& samples
!= 0) {
725 print
.name
= base
+ "mean";
726 print
.value
= sum
/ samples
;
729 print
.name
= base
+ "stdev";
730 print
.value
= sqrt((samples
* squares
- sum
* sum
) /
731 (samples
* (samples
- 1.0)));
735 if (mode
== mode_simplescalar
)
736 ccprintf(stream
, "%send_dist\n\n", base
);
740 ScalarDataBase::display(ostream
&stream
) const
746 print
.precision
= precision
;
753 VectorDataBase::display(ostream
&stream
) const
755 int size
= this->size();
756 const_cast<VectorDataBase
*>(this)->update();
764 print
.precision
= precision
;
766 print
.total
= total();
768 for (int i
= 0; i
< size
; ++i
) {
769 if (!subnames
[i
].empty()) {
770 print
.subnames
= subnames
;
771 print
.subnames
.resize(size
);
772 for (int i
= 0; i
< size
; ++i
) {
773 if (!subnames
[i
].empty() && !subdescs
[i
].empty()) {
774 print
.subdescs
= subdescs
;
775 print
.subdescs
.resize(size
);
788 Vector2dDataBase::display(ostream
&stream
) const
790 const_cast<Vector2dDataBase
*>(this)->update();
792 bool havesub
= false;
795 print
.subnames
= y_subnames
;
798 print
.precision
= precision
;
800 if (!subnames
.empty()) {
801 for (int i
= 0; i
< x
; ++i
)
802 if (!subnames
[i
].empty())
807 result_t super_total
= 0.0;
808 for (int i
= 0; i
< x
; ++i
) {
809 if (havesub
&& (i
>= subnames
.size() || subnames
[i
].empty()))
815 result_t total
= 0.0;
816 for (int j
= 0; j
< y
; ++j
) {
817 yvec
[j
] = vec
[iy
+ j
];
818 tot_vec
[j
] += yvec
[j
];
820 super_total
+= yvec
[j
];
823 print
.name
= name
+ "_" + (havesub
? subnames
[i
] : to_string(i
));
830 if ((flags
& ::Statistics::total
) && (x
> 1)) {
834 print
.total
= super_total
;
840 DistDataBase::display(ostream
&stream
) const
842 const_cast<DistDataBase
*>(this)->update();
848 print
.precision
= precision
;
852 print
.min_val
= data
.min_val
;
853 print
.max_val
= data
.max_val
;
854 print
.underflow
= data
.underflow
;
855 print
.overflow
= data
.overflow
;
856 print
.vec
= data
.vec
;
857 print
.sum
= data
.sum
;
858 print
.squares
= data
.squares
;
859 print
.samples
= data
.samples
;
861 print
.min
= data
.min
;
862 print
.max
= data
.max
;
863 print
.bucket_size
= data
.bucket_size
;
864 print
.size
= data
.size
;
865 print
.fancy
= data
.fancy
;
871 VectorDistDataBase::display(ostream
&stream
) const
873 const_cast<VectorDistDataBase
*>(this)->update();
875 for (int i
= 0; i
< size(); ++i
) {
879 (subnames
[i
].empty() ? ("_" + to_string(i
)) : subnames
[i
]);
880 print
.desc
= subdescs
[i
].empty() ? desc
: subdescs
[i
];
881 print
.precision
= precision
;
885 print
.min_val
= data
[i
].min_val
;
886 print
.max_val
= data
[i
].max_val
;
887 print
.underflow
= data
[i
].underflow
;
888 print
.overflow
= data
[i
].overflow
;
889 print
.vec
= data
[i
].vec
;
890 print
.sum
= data
[i
].sum
;
891 print
.squares
= data
[i
].squares
;
892 print
.samples
= data
[i
].samples
;
894 print
.min
= data
[i
].min
;
895 print
.max
= data
[i
].max
;
896 print
.bucket_size
= data
[i
].bucket_size
;
897 print
.size
= data
[i
].size
;
898 print
.fancy
= data
[i
].fancy
;
905 FormulaBase::val(rvec_t
&vec
) const
911 FormulaBase::total() const
913 return root
->total();
917 FormulaBase::size() const
926 FormulaBase::binned() const
928 return root
->binned();
937 FormulaBase::zero() const
941 for (int i
= 0; i
< vec
.size(); ++i
)
948 FormulaBase::update(StatData
*)
957 Formula::Formula(Temp r
)
964 Formula::operator=(Temp r
)
966 assert(!root
&& "Can't change formulas");
973 Formula::operator+=(Temp r
)
976 root
= NodePtr(new BinaryNode
<std::plus
<result_t
> >(root
, r
));
983 MainBin::MainBin(const string
&name
)
984 : _name(name
), mem(NULL
), memsize(-1)
986 Database::StatDB().regBin(this, name
);
996 MainBin::memory(off_t off
)
999 memsize
= CeilPow2((size_t) offset());
1002 mem
= new char[memsize
];
1003 memset(mem
, 0, memsize
);
1006 assert(offset() <= size());
1013 Database::StatDB().check();
1017 dump(ostream
&stream
)
1019 Database::StatDB().dump(stream
);
1022 CallbackQueue resetQueue
;
1025 RegResetCallback(Callback
*cb
)
1033 Database::StatDB().reset();
1034 resetQueue
.process();
1037 } // namespace Statistics