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#include "base/stats/statdb.hh"
| 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#include "base/stats/statdb.hh"
|
46#include "config/stats_binning.hh"
| |
47 48using namespace std; 49 50namespace Stats { 51 52StatData * 53DataAccess::find() const 54{ 55 return Database::find(const_cast<void *>((const void *)this)); 56} 57 58const StatData * 59getStatData(const void *stat) 60{ 61 return Database::find(const_cast<void *>(stat)); 62} 63 64void 65DataAccess::map(StatData *data) 66{ 67 Database::regStat(this, data); 68} 69 70StatData * 71DataAccess::statData() 72{ 73 StatData *ptr = find(); 74 assert(ptr); 75 return ptr; 76} 77 78const StatData * 79DataAccess::statData() const 80{ 81 const StatData *ptr = find(); 82 assert(ptr); 83 return ptr; 84} 85 86void 87DataAccess::setInit() 88{ 89 statData()->flags |= init; 90} 91 92void 93DataAccess::setPrint() 94{ 95 Database::regPrint(this); 96} 97 98StatData::StatData() 99 : flags(none), precision(-1), prereq(0) 100{ 101 static int count = 0; 102 id = count++; 103} 104 105StatData::~StatData() 106{ 107} 108 109bool 110StatData::less(StatData *stat1, StatData *stat2) 111{ 112 const string &name1 = stat1->name; 113 const string &name2 = stat2->name; 114 115 vector<string> v1; 116 vector<string> v2; 117 118 tokenize(v1, name1, '.'); 119 tokenize(v2, name2, '.'); 120 121 int last = min(v1.size(), v2.size()) - 1; 122 for (int i = 0; i < last; ++i) 123 if (v1[i] != v2[i]) 124 return v1[i] < v2[i]; 125 126 // Special compare for last element. 127 if (v1[last] == v2[last]) 128 return v1.size() < v2.size(); 129 else 130 return v1[last] < v2[last]; 131 132 return false; 133} 134 135bool 136StatData::baseCheck() const 137{ 138 if (!(flags & init)) { 139#ifdef DEBUG 140 cprintf("this is stat number %d\n", id); 141#endif 142 panic("Not all stats have been initialized"); 143 return false; 144 } 145 146 if ((flags & print) && name.empty()) { 147 panic("all printable stats must be named"); 148 return false; 149 } 150 151 return true; 152} 153 154 155void 156FormulaBase::result(VResult &vec) const 157{ 158 if (root) 159 vec = root->result(); 160} 161 162Result 163FormulaBase::total() const 164{ 165 return root ? root->total() : 0.0; 166} 167 168size_t 169FormulaBase::size() const 170{ 171 if (!root) 172 return 0; 173 else 174 return root->size(); 175} 176
| 46 47using namespace std; 48 49namespace Stats { 50 51StatData * 52DataAccess::find() const 53{ 54 return Database::find(const_cast<void *>((const void *)this)); 55} 56 57const StatData * 58getStatData(const void *stat) 59{ 60 return Database::find(const_cast<void *>(stat)); 61} 62 63void 64DataAccess::map(StatData *data) 65{ 66 Database::regStat(this, data); 67} 68 69StatData * 70DataAccess::statData() 71{ 72 StatData *ptr = find(); 73 assert(ptr); 74 return ptr; 75} 76 77const StatData * 78DataAccess::statData() const 79{ 80 const StatData *ptr = find(); 81 assert(ptr); 82 return ptr; 83} 84 85void 86DataAccess::setInit() 87{ 88 statData()->flags |= init; 89} 90 91void 92DataAccess::setPrint() 93{ 94 Database::regPrint(this); 95} 96 97StatData::StatData() 98 : flags(none), precision(-1), prereq(0) 99{ 100 static int count = 0; 101 id = count++; 102} 103 104StatData::~StatData() 105{ 106} 107 108bool 109StatData::less(StatData *stat1, StatData *stat2) 110{ 111 const string &name1 = stat1->name; 112 const string &name2 = stat2->name; 113 114 vector<string> v1; 115 vector<string> v2; 116 117 tokenize(v1, name1, '.'); 118 tokenize(v2, name2, '.'); 119 120 int last = min(v1.size(), v2.size()) - 1; 121 for (int i = 0; i < last; ++i) 122 if (v1[i] != v2[i]) 123 return v1[i] < v2[i]; 124 125 // Special compare for last element. 126 if (v1[last] == v2[last]) 127 return v1.size() < v2.size(); 128 else 129 return v1[last] < v2[last]; 130 131 return false; 132} 133 134bool 135StatData::baseCheck() const 136{ 137 if (!(flags & init)) { 138#ifdef DEBUG 139 cprintf("this is stat number %d\n", id); 140#endif 141 panic("Not all stats have been initialized"); 142 return false; 143 } 144 145 if ((flags & print) && name.empty()) { 146 panic("all printable stats must be named"); 147 return false; 148 } 149 150 return true; 151} 152 153 154void 155FormulaBase::result(VResult &vec) const 156{ 157 if (root) 158 vec = root->result(); 159} 160 161Result 162FormulaBase::total() const 163{ 164 return root ? root->total() : 0.0; 165} 166 167size_t 168FormulaBase::size() const 169{ 170 if (!root) 171 return 0; 172 else 173 return root->size(); 174} 175
|
177bool 178FormulaBase::binned() const 179{ 180 return root && root->binned(); 181} 182
| |
183void 184FormulaBase::reset() 185{ 186} 187 188bool 189FormulaBase::zero() const 190{ 191 VResult vec; 192 result(vec); 193 for (int i = 0; i < vec.size(); ++i) 194 if (vec[i] != 0.0) 195 return false; 196 return true; 197} 198 199void 200FormulaBase::update(StatData *) 201{ 202} 203 204string 205FormulaBase::str() const 206{ 207 return root ? root->str() : ""; 208} 209 210Formula::Formula() 211{ 212 setInit(); 213} 214 215Formula::Formula(Temp r) 216{ 217 root = r; 218 assert(size()); 219} 220 221const Formula & 222Formula::operator=(Temp r) 223{ 224 assert(!root && "Can't change formulas"); 225 root = r; 226 assert(size()); 227 return *this; 228} 229 230const Formula & 231Formula::operator+=(Temp r) 232{ 233 if (root) 234 root = NodePtr(new BinaryNode<std::plus<Result> >(root, r)); 235 else 236 root = r; 237 assert(size()); 238 return *this; 239} 240
| 176void 177FormulaBase::reset() 178{ 179} 180 181bool 182FormulaBase::zero() const 183{ 184 VResult vec; 185 result(vec); 186 for (int i = 0; i < vec.size(); ++i) 187 if (vec[i] != 0.0) 188 return false; 189 return true; 190} 191 192void 193FormulaBase::update(StatData *) 194{ 195} 196 197string 198FormulaBase::str() const 199{ 200 return root ? root->str() : ""; 201} 202 203Formula::Formula() 204{ 205 setInit(); 206} 207 208Formula::Formula(Temp r) 209{ 210 root = r; 211 assert(size()); 212} 213 214const Formula & 215Formula::operator=(Temp r) 216{ 217 assert(!root && "Can't change formulas"); 218 root = r; 219 assert(size()); 220 return *this; 221} 222 223const Formula & 224Formula::operator+=(Temp r) 225{ 226 if (root) 227 root = NodePtr(new BinaryNode<std::plus<Result> >(root, r)); 228 else 229 root = r; 230 assert(size()); 231 return *this; 232} 233
|
241MainBin::MainBin(const string &name) 242 : _name(name), mem(NULL), memsize(-1) 243{ 244 Database::regBin(this, name); 245} 246 247MainBin::~MainBin() 248{ 249 if (mem) 250 delete [] mem; 251} 252 253char * 254MainBin::memory(off_t off) 255{ 256 if (memsize == -1) 257 memsize = ceilPow2((size_t) offset()); 258 259 if (!mem) { 260 mem = new char[memsize]; 261 memset(mem, 0, memsize); 262 } 263 264 assert(offset() <= size()); 265 return mem + off; 266} 267
| |
268void 269check() 270{ 271 typedef Database::stat_list_t::iterator iter_t; 272 273 iter_t i, end = Database::stats().end(); 274 for (i = Database::stats().begin(); i != end; ++i) { 275 StatData *data = *i; 276 assert(data); 277 if (!data->check() || !data->baseCheck()) 278 panic("stat check failed for %s\n", data->name); 279 } 280 281 int j = 0; 282 for (i = Database::stats().begin(); i != end; ++i) { 283 StatData *data = *i; 284 if (!(data->flags & print)) 285 data->name = "__Stat" + to_string(j++); 286 } 287 288 Database::stats().sort(StatData::less); 289
| 234void 235check() 236{ 237 typedef Database::stat_list_t::iterator iter_t; 238 239 iter_t i, end = Database::stats().end(); 240 for (i = Database::stats().begin(); i != end; ++i) { 241 StatData *data = *i; 242 assert(data); 243 if (!data->check() || !data->baseCheck()) 244 panic("stat check failed for %s\n", data->name); 245 } 246 247 int j = 0; 248 for (i = Database::stats().begin(); i != end; ++i) { 249 StatData *data = *i; 250 if (!(data->flags & print)) 251 data->name = "__Stat" + to_string(j++); 252 } 253 254 Database::stats().sort(StatData::less); 255
|
290#if STATS_BINNING 291 if (MainBin::curBin() == NULL) { 292 static MainBin mainBin("main bin"); 293 mainBin.activate(); 294 } 295#endif 296
| |
297 if (i == end) 298 return; 299 300 iter_t last = i; 301 ++i; 302 303 for (i = Database::stats().begin(); i != end; ++i) { 304 if ((*i)->name == (*last)->name) 305 panic("same name used twice! name=%s\n", (*i)->name); 306 307 last = i; 308 } 309} 310 311CallbackQueue resetQueue; 312 313void 314reset() 315{
| 256 if (i == end) 257 return; 258 259 iter_t last = i; 260 ++i; 261 262 for (i = Database::stats().begin(); i != end; ++i) { 263 if ((*i)->name == (*last)->name) 264 panic("same name used twice! name=%s\n", (*i)->name); 265 266 last = i; 267 } 268} 269 270CallbackQueue resetQueue; 271 272void 273reset() 274{
|
316 // reset non-binned stats
| |
317 Database::stat_list_t::iterator i = Database::stats().begin(); 318 Database::stat_list_t::iterator end = Database::stats().end(); 319 while (i != end) { 320 StatData *data = *i;
| 275 Database::stat_list_t::iterator i = Database::stats().begin(); 276 Database::stat_list_t::iterator end = Database::stats().end(); 277 while (i != end) { 278 StatData *data = *i;
|
321 if (!data->binned()) 322 data->reset();
| 279 data->reset();
|
323 ++i; 324 } 325
| 280 ++i; 281 } 282
|
326 // save the bin so we can go back to where we were 327 MainBin *orig = MainBin::curBin(); 328 329 // reset binned stats 330 Database::bin_list_t::iterator bi = Database::bins().begin(); 331 Database::bin_list_t::iterator be = Database::bins().end(); 332 while (bi != be) { 333 MainBin *bin = *bi; 334 bin->activate(); 335 336 i = Database::stats().begin(); 337 while (i != end) { 338 StatData *data = *i; 339 if (data->binned()) 340 data->reset(); 341 ++i; 342 } 343 ++bi; 344 } 345 346 // restore bin 347 MainBin::curBin() = orig; 348
| |
349 resetQueue.process(); 350} 351 352void 353registerResetCallback(Callback *cb) 354{ 355 resetQueue.add(cb); 356} 357 358/* namespace Stats */ }
| 283 resetQueue.process(); 284} 285 286void 287registerResetCallback(Callback *cb) 288{ 289 resetQueue.add(cb); 290} 291 292/* namespace Stats */ }
|