statistics.cc revision 2665
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 312SN/A#include <iomanip> 32456SN/A#include <fstream> 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" 39441SN/A#include "base/hostinfo.hh" 4056SN/A#include "base/misc.hh" 4156SN/A#include "base/statistics.hh" 4256SN/A#include "base/str.hh" 43441SN/A#include "base/time.hh" 44433SN/A#include "base/trace.hh" 45695SN/A#include "base/stats/statdb.hh" 461858SN/A#include "config/stats_binning.hh" 472SN/A 482SN/Ausing namespace std; 492SN/A 50729SN/Anamespace Stats { 51388SN/A 52388SN/AStatData * 53388SN/ADataAccess::find() const 54388SN/A{ 55695SN/A return Database::find(const_cast<void *>((const void *)this)); 56388SN/A} 57388SN/A 58441SN/Aconst StatData * 59441SN/AgetStatData(const void *stat) 60441SN/A{ 61695SN/A return Database::find(const_cast<void *>(stat)); 62441SN/A} 63441SN/A 64388SN/Avoid 65388SN/ADataAccess::map(StatData *data) 66388SN/A{ 67695SN/A Database::regStat(this, data); 68388SN/A} 69388SN/A 70388SN/AStatData * 71388SN/ADataAccess::statData() 72388SN/A{ 73388SN/A StatData *ptr = find(); 74388SN/A assert(ptr); 75388SN/A return ptr; 76388SN/A} 77388SN/A 78388SN/Aconst StatData * 79388SN/ADataAccess::statData() const 80388SN/A{ 81388SN/A const StatData *ptr = find(); 82388SN/A assert(ptr); 83388SN/A return ptr; 84388SN/A} 85388SN/A 86388SN/Avoid 87388SN/ADataAccess::setInit() 88388SN/A{ 89434SN/A statData()->flags |= init; 90388SN/A} 91388SN/A 92388SN/Avoid 93388SN/ADataAccess::setPrint() 94388SN/A{ 95695SN/A Database::regPrint(this); 96388SN/A} 97388SN/A 98582SN/AStatData::StatData() 99582SN/A : flags(none), precision(-1), prereq(0) 100582SN/A{ 101695SN/A static int count = 0; 102695SN/A id = count++; 103582SN/A} 104582SN/A 105388SN/AStatData::~StatData() 106388SN/A{ 107388SN/A} 108388SN/A 1092SN/Abool 110388SN/AStatData::less(StatData *stat1, StatData *stat2) 1112SN/A{ 112388SN/A const string &name1 = stat1->name; 113388SN/A const string &name2 = stat2->name; 1142SN/A 1152SN/A vector<string> v1; 1162SN/A vector<string> v2; 1172SN/A 1182SN/A tokenize(v1, name1, '.'); 1192SN/A tokenize(v2, name2, '.'); 1202SN/A 1212SN/A int last = min(v1.size(), v2.size()) - 1; 1222SN/A for (int i = 0; i < last; ++i) 1232SN/A if (v1[i] != v2[i]) 1242SN/A return v1[i] < v2[i]; 1252SN/A 1262SN/A // Special compare for last element. 1272SN/A if (v1[last] == v2[last]) 1282SN/A return v1.size() < v2.size(); 1292SN/A else 1302SN/A return v1[last] < v2[last]; 1312SN/A 1322SN/A return false; 1332SN/A} 1342SN/A 135388SN/Abool 136414SN/AStatData::baseCheck() const 1372SN/A{ 138434SN/A if (!(flags & init)) { 139582SN/A#ifdef DEBUG 140695SN/A cprintf("this is stat number %d\n", id); 141388SN/A#endif 142388SN/A panic("Not all stats have been initialized"); 143388SN/A return false; 144388SN/A } 1452SN/A 146434SN/A if ((flags & print) && name.empty()) { 147388SN/A panic("all printable stats must be named"); 148388SN/A return false; 149388SN/A } 1502SN/A 151388SN/A return true; 1522SN/A} 1532SN/A 154695SN/A 155695SN/Avoid 156695SN/AFormulaBase::result(VResult &vec) const 1572SN/A{ 158695SN/A if (root) 159695SN/A vec = root->result(); 1602SN/A} 1612SN/A 162695SN/AResult 163388SN/AFormulaBase::total() const 164388SN/A{ 165456SN/A return root ? root->total() : 0.0; 166388SN/A} 167388SN/A 168388SN/Asize_t 169388SN/AFormulaBase::size() const 170388SN/A{ 171388SN/A if (!root) 172388SN/A return 0; 173388SN/A else 174388SN/A return root->size(); 175388SN/A} 176388SN/A 177388SN/Abool 178388SN/AFormulaBase::binned() const 179388SN/A{ 180436SN/A return root && root->binned(); 181388SN/A} 182388SN/A 183388SN/Avoid 184388SN/AFormulaBase::reset() 185388SN/A{ 186388SN/A} 187388SN/A 188388SN/Abool 189388SN/AFormulaBase::zero() const 190388SN/A{ 191695SN/A VResult vec; 192695SN/A result(vec); 193388SN/A for (int i = 0; i < vec.size(); ++i) 194388SN/A if (vec[i] != 0.0) 195388SN/A return false; 196388SN/A return true; 197388SN/A} 198388SN/A 199388SN/Avoid 200388SN/AFormulaBase::update(StatData *) 201388SN/A{ 202388SN/A} 203388SN/A 204441SN/Astring 205441SN/AFormulaBase::str() const 206441SN/A{ 207441SN/A return root ? root->str() : ""; 208441SN/A} 209441SN/A 210388SN/AFormula::Formula() 211388SN/A{ 212388SN/A setInit(); 213388SN/A} 214388SN/A 215388SN/AFormula::Formula(Temp r) 216388SN/A{ 217388SN/A root = r; 218388SN/A assert(size()); 219388SN/A} 220388SN/A 221388SN/Aconst Formula & 222388SN/AFormula::operator=(Temp r) 223388SN/A{ 224388SN/A assert(!root && "Can't change formulas"); 225388SN/A root = r; 226388SN/A assert(size()); 227388SN/A return *this; 228388SN/A} 229388SN/A 230388SN/Aconst Formula & 231388SN/AFormula::operator+=(Temp r) 232388SN/A{ 233388SN/A if (root) 234695SN/A root = NodePtr(new BinaryNode<std::plus<Result> >(root, r)); 235388SN/A else 236388SN/A root = r; 237388SN/A assert(size()); 238388SN/A return *this; 239388SN/A} 240388SN/A 241388SN/AMainBin::MainBin(const string &name) 242365SN/A : _name(name), mem(NULL), memsize(-1) 2432SN/A{ 244695SN/A Database::regBin(this, name); 2452SN/A} 2462SN/A 247365SN/AMainBin::~MainBin() 2482SN/A{ 2492SN/A if (mem) 2502SN/A delete [] mem; 2512SN/A} 2522SN/A 2532SN/Achar * 254365SN/AMainBin::memory(off_t off) 2552SN/A{ 256388SN/A if (memsize == -1) 2572020SN/A memsize = ceilPow2((size_t) offset()); 258388SN/A 2592SN/A if (!mem) { 2602SN/A mem = new char[memsize]; 2612SN/A memset(mem, 0, memsize); 2622SN/A } 2632SN/A 264365SN/A assert(offset() <= size()); 265365SN/A return mem + off; 2662SN/A} 2672SN/A 268142SN/Avoid 2692SN/Acheck() 2702SN/A{ 271695SN/A typedef Database::stat_list_t::iterator iter_t; 272695SN/A 273695SN/A iter_t i, end = Database::stats().end(); 274695SN/A for (i = Database::stats().begin(); i != end; ++i) { 275695SN/A StatData *data = *i; 276695SN/A assert(data); 2771014SN/A if (!data->check() || !data->baseCheck()) 2781014SN/A panic("stat check failed for %s\n", data->name); 279695SN/A } 280695SN/A 281695SN/A int j = 0; 282695SN/A for (i = Database::stats().begin(); i != end; ++i) { 283695SN/A StatData *data = *i; 284695SN/A if (!(data->flags & print)) 285695SN/A data->name = "__Stat" + to_string(j++); 286695SN/A } 287695SN/A 288695SN/A Database::stats().sort(StatData::less); 289695SN/A 2901858SN/A#if STATS_BINNING 2911395SN/A if (MainBin::curBin() == NULL) { 2921395SN/A static MainBin mainBin("main bin"); 2931395SN/A mainBin.activate(); 2941395SN/A } 2951395SN/A#endif 2961395SN/A 297695SN/A if (i == end) 298695SN/A return; 299695SN/A 300695SN/A iter_t last = i; 301695SN/A ++i; 302695SN/A 303695SN/A for (i = Database::stats().begin(); i != end; ++i) { 304695SN/A if ((*i)->name == (*last)->name) 305695SN/A panic("same name used twice! name=%s\n", (*i)->name); 306695SN/A 307695SN/A last = i; 308695SN/A } 3092SN/A} 3102SN/A 311695SN/ACallbackQueue resetQueue; 3122SN/A 313456SN/Avoid 314695SN/Areset() 315456SN/A{ 316695SN/A // reset non-binned stats 317695SN/A Database::stat_list_t::iterator i = Database::stats().begin(); 318695SN/A Database::stat_list_t::iterator end = Database::stats().end(); 319695SN/A while (i != end) { 320695SN/A StatData *data = *i; 321695SN/A if (!data->binned()) 322695SN/A data->reset(); 323695SN/A ++i; 324695SN/A } 325695SN/A 326695SN/A // save the bin so we can go back to where we were 327695SN/A MainBin *orig = MainBin::curBin(); 328695SN/A 329695SN/A // reset binned stats 330695SN/A Database::bin_list_t::iterator bi = Database::bins().begin(); 331695SN/A Database::bin_list_t::iterator be = Database::bins().end(); 332695SN/A while (bi != be) { 333695SN/A MainBin *bin = *bi; 334695SN/A bin->activate(); 335695SN/A 336695SN/A i = Database::stats().begin(); 337695SN/A while (i != end) { 338695SN/A StatData *data = *i; 339695SN/A if (data->binned()) 340695SN/A data->reset(); 341695SN/A ++i; 342695SN/A } 343695SN/A ++bi; 344695SN/A } 345695SN/A 346695SN/A // restore bin 347695SN/A MainBin::curBin() = orig; 348695SN/A 349695SN/A resetQueue.process(); 350456SN/A} 351456SN/A 352456SN/Avoid 353394SN/AregisterResetCallback(Callback *cb) 354148SN/A{ 355148SN/A resetQueue.add(cb); 356148SN/A} 357148SN/A 358729SN/A/* namespace Stats */ } 359