statistics.cc revision 8243
12SN/A/* 21762SN/A * Copyright (c) 2003-2005 The Regents of The University of Michigan 32SN/A * All rights reserved. 42SN/A * 52SN/A * Redistribution and use in source and binary forms, with or without 62SN/A * modification, are permitted provided that the following conditions are 72SN/A * met: redistributions of source code must retain the above copyright 82SN/A * notice, this list of conditions and the following disclaimer; 92SN/A * redistributions in binary form must reproduce the above copyright 102SN/A * notice, this list of conditions and the following disclaimer in the 112SN/A * documentation and/or other materials provided with the distribution; 122SN/A * neither the name of the copyright holders nor the names of its 132SN/A * contributors may be used to endorse or promote products derived from 142SN/A * this software without specific prior written permission. 152SN/A * 162SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 172SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 182SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 192SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 202SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 212SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 222SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 242SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 252SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 262SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272665Ssaidi@eecs.umich.edu * 282665Ssaidi@eecs.umich.edu * Authors: Nathan Binkert 292SN/A */ 302SN/A 318229Snate@binkert.org#include <fstream> 322SN/A#include <iomanip> 332SN/A#include <list> 342SN/A#include <map> 352SN/A#include <string> 362SN/A 37148SN/A#include "base/callback.hh" 3856SN/A#include "base/cprintf.hh" 395889Snate@binkert.org#include "base/debug.hh" 40441SN/A#include "base/hostinfo.hh" 4156SN/A#include "base/misc.hh" 4256SN/A#include "base/statistics.hh" 4356SN/A#include "base/str.hh" 44441SN/A#include "base/time.hh" 45433SN/A#include "base/trace.hh" 462SN/A 472SN/Ausing namespace std; 482SN/A 49729SN/Anamespace Stats { 50388SN/A 518243Sbradley.danofsky@amd.comstd::string Info::separatorString = "::"; 525887Snate@binkert.orgtypedef map<const void *, Info *> MapType; 535887Snate@binkert.org 545887Snate@binkert.org// We wrap these in a function to make sure they're built in time. 555887Snate@binkert.orglist<Info *> & 565887Snate@binkert.orgstatsList() 57388SN/A{ 585887Snate@binkert.org static list<Info *> the_list; 595887Snate@binkert.org return the_list; 60388SN/A} 61388SN/A 625887Snate@binkert.orgMapType & 635887Snate@binkert.orgstatsMap() 64441SN/A{ 655887Snate@binkert.org static MapType the_map; 665887Snate@binkert.org return the_map; 67441SN/A} 68441SN/A 69388SN/Avoid 705886Snate@binkert.orgInfoAccess::setInfo(Info *info) 71388SN/A{ 725887Snate@binkert.org if (statsMap().find(this) != statsMap().end()) 735887Snate@binkert.org panic("shouldn't register stat twice!"); 745887Snate@binkert.org 755887Snate@binkert.org statsList().push_back(info); 765887Snate@binkert.org 775887Snate@binkert.org#ifndef NDEBUG 785887Snate@binkert.org pair<MapType::iterator, bool> result = 795887Snate@binkert.org#endif 805887Snate@binkert.org statsMap().insert(make_pair(this, info)); 815887Snate@binkert.org assert(result.second && "this should never fail"); 825887Snate@binkert.org assert(statsMap().find(this) != statsMap().end()); 83388SN/A} 84388SN/A 85388SN/Avoid 865889Snate@binkert.orgInfoAccess::setParams(const StorageParams *params) 875889Snate@binkert.org{ 885889Snate@binkert.org info()->storageParams = params; 895889Snate@binkert.org} 905889Snate@binkert.org 915889Snate@binkert.orgvoid 925886Snate@binkert.orgInfoAccess::setInit() 93388SN/A{ 946130Snate@binkert.org info()->flags.set(init); 95388SN/A} 96388SN/A 975886Snate@binkert.orgInfo * 985886Snate@binkert.orgInfoAccess::info() 99388SN/A{ 1005887Snate@binkert.org MapType::const_iterator i = statsMap().find(this); 1015887Snate@binkert.org assert(i != statsMap().end()); 1025887Snate@binkert.org return (*i).second; 103388SN/A} 104388SN/A 1055886Snate@binkert.orgconst Info * 1065886Snate@binkert.orgInfoAccess::info() const 1075886Snate@binkert.org{ 1085887Snate@binkert.org MapType::const_iterator i = statsMap().find(this); 1095887Snate@binkert.org assert(i != statsMap().end()); 1105887Snate@binkert.org return (*i).second; 1115886Snate@binkert.org} 1125886Snate@binkert.org 1135889Snate@binkert.orgStorageParams::~StorageParams() 1145889Snate@binkert.org{ 1155889Snate@binkert.org} 1165889Snate@binkert.org 1176026Snate@binkert.orgtypedef map<std::string, Info *> NameMapType; 1186026Snate@binkert.orgNameMapType & 1196026Snate@binkert.orgnameMap() 1206026Snate@binkert.org{ 1216026Snate@binkert.org static NameMapType the_map; 1226026Snate@binkert.org return the_map; 1236026Snate@binkert.org} 1246026Snate@binkert.org 1255889Snate@binkert.orgint Info::id_count = 0; 1265889Snate@binkert.org 1275889Snate@binkert.orgint debug_break_id = -1; 1285889Snate@binkert.org 1295886Snate@binkert.orgInfo::Info() 1305889Snate@binkert.org : flags(none), precision(-1), prereq(0), storageParams(NULL) 131582SN/A{ 1325889Snate@binkert.org id = id_count++; 1335889Snate@binkert.org if (debug_break_id >= 0 and debug_break_id == id) 1348231Snate@binkert.org Debug::breakpoint(); 135582SN/A} 136582SN/A 1375886Snate@binkert.orgInfo::~Info() 138388SN/A{ 139388SN/A} 140388SN/A 1416026Snate@binkert.orgvoid 1426026Snate@binkert.orgInfo::setName(const string &name) 1436026Snate@binkert.org{ 1446026Snate@binkert.org pair<NameMapType::iterator, bool> p = 1456026Snate@binkert.org nameMap().insert(make_pair(name, this)); 1466026Snate@binkert.org 1476026Snate@binkert.org Info *other = p.first->second; 1486026Snate@binkert.org bool result = p.second; 1496026Snate@binkert.org 1506026Snate@binkert.org if (!result) { 1516026Snate@binkert.org // using other->name instead of just name to avoid a compiler 1526026Snate@binkert.org // warning. They should be the same. 1536026Snate@binkert.org panic("same statistic name used twice! name=%s\n", other->name); 1546026Snate@binkert.org } 1556026Snate@binkert.org 1566026Snate@binkert.org this->name = name; 1576026Snate@binkert.org} 1586026Snate@binkert.org 1592SN/Abool 1605886Snate@binkert.orgInfo::less(Info *stat1, Info *stat2) 1612SN/A{ 162388SN/A const string &name1 = stat1->name; 163388SN/A const string &name2 = stat2->name; 1642SN/A 1652SN/A vector<string> v1; 1662SN/A vector<string> v2; 1672SN/A 1682SN/A tokenize(v1, name1, '.'); 1692SN/A tokenize(v2, name2, '.'); 1702SN/A 1715599Snate@binkert.org size_type last = min(v1.size(), v2.size()) - 1; 1725599Snate@binkert.org for (off_type i = 0; i < last; ++i) 1732SN/A if (v1[i] != v2[i]) 1742SN/A return v1[i] < v2[i]; 1752SN/A 1762SN/A // Special compare for last element. 1772SN/A if (v1[last] == v2[last]) 1782SN/A return v1.size() < v2.size(); 1792SN/A else 1802SN/A return v1[last] < v2[last]; 1812SN/A 1822SN/A return false; 1832SN/A} 1842SN/A 185388SN/Abool 1865886Snate@binkert.orgInfo::baseCheck() const 1872SN/A{ 1886000Snate@binkert.org if (!(flags & Stats::init)) { 189582SN/A#ifdef DEBUG 190695SN/A cprintf("this is stat number %d\n", id); 191388SN/A#endif 192388SN/A panic("Not all stats have been initialized"); 193388SN/A return false; 194388SN/A } 1952SN/A 1967462Snate@binkert.org if ((flags & display) && name.empty()) { 197388SN/A panic("all printable stats must be named"); 198388SN/A return false; 199388SN/A } 2002SN/A 201388SN/A return true; 2022SN/A} 2032SN/A 2046001Snate@binkert.orgvoid 2056001Snate@binkert.orgInfo::enable() 2066001Snate@binkert.org{ 2076001Snate@binkert.org} 2086001Snate@binkert.org 2096001Snate@binkert.orgvoid 2106128Snate@binkert.orgVectorInfo::enable() 2116001Snate@binkert.org{ 2126001Snate@binkert.org size_type s = size(); 2136001Snate@binkert.org if (subnames.size() < s) 2146001Snate@binkert.org subnames.resize(s); 2156001Snate@binkert.org if (subdescs.size() < s) 2166001Snate@binkert.org subdescs.resize(s); 2176001Snate@binkert.org} 2186001Snate@binkert.org 2196001Snate@binkert.orgvoid 2206128Snate@binkert.orgVectorDistInfo::enable() 2216001Snate@binkert.org{ 2226001Snate@binkert.org size_type s = size(); 2236001Snate@binkert.org if (subnames.size() < s) 2246001Snate@binkert.org subnames.resize(s); 2256001Snate@binkert.org if (subdescs.size() < s) 2266001Snate@binkert.org subdescs.resize(s); 2276001Snate@binkert.org} 2286001Snate@binkert.org 2296001Snate@binkert.orgvoid 2306128Snate@binkert.orgVector2dInfo::enable() 2316001Snate@binkert.org{ 2326001Snate@binkert.org if (subnames.size() < x) 2336001Snate@binkert.org subnames.resize(x); 2346001Snate@binkert.org if (subdescs.size() < x) 2356001Snate@binkert.org subdescs.resize(x); 2366001Snate@binkert.org if (y_subnames.size() < y) 2376001Snate@binkert.org y_subnames.resize(y); 2386001Snate@binkert.org} 239695SN/A 2407831Snate@binkert.orgvoid 2417831Snate@binkert.orgHistStor::grow_out() 2427831Snate@binkert.org{ 2437831Snate@binkert.org int size = cvec.size(); 2447831Snate@binkert.org int zero = size / 2; // round down! 2457831Snate@binkert.org int top_half = zero + (size - zero + 1) / 2; // round up! 2467831Snate@binkert.org int bottom_half = (size - zero) / 2; // round down! 2477831Snate@binkert.org 2487831Snate@binkert.org // grow down 2497831Snate@binkert.org int low_pair = zero - 1; 2507831Snate@binkert.org for (int i = zero - 1; i >= bottom_half; i--) { 2517831Snate@binkert.org cvec[i] = cvec[low_pair]; 2527831Snate@binkert.org if (low_pair - 1 >= 0) 2537831Snate@binkert.org cvec[i] += cvec[low_pair - 1]; 2547831Snate@binkert.org low_pair -= 2; 2557831Snate@binkert.org } 2567831Snate@binkert.org assert(low_pair == 0 || low_pair == -1 || low_pair == -2); 2577831Snate@binkert.org 2587831Snate@binkert.org for (int i = bottom_half - 1; i >= 0; i--) 2597831Snate@binkert.org cvec[i] = Counter(); 2607831Snate@binkert.org 2617831Snate@binkert.org // grow up 2627831Snate@binkert.org int high_pair = zero; 2637831Snate@binkert.org for (int i = zero; i < top_half; i++) { 2647831Snate@binkert.org cvec[i] = cvec[high_pair]; 2657831Snate@binkert.org if (high_pair + 1 < size) 2667831Snate@binkert.org cvec[i] += cvec[high_pair + 1]; 2677831Snate@binkert.org high_pair += 2; 2687831Snate@binkert.org } 2697831Snate@binkert.org assert(high_pair == size || high_pair == size + 1); 2707831Snate@binkert.org 2717831Snate@binkert.org for (int i = top_half; i < size; i++) 2727831Snate@binkert.org cvec[i] = Counter(); 2737831Snate@binkert.org 2747831Snate@binkert.org max_bucket *= 2; 2757831Snate@binkert.org min_bucket *= 2; 2767831Snate@binkert.org bucket_size *= 2; 2777831Snate@binkert.org} 2787831Snate@binkert.org 2797831Snate@binkert.orgvoid 2807831Snate@binkert.orgHistStor::grow_convert() 2817831Snate@binkert.org{ 2827831Snate@binkert.org int size = cvec.size(); 2837831Snate@binkert.org int half = (size + 1) / 2; // round up! 2847831Snate@binkert.org //bool even = (size & 1) == 0; 2857831Snate@binkert.org 2867831Snate@binkert.org int pair = size - 1; 2877831Snate@binkert.org for (int i = size - 1; i >= half; --i) { 2887831Snate@binkert.org cvec[i] = cvec[pair]; 2897831Snate@binkert.org if (pair - 1 >= 0) 2907831Snate@binkert.org cvec[i] += cvec[pair - 1]; 2917831Snate@binkert.org pair -= 2; 2927831Snate@binkert.org } 2937831Snate@binkert.org 2947831Snate@binkert.org for (int i = half - 1; i >= 0; i--) 2957831Snate@binkert.org cvec[i] = Counter(); 2967831Snate@binkert.org 2977831Snate@binkert.org min_bucket = -max_bucket;// - (even ? bucket_size : 0); 2987831Snate@binkert.org bucket_size *= 2; 2997831Snate@binkert.org} 3007831Snate@binkert.org 3017831Snate@binkert.orgvoid 3027831Snate@binkert.orgHistStor::grow_up() 3037831Snate@binkert.org{ 3047831Snate@binkert.org int size = cvec.size(); 3057831Snate@binkert.org int half = (size + 1) / 2; // round up! 3067831Snate@binkert.org 3077831Snate@binkert.org int pair = 0; 3087831Snate@binkert.org for (int i = 0; i < half; i++) { 3097831Snate@binkert.org cvec[i] = cvec[pair]; 3107831Snate@binkert.org if (pair + 1 < size) 3117831Snate@binkert.org cvec[i] += cvec[pair + 1]; 3127831Snate@binkert.org pair += 2; 3137831Snate@binkert.org } 3147831Snate@binkert.org assert(pair == size || pair == size + 1); 3157831Snate@binkert.org 3167831Snate@binkert.org for (int i = half; i < size; i++) 3177831Snate@binkert.org cvec[i] = Counter(); 3187831Snate@binkert.org 3197831Snate@binkert.org max_bucket *= 2; 3207831Snate@binkert.org bucket_size *= 2; 3217831Snate@binkert.org} 3227831Snate@binkert.org 323388SN/AFormula::Formula() 324388SN/A{ 325388SN/A} 326388SN/A 327388SN/AFormula::Formula(Temp r) 328388SN/A{ 329388SN/A root = r; 3307461Snate@binkert.org setInit(); 331388SN/A assert(size()); 332388SN/A} 333388SN/A 334388SN/Aconst Formula & 335388SN/AFormula::operator=(Temp r) 336388SN/A{ 337388SN/A assert(!root && "Can't change formulas"); 338388SN/A root = r; 3397461Snate@binkert.org setInit(); 340388SN/A assert(size()); 341388SN/A return *this; 342388SN/A} 343388SN/A 344388SN/Aconst Formula & 345388SN/AFormula::operator+=(Temp r) 346388SN/A{ 347388SN/A if (root) 348695SN/A root = NodePtr(new BinaryNode<std::plus<Result> >(root, r)); 3497461Snate@binkert.org else { 350388SN/A root = r; 3517461Snate@binkert.org setInit(); 3527461Snate@binkert.org } 3537461Snate@binkert.org 354388SN/A assert(size()); 355388SN/A return *this; 356388SN/A} 357388SN/A 358142SN/Avoid 3596000Snate@binkert.orgFormula::result(VResult &vec) const 3606000Snate@binkert.org{ 3616000Snate@binkert.org if (root) 3626000Snate@binkert.org vec = root->result(); 3636000Snate@binkert.org} 3646000Snate@binkert.org 3656000Snate@binkert.orgResult 3666000Snate@binkert.orgFormula::total() const 3676000Snate@binkert.org{ 3686000Snate@binkert.org return root ? root->total() : 0.0; 3696000Snate@binkert.org} 3706000Snate@binkert.org 3716000Snate@binkert.orgsize_type 3726000Snate@binkert.orgFormula::size() const 3736000Snate@binkert.org{ 3746000Snate@binkert.org if (!root) 3756000Snate@binkert.org return 0; 3766000Snate@binkert.org else 3776000Snate@binkert.org return root->size(); 3786000Snate@binkert.org} 3796000Snate@binkert.org 3806000Snate@binkert.orgvoid 3816000Snate@binkert.orgFormula::reset() 3826000Snate@binkert.org{ 3836000Snate@binkert.org} 3846000Snate@binkert.org 3856000Snate@binkert.orgbool 3866000Snate@binkert.orgFormula::zero() const 3876000Snate@binkert.org{ 3886000Snate@binkert.org VResult vec; 3896000Snate@binkert.org result(vec); 3906227Snate@binkert.org for (VResult::size_type i = 0; i < vec.size(); ++i) 3916000Snate@binkert.org if (vec[i] != 0.0) 3926000Snate@binkert.org return false; 3936000Snate@binkert.org return true; 3946000Snate@binkert.org} 3956000Snate@binkert.org 3966000Snate@binkert.orgstring 3976000Snate@binkert.orgFormula::str() const 3986000Snate@binkert.org{ 3996000Snate@binkert.org return root ? root->str() : ""; 4006000Snate@binkert.org} 4016000Snate@binkert.org 4026000Snate@binkert.orgvoid 4036001Snate@binkert.orgenable() 4042SN/A{ 4055887Snate@binkert.org typedef list<Info *>::iterator iter_t; 406695SN/A 4075887Snate@binkert.org iter_t i, end = statsList().end(); 4085887Snate@binkert.org for (i = statsList().begin(); i != end; ++i) { 4095886Snate@binkert.org Info *info = *i; 4105886Snate@binkert.org assert(info); 4115886Snate@binkert.org if (!info->check() || !info->baseCheck()) 4125889Snate@binkert.org panic("stat check failed for '%s' %d\n", info->name, info->id); 413695SN/A } 414695SN/A 4155599Snate@binkert.org off_t j = 0; 4165887Snate@binkert.org for (i = statsList().begin(); i != end; ++i) { 4175886Snate@binkert.org Info *info = *i; 4187462Snate@binkert.org if (!(info->flags & display)) 4195886Snate@binkert.org info->name = "__Stat" + to_string(j++); 420695SN/A } 421695SN/A 4225887Snate@binkert.org statsList().sort(Info::less); 423695SN/A 4246001Snate@binkert.org for (i = statsList().begin(); i != end; ++i) { 4256001Snate@binkert.org Info *info = *i; 4266001Snate@binkert.org info->enable(); 4276001Snate@binkert.org } 4286001Snate@binkert.org} 429695SN/A 4306001Snate@binkert.orgvoid 4316001Snate@binkert.orgprepare() 4326001Snate@binkert.org{ 4336001Snate@binkert.org list<Info *>::iterator i = statsList().begin(); 4346001Snate@binkert.org list<Info *>::iterator end = statsList().end(); 4356001Snate@binkert.org while (i != end) { 4366001Snate@binkert.org Info *info = *i; 4376001Snate@binkert.org info->prepare(); 4386001Snate@binkert.org ++i; 439695SN/A } 4402SN/A} 4412SN/A 442695SN/ACallbackQueue resetQueue; 4432SN/A 444456SN/Avoid 445695SN/Areset() 446456SN/A{ 4475887Snate@binkert.org list<Info *>::iterator i = statsList().begin(); 4485887Snate@binkert.org list<Info *>::iterator end = statsList().end(); 449695SN/A while (i != end) { 4505886Snate@binkert.org Info *info = *i; 4515886Snate@binkert.org info->reset(); 452695SN/A ++i; 453695SN/A } 454695SN/A 455695SN/A resetQueue.process(); 456456SN/A} 457456SN/A 458456SN/Avoid 459394SN/AregisterResetCallback(Callback *cb) 460148SN/A{ 461148SN/A resetQueue.add(cb); 462148SN/A} 463148SN/A 4647811Ssteve.reinhardt@amd.com} // namespace Stats 465