statistics.cc revision 5887:6b312cafaa59
1/* 2 * Copyright (c) 2003-2005 The Regents of The University of Michigan 3 * All rights reserved. 4 * 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. 15 * 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. 27 * 28 * Authors: Nathan Binkert 29 */ 30 31#include <iomanip> 32#include <fstream> 33#include <list> 34#include <map> 35#include <string> 36 37#include "base/callback.hh" 38#include "base/cprintf.hh" 39#include "base/hostinfo.hh" 40#include "base/misc.hh" 41#include "base/statistics.hh" 42#include "base/str.hh" 43#include "base/time.hh" 44#include "base/trace.hh" 45 46using namespace std; 47 48namespace Stats { 49 50typedef map<const void *, Info *> MapType; 51 52// We wrap these in a function to make sure they're built in time. 53list<Info *> & 54statsList() 55{ 56 static list<Info *> the_list; 57 return the_list; 58} 59 60MapType & 61statsMap() 62{ 63 static MapType the_map; 64 return the_map; 65} 66 67void 68InfoAccess::setInfo(Info *info) 69{ 70 if (statsMap().find(this) != statsMap().end()) 71 panic("shouldn't register stat twice!"); 72 73 statsList().push_back(info); 74 75#ifndef NDEBUG 76 pair<MapType::iterator, bool> result = 77#endif 78 statsMap().insert(make_pair(this, info)); 79 assert(result.second && "this should never fail"); 80 assert(statsMap().find(this) != statsMap().end()); 81} 82 83void 84InfoAccess::setInit() 85{ 86 info()->flags |= init; 87} 88 89Info * 90InfoAccess::info() 91{ 92 MapType::const_iterator i = statsMap().find(this); 93 assert(i != statsMap().end()); 94 return (*i).second; 95} 96 97const Info * 98InfoAccess::info() const 99{ 100 MapType::const_iterator i = statsMap().find(this); 101 assert(i != statsMap().end()); 102 return (*i).second; 103} 104 105Info::Info() 106 : flags(none), precision(-1), prereq(0) 107{ 108 static int count = 0; 109 id = count++; 110} 111 112Info::~Info() 113{ 114} 115 116bool 117Info::less(Info *stat1, Info *stat2) 118{ 119 const string &name1 = stat1->name; 120 const string &name2 = stat2->name; 121 122 vector<string> v1; 123 vector<string> v2; 124 125 tokenize(v1, name1, '.'); 126 tokenize(v2, name2, '.'); 127 128 size_type last = min(v1.size(), v2.size()) - 1; 129 for (off_type i = 0; i < last; ++i) 130 if (v1[i] != v2[i]) 131 return v1[i] < v2[i]; 132 133 // Special compare for last element. 134 if (v1[last] == v2[last]) 135 return v1.size() < v2.size(); 136 else 137 return v1[last] < v2[last]; 138 139 return false; 140} 141 142bool 143Info::baseCheck() const 144{ 145 if (!(flags & init)) { 146#ifdef DEBUG 147 cprintf("this is stat number %d\n", id); 148#endif 149 panic("Not all stats have been initialized"); 150 return false; 151 } 152 153 if ((flags & print) && name.empty()) { 154 panic("all printable stats must be named"); 155 return false; 156 } 157 158 return true; 159} 160 161 162void 163FormulaBase::result(VResult &vec) const 164{ 165 if (root) 166 vec = root->result(); 167} 168 169Result 170FormulaBase::total() const 171{ 172 return root ? root->total() : 0.0; 173} 174 175size_type 176FormulaBase::size() const 177{ 178 if (!root) 179 return 0; 180 else 181 return root->size(); 182} 183 184void 185FormulaBase::reset() 186{ 187} 188 189bool 190FormulaBase::zero() const 191{ 192 VResult vec; 193 result(vec); 194 for (off_t i = 0; i < vec.size(); ++i) 195 if (vec[i] != 0.0) 196 return false; 197 return true; 198} 199 200void 201FormulaBase::update(Info *) 202{ 203} 204 205string 206FormulaBase::str() const 207{ 208 return root ? root->str() : ""; 209} 210 211Formula::Formula() 212{ 213 setInit(); 214} 215 216Formula::Formula(Temp r) 217{ 218 root = r; 219 assert(size()); 220} 221 222const Formula & 223Formula::operator=(Temp r) 224{ 225 assert(!root && "Can't change formulas"); 226 root = r; 227 assert(size()); 228 return *this; 229} 230 231const Formula & 232Formula::operator+=(Temp r) 233{ 234 if (root) 235 root = NodePtr(new BinaryNode<std::plus<Result> >(root, r)); 236 else 237 root = r; 238 assert(size()); 239 return *this; 240} 241 242void 243check() 244{ 245 typedef list<Info *>::iterator iter_t; 246 247 iter_t i, end = statsList().end(); 248 for (i = statsList().begin(); i != end; ++i) { 249 Info *info = *i; 250 assert(info); 251 if (!info->check() || !info->baseCheck()) 252 panic("stat check failed for %s\n", info->name); 253 } 254 255 off_t j = 0; 256 for (i = statsList().begin(); i != end; ++i) { 257 Info *info = *i; 258 if (!(info->flags & print)) 259 info->name = "__Stat" + to_string(j++); 260 } 261 262 statsList().sort(Info::less); 263 264 if (i == end) 265 return; 266 267 iter_t last = i; 268 ++i; 269 270 for (i = statsList().begin(); i != end; ++i) { 271 if ((*i)->name == (*last)->name) 272 panic("same name used twice! name=%s\n", (*i)->name); 273 274 last = i; 275 } 276} 277 278CallbackQueue resetQueue; 279 280void 281reset() 282{ 283 list<Info *>::iterator i = statsList().begin(); 284 list<Info *>::iterator end = statsList().end(); 285 while (i != end) { 286 Info *info = *i; 287 info->reset(); 288 ++i; 289 } 290 291 resetQueue.process(); 292} 293 294void 295registerResetCallback(Callback *cb) 296{ 297 resetQueue.add(cb); 298} 299 300/* namespace Stats */ } 301