statistics.cc revision 9554:406fbcf60223
16876Ssteve.reinhardt@amd.com/* 210089Sandreas.hansson@arm.com * Copyright (c) 2003-2005 The Regents of The University of Michigan 38922Swilliam.wang@arm.com * All rights reserved. 48922Swilliam.wang@arm.com * 58922Swilliam.wang@arm.com * Redistribution and use in source and binary forms, with or without 68922Swilliam.wang@arm.com * modification, are permitted provided that the following conditions are 78922Swilliam.wang@arm.com * met: redistributions of source code must retain the above copyright 88922Swilliam.wang@arm.com * notice, this list of conditions and the following disclaimer; 98922Swilliam.wang@arm.com * redistributions in binary form must reproduce the above copyright 108922Swilliam.wang@arm.com * notice, this list of conditions and the following disclaimer in the 118922Swilliam.wang@arm.com * documentation and/or other materials provided with the distribution; 128922Swilliam.wang@arm.com * neither the name of the copyright holders nor the names of its 138922Swilliam.wang@arm.com * contributors may be used to endorse or promote products derived from 146876Ssteve.reinhardt@amd.com * this software without specific prior written permission. 158717Snilay@cs.wisc.edu * 166876Ssteve.reinhardt@amd.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 176876Ssteve.reinhardt@amd.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 186876Ssteve.reinhardt@amd.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 196876Ssteve.reinhardt@amd.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 206876Ssteve.reinhardt@amd.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 216876Ssteve.reinhardt@amd.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 226876Ssteve.reinhardt@amd.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 236876Ssteve.reinhardt@amd.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 246876Ssteve.reinhardt@amd.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 256876Ssteve.reinhardt@amd.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 266876Ssteve.reinhardt@amd.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 276876Ssteve.reinhardt@amd.com * 286876Ssteve.reinhardt@amd.com * Authors: Nathan Binkert 296876Ssteve.reinhardt@amd.com */ 306876Ssteve.reinhardt@amd.com 316876Ssteve.reinhardt@amd.com#include <fstream> 326876Ssteve.reinhardt@amd.com#include <iomanip> 336876Ssteve.reinhardt@amd.com#include <list> 346876Ssteve.reinhardt@amd.com#include <map> 356876Ssteve.reinhardt@amd.com#include <string> 366876Ssteve.reinhardt@amd.com 376876Ssteve.reinhardt@amd.com#include "base/callback.hh" 386876Ssteve.reinhardt@amd.com#include "base/cprintf.hh" 396876Ssteve.reinhardt@amd.com#include "base/debug.hh" 406876Ssteve.reinhardt@amd.com#include "base/hostinfo.hh" 416876Ssteve.reinhardt@amd.com#include "base/misc.hh" 427039Snate@binkert.org#include "base/statistics.hh" 437039Snate@binkert.org#include "base/str.hh" 446285Snate@binkert.org#include "base/time.hh" 457039Snate@binkert.org#include "base/trace.hh" 466285Snate@binkert.org 476285Snate@binkert.orgusing namespace std; 486922SBrad.Beckmann@amd.com 4910301Snilay@cs.wisc.edunamespace Stats { 507909Shestness@cs.utexas.edu 518229Snate@binkert.orgstd::string Info::separatorString = "::"; 527039Snate@binkert.org 536876Ssteve.reinhardt@amd.com// We wrap these in a function to make sure they're built in time. 546876Ssteve.reinhardt@amd.comlist<Info *> & 556876Ssteve.reinhardt@amd.comstatsList() 566876Ssteve.reinhardt@amd.com{ 577039Snate@binkert.org static list<Info *> the_list; 587039Snate@binkert.org return the_list; 597039Snate@binkert.org} 6010090Snilay@cs.wisc.edu 6110090Snilay@cs.wisc.eduMapType & 6210090Snilay@cs.wisc.edustatsMap() 6310713Sandreas.hansson@arm.com{ 6410713Sandreas.hansson@arm.com static MapType the_map; 6510090Snilay@cs.wisc.edu return the_map; 6610090Snilay@cs.wisc.edu} 6710090Snilay@cs.wisc.edu 6810090Snilay@cs.wisc.eduvoid 6910090Snilay@cs.wisc.eduInfoAccess::setInfo(Info *info) 7010090Snilay@cs.wisc.edu{ 7110090Snilay@cs.wisc.edu if (statsMap().find(this) != statsMap().end()) 7210090Snilay@cs.wisc.edu panic("shouldn't register stat twice!"); 7310090Snilay@cs.wisc.edu 7410090Snilay@cs.wisc.edu statsList().push_back(info); 756882SBrad.Beckmann@amd.com 767039Snate@binkert.org#ifndef NDEBUG 7710713Sandreas.hansson@arm.com pair<MapType::iterator, bool> result = 788436SBrad.Beckmann@amd.com#endif 7910525Snilay@cs.wisc.edu statsMap().insert(make_pair(this, info)); 806882SBrad.Beckmann@amd.com assert(result.second && "this should never fail"); 816882SBrad.Beckmann@amd.com assert(statsMap().find(this) != statsMap().end()); 8210090Snilay@cs.wisc.edu} 8310525Snilay@cs.wisc.edu 846882SBrad.Beckmann@amd.comvoid 858717Snilay@cs.wisc.eduInfoAccess::setParams(const StorageParams *params) 866882SBrad.Beckmann@amd.com{ 876882SBrad.Beckmann@amd.com info()->storageParams = params; 8810089Sandreas.hansson@arm.com} 8910090Snilay@cs.wisc.edu 9010090Snilay@cs.wisc.eduvoid 9110090Snilay@cs.wisc.eduInfoAccess::setInit() 9210090Snilay@cs.wisc.edu{ 9310089Sandreas.hansson@arm.com info()->flags.set(init); 9410090Snilay@cs.wisc.edu} 9510090Snilay@cs.wisc.edu 9610090Snilay@cs.wisc.eduInfo * 976882SBrad.Beckmann@amd.comInfoAccess::info() 986882SBrad.Beckmann@amd.com{ 9910089Sandreas.hansson@arm.com MapType::const_iterator i = statsMap().find(this); 1006882SBrad.Beckmann@amd.com assert(i != statsMap().end()); 1016882SBrad.Beckmann@amd.com return (*i).second; 10210090Snilay@cs.wisc.edu} 1036882SBrad.Beckmann@amd.com 1047039Snate@binkert.orgconst Info * 10510713Sandreas.hansson@arm.comInfoAccess::info() const 10610713Sandreas.hansson@arm.com{ 1078914Sandreas.hansson@arm.com MapType::const_iterator i = statsMap().find(this); 1086882SBrad.Beckmann@amd.com assert(i != statsMap().end()); 10910090Snilay@cs.wisc.edu return (*i).second; 1106882SBrad.Beckmann@amd.com} 1116882SBrad.Beckmann@amd.com 11210090Snilay@cs.wisc.eduStorageParams::~StorageParams() 11310090Snilay@cs.wisc.edu{ 1146882SBrad.Beckmann@amd.com} 1156882SBrad.Beckmann@amd.com 11610090Snilay@cs.wisc.eduNameMapType & 11710090Snilay@cs.wisc.edunameMap() 11810090Snilay@cs.wisc.edu{ 11910713Sandreas.hansson@arm.com static NameMapType the_map; 12010090Snilay@cs.wisc.edu return the_map; 12110090Snilay@cs.wisc.edu} 12210090Snilay@cs.wisc.edu 12310090Snilay@cs.wisc.eduint Info::id_count = 0; 12410090Snilay@cs.wisc.edu 12510090Snilay@cs.wisc.eduint debug_break_id = -1; 12610090Snilay@cs.wisc.edu 12710090Snilay@cs.wisc.eduInfo::Info() 12810090Snilay@cs.wisc.edu : flags(none), precision(-1), prereq(0), storageParams(NULL) 12910090Snilay@cs.wisc.edu{ 13010090Snilay@cs.wisc.edu id = id_count++; 13110090Snilay@cs.wisc.edu if (debug_break_id >= 0 and debug_break_id == id) 13210090Snilay@cs.wisc.edu Debug::breakpoint(); 13310090Snilay@cs.wisc.edu} 13410090Snilay@cs.wisc.edu 13510090Snilay@cs.wisc.eduInfo::~Info() 13610090Snilay@cs.wisc.edu{ 13710090Snilay@cs.wisc.edu} 13810090Snilay@cs.wisc.edu 13910090Snilay@cs.wisc.edubool 14010090Snilay@cs.wisc.eduvalidateStatName(const string &name) 14110090Snilay@cs.wisc.edu{ 14210090Snilay@cs.wisc.edu if (name.empty()) 1436876Ssteve.reinhardt@amd.com return false; 1446876Ssteve.reinhardt@amd.com 1456882SBrad.Beckmann@amd.com vector<string> vec; 1466882SBrad.Beckmann@amd.com tokenize(vec, name, '.'); 1476882SBrad.Beckmann@amd.com vector<string>::const_iterator item = vec.begin(); 1486285Snate@binkert.org while (item != vec.end()) { 1499294Sandreas.hansson@arm.com if (item->empty()) 1509294Sandreas.hansson@arm.com return false; 1519294Sandreas.hansson@arm.com 1529294Sandreas.hansson@arm.com string::const_iterator c = item->begin(); 1536876Ssteve.reinhardt@amd.com 1548615Snilay@cs.wisc.edu // The first character is different 1558688Snilay@cs.wisc.edu if (!isalpha(*c) && *c != '_') 1568688Snilay@cs.wisc.edu return false; 1578688Snilay@cs.wisc.edu 1586882SBrad.Beckmann@amd.com // The rest of the characters have different rules. 1596882SBrad.Beckmann@amd.com while (++c != item->end()) { 1606882SBrad.Beckmann@amd.com if (!isalnum(*c) && *c != '_') 1616882SBrad.Beckmann@amd.com return false; 1626882SBrad.Beckmann@amd.com } 1636882SBrad.Beckmann@amd.com 16410012Snilay@cs.wisc.edu ++item; 1659342SAndreas.Sandberg@arm.com } 1666285Snate@binkert.org 1677039Snate@binkert.org return true; 1687039Snate@binkert.org} 1698688Snilay@cs.wisc.edu 1708717Snilay@cs.wisc.eduvoid 1716285Snate@binkert.orgInfo::setName(const string &name) 17210089Sandreas.hansson@arm.com{ 17310089Sandreas.hansson@arm.com if (!validateStatName(name)) 17410089Sandreas.hansson@arm.com panic("invalid stat name '%s'", name); 17510089Sandreas.hansson@arm.com 17610089Sandreas.hansson@arm.com pair<NameMapType::iterator, bool> p = 17710089Sandreas.hansson@arm.com nameMap().insert(make_pair(name, this)); 17810089Sandreas.hansson@arm.com 17910089Sandreas.hansson@arm.com Info *other = p.first->second; 18010089Sandreas.hansson@arm.com bool result = p.second; 18110089Sandreas.hansson@arm.com 18210012Snilay@cs.wisc.edu if (!result) { 1837039Snate@binkert.org // using other->name instead of just name to avoid a compiler 1847039Snate@binkert.org // warning. They should be the same. 1857910SBrad.Beckmann@amd.com panic("same statistic name used twice! name=%s\n", other->name); 18610467Sandreas.hansson@arm.com } 1876876Ssteve.reinhardt@amd.com 1887039Snate@binkert.org this->name = name; 18910090Snilay@cs.wisc.edu} 1907910SBrad.Beckmann@amd.com 19110089Sandreas.hansson@arm.combool 19210089Sandreas.hansson@arm.comInfo::less(Info *stat1, Info *stat2) 19310089Sandreas.hansson@arm.com{ 1947910SBrad.Beckmann@amd.com const string &name1 = stat1->name; 1957910SBrad.Beckmann@amd.com const string &name2 = stat2->name; 1969342SAndreas.Sandberg@arm.com 1978688Snilay@cs.wisc.edu vector<string> v1; 19810090Snilay@cs.wisc.edu vector<string> v2; 19910090Snilay@cs.wisc.edu 20010090Snilay@cs.wisc.edu tokenize(v1, name1, '.'); 20110090Snilay@cs.wisc.edu tokenize(v2, name2, '.'); 20210090Snilay@cs.wisc.edu 20310090Snilay@cs.wisc.edu size_type last = min(v1.size(), v2.size()) - 1; 2048922Swilliam.wang@arm.com for (off_type i = 0; i < last; ++i) 20510090Snilay@cs.wisc.edu if (v1[i] != v2[i]) 20610090Snilay@cs.wisc.edu return v1[i] < v2[i]; 20710090Snilay@cs.wisc.edu 2088686Snilay@cs.wisc.edu // Special compare for last element. 2099342SAndreas.Sandberg@arm.com if (v1[last] == v2[last]) 2107910SBrad.Beckmann@amd.com return v1.size() < v2.size(); 2117910SBrad.Beckmann@amd.com else 2127910SBrad.Beckmann@amd.com return v1[last] < v2[last]; 2137910SBrad.Beckmann@amd.com 2147910SBrad.Beckmann@amd.com return false; 21510090Snilay@cs.wisc.edu} 2166285Snate@binkert.org 2176285Snate@binkert.orgbool 2187039Snate@binkert.orgInfo::baseCheck() const 219{ 220 if (!(flags & Stats::init)) { 221#ifdef DEBUG 222 cprintf("this is stat number %d\n", id); 223#endif 224 panic("Not all stats have been initialized"); 225 return false; 226 } 227 228 if ((flags & display) && name.empty()) { 229 panic("all printable stats must be named"); 230 return false; 231 } 232 233 return true; 234} 235 236void 237Info::enable() 238{ 239} 240 241void 242VectorInfo::enable() 243{ 244 size_type s = size(); 245 if (subnames.size() < s) 246 subnames.resize(s); 247 if (subdescs.size() < s) 248 subdescs.resize(s); 249} 250 251void 252VectorDistInfo::enable() 253{ 254 size_type s = size(); 255 if (subnames.size() < s) 256 subnames.resize(s); 257 if (subdescs.size() < s) 258 subdescs.resize(s); 259} 260 261void 262Vector2dInfo::enable() 263{ 264 if (subnames.size() < x) 265 subnames.resize(x); 266 if (subdescs.size() < x) 267 subdescs.resize(x); 268 if (y_subnames.size() < y) 269 y_subnames.resize(y); 270} 271 272void 273HistStor::grow_out() 274{ 275 int size = cvec.size(); 276 int zero = size / 2; // round down! 277 int top_half = zero + (size - zero + 1) / 2; // round up! 278 int bottom_half = (size - zero) / 2; // round down! 279 280 // grow down 281 int low_pair = zero - 1; 282 for (int i = zero - 1; i >= bottom_half; i--) { 283 cvec[i] = cvec[low_pair]; 284 if (low_pair - 1 >= 0) 285 cvec[i] += cvec[low_pair - 1]; 286 low_pair -= 2; 287 } 288 assert(low_pair == 0 || low_pair == -1 || low_pair == -2); 289 290 for (int i = bottom_half - 1; i >= 0; i--) 291 cvec[i] = Counter(); 292 293 // grow up 294 int high_pair = zero; 295 for (int i = zero; i < top_half; i++) { 296 cvec[i] = cvec[high_pair]; 297 if (high_pair + 1 < size) 298 cvec[i] += cvec[high_pair + 1]; 299 high_pair += 2; 300 } 301 assert(high_pair == size || high_pair == size + 1); 302 303 for (int i = top_half; i < size; i++) 304 cvec[i] = Counter(); 305 306 max_bucket *= 2; 307 min_bucket *= 2; 308 bucket_size *= 2; 309} 310 311void 312HistStor::grow_convert() 313{ 314 int size = cvec.size(); 315 int half = (size + 1) / 2; // round up! 316 //bool even = (size & 1) == 0; 317 318 int pair = size - 1; 319 for (int i = size - 1; i >= half; --i) { 320 cvec[i] = cvec[pair]; 321 if (pair - 1 >= 0) 322 cvec[i] += cvec[pair - 1]; 323 pair -= 2; 324 } 325 326 for (int i = half - 1; i >= 0; i--) 327 cvec[i] = Counter(); 328 329 min_bucket = -max_bucket;// - (even ? bucket_size : 0); 330 bucket_size *= 2; 331} 332 333void 334HistStor::grow_up() 335{ 336 int size = cvec.size(); 337 int half = (size + 1) / 2; // round up! 338 339 int pair = 0; 340 for (int i = 0; i < half; i++) { 341 cvec[i] = cvec[pair]; 342 if (pair + 1 < size) 343 cvec[i] += cvec[pair + 1]; 344 pair += 2; 345 } 346 assert(pair == size || pair == size + 1); 347 348 for (int i = half; i < size; i++) 349 cvec[i] = Counter(); 350 351 max_bucket *= 2; 352 bucket_size *= 2; 353} 354 355Formula::Formula() 356{ 357} 358 359Formula::Formula(Temp r) 360{ 361 root = r; 362 setInit(); 363 assert(size()); 364} 365 366const Formula & 367Formula::operator=(Temp r) 368{ 369 assert(!root && "Can't change formulas"); 370 root = r; 371 setInit(); 372 assert(size()); 373 return *this; 374} 375 376const Formula & 377Formula::operator+=(Temp r) 378{ 379 if (root) 380 root = NodePtr(new BinaryNode<std::plus<Result> >(root, r)); 381 else { 382 root = r; 383 setInit(); 384 } 385 386 assert(size()); 387 return *this; 388} 389 390void 391Formula::result(VResult &vec) const 392{ 393 if (root) 394 vec = root->result(); 395} 396 397Result 398Formula::total() const 399{ 400 return root ? root->total() : 0.0; 401} 402 403size_type 404Formula::size() const 405{ 406 if (!root) 407 return 0; 408 else 409 return root->size(); 410} 411 412void 413Formula::reset() 414{ 415} 416 417bool 418Formula::zero() const 419{ 420 VResult vec; 421 result(vec); 422 for (VResult::size_type i = 0; i < vec.size(); ++i) 423 if (vec[i] != 0.0) 424 return false; 425 return true; 426} 427 428string 429Formula::str() const 430{ 431 return root ? root->str() : ""; 432} 433 434CallbackQueue dumpQueue; 435CallbackQueue resetQueue; 436 437void 438registerResetCallback(Callback *cb) 439{ 440 resetQueue.add(cb); 441} 442 443bool _enabled = false; 444 445bool 446enabled() 447{ 448 return _enabled; 449} 450 451void 452enable() 453{ 454 if (_enabled) 455 fatal("Stats are already enabled"); 456 457 _enabled = true; 458} 459 460void 461registerDumpCallback(Callback *cb) 462{ 463 dumpQueue.add(cb); 464} 465 466} // namespace Stats 467 468void 469debugDumpStats() 470{ 471 Stats::dump(); 472} 473