gem5  v19.0.0.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
statistics.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2019 Arm Limited
3  * All rights reserved.
4  *
5  * The license below extends only to copyright in the software and shall
6  * not be construed as granting a license to any other intellectual
7  * property including but not limited to intellectual property relating
8  * to a hardware implementation of the functionality of the software
9  * licensed hereunder. You may use the software subject to the license
10  * terms below provided that you ensure that this notice is replicated
11  * unmodified and in its entirety in all distributions of the software,
12  * modified or unmodified, in source code or in binary form.
13  *
14  * Copyright (c) 2003-2005 The Regents of The University of Michigan
15  * All rights reserved.
16  *
17  * Redistribution and use in source and binary forms, with or without
18  * modification, are permitted provided that the following conditions are
19  * met: redistributions of source code must retain the above copyright
20  * notice, this list of conditions and the following disclaimer;
21  * redistributions in binary form must reproduce the above copyright
22  * notice, this list of conditions and the following disclaimer in the
23  * documentation and/or other materials provided with the distribution;
24  * neither the name of the copyright holders nor the names of its
25  * contributors may be used to endorse or promote products derived from
26  * this software without specific prior written permission.
27  *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39  *
40  * Authors: Nathan Binkert
41  */
42 
43 #include "base/statistics.hh"
44 
45 #include <fstream>
46 #include <iomanip>
47 #include <list>
48 #include <map>
49 #include <string>
50 
51 #include "base/callback.hh"
52 #include "base/cprintf.hh"
53 #include "base/debug.hh"
54 #include "base/hostinfo.hh"
55 #include "base/logging.hh"
56 #include "base/str.hh"
57 #include "base/time.hh"
58 #include "base/trace.hh"
59 
60 using namespace std;
61 
62 namespace Stats {
63 
64 std::string Info::separatorString = "::";
65 
66 // We wrap these in a function to make sure they're built in time.
69 {
70  static list<Info *> the_list;
71  return the_list;
72 }
73 
74 MapType &
76 {
77  static MapType the_map;
78  return the_map;
79 }
80 
81 void
82 InfoAccess::setInfo(Group *parent, Info *info)
83 {
84  panic_if(statsMap().find(this) != statsMap().end() ||
85  _info != nullptr,
86  "shouldn't register stat twice!");
87 
88  // New-style stats are reachable through the hierarchy and
89  // shouldn't be added to the global lists.
90  if (parent) {
91  _info = info;
92  return;
93  }
94 
95  statsList().push_back(info);
96 
97 #ifndef NDEBUG
99 #endif
100  statsMap().insert(make_pair(this, info));
101  assert(result.second && "this should never fail");
102  assert(statsMap().find(this) != statsMap().end());
103 }
104 
105 void
106 InfoAccess::setParams(const StorageParams *params)
107 {
108  info()->storageParams = params;
109 }
110 
111 void
112 InfoAccess::setInit()
113 {
114  info()->flags.set(init);
115 }
116 
117 Info *
118 InfoAccess::info()
119 {
120  if (_info) {
121  // New-style stats
122  return _info;
123  } else {
124  // Legacy stats
125  MapType::const_iterator i = statsMap().find(this);
126  assert(i != statsMap().end());
127  return (*i).second;
128  }
129 }
130 
131 const Info *
132 InfoAccess::info() const
133 {
134  if (_info) {
135  // New-style stats
136  return _info;
137  } else {
138  // Legacy stats
139  MapType::const_iterator i = statsMap().find(this);
140  assert(i != statsMap().end());
141  return (*i).second;
142  }
143 }
144 
145 StorageParams::~StorageParams()
146 {
147 }
148 
149 NameMapType &
151 {
152  static NameMapType the_map;
153  return the_map;
154 }
155 
156 int Info::id_count = 0;
157 
158 int debug_break_id = -1;
159 
160 Info::Info()
161  : flags(none), precision(-1), prereq(0), storageParams(NULL)
162 {
163  id = id_count++;
164  if (debug_break_id >= 0 and debug_break_id == id)
166 }
167 
169 {
170 }
171 
172 bool
173 validateStatName(const string &name)
174 {
175  if (name.empty())
176  return false;
177 
178  vector<string> vec;
179  tokenize(vec, name, '.');
180  vector<string>::const_iterator item = vec.begin();
181  while (item != vec.end()) {
182  if (item->empty())
183  return false;
184 
185  string::const_iterator c = item->begin();
186 
187  // The first character is different
188  if (!isalpha(*c) && *c != '_')
189  return false;
190 
191  // The rest of the characters have different rules.
192  while (++c != item->end()) {
193  if (!isalnum(*c) && *c != '_')
194  return false;
195  }
196 
197  ++item;
198  }
199 
200  return true;
201 }
202 
203 void
204 Info::setName(const string &name)
205 {
206  setName(nullptr, name);
207 }
208 
209 void
210 Info::setName(const Group *parent, const string &name)
211 {
212  if (!validateStatName(name))
213  panic("invalid stat name '%s'", name);
214 
215  // We only register the stat with the nameMap() if we are using
216  // old-style stats without a parent group. New-style stats should
217  // be unique since their names should correspond to a member
218  // variable.
219  if (!parent) {
220  auto p = nameMap().insert(make_pair(name, this));
221 
222  if (!p.second)
223  panic("same statistic name used twice! name=%s\n",
224  name);
225  }
226 
227  this->name = name;
228 }
229 
230 bool
231 Info::less(Info *stat1, Info *stat2)
232 {
233  const string &name1 = stat1->name;
234  const string &name2 = stat2->name;
235 
236  vector<string> v1;
237  vector<string> v2;
238 
239  tokenize(v1, name1, '.');
240  tokenize(v2, name2, '.');
241 
242  size_type last = min(v1.size(), v2.size()) - 1;
243  for (off_type i = 0; i < last; ++i)
244  if (v1[i] != v2[i])
245  return v1[i] < v2[i];
246 
247  // Special compare for last element.
248  if (v1[last] == v2[last])
249  return v1.size() < v2.size();
250  else
251  return v1[last] < v2[last];
252 
253  return false;
254 }
255 
256 bool
258 {
259  if (!(flags & Stats::init)) {
260 #ifdef DEBUG
261  cprintf("this is stat number %d\n", id);
262 #endif
263  panic("Not all stats have been initialized.\n"
264  "You may need to add <ParentClass>::regStats() to a"
265  " new SimObject's regStats() function. Name: %s",
266  name);
267  return false;
268  }
269 
270  if ((flags & display) && name.empty()) {
271  panic("all printable stats must be named");
272  return false;
273  }
274 
275  return true;
276 }
277 
278 void
280 {
281 }
282 
283 void
285 {
286  size_type s = size();
287  if (subnames.size() < s)
288  subnames.resize(s);
289  if (subdescs.size() < s)
290  subdescs.resize(s);
291 }
292 
293 void
295 {
296  size_type s = size();
297  if (subnames.size() < s)
298  subnames.resize(s);
299  if (subdescs.size() < s)
300  subdescs.resize(s);
301 }
302 
303 void
305 {
306  if (subnames.size() < x)
307  subnames.resize(x);
308  if (subdescs.size() < x)
309  subdescs.resize(x);
310  if (y_subnames.size() < y)
311  y_subnames.resize(y);
312 }
313 
314 void
316 {
317  int size = cvec.size();
318  int zero = size / 2; // round down!
319  int top_half = zero + (size - zero + 1) / 2; // round up!
320  int bottom_half = (size - zero) / 2; // round down!
321 
322  // grow down
323  int low_pair = zero - 1;
324  for (int i = zero - 1; i >= bottom_half; i--) {
325  cvec[i] = cvec[low_pair];
326  if (low_pair - 1 >= 0)
327  cvec[i] += cvec[low_pair - 1];
328  low_pair -= 2;
329  }
330  assert(low_pair == 0 || low_pair == -1 || low_pair == -2);
331 
332  for (int i = bottom_half - 1; i >= 0; i--)
333  cvec[i] = Counter();
334 
335  // grow up
336  int high_pair = zero;
337  for (int i = zero; i < top_half; i++) {
338  cvec[i] = cvec[high_pair];
339  if (high_pair + 1 < size)
340  cvec[i] += cvec[high_pair + 1];
341  high_pair += 2;
342  }
343  assert(high_pair == size || high_pair == size + 1);
344 
345  for (int i = top_half; i < size; i++)
346  cvec[i] = Counter();
347 
348  max_bucket *= 2;
349  min_bucket *= 2;
350  bucket_size *= 2;
351 }
352 
353 void
355 {
356  int size = cvec.size();
357  int half = (size + 1) / 2; // round up!
358  //bool even = (size & 1) == 0;
359 
360  int pair = size - 1;
361  for (int i = size - 1; i >= half; --i) {
362  cvec[i] = cvec[pair];
363  if (pair - 1 >= 0)
364  cvec[i] += cvec[pair - 1];
365  pair -= 2;
366  }
367 
368  for (int i = half - 1; i >= 0; i--)
369  cvec[i] = Counter();
370 
371  min_bucket = -max_bucket;// - (even ? bucket_size : 0);
372  bucket_size *= 2;
373 }
374 
375 void
377 {
378  int size = cvec.size();
379  int half = (size + 1) / 2; // round up!
380 
381  int pair = 0;
382  for (int i = 0; i < half; i++) {
383  cvec[i] = cvec[pair];
384  if (pair + 1 < size)
385  cvec[i] += cvec[pair + 1];
386  pair += 2;
387  }
388  assert(pair == size || pair == size + 1);
389 
390  for (int i = half; i < size; i++)
391  cvec[i] = Counter();
392 
393  max_bucket *= 2;
394  bucket_size *= 2;
395 }
396 
397 void
399 {
400  int b_size = hs->size();
401  assert(size() == b_size);
402  assert(min_bucket == hs->min_bucket);
403 
404  sum += hs->sum;
405  logs += hs->logs;
406  squares += hs->squares;
407  samples += hs->samples;
408 
409  while (bucket_size > hs->bucket_size)
410  hs->grow_up();
411  while (bucket_size < hs->bucket_size)
412  grow_up();
413 
414  for (uint32_t i = 0; i < b_size; i++)
415  cvec[i] += hs->cvec[i];
416 }
417 
418 Formula::Formula(Group *parent, const char *name, const char *desc)
419  : DataWrapVec<Formula, FormulaInfoProxy>(parent, name, desc)
420 
421 {
422 }
423 
424 
425 
426 Formula::Formula(Group *parent, const char *name, const char *desc,
427  const Temp &r)
428  : DataWrapVec<Formula, FormulaInfoProxy>(parent, name, desc)
429 {
430  *this = r;
431 }
432 
433 const Formula &
435 {
436  assert(!root && "Can't change formulas");
437  root = r.getNodePtr();
438  setInit();
439  assert(size());
440  return *this;
441 }
442 
443 const Formula &
445 {
446  if (root)
447  root = NodePtr(new BinaryNode<std::plus<Result> >(root, r));
448  else {
449  root = r.getNodePtr();
450  setInit();
451  }
452 
453  assert(size());
454  return *this;
455 }
456 
457 const Formula &
459 {
460  assert (root);
461  root = NodePtr(new BinaryNode<std::divides<Result> >(root, r));
462 
463  assert(size());
464  return *this;
465 }
466 
467 
468 void
470 {
471  if (root)
472  vec = root->result();
473 }
474 
475 Result
477 {
478  return root ? root->total() : 0.0;
479 }
480 
481 size_type
483 {
484  if (!root)
485  return 0;
486  else
487  return root->size();
488 }
489 
490 void
492 {
493 }
494 
495 bool
497 {
498  VResult vec;
499  result(vec);
500  for (VResult::size_type i = 0; i < vec.size(); ++i)
501  if (vec[i] != 0.0)
502  return false;
503  return true;
504 }
505 
506 string
508 {
509  return root ? root->str() : "";
510 }
511 
514 
515 void
516 registerHandlers(Handler reset_handler, Handler dump_handler)
517 {
518  resetHandler = reset_handler;
519  dumpHandler = dump_handler;
520 }
521 
524 
525 void
527 {
528  resetQueue.process();
529 }
530 
531 void
533 {
534  dumpQueue.process();
535 }
536 
537 void
539 {
540  resetQueue.add(cb);
541 }
542 
543 bool _enabled = false;
544 
545 bool
547 {
548  return _enabled;
549 }
550 
551 void
553 {
554  if (_enabled)
555  fatal("Stats are already enabled");
556 
557  _enabled = true;
558 }
559 
560 void
562 {
563  if (dumpHandler)
564  dumpHandler();
565  else
566  fatal("No registered Stats::dump handler");
567 }
568 
569 void
571 {
572  if (resetHandler)
573  resetHandler();
574  else
575  fatal("No registered Stats::reset handler");
576 }
577 
578 void
580 {
581  dumpQueue.add(cb);
582 }
583 
584 } // namespace Stats
585 
586 void
588 {
589  Stats::dump();
590 }
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:167
double Result
All results are doubles.
Definition: types.hh:52
Counter samples
The number of samples.
Definition: statistics.hh:1573
std::string name
The name of the stat.
Definition: info.hh:75
void debugDumpStats()
Definition: statistics.cc:587
static int id_count
A unique stat ID for each stat in the simulator.
Definition: info.hh:90
void enable()
Enable the stat for use.
Definition: statistics.cc:304
void processDumpQueue()
Process all the callbacks in the dump callbacks queue.
Definition: statistics.cc:532
void breakpoint()
Definition: debug.cc:52
bool baseCheck() const
Definition: statistics.cc:257
#define fatal(...)
This implements a cprintf based fatal() function.
Definition: logging.hh:175
Generic callback class.
Definition: callback.hh:41
Bitfield< 7 > i
STL pair class.
Definition: stl.hh:61
virtual bool zero() const =0
const Formula & operator/=(Temp r)
Divide the existing tree by the given one.
Definition: statistics.cc:458
NodePtr getNodePtr() const
Makde gcc < 4.6.3 happy and explicitly get the underlying node.
Definition: statistics.hh:3143
void process()
process all callbacks
Definition: callback.hh:135
VCounter cvec
Counter for each bucket.
Definition: statistics.hh:1575
void(* Handler)()
Register reset and dump handlers.
Definition: statistics.hh:3361
virtual void enable()
Enable the stat for use.
Definition: statistics.cc:279
Overload hash function for BasicBlockRange type.
Definition: vec_reg.hh:586
list< Info * > & statsList()
Definition: statistics.cc:68
bool _enabled
Definition: statistics.cc:543
Counter logs
The sum of logarithm of each sample, used to compute geometric mean.
Definition: statistics.hh:1569
void add(HistStor *)
Definition: statistics.cc:398
void enable()
Enable the stat for use.
Definition: statistics.cc:294
CallbackQueue resetQueue
Definition: statistics.cc:523
Counter squares
The sum of squares.
Definition: statistics.hh:1571
Counter min_bucket
The minimum value to track.
Definition: statistics.hh:1560
unsigned int size_type
Definition: types.hh:56
Declaration of Statistics objects.
const Formula & operator+=(Temp r)
Add the given tree to the existing one.
Definition: statistics.cc:444
double Counter
All counters are of 64-bit values.
Definition: types.hh:43
void enable()
Definition: statistics.cc:552
void add(Callback *callback)
Add a callback to the end of the queue.
Definition: callback.hh:107
Bitfield< 4 > s
Templatized storage and interface for a histogram stat.
Definition: statistics.hh:1546
void reset()
Formulas don&#39;t need to be reset.
Definition: statistics.cc:491
static bool less(Info *stat1, Info *stat2)
Checks if the first stat&#39;s name is alphabetically less than the second.
Definition: statistics.cc:231
Counter sum
The current sum.
Definition: statistics.hh:1567
void result(VResult &vec) const
Return the result of the Fomula in a vector.
Definition: statistics.cc:469
std::shared_ptr< Node > NodePtr
Shared pointer to a function Node.
Definition: statistics.hh:2129
void grow_convert()
Definition: statistics.cc:354
Flags flags
The formatting flags.
Definition: info.hh:81
void registerResetCallback(Callback *cb)
Register a callback that should be called whenever statistics are reset.
Definition: statistics.cc:538
size_type size() const
Return the number of elements in the tree.
Definition: statistics.cc:482
void setName(const std::string &name)
Set the name of this statistic.
STL list class.
Definition: stl.hh:54
const FlagsType display
Print this stat.
Definition: info.hh:49
const FlagsType none
Nothing extra to print.
Definition: info.hh:45
virtual ~Info()
Definition: statistics.cc:168
int debug_break_id
Definition: statistics.cc:158
unsigned int off_type
Definition: types.hh:57
bool zero() const
Definition: statistics.cc:496
std::map< const void *, Info * > MapType
Definition: statistics.hh:3389
void enable()
Enable the stat for use.
Definition: statistics.cc:284
Counter bucket_size
The number of entries in each bucket.
Definition: statistics.hh:1564
Statistics container.
Definition: group.hh:85
Helper class to construct formula node trees.
Definition: statistics.hh:3117
bool enabled()
Definition: statistics.cc:546
NameMapType & nameMap()
Definition: statistics.cc:150
void registerDumpCallback(Callback *cb)
Register a callback that should be called whenever statistics are about to be dumped.
Definition: statistics.cc:579
A formula for statistics that is calculated when printed.
Definition: statistics.hh:3012
Temp sum(Temp val)
Definition: statistics.hh:3345
void setInit()
Save Storage class parameters if any.
Definition: statistics.cc:112
Bitfield< 29 > c
Result total() const
Return the total Formula result.
Definition: statistics.cc:476
void processResetQueue()
Process all the callbacks in the reset callbacks queue.
Definition: statistics.cc:526
bool validateStatName(const string &name)
Definition: statistics.cc:173
Handler resetHandler
Definition: statistics.cc:512
std::string str() const
Definition: statistics.cc:507
void tokenize(vector< string > &v, const string &s, char token, bool ignore)
Definition: str.cc:69
Handler dumpHandler
Definition: statistics.cc:513
size_type size() const
Return the number of buckets in this distribution.
Definition: statistics.hh:1630
NodePtr root
The root of the tree which represents the Formula.
Definition: statistics.hh:3016
Formula & desc(const std::string &_desc)
Set the description and marks this stat to print at the end of simulation.
Definition: statistics.hh:312
void dump()
Dump all statistics data to the registered outputs.
Definition: statistics.cc:561
std::map< std::string, Info * > NameMapType
Definition: statistics.hh:3392
CallbackQueue dumpQueue
Definition: statistics.cc:522
Formula(Group *parent=nullptr, const char *name=nullptr, const char *desc=nullptr)
Create and initialize thie formula, and register it with the database.
Definition: statistics.cc:418
void registerHandlers(Handler reset_handler, Handler dump_handler)
Definition: statistics.cc:516
Bitfield< 0 > p
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition: logging.hh:185
Bitfield< 1 > x
Definition: types.hh:105
const FlagsType init
This Stat is Initialized.
Definition: info.hh:47
const Formula & operator=(const Temp &r)
Set an unitialized Formula to the given root.
Definition: statistics.cc:434
void cprintf(const char *format, const Args &...args)
Definition: cprintf.hh:156
MapType & statsMap()
Definition: statistics.cc:75
std::string desc
The description of the stat.
Definition: info.hh:79

Generated on Fri Feb 28 2020 16:26:58 for gem5 by doxygen 1.8.13