statistics.cc revision 5887
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" 452SN/A 462SN/Ausing namespace std; 472SN/A 48729SN/Anamespace Stats { 49388SN/A 505887Snate@binkert.orgtypedef map<const void *, Info *> MapType; 515887Snate@binkert.org 525887Snate@binkert.org// We wrap these in a function to make sure they're built in time. 535887Snate@binkert.orglist<Info *> & 545887Snate@binkert.orgstatsList() 55388SN/A{ 565887Snate@binkert.org static list<Info *> the_list; 575887Snate@binkert.org return the_list; 58388SN/A} 59388SN/A 605887Snate@binkert.orgMapType & 615887Snate@binkert.orgstatsMap() 62441SN/A{ 635887Snate@binkert.org static MapType the_map; 645887Snate@binkert.org return the_map; 65441SN/A} 66441SN/A 67388SN/Avoid 685886Snate@binkert.orgInfoAccess::setInfo(Info *info) 69388SN/A{ 705887Snate@binkert.org if (statsMap().find(this) != statsMap().end()) 715887Snate@binkert.org panic("shouldn't register stat twice!"); 725887Snate@binkert.org 735887Snate@binkert.org statsList().push_back(info); 745887Snate@binkert.org 755887Snate@binkert.org#ifndef NDEBUG 765887Snate@binkert.org pair<MapType::iterator, bool> result = 775887Snate@binkert.org#endif 785887Snate@binkert.org statsMap().insert(make_pair(this, info)); 795887Snate@binkert.org assert(result.second && "this should never fail"); 805887Snate@binkert.org assert(statsMap().find(this) != statsMap().end()); 81388SN/A} 82388SN/A 83388SN/Avoid 845886Snate@binkert.orgInfoAccess::setInit() 85388SN/A{ 865886Snate@binkert.org info()->flags |= init; 87388SN/A} 88388SN/A 895886Snate@binkert.orgInfo * 905886Snate@binkert.orgInfoAccess::info() 91388SN/A{ 925887Snate@binkert.org MapType::const_iterator i = statsMap().find(this); 935887Snate@binkert.org assert(i != statsMap().end()); 945887Snate@binkert.org return (*i).second; 95388SN/A} 96388SN/A 975886Snate@binkert.orgconst Info * 985886Snate@binkert.orgInfoAccess::info() const 995886Snate@binkert.org{ 1005887Snate@binkert.org MapType::const_iterator i = statsMap().find(this); 1015887Snate@binkert.org assert(i != statsMap().end()); 1025887Snate@binkert.org return (*i).second; 1035886Snate@binkert.org} 1045886Snate@binkert.org 1055886Snate@binkert.orgInfo::Info() 106582SN/A : flags(none), precision(-1), prereq(0) 107582SN/A{ 108695SN/A static int count = 0; 109695SN/A id = count++; 110582SN/A} 111582SN/A 1125886Snate@binkert.orgInfo::~Info() 113388SN/A{ 114388SN/A} 115388SN/A 1162SN/Abool 1175886Snate@binkert.orgInfo::less(Info *stat1, Info *stat2) 1182SN/A{ 119388SN/A const string &name1 = stat1->name; 120388SN/A const string &name2 = stat2->name; 1212SN/A 1222SN/A vector<string> v1; 1232SN/A vector<string> v2; 1242SN/A 1252SN/A tokenize(v1, name1, '.'); 1262SN/A tokenize(v2, name2, '.'); 1272SN/A 1285599Snate@binkert.org size_type last = min(v1.size(), v2.size()) - 1; 1295599Snate@binkert.org for (off_type i = 0; i < last; ++i) 1302SN/A if (v1[i] != v2[i]) 1312SN/A return v1[i] < v2[i]; 1322SN/A 1332SN/A // Special compare for last element. 1342SN/A if (v1[last] == v2[last]) 1352SN/A return v1.size() < v2.size(); 1362SN/A else 1372SN/A return v1[last] < v2[last]; 1382SN/A 1392SN/A return false; 1402SN/A} 1412SN/A 142388SN/Abool 1435886Snate@binkert.orgInfo::baseCheck() const 1442SN/A{ 145434SN/A if (!(flags & init)) { 146582SN/A#ifdef DEBUG 147695SN/A cprintf("this is stat number %d\n", id); 148388SN/A#endif 149388SN/A panic("Not all stats have been initialized"); 150388SN/A return false; 151388SN/A } 1522SN/A 153434SN/A if ((flags & print) && name.empty()) { 154388SN/A panic("all printable stats must be named"); 155388SN/A return false; 156388SN/A } 1572SN/A 158388SN/A return true; 1592SN/A} 1602SN/A 161695SN/A 162695SN/Avoid 163695SN/AFormulaBase::result(VResult &vec) const 1642SN/A{ 165695SN/A if (root) 166695SN/A vec = root->result(); 1672SN/A} 1682SN/A 169695SN/AResult 170388SN/AFormulaBase::total() const 171388SN/A{ 172456SN/A return root ? root->total() : 0.0; 173388SN/A} 174388SN/A 1755599Snate@binkert.orgsize_type 176388SN/AFormulaBase::size() const 177388SN/A{ 178388SN/A if (!root) 179388SN/A return 0; 180388SN/A else 181388SN/A return root->size(); 182388SN/A} 183388SN/A 184388SN/Avoid 185388SN/AFormulaBase::reset() 186388SN/A{ 187388SN/A} 188388SN/A 189388SN/Abool 190388SN/AFormulaBase::zero() const 191388SN/A{ 192695SN/A VResult vec; 193695SN/A result(vec); 1945599Snate@binkert.org for (off_t i = 0; i < vec.size(); ++i) 195388SN/A if (vec[i] != 0.0) 196388SN/A return false; 197388SN/A return true; 198388SN/A} 199388SN/A 200388SN/Avoid 2015886Snate@binkert.orgFormulaBase::update(Info *) 202388SN/A{ 203388SN/A} 204388SN/A 205441SN/Astring 206441SN/AFormulaBase::str() const 207441SN/A{ 208441SN/A return root ? root->str() : ""; 209441SN/A} 210441SN/A 211388SN/AFormula::Formula() 212388SN/A{ 213388SN/A setInit(); 214388SN/A} 215388SN/A 216388SN/AFormula::Formula(Temp r) 217388SN/A{ 218388SN/A root = r; 219388SN/A assert(size()); 220388SN/A} 221388SN/A 222388SN/Aconst Formula & 223388SN/AFormula::operator=(Temp r) 224388SN/A{ 225388SN/A assert(!root && "Can't change formulas"); 226388SN/A root = r; 227388SN/A assert(size()); 228388SN/A return *this; 229388SN/A} 230388SN/A 231388SN/Aconst Formula & 232388SN/AFormula::operator+=(Temp r) 233388SN/A{ 234388SN/A if (root) 235695SN/A root = NodePtr(new BinaryNode<std::plus<Result> >(root, r)); 236388SN/A else 237388SN/A root = r; 238388SN/A assert(size()); 239388SN/A return *this; 240388SN/A} 241388SN/A 242142SN/Avoid 2432SN/Acheck() 2442SN/A{ 2455887Snate@binkert.org typedef list<Info *>::iterator iter_t; 246695SN/A 2475887Snate@binkert.org iter_t i, end = statsList().end(); 2485887Snate@binkert.org for (i = statsList().begin(); i != end; ++i) { 2495886Snate@binkert.org Info *info = *i; 2505886Snate@binkert.org assert(info); 2515886Snate@binkert.org if (!info->check() || !info->baseCheck()) 2525886Snate@binkert.org panic("stat check failed for %s\n", info->name); 253695SN/A } 254695SN/A 2555599Snate@binkert.org off_t j = 0; 2565887Snate@binkert.org for (i = statsList().begin(); i != end; ++i) { 2575886Snate@binkert.org Info *info = *i; 2585886Snate@binkert.org if (!(info->flags & print)) 2595886Snate@binkert.org info->name = "__Stat" + to_string(j++); 260695SN/A } 261695SN/A 2625887Snate@binkert.org statsList().sort(Info::less); 263695SN/A 264695SN/A if (i == end) 265695SN/A return; 266695SN/A 267695SN/A iter_t last = i; 268695SN/A ++i; 269695SN/A 2705887Snate@binkert.org for (i = statsList().begin(); i != end; ++i) { 271695SN/A if ((*i)->name == (*last)->name) 272695SN/A panic("same name used twice! name=%s\n", (*i)->name); 273695SN/A 274695SN/A last = i; 275695SN/A } 2762SN/A} 2772SN/A 278695SN/ACallbackQueue resetQueue; 2792SN/A 280456SN/Avoid 281695SN/Areset() 282456SN/A{ 2835887Snate@binkert.org list<Info *>::iterator i = statsList().begin(); 2845887Snate@binkert.org list<Info *>::iterator end = statsList().end(); 285695SN/A while (i != end) { 2865886Snate@binkert.org Info *info = *i; 2875886Snate@binkert.org info->reset(); 288695SN/A ++i; 289695SN/A } 290695SN/A 291695SN/A resetQueue.process(); 292456SN/A} 293456SN/A 294456SN/Avoid 295394SN/AregisterResetCallback(Callback *cb) 296148SN/A{ 297148SN/A resetQueue.add(cb); 298148SN/A} 299148SN/A 300729SN/A/* namespace Stats */ } 301