statistics.cc revision 8229:78bf55f23338
13536Sgblack@eecs.umich.edu/* 211274Sshingarov@labware.com * Copyright (c) 2003-2005 The Regents of The University of Michigan 33536Sgblack@eecs.umich.edu * All rights reserved. 43536Sgblack@eecs.umich.edu * 53536Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without 63536Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are 73536Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright 83536Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer; 93536Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright 103536Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 113536Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution; 123536Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 133536Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 143536Sgblack@eecs.umich.edu * this software without specific prior written permission. 153536Sgblack@eecs.umich.edu * 163536Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 173536Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 183536Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 193536Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 203536Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 213536Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 223536Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 233536Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 243536Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 253536Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 263536Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 273536Sgblack@eecs.umich.edu * 283536Sgblack@eecs.umich.edu * Authors: Nathan Binkert 293536Sgblack@eecs.umich.edu */ 3011274Sshingarov@labware.com 313536Sgblack@eecs.umich.edu#include <fstream> 323536Sgblack@eecs.umich.edu#include <iomanip> 333536Sgblack@eecs.umich.edu#include <list> 343536Sgblack@eecs.umich.edu#include <map> 353536Sgblack@eecs.umich.edu#include <string> 363536Sgblack@eecs.umich.edu 373536Sgblack@eecs.umich.edu#include "base/callback.hh" 383536Sgblack@eecs.umich.edu#include "base/cprintf.hh" 398229Snate@binkert.org#include "base/debug.hh" 403536Sgblack@eecs.umich.edu#include "base/hostinfo.hh" 418229Snate@binkert.org#include "base/misc.hh" 423536Sgblack@eecs.umich.edu#include "base/statistics.hh" 433536Sgblack@eecs.umich.edu#include "base/str.hh" 443536Sgblack@eecs.umich.edu#include "base/time.hh" 453536Sgblack@eecs.umich.edu#include "base/trace.hh" 463536Sgblack@eecs.umich.edu 475569Snate@binkert.orgusing namespace std; 485569Snate@binkert.org 495569Snate@binkert.orgnamespace Stats { 503536Sgblack@eecs.umich.edu 515569Snate@binkert.orgtypedef map<const void *, Info *> MapType; 525569Snate@binkert.org 535569Snate@binkert.org// We wrap these in a function to make sure they're built in time. 545569Snate@binkert.orglist<Info *> & 553536Sgblack@eecs.umich.edustatsList() 5610601Sgabeblack@google.com{ 578700Ssteve.reinhardt@amd.com static list<Info *> the_list; 5811274Sshingarov@labware.com return the_list; 5911274Sshingarov@labware.com} 6011274Sshingarov@labware.com 6111274Sshingarov@labware.comMapType & 6211274Sshingarov@labware.comstatsMap() 6311274Sshingarov@labware.com{ 6411274Sshingarov@labware.com static MapType the_map; 6511274Sshingarov@labware.com return the_map; 6611274Sshingarov@labware.com} 6711274Sshingarov@labware.com 6811274Sshingarov@labware.comvoid 6911274Sshingarov@labware.comInfoAccess::setInfo(Info *info) 7011274Sshingarov@labware.com{ 7111274Sshingarov@labware.com if (statsMap().find(this) != statsMap().end()) 7211274Sshingarov@labware.com panic("shouldn't register stat twice!"); 7311274Sshingarov@labware.com 7411274Sshingarov@labware.com statsList().push_back(info); 7511274Sshingarov@labware.com 765569Snate@binkert.org#ifndef NDEBUG 775569Snate@binkert.org pair<MapType::iterator, bool> result = 7811274Sshingarov@labware.com#endif 795569Snate@binkert.org statsMap().insert(make_pair(this, info)); 803536Sgblack@eecs.umich.edu assert(result.second && "this should never fail"); 815569Snate@binkert.org assert(statsMap().find(this) != statsMap().end()); 823536Sgblack@eecs.umich.edu} 835569Snate@binkert.org 84void 85InfoAccess::setParams(const StorageParams *params) 86{ 87 info()->storageParams = params; 88} 89 90void 91InfoAccess::setInit() 92{ 93 info()->flags.set(init); 94} 95 96Info * 97InfoAccess::info() 98{ 99 MapType::const_iterator i = statsMap().find(this); 100 assert(i != statsMap().end()); 101 return (*i).second; 102} 103 104const Info * 105InfoAccess::info() const 106{ 107 MapType::const_iterator i = statsMap().find(this); 108 assert(i != statsMap().end()); 109 return (*i).second; 110} 111 112StorageParams::~StorageParams() 113{ 114} 115 116typedef map<std::string, Info *> NameMapType; 117NameMapType & 118nameMap() 119{ 120 static NameMapType the_map; 121 return the_map; 122} 123 124int Info::id_count = 0; 125 126int debug_break_id = -1; 127 128Info::Info() 129 : flags(none), precision(-1), prereq(0), storageParams(NULL) 130{ 131 id = id_count++; 132 if (debug_break_id >= 0 and debug_break_id == id) 133 debug_break(); 134} 135 136Info::~Info() 137{ 138} 139 140void 141Info::setName(const string &name) 142{ 143 pair<NameMapType::iterator, bool> p = 144 nameMap().insert(make_pair(name, this)); 145 146 Info *other = p.first->second; 147 bool result = p.second; 148 149 if (!result) { 150 // using other->name instead of just name to avoid a compiler 151 // warning. They should be the same. 152 panic("same statistic name used twice! name=%s\n", other->name); 153 } 154 155 this->name = name; 156} 157 158bool 159Info::less(Info *stat1, Info *stat2) 160{ 161 const string &name1 = stat1->name; 162 const string &name2 = stat2->name; 163 164 vector<string> v1; 165 vector<string> v2; 166 167 tokenize(v1, name1, '.'); 168 tokenize(v2, name2, '.'); 169 170 size_type last = min(v1.size(), v2.size()) - 1; 171 for (off_type i = 0; i < last; ++i) 172 if (v1[i] != v2[i]) 173 return v1[i] < v2[i]; 174 175 // Special compare for last element. 176 if (v1[last] == v2[last]) 177 return v1.size() < v2.size(); 178 else 179 return v1[last] < v2[last]; 180 181 return false; 182} 183 184bool 185Info::baseCheck() const 186{ 187 if (!(flags & Stats::init)) { 188#ifdef DEBUG 189 cprintf("this is stat number %d\n", id); 190#endif 191 panic("Not all stats have been initialized"); 192 return false; 193 } 194 195 if ((flags & display) && name.empty()) { 196 panic("all printable stats must be named"); 197 return false; 198 } 199 200 return true; 201} 202 203void 204Info::enable() 205{ 206} 207 208void 209VectorInfo::enable() 210{ 211 size_type s = size(); 212 if (subnames.size() < s) 213 subnames.resize(s); 214 if (subdescs.size() < s) 215 subdescs.resize(s); 216} 217 218void 219VectorDistInfo::enable() 220{ 221 size_type s = size(); 222 if (subnames.size() < s) 223 subnames.resize(s); 224 if (subdescs.size() < s) 225 subdescs.resize(s); 226} 227 228void 229Vector2dInfo::enable() 230{ 231 if (subnames.size() < x) 232 subnames.resize(x); 233 if (subdescs.size() < x) 234 subdescs.resize(x); 235 if (y_subnames.size() < y) 236 y_subnames.resize(y); 237} 238 239void 240HistStor::grow_out() 241{ 242 int size = cvec.size(); 243 int zero = size / 2; // round down! 244 int top_half = zero + (size - zero + 1) / 2; // round up! 245 int bottom_half = (size - zero) / 2; // round down! 246 247 // grow down 248 int low_pair = zero - 1; 249 for (int i = zero - 1; i >= bottom_half; i--) { 250 cvec[i] = cvec[low_pair]; 251 if (low_pair - 1 >= 0) 252 cvec[i] += cvec[low_pair - 1]; 253 low_pair -= 2; 254 } 255 assert(low_pair == 0 || low_pair == -1 || low_pair == -2); 256 257 for (int i = bottom_half - 1; i >= 0; i--) 258 cvec[i] = Counter(); 259 260 // grow up 261 int high_pair = zero; 262 for (int i = zero; i < top_half; i++) { 263 cvec[i] = cvec[high_pair]; 264 if (high_pair + 1 < size) 265 cvec[i] += cvec[high_pair + 1]; 266 high_pair += 2; 267 } 268 assert(high_pair == size || high_pair == size + 1); 269 270 for (int i = top_half; i < size; i++) 271 cvec[i] = Counter(); 272 273 max_bucket *= 2; 274 min_bucket *= 2; 275 bucket_size *= 2; 276} 277 278void 279HistStor::grow_convert() 280{ 281 int size = cvec.size(); 282 int half = (size + 1) / 2; // round up! 283 //bool even = (size & 1) == 0; 284 285 int pair = size - 1; 286 for (int i = size - 1; i >= half; --i) { 287 cvec[i] = cvec[pair]; 288 if (pair - 1 >= 0) 289 cvec[i] += cvec[pair - 1]; 290 pair -= 2; 291 } 292 293 for (int i = half - 1; i >= 0; i--) 294 cvec[i] = Counter(); 295 296 min_bucket = -max_bucket;// - (even ? bucket_size : 0); 297 bucket_size *= 2; 298} 299 300void 301HistStor::grow_up() 302{ 303 int size = cvec.size(); 304 int half = (size + 1) / 2; // round up! 305 306 int pair = 0; 307 for (int i = 0; i < half; i++) { 308 cvec[i] = cvec[pair]; 309 if (pair + 1 < size) 310 cvec[i] += cvec[pair + 1]; 311 pair += 2; 312 } 313 assert(pair == size || pair == size + 1); 314 315 for (int i = half; i < size; i++) 316 cvec[i] = Counter(); 317 318 max_bucket *= 2; 319 bucket_size *= 2; 320} 321 322Formula::Formula() 323{ 324} 325 326Formula::Formula(Temp r) 327{ 328 root = r; 329 setInit(); 330 assert(size()); 331} 332 333const Formula & 334Formula::operator=(Temp r) 335{ 336 assert(!root && "Can't change formulas"); 337 root = r; 338 setInit(); 339 assert(size()); 340 return *this; 341} 342 343const Formula & 344Formula::operator+=(Temp r) 345{ 346 if (root) 347 root = NodePtr(new BinaryNode<std::plus<Result> >(root, r)); 348 else { 349 root = r; 350 setInit(); 351 } 352 353 assert(size()); 354 return *this; 355} 356 357void 358Formula::result(VResult &vec) const 359{ 360 if (root) 361 vec = root->result(); 362} 363 364Result 365Formula::total() const 366{ 367 return root ? root->total() : 0.0; 368} 369 370size_type 371Formula::size() const 372{ 373 if (!root) 374 return 0; 375 else 376 return root->size(); 377} 378 379void 380Formula::reset() 381{ 382} 383 384bool 385Formula::zero() const 386{ 387 VResult vec; 388 result(vec); 389 for (VResult::size_type i = 0; i < vec.size(); ++i) 390 if (vec[i] != 0.0) 391 return false; 392 return true; 393} 394 395string 396Formula::str() const 397{ 398 return root ? root->str() : ""; 399} 400 401void 402enable() 403{ 404 typedef list<Info *>::iterator iter_t; 405 406 iter_t i, end = statsList().end(); 407 for (i = statsList().begin(); i != end; ++i) { 408 Info *info = *i; 409 assert(info); 410 if (!info->check() || !info->baseCheck()) 411 panic("stat check failed for '%s' %d\n", info->name, info->id); 412 } 413 414 off_t j = 0; 415 for (i = statsList().begin(); i != end; ++i) { 416 Info *info = *i; 417 if (!(info->flags & display)) 418 info->name = "__Stat" + to_string(j++); 419 } 420 421 statsList().sort(Info::less); 422 423 for (i = statsList().begin(); i != end; ++i) { 424 Info *info = *i; 425 info->enable(); 426 } 427} 428 429void 430prepare() 431{ 432 list<Info *>::iterator i = statsList().begin(); 433 list<Info *>::iterator end = statsList().end(); 434 while (i != end) { 435 Info *info = *i; 436 info->prepare(); 437 ++i; 438 } 439} 440 441CallbackQueue resetQueue; 442 443void 444reset() 445{ 446 list<Info *>::iterator i = statsList().begin(); 447 list<Info *>::iterator end = statsList().end(); 448 while (i != end) { 449 Info *info = *i; 450 info->reset(); 451 ++i; 452 } 453 454 resetQueue.process(); 455} 456 457void 458registerResetCallback(Callback *cb) 459{ 460 resetQueue.add(cb); 461} 462 463} // namespace Stats 464