statistics.cc revision 388
110391SAndreas.Sandberg@ARM.com/* 212187Sanouk.vanlaer@arm.com * Copyright (c) 2003 The Regents of The University of Michigan 310391SAndreas.Sandberg@ARM.com * All rights reserved. 410391SAndreas.Sandberg@ARM.com * 510391SAndreas.Sandberg@ARM.com * Redistribution and use in source and binary forms, with or without 610391SAndreas.Sandberg@ARM.com * modification, are permitted provided that the following conditions are 710391SAndreas.Sandberg@ARM.com * met: redistributions of source code must retain the above copyright 810391SAndreas.Sandberg@ARM.com * notice, this list of conditions and the following disclaimer; 910391SAndreas.Sandberg@ARM.com * redistributions in binary form must reproduce the above copyright 1010391SAndreas.Sandberg@ARM.com * notice, this list of conditions and the following disclaimer in the 1110391SAndreas.Sandberg@ARM.com * documentation and/or other materials provided with the distribution; 1210391SAndreas.Sandberg@ARM.com * neither the name of the copyright holders nor the names of its 1310391SAndreas.Sandberg@ARM.com * contributors may be used to endorse or promote products derived from 1410391SAndreas.Sandberg@ARM.com * this software without specific prior written permission. 1510391SAndreas.Sandberg@ARM.com * 1610391SAndreas.Sandberg@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1710391SAndreas.Sandberg@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1810391SAndreas.Sandberg@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1910391SAndreas.Sandberg@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2010391SAndreas.Sandberg@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2110391SAndreas.Sandberg@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2210391SAndreas.Sandberg@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2310391SAndreas.Sandberg@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2410391SAndreas.Sandberg@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2510391SAndreas.Sandberg@ARM.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2610391SAndreas.Sandberg@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2710391SAndreas.Sandberg@ARM.com */ 2810391SAndreas.Sandberg@ARM.com 2910391SAndreas.Sandberg@ARM.com#include <iomanip> 3010391SAndreas.Sandberg@ARM.com#include <iostream> 3110391SAndreas.Sandberg@ARM.com#include <list> 3210391SAndreas.Sandberg@ARM.com#include <map> 3310391SAndreas.Sandberg@ARM.com#include <string> 3410391SAndreas.Sandberg@ARM.com#include <sstream> 3510391SAndreas.Sandberg@ARM.com 3610391SAndreas.Sandberg@ARM.com#include "base/callback.hh" 3710391SAndreas.Sandberg@ARM.com#include "base/cprintf.hh" 3810391SAndreas.Sandberg@ARM.com#include "base/misc.hh" 3910391SAndreas.Sandberg@ARM.com#include "base/statistics.hh" 4010391SAndreas.Sandberg@ARM.com#include "base/str.hh" 4110391SAndreas.Sandberg@ARM.com#include "sim/universe.hh" 4210391SAndreas.Sandberg@ARM.com 4310391SAndreas.Sandberg@ARM.com#ifdef __M5_NAN 4410391SAndreas.Sandberg@ARM.comfloat 4510391SAndreas.Sandberg@ARM.com__nan() 4610391SAndreas.Sandberg@ARM.com{ 4710391SAndreas.Sandberg@ARM.com union { 4810391SAndreas.Sandberg@ARM.com uint32_t ui; 4910391SAndreas.Sandberg@ARM.com float f; 5010391SAndreas.Sandberg@ARM.com } nan; 5110391SAndreas.Sandberg@ARM.com 5210391SAndreas.Sandberg@ARM.com nan.ui = 0x7fc00000; 5310391SAndreas.Sandberg@ARM.com return nan.f; 5410391SAndreas.Sandberg@ARM.com} 5510391SAndreas.Sandberg@ARM.com#endif 5610391SAndreas.Sandberg@ARM.com 5710391SAndreas.Sandberg@ARM.com#ifdef STAT_DEBUG 5810391SAndreas.Sandberg@ARM.comstatic int total_stats = 0; 5910391SAndreas.Sandberg@ARM.com#endif 6010391SAndreas.Sandberg@ARM.com 6110391SAndreas.Sandberg@ARM.comusing namespace std; 6210391SAndreas.Sandberg@ARM.com 6310391SAndreas.Sandberg@ARM.com// This is a hack to get this parameter from the old stats package. 6410391SAndreas.Sandberg@ARM.comnamespace Statistics { 6510391SAndreas.Sandberg@ARM.combool PrintDescriptions = true; 6610391SAndreas.Sandberg@ARM.comDisplayMode default_mode = mode_simplescalar; 6710391SAndreas.Sandberg@ARM.com 6810391SAndreas.Sandberg@ARM.comnamespace Database 6910391SAndreas.Sandberg@ARM.com{ 7010391SAndreas.Sandberg@ARM.com class Data 7110391SAndreas.Sandberg@ARM.com { 7210391SAndreas.Sandberg@ARM.com private: 7310391SAndreas.Sandberg@ARM.com typedef list<StatData *> list_t; 7410391SAndreas.Sandberg@ARM.com typedef map<void *, StatData *> map_t; 7510391SAndreas.Sandberg@ARM.com 7610391SAndreas.Sandberg@ARM.com list<MainBin *> bins; 7710391SAndreas.Sandberg@ARM.com map<const MainBin *, string > bin_names; 7810391SAndreas.Sandberg@ARM.com list_t binnedStats; 7910391SAndreas.Sandberg@ARM.com 8010391SAndreas.Sandberg@ARM.com list_t allStats; 8110391SAndreas.Sandberg@ARM.com list_t printStats; 8210391SAndreas.Sandberg@ARM.com map_t statMap; 8310391SAndreas.Sandberg@ARM.com 8410391SAndreas.Sandberg@ARM.com public: 8510391SAndreas.Sandberg@ARM.com void dump(ostream &stream); 8610391SAndreas.Sandberg@ARM.com 8710391SAndreas.Sandberg@ARM.com StatData *find(void *stat); 8810391SAndreas.Sandberg@ARM.com void mapStat(void *stat, StatData *data); 8910391SAndreas.Sandberg@ARM.com 9010391SAndreas.Sandberg@ARM.com void check(); 9110391SAndreas.Sandberg@ARM.com void reset(); 9210391SAndreas.Sandberg@ARM.com void regBin(MainBin *bin, string name); 9310391SAndreas.Sandberg@ARM.com void regPrint(void *stat); 9410391SAndreas.Sandberg@ARM.com }; 9510391SAndreas.Sandberg@ARM.com 9610391SAndreas.Sandberg@ARM.com 9710391SAndreas.Sandberg@ARM.comvoid 9810391SAndreas.Sandberg@ARM.comData::dump(ostream &stream) 9910391SAndreas.Sandberg@ARM.com{ 10010391SAndreas.Sandberg@ARM.com#ifndef FS_MEASURE 10110391SAndreas.Sandberg@ARM.com list_t::iterator i = printStats.begin(); 10210391SAndreas.Sandberg@ARM.com list_t::iterator end = printStats.end(); 10310391SAndreas.Sandberg@ARM.com while (i != end) { 10410391SAndreas.Sandberg@ARM.com StatData *stat = *i; 10510391SAndreas.Sandberg@ARM.com if (stat->binned()) 10610391SAndreas.Sandberg@ARM.com binnedStats.push_back(stat); 10710391SAndreas.Sandberg@ARM.com ++i; 10810391SAndreas.Sandberg@ARM.com } 10910391SAndreas.Sandberg@ARM.com#endif //FS_MEASURE 11010391SAndreas.Sandberg@ARM.com 11110391SAndreas.Sandberg@ARM.com list<MainBin *>::iterator j = bins.begin(); 11210391SAndreas.Sandberg@ARM.com list<MainBin *>::iterator bins_end=bins.end(); 11310391SAndreas.Sandberg@ARM.com 11410391SAndreas.Sandberg@ARM.com if (!bins.empty()) { 11510391SAndreas.Sandberg@ARM.com ccprintf(stream, "PRINTING BINNED STATS\n"); 11610391SAndreas.Sandberg@ARM.com while (j != bins_end) { 11710391SAndreas.Sandberg@ARM.com (*j)->activate(); 11810391SAndreas.Sandberg@ARM.com map<const MainBin *, string>::const_iterator iter; 11910391SAndreas.Sandberg@ARM.com iter = bin_names.find(*j); 12010391SAndreas.Sandberg@ARM.com if (iter == bin_names.end()) 12110391SAndreas.Sandberg@ARM.com panic("a binned stat not found in names map!"); 12210391SAndreas.Sandberg@ARM.com ccprintf(stream,"---%s Bin------------\n", (*iter).second); 12310391SAndreas.Sandberg@ARM.com 12410391SAndreas.Sandberg@ARM.com#ifdef FS_MEASURE 12510391SAndreas.Sandberg@ARM.com list_t::iterator i = printStats.begin(); 12610391SAndreas.Sandberg@ARM.com list_t::iterator end = printStats.end(); 12710391SAndreas.Sandberg@ARM.com#else 12810391SAndreas.Sandberg@ARM.com list_t::iterator i = binnedStats.begin(); 12910391SAndreas.Sandberg@ARM.com list_t::iterator end = binnedStats.end(); 13010391SAndreas.Sandberg@ARM.com#endif 13110391SAndreas.Sandberg@ARM.com while (i != end) { 13210391SAndreas.Sandberg@ARM.com StatData *stat = *i; 13310391SAndreas.Sandberg@ARM.com if (stat->dodisplay()) 13410391SAndreas.Sandberg@ARM.com stat->display(stream); 13510391SAndreas.Sandberg@ARM.com ++i; 13610391SAndreas.Sandberg@ARM.com } 13710391SAndreas.Sandberg@ARM.com ++j; 13810391SAndreas.Sandberg@ARM.com ccprintf(stream, "---------------------------------\n"); 13910391SAndreas.Sandberg@ARM.com } 14010391SAndreas.Sandberg@ARM.com#ifndef FS_MEASURE 14110391SAndreas.Sandberg@ARM.com ccprintf(stream, "**************ALL STATS************\n"); 14210391SAndreas.Sandberg@ARM.com#endif 14310391SAndreas.Sandberg@ARM.com } 14410391SAndreas.Sandberg@ARM.com 14510391SAndreas.Sandberg@ARM.com/** 14610391SAndreas.Sandberg@ARM.com * get bin totals working, then print the stat here (as total), even if 14710391SAndreas.Sandberg@ARM.com * its' binned. (this is only for the case you selectively bin a few stats 14810391SAndreas.Sandberg@ARM.com */ 14910391SAndreas.Sandberg@ARM.com#ifndef FS_MEASURE 15010391SAndreas.Sandberg@ARM.com list_t::iterator k = printStats.begin(); 15110391SAndreas.Sandberg@ARM.com list_t::iterator endprint = printStats.end(); 15210391SAndreas.Sandberg@ARM.com while (k != endprint) { 15310391SAndreas.Sandberg@ARM.com StatData *stat = *k; 15410391SAndreas.Sandberg@ARM.com if (stat->dodisplay() /*&& !stat->binned()*/) 15510391SAndreas.Sandberg@ARM.com stat->display(stream); 15610391SAndreas.Sandberg@ARM.com ++k; 15710391SAndreas.Sandberg@ARM.com } 15810391SAndreas.Sandberg@ARM.com#endif 15910391SAndreas.Sandberg@ARM.com} 16010391SAndreas.Sandberg@ARM.com 16110391SAndreas.Sandberg@ARM.comStatData * 16210391SAndreas.Sandberg@ARM.comData::find(void *stat) 16310391SAndreas.Sandberg@ARM.com{ 16410391SAndreas.Sandberg@ARM.com map_t::const_iterator i = statMap.find(stat); 16510391SAndreas.Sandberg@ARM.com 16610391SAndreas.Sandberg@ARM.com if (i == statMap.end()) 16710391SAndreas.Sandberg@ARM.com return NULL; 16810391SAndreas.Sandberg@ARM.com 16910391SAndreas.Sandberg@ARM.com return (*i).second; 17010391SAndreas.Sandberg@ARM.com} 17110391SAndreas.Sandberg@ARM.com 17210391SAndreas.Sandberg@ARM.comvoid 17310391SAndreas.Sandberg@ARM.comData::check() 17410391SAndreas.Sandberg@ARM.com{ 17510391SAndreas.Sandberg@ARM.com list_t::iterator i = allStats.begin(); 17610391SAndreas.Sandberg@ARM.com list_t::iterator end = allStats.end(); 17710391SAndreas.Sandberg@ARM.com 17810391SAndreas.Sandberg@ARM.com while (i != end) { 17910391SAndreas.Sandberg@ARM.com StatData *stat = *i; 18010391SAndreas.Sandberg@ARM.com assert(stat); 18110391SAndreas.Sandberg@ARM.com stat->check(); 18210391SAndreas.Sandberg@ARM.com ++i; 18310391SAndreas.Sandberg@ARM.com } 18410391SAndreas.Sandberg@ARM.com} 18510391SAndreas.Sandberg@ARM.com 18610391SAndreas.Sandberg@ARM.comvoid 18710391SAndreas.Sandberg@ARM.comData::reset() 18810391SAndreas.Sandberg@ARM.com{ 18910391SAndreas.Sandberg@ARM.com list_t::iterator i = allStats.begin(); 19010391SAndreas.Sandberg@ARM.com list_t::iterator end = allStats.end(); 19110391SAndreas.Sandberg@ARM.com while (i != end) { 19210391SAndreas.Sandberg@ARM.com StatData *stat = *i; 19310391SAndreas.Sandberg@ARM.com stat->reset(); 19410391SAndreas.Sandberg@ARM.com ++i; 19510391SAndreas.Sandberg@ARM.com } 19610391SAndreas.Sandberg@ARM.com 19710391SAndreas.Sandberg@ARM.com MainBin *orig = MainBin::curBin(); 19810391SAndreas.Sandberg@ARM.com 19910391SAndreas.Sandberg@ARM.com list<MainBin *>::iterator bi = bins.begin(); 20010391SAndreas.Sandberg@ARM.com list<MainBin *>::iterator be = bins.end(); 20110391SAndreas.Sandberg@ARM.com while (bi != be) { 20210391SAndreas.Sandberg@ARM.com MainBin *bin = *bi; 20310391SAndreas.Sandberg@ARM.com bin->activate(); 20410391SAndreas.Sandberg@ARM.com 20510391SAndreas.Sandberg@ARM.com i = allStats.begin(); 20610391SAndreas.Sandberg@ARM.com while (i != end) { 20710391SAndreas.Sandberg@ARM.com StatData *stat = *i; 20810391SAndreas.Sandberg@ARM.com stat->reset(); 20910391SAndreas.Sandberg@ARM.com ++i; 21010391SAndreas.Sandberg@ARM.com } 21110391SAndreas.Sandberg@ARM.com ++bi; 21210391SAndreas.Sandberg@ARM.com } 21310391SAndreas.Sandberg@ARM.com 21410391SAndreas.Sandberg@ARM.com if (orig) 21510391SAndreas.Sandberg@ARM.com orig->activate(); 21610391SAndreas.Sandberg@ARM.com} 21710391SAndreas.Sandberg@ARM.com 21810391SAndreas.Sandberg@ARM.comvoid 21911168Sandreas.hansson@arm.comData::mapStat(void *stat, StatData *data) 22011168Sandreas.hansson@arm.com{ 22110391SAndreas.Sandberg@ARM.com if (statMap.find(stat) != statMap.end()) 22210391SAndreas.Sandberg@ARM.com panic("shouldn't register stat twice!"); 22311169Sandreas.hansson@arm.com 22411169Sandreas.hansson@arm.com allStats.push_back(data); 22510391SAndreas.Sandberg@ARM.com 22610391SAndreas.Sandberg@ARM.com bool success = (statMap.insert(make_pair(stat, data))).second; 22710391SAndreas.Sandberg@ARM.com assert(statMap.find(stat) != statMap.end()); 22810391SAndreas.Sandberg@ARM.com assert(success && "this should never fail"); 22910391SAndreas.Sandberg@ARM.com} 23010391SAndreas.Sandberg@ARM.com 23110391SAndreas.Sandberg@ARM.comvoid 23210391SAndreas.Sandberg@ARM.comData::regBin(MainBin *bin, string name) 23310391SAndreas.Sandberg@ARM.com{ 23410391SAndreas.Sandberg@ARM.com if (bin_names.find(bin) != bin_names.end()) 23510391SAndreas.Sandberg@ARM.com panic("shouldn't register bin twice"); 23610391SAndreas.Sandberg@ARM.com 23710391SAndreas.Sandberg@ARM.com bins.push_back(bin); 23810391SAndreas.Sandberg@ARM.com 23910391SAndreas.Sandberg@ARM.com bool success = (bin_names.insert(make_pair(bin,name))).second; 24010391SAndreas.Sandberg@ARM.com assert(bin_names.find(bin) != bin_names.end()); 24110391SAndreas.Sandberg@ARM.com assert(success && "this should not fail"); 24210391SAndreas.Sandberg@ARM.com 24310391SAndreas.Sandberg@ARM.com cprintf("registering %s\n", name); 24410391SAndreas.Sandberg@ARM.com} 24510391SAndreas.Sandberg@ARM.com 24610391SAndreas.Sandberg@ARM.comvoid 24710391SAndreas.Sandberg@ARM.comData::regPrint(void *stat) 24810391SAndreas.Sandberg@ARM.com{ 24910391SAndreas.Sandberg@ARM.com StatData *data = find(stat); 25010391SAndreas.Sandberg@ARM.com 25110391SAndreas.Sandberg@ARM.com if (!data->print) { 25210391SAndreas.Sandberg@ARM.com data->print = true; 25310391SAndreas.Sandberg@ARM.com 25410391SAndreas.Sandberg@ARM.com list_t::iterator j = printStats.insert(printStats.end(), data); 25510391SAndreas.Sandberg@ARM.com inplace_merge(printStats.begin(), j, 25610391SAndreas.Sandberg@ARM.com printStats.end(), StatData::less); 25710391SAndreas.Sandberg@ARM.com } 25810391SAndreas.Sandberg@ARM.com 25910391SAndreas.Sandberg@ARM.com} 26010391SAndreas.Sandberg@ARM.com 26110391SAndreas.Sandberg@ARM.comData & 26210391SAndreas.Sandberg@ARM.comStatDB() 26310391SAndreas.Sandberg@ARM.com{ 26410391SAndreas.Sandberg@ARM.com static Data db; 26510391SAndreas.Sandberg@ARM.com return db; 26610391SAndreas.Sandberg@ARM.com} 26710391SAndreas.Sandberg@ARM.com 26810391SAndreas.Sandberg@ARM.com} 26910391SAndreas.Sandberg@ARM.com 27010391SAndreas.Sandberg@ARM.comStatData * 27110391SAndreas.Sandberg@ARM.comDataAccess::find() const 27211204Ssascha.bischoff@ARM.com{ 27311204Ssascha.bischoff@ARM.com return Database::StatDB().find(const_cast<void *>((const void *)this)); 27411204Ssascha.bischoff@ARM.com} 27511204Ssascha.bischoff@ARM.com 27611204Ssascha.bischoff@ARM.comvoid 27711204Ssascha.bischoff@ARM.comDataAccess::map(StatData *data) 27811204Ssascha.bischoff@ARM.com{ 27911204Ssascha.bischoff@ARM.com Database::StatDB().mapStat(this, data); 28011204Ssascha.bischoff@ARM.com} 28111204Ssascha.bischoff@ARM.com 28211204Ssascha.bischoff@ARM.comStatData * 28310391SAndreas.Sandberg@ARM.comDataAccess::statData() 28410391SAndreas.Sandberg@ARM.com{ 28510391SAndreas.Sandberg@ARM.com StatData *ptr = find(); 28610391SAndreas.Sandberg@ARM.com assert(ptr); 28710391SAndreas.Sandberg@ARM.com return ptr; 28810391SAndreas.Sandberg@ARM.com} 28910391SAndreas.Sandberg@ARM.com 29010391SAndreas.Sandberg@ARM.comconst StatData * 29110391SAndreas.Sandberg@ARM.comDataAccess::statData() const 29210391SAndreas.Sandberg@ARM.com{ 29310391SAndreas.Sandberg@ARM.com const StatData *ptr = find(); 29410391SAndreas.Sandberg@ARM.com assert(ptr); 29510391SAndreas.Sandberg@ARM.com return ptr; 29610391SAndreas.Sandberg@ARM.com} 29710391SAndreas.Sandberg@ARM.com 29810391SAndreas.Sandberg@ARM.comvoid 29910391SAndreas.Sandberg@ARM.comDataAccess::setInit() 30010391SAndreas.Sandberg@ARM.com{ 30110391SAndreas.Sandberg@ARM.com statData()->init = true; 30210391SAndreas.Sandberg@ARM.com} 30310391SAndreas.Sandberg@ARM.com 30410391SAndreas.Sandberg@ARM.comvoid 30510391SAndreas.Sandberg@ARM.comDataAccess::setPrint() 30610391SAndreas.Sandberg@ARM.com{ 30710391SAndreas.Sandberg@ARM.com Database::StatDB().regPrint(this); 30812187Sanouk.vanlaer@arm.com} 30912187Sanouk.vanlaer@arm.com 31010391SAndreas.Sandberg@ARM.comStatData::~StatData() 31110391SAndreas.Sandberg@ARM.com{ 31210391SAndreas.Sandberg@ARM.com} 31310391SAndreas.Sandberg@ARM.com 31410391SAndreas.Sandberg@ARM.combool 31510391SAndreas.Sandberg@ARM.comStatData::less(StatData *stat1, StatData *stat2) 31610391SAndreas.Sandberg@ARM.com{ 31710391SAndreas.Sandberg@ARM.com const string &name1 = stat1->name; 31810391SAndreas.Sandberg@ARM.com const string &name2 = stat2->name; 31910391SAndreas.Sandberg@ARM.com 32010391SAndreas.Sandberg@ARM.com vector<string> v1; 32110391SAndreas.Sandberg@ARM.com vector<string> v2; 32210391SAndreas.Sandberg@ARM.com 32310391SAndreas.Sandberg@ARM.com tokenize(v1, name1, '.'); 32410391SAndreas.Sandberg@ARM.com tokenize(v2, name2, '.'); 32510391SAndreas.Sandberg@ARM.com 32610391SAndreas.Sandberg@ARM.com int last = min(v1.size(), v2.size()) - 1; 32710391SAndreas.Sandberg@ARM.com for (int i = 0; i < last; ++i) 32810391SAndreas.Sandberg@ARM.com if (v1[i] != v2[i]) 32910391SAndreas.Sandberg@ARM.com return v1[i] < v2[i]; 33010391SAndreas.Sandberg@ARM.com 33110391SAndreas.Sandberg@ARM.com // Special compare for last element. 33210391SAndreas.Sandberg@ARM.com if (v1[last] == v2[last]) 33310391SAndreas.Sandberg@ARM.com return v1.size() < v2.size(); 33410391SAndreas.Sandberg@ARM.com else 33510391SAndreas.Sandberg@ARM.com return v1[last] < v2[last]; 33610391SAndreas.Sandberg@ARM.com 33710391SAndreas.Sandberg@ARM.com return false; 33810391SAndreas.Sandberg@ARM.com} 33910391SAndreas.Sandberg@ARM.com 34010391SAndreas.Sandberg@ARM.combool 34110391SAndreas.Sandberg@ARM.comStatData::check() const 34210391SAndreas.Sandberg@ARM.com{ 34310391SAndreas.Sandberg@ARM.com if (!init) { 34410391SAndreas.Sandberg@ARM.com#ifdef STAT_DEBUG 34510391SAndreas.Sandberg@ARM.com cprintf("this is stat number %d\n",(*i)->number); 34610391SAndreas.Sandberg@ARM.com#endif 34710391SAndreas.Sandberg@ARM.com panic("Not all stats have been initialized"); 34810391SAndreas.Sandberg@ARM.com return false; 34910391SAndreas.Sandberg@ARM.com } 35010391SAndreas.Sandberg@ARM.com 35110391SAndreas.Sandberg@ARM.com if (print && name.empty()) { 35210391SAndreas.Sandberg@ARM.com panic("all printable stats must be named"); 35310391SAndreas.Sandberg@ARM.com return false; 35410391SAndreas.Sandberg@ARM.com } 35510391SAndreas.Sandberg@ARM.com 35610391SAndreas.Sandberg@ARM.com return true; 35710391SAndreas.Sandberg@ARM.com} 35810391SAndreas.Sandberg@ARM.com 35910391SAndreas.Sandberg@ARM.comstring 36010391SAndreas.Sandberg@ARM.comValueToString(result_t value, DisplayMode mode, int precision) 36110391SAndreas.Sandberg@ARM.com{ 36210391SAndreas.Sandberg@ARM.com stringstream val; 36310391SAndreas.Sandberg@ARM.com 36410391SAndreas.Sandberg@ARM.com if (!isnan(value)) { 36510391SAndreas.Sandberg@ARM.com if (precision != -1) 36610391SAndreas.Sandberg@ARM.com val.precision(precision); 36710391SAndreas.Sandberg@ARM.com else if (value == rint(value)) 36810391SAndreas.Sandberg@ARM.com val.precision(0); 36910391SAndreas.Sandberg@ARM.com 37010391SAndreas.Sandberg@ARM.com val.unsetf(ios::showpoint); 37110391SAndreas.Sandberg@ARM.com val.setf(ios::fixed); 37210391SAndreas.Sandberg@ARM.com val << value; 37310391SAndreas.Sandberg@ARM.com } else { 37410391SAndreas.Sandberg@ARM.com val << (mode == mode_m5 ? "no value" : "<err: div-0>"); 37510391SAndreas.Sandberg@ARM.com } 37610391SAndreas.Sandberg@ARM.com 37710391SAndreas.Sandberg@ARM.com return val.str(); 37810391SAndreas.Sandberg@ARM.com} 37910391SAndreas.Sandberg@ARM.com 38010391SAndreas.Sandberg@ARM.comstruct ScalarPrint 38110391SAndreas.Sandberg@ARM.com{ 38210391SAndreas.Sandberg@ARM.com result_t value; 38310391SAndreas.Sandberg@ARM.com string name; 38410391SAndreas.Sandberg@ARM.com string desc; 38510391SAndreas.Sandberg@ARM.com int precision; 386 DisplayMode mode; 387 FormatFlags flags; 388 result_t pdf; 389 result_t cdf; 390 391 ScalarPrint() 392 : value(0.0), precision(0), mode(default_mode), flags(0), 393 pdf(NAN), cdf(NAN) 394 {} 395 396 void operator()(ostream &stream) const; 397}; 398 399void 400ScalarPrint::operator()(ostream &stream) const 401{ 402 if (flags & nozero && value == 0.0 || 403 flags & nonan && isnan(value)) 404 return; 405 406 stringstream pdfstr, cdfstr; 407 408 if (!isnan(pdf)) 409 ccprintf(pdfstr, "%.2f%%", pdf * 100.0); 410 411 if (!isnan(cdf)) 412 ccprintf(cdfstr, "%.2f%%", cdf * 100.0); 413 414 if (mode == mode_simplescalar && flags & __substat) { 415 ccprintf(stream, "%32s %12s %10s %10s", name, 416 ValueToString(value, mode, precision), 417 pdfstr, cdfstr); 418 } else { 419 ccprintf(stream, "%-40s %12s %10s %10s", name, 420 ValueToString(value, mode, precision), pdfstr, cdfstr); 421 } 422 423 if (PrintDescriptions) { 424 if (!desc.empty()) 425 ccprintf(stream, " # %s", desc); 426 } 427 stream << endl; 428} 429 430struct VectorPrint 431{ 432 string name; 433 string desc; 434 vector<string> subnames; 435 vector<string> subdescs; 436 int precision; 437 DisplayMode mode; 438 FormatFlags flags; 439 rvec_t vec; 440 result_t total; 441 442 VectorPrint() 443 : subnames(0), subdescs(0), precision(-1), mode(default_mode), 444 flags(0), total(NAN) 445 {} 446 447 void operator()(ostream &stream) const; 448}; 449 450void 451VectorPrint::operator()(std::ostream &stream) const 452{ 453 int _size = vec.size(); 454 result_t _total = 0.0; 455 456 if (flags & (pdf | cdf)) { 457 for (int i = 0; i < _size; ++i) { 458 _total += vec[i]; 459 } 460 } 461 462 string base = name + ((mode == mode_simplescalar) ? "_" : "::"); 463 464 ScalarPrint print; 465 print.name = name; 466 print.desc = desc; 467 print.precision = precision; 468 print.flags = flags; 469 470 bool havesub = !subnames.empty(); 471 472 if (_size == 1) { 473 print.value = vec[0]; 474 print(stream); 475 } else if (mode == mode_m5) { 476 for (int i = 0; i < _size; ++i) { 477 if (havesub && (i >= subnames.size() || subnames[i].empty())) 478 continue; 479 480 print.name = base + (havesub ? subnames[i] : to_string(i)); 481 print.desc = subdescs.empty() ? desc : subdescs[i]; 482 print.value = vec[i]; 483 484 if (_total && (flags & pdf)) { 485 print.pdf = vec[i] / _total; 486 print.cdf += print.pdf; 487 } 488 489 print(stream); 490 } 491 492 if (flags & ::Statistics::total) { 493 print.name = base + "total"; 494 print.desc = desc; 495 print.value = total; 496 print(stream); 497 } 498 } else { 499 if (flags & ::Statistics::total) { 500 print.value = total; 501 print(stream); 502 } 503 504 result_t _pdf = 0.0; 505 result_t _cdf = 0.0; 506 if (flags & dist) { 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]; 513 514 if (_total) { 515 _pdf = vec[i] / _total; 516 _cdf += _pdf; 517 } 518 519 if (flags & pdf) 520 print.pdf = _pdf; 521 if (flags & cdf) 522 print.cdf = _cdf; 523 524 print(stream); 525 } 526 ccprintf(stream, "%s.end_dist\n", name); 527 } else { 528 for (int i = 0; i < _size; ++i) { 529 if (havesub && subnames[i].empty()) 530 continue; 531 532 print.name = base; 533 print.name += havesub ? subnames[i] : to_string(i); 534 print.desc = subdescs.empty() ? desc : subdescs[i]; 535 print.value = vec[i]; 536 537 if (_total) { 538 _pdf = vec[i] / _total; 539 _cdf += _pdf; 540 } else { 541 _pdf = _cdf = NAN; 542 } 543 544 if (flags & pdf) { 545 print.pdf = _pdf; 546 print.cdf = _cdf; 547 } 548 549 print(stream); 550 } 551 } 552 } 553} 554 555struct DistPrint 556{ 557 string name; 558 string desc; 559 int precision; 560 DisplayMode mode; 561 FormatFlags flags; 562 563 result_t min_val; 564 result_t max_val; 565 result_t underflow; 566 result_t overflow; 567 rvec_t vec; 568 result_t sum; 569 result_t squares; 570 result_t samples; 571 572 int min; 573 int max; 574 int bucket_size; 575 int size; 576 bool fancy; 577 578 void operator()(ostream &stream) const; 579}; 580 581void 582DistPrint::operator()(ostream &stream) const 583{ 584 if (fancy) { 585 ScalarPrint print; 586 string base = name + ((mode == mode_m5) ? "::" : "_"); 587 588 print.precision = precision; 589 print.flags = flags; 590 print.desc = desc; 591 592 print.name = base + "mean"; 593 print.value = samples ? sum / samples : NAN; 594 print(stream); 595 596 print.name = base + "stdev"; 597 print.value = samples ? sqrt((samples * squares - sum * sum) / 598 (samples * (samples - 1.0))) : NAN; 599 print(stream); 600 601 print.name = "**Ignore: " + base + "TOT"; 602 print.value = samples; 603 print(stream); 604 return; 605 } 606 607 assert(size == vec.size()); 608 609 result_t total = 0.0; 610 611 total += underflow; 612 for (int i = 0; i < size; ++i) 613 total += vec[i]; 614 total += overflow; 615 616 string base = name + (mode == mode_m5 ? "::" : "."); 617 618 ScalarPrint print; 619 print.desc = (mode == mode_m5) ? desc : ""; 620 print.precision = precision; 621 print.mode = mode; 622 print.flags = flags; 623 624 if (mode == mode_simplescalar) { 625 ccprintf(stream, "%-42s", base + "start_dist"); 626 if (PrintDescriptions && !desc.empty()) 627 ccprintf(stream, " # %s", desc); 628 stream << endl; 629 } 630 631 print.name = base + "samples"; 632 print.value = samples; 633 print(stream); 634 635 print.name = base + "min_value"; 636 print.value = min_val; 637 print(stream); 638 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; 645 } 646 print(stream); 647 } 648 649 650 if (mode == mode_m5) { 651 for (int i = 0; i < size; ++i) { 652 stringstream namestr; 653 namestr << name; 654 655 int low = i * bucket_size + min; 656 int high = ::min((i + 1) * bucket_size + min - 1, max); 657 namestr << low; 658 if (low < high) 659 namestr << "-" << high; 660 661 print.name = namestr.str(); 662 print.value = vec[i]; 663 if (total) { 664 print.pdf = vec[i] / total; 665 print.cdf += print.pdf; 666 } 667 print(stream); 668 } 669 670 } else { 671 int _min; 672 result_t _pdf; 673 result_t _cdf = 0.0; 674 675 print.flags = flags | __substat; 676 677 for (int i = 0; i < size; ++i) { 678 if (flags & nozero && vec[i] == 0.0 || 679 flags & nonan && isnan(vec[i])) 680 continue; 681 682 _min = i * bucket_size + min; 683 _pdf = vec[i] / total * 100.0; 684 _cdf += _pdf; 685 686 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; 691 print(stream); 692 } 693 694 print.flags = flags; 695 if (flags & (pdf || cdf)) { 696 print.pdf = NAN; 697 print.cdf = NAN; 698 } 699 } 700 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; 707 } 708 print(stream); 709 } 710 711 print.pdf = NAN; 712 print.cdf = NAN; 713 714 if (mode != mode_simplescalar) { 715 print.name = base + "total"; 716 print.value = total; 717 print(stream); 718 } 719 720 print.name = base + "max_value"; 721 print.value = max_val; 722 print(stream); 723 724 if (mode != mode_simplescalar && samples != 0) { 725 print.name = base + "mean"; 726 print.value = sum / samples; 727 print(stream); 728 729 print.name = base + "stdev"; 730 print.value = sqrt((samples * squares - sum * sum) / 731 (samples * (samples - 1.0))); 732 print(stream); 733 } 734 735 if (mode == mode_simplescalar) 736 ccprintf(stream, "%send_dist\n\n", base); 737} 738 739void 740ScalarDataBase::display(ostream &stream) const 741{ 742 ScalarPrint print; 743 print.value = val(); 744 print.name = name; 745 print.desc = desc; 746 print.precision = precision; 747 print.flags = flags; 748 749 print(stream); 750} 751 752void 753VectorDataBase::display(ostream &stream) const 754{ 755 int size = this->size(); 756 const_cast<VectorDataBase *>(this)->update(); 757 758 VectorPrint print; 759 760 print.name = name; 761 print.desc = desc; 762 print.mode = mode; 763 print.flags = flags; 764 print.precision = precision; 765 print.vec = val(); 766 print.total = total(); 767 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); 776 break; 777 } 778 } 779 break; 780 } 781 } 782 783 784 print(stream); 785} 786 787void 788Vector2dDataBase::display(ostream &stream) const 789{ 790 const_cast<Vector2dDataBase *>(this)->update(); 791 792 bool havesub = false; 793 VectorPrint print; 794 795 print.subnames = y_subnames; 796 print.mode = mode; 797 print.flags = flags; 798 print.precision = precision; 799 800 if (!subnames.empty()) { 801 for (int i = 0; i < x; ++i) 802 if (!subnames[i].empty()) 803 havesub = true; 804 } 805 806 rvec_t tot_vec(y); 807 result_t super_total = 0.0; 808 for (int i = 0; i < x; ++i) { 809 if (havesub && (i >= subnames.size() || subnames[i].empty())) 810 continue; 811 812 int iy = i * y; 813 rvec_t yvec(y); 814 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]; 819 total += yvec[j]; 820 super_total += yvec[j]; 821 } 822 823 print.name = name + "_" + (havesub ? subnames[i] : to_string(i)); 824 print.desc = desc; 825 print.vec = yvec; 826 print.total = total; 827 print(stream); 828 } 829 830 if ((flags & ::Statistics::total) && (x > 1)) { 831 print.name = name; 832 print.desc = desc; 833 print.vec = tot_vec; 834 print.total = super_total; 835 print(stream); 836 } 837} 838 839void 840DistDataBase::display(ostream &stream) const 841{ 842 const_cast<DistDataBase *>(this)->update(); 843 844 DistPrint print; 845 846 print.name = name; 847 print.desc = desc; 848 print.precision = precision; 849 print.mode = mode; 850 print.flags = flags; 851 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; 860 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; 866 867 print(stream); 868} 869 870void 871VectorDistDataBase::display(ostream &stream) const 872{ 873 const_cast<VectorDistDataBase *>(this)->update(); 874 875 for (int i = 0; i < size(); ++i) { 876 DistPrint print; 877 878 print.name = name + 879 (subnames[i].empty() ? ("_" + to_string(i)) : subnames[i]); 880 print.desc = subdescs[i].empty() ? desc : subdescs[i]; 881 print.precision = precision; 882 print.mode = mode; 883 print.flags = flags; 884 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; 893 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; 899 900 print(stream); 901 } 902} 903 904void 905FormulaBase::val(rvec_t &vec) const 906{ 907 vec = root->val(); 908} 909 910result_t 911FormulaBase::total() const 912{ 913 return root->total(); 914} 915 916size_t 917FormulaBase::size() const 918{ 919 if (!root) 920 return 0; 921 else 922 return root->size(); 923} 924 925bool 926FormulaBase::binned() const 927{ 928 return root->binned(); 929} 930 931void 932FormulaBase::reset() 933{ 934} 935 936bool 937FormulaBase::zero() const 938{ 939 rvec_t vec; 940 val(vec); 941 for (int i = 0; i < vec.size(); ++i) 942 if (vec[i] != 0.0) 943 return false; 944 return true; 945} 946 947void 948FormulaBase::update(StatData *) 949{ 950} 951 952Formula::Formula() 953{ 954 setInit(); 955} 956 957Formula::Formula(Temp r) 958{ 959 root = r; 960 assert(size()); 961} 962 963const Formula & 964Formula::operator=(Temp r) 965{ 966 assert(!root && "Can't change formulas"); 967 root = r; 968 assert(size()); 969 return *this; 970} 971 972const Formula & 973Formula::operator+=(Temp r) 974{ 975 if (root) 976 root = NodePtr(new BinaryNode<std::plus<result_t> >(root, r)); 977 else 978 root = r; 979 assert(size()); 980 return *this; 981} 982 983MainBin::MainBin(const string &name) 984 : _name(name), mem(NULL), memsize(-1) 985{ 986 Database::StatDB().regBin(this, name); 987} 988 989MainBin::~MainBin() 990{ 991 if (mem) 992 delete [] mem; 993} 994 995char * 996MainBin::memory(off_t off) 997{ 998 if (memsize == -1) 999 memsize = CeilPow2((size_t) offset()); 1000 1001 if (!mem) { 1002 mem = new char[memsize]; 1003 memset(mem, 0, memsize); 1004 } 1005 1006 assert(offset() <= size()); 1007 return mem + off; 1008} 1009 1010void 1011check() 1012{ 1013 Database::StatDB().check(); 1014} 1015 1016void 1017dump(ostream &stream) 1018{ 1019 Database::StatDB().dump(stream); 1020} 1021 1022CallbackQueue resetQueue; 1023 1024void 1025RegResetCallback(Callback *cb) 1026{ 1027 resetQueue.add(cb); 1028} 1029 1030void 1031reset() 1032{ 1033 Database::StatDB().reset(); 1034 resetQueue.process(); 1035} 1036 1037} // namespace Statistics 1038