2 * Copyright (c) 2003-2005 The Regents of The University of Michigan
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.
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.
28 * Authors: Nathan Binkert
31 #include "base/statistics.hh"
39 #include "base/callback.hh"
40 #include "base/cprintf.hh"
41 #include "base/debug.hh"
42 #include "base/hostinfo.hh"
43 #include "base/logging.hh"
44 #include "base/str.hh"
45 #include "base/time.hh"
46 #include "base/trace.hh"
52 std::string
Info::separatorString
= "::";
54 // We wrap these in a function to make sure they're built in time.
58 static list
<Info
*> the_list
;
65 static MapType the_map
;
70 InfoAccess::setInfo(Info
*info
)
72 if (statsMap().find(this) != statsMap().end())
73 panic("shouldn't register stat twice!");
75 statsList().push_back(info
);
78 pair
<MapType::iterator
, bool> result
=
80 statsMap().insert(make_pair(this, info
));
81 assert(result
.second
&& "this should never fail");
82 assert(statsMap().find(this) != statsMap().end());
86 InfoAccess::setParams(const StorageParams
*params
)
88 info()->storageParams
= params
;
94 info()->flags
.set(init
);
100 MapType::const_iterator i
= statsMap().find(this);
101 assert(i
!= statsMap().end());
106 InfoAccess::info() const
108 MapType::const_iterator i
= statsMap().find(this);
109 assert(i
!= statsMap().end());
113 StorageParams::~StorageParams()
120 static NameMapType the_map
;
124 int Info::id_count
= 0;
126 int debug_break_id
= -1;
129 : flags(none
), precision(-1), prereq(0), storageParams(NULL
)
132 if (debug_break_id
>= 0 and debug_break_id
== id
)
141 validateStatName(const string
&name
)
147 tokenize(vec
, name
, '.');
148 vector
<string
>::const_iterator item
= vec
.begin();
149 while (item
!= vec
.end()) {
153 string::const_iterator c
= item
->begin();
155 // The first character is different
156 if (!isalpha(*c
) && *c
!= '_')
159 // The rest of the characters have different rules.
160 while (++c
!= item
->end()) {
161 if (!isalnum(*c
) && *c
!= '_')
172 Info::setName(const string
&name
)
174 if (!validateStatName(name
))
175 panic("invalid stat name '%s'", name
);
177 pair
<NameMapType::iterator
, bool> p
=
178 nameMap().insert(make_pair(name
, this));
180 Info
*other
= p
.first
->second
;
181 bool result
= p
.second
;
184 // using other->name instead of just name to avoid a compiler
185 // warning. They should be the same.
186 panic("same statistic name used twice! name=%s\n", other
->name
);
193 Info::less(Info
*stat1
, Info
*stat2
)
195 const string
&name1
= stat1
->name
;
196 const string
&name2
= stat2
->name
;
201 tokenize(v1
, name1
, '.');
202 tokenize(v2
, name2
, '.');
204 size_type last
= min(v1
.size(), v2
.size()) - 1;
205 for (off_type i
= 0; i
< last
; ++i
)
207 return v1
[i
] < v2
[i
];
209 // Special compare for last element.
210 if (v1
[last
] == v2
[last
])
211 return v1
.size() < v2
.size();
213 return v1
[last
] < v2
[last
];
219 Info::baseCheck() const
221 if (!(flags
& Stats::init
)) {
223 cprintf("this is stat number %d\n", id
);
225 panic("Not all stats have been initialized.\n"
226 "You may need to add <ParentClass>::regStats() to a"
227 " new SimObject's regStats() function.");
231 if ((flags
& display
) && name
.empty()) {
232 panic("all printable stats must be named");
247 size_type s
= size();
248 if (subnames
.size() < s
)
250 if (subdescs
.size() < s
)
255 VectorDistInfo::enable()
257 size_type s
= size();
258 if (subnames
.size() < s
)
260 if (subdescs
.size() < s
)
265 Vector2dInfo::enable()
267 if (subnames
.size() < x
)
269 if (subdescs
.size() < x
)
271 if (y_subnames
.size() < y
)
272 y_subnames
.resize(y
);
278 int size
= cvec
.size();
279 int zero
= size
/ 2; // round down!
280 int top_half
= zero
+ (size
- zero
+ 1) / 2; // round up!
281 int bottom_half
= (size
- zero
) / 2; // round down!
284 int low_pair
= zero
- 1;
285 for (int i
= zero
- 1; i
>= bottom_half
; i
--) {
286 cvec
[i
] = cvec
[low_pair
];
287 if (low_pair
- 1 >= 0)
288 cvec
[i
] += cvec
[low_pair
- 1];
291 assert(low_pair
== 0 || low_pair
== -1 || low_pair
== -2);
293 for (int i
= bottom_half
- 1; i
>= 0; i
--)
297 int high_pair
= zero
;
298 for (int i
= zero
; i
< top_half
; i
++) {
299 cvec
[i
] = cvec
[high_pair
];
300 if (high_pair
+ 1 < size
)
301 cvec
[i
] += cvec
[high_pair
+ 1];
304 assert(high_pair
== size
|| high_pair
== size
+ 1);
306 for (int i
= top_half
; i
< size
; i
++)
315 HistStor::grow_convert()
317 int size
= cvec
.size();
318 int half
= (size
+ 1) / 2; // round up!
319 //bool even = (size & 1) == 0;
322 for (int i
= size
- 1; i
>= half
; --i
) {
323 cvec
[i
] = cvec
[pair
];
325 cvec
[i
] += cvec
[pair
- 1];
329 for (int i
= half
- 1; i
>= 0; i
--)
332 min_bucket
= -max_bucket
;// - (even ? bucket_size : 0);
339 int size
= cvec
.size();
340 int half
= (size
+ 1) / 2; // round up!
343 for (int i
= 0; i
< half
; i
++) {
344 cvec
[i
] = cvec
[pair
];
346 cvec
[i
] += cvec
[pair
+ 1];
349 assert(pair
== size
|| pair
== size
+ 1);
351 for (int i
= half
; i
< size
; i
++)
359 HistStor::add(HistStor
*hs
)
361 int b_size
= hs
->size();
362 assert(size() == b_size
);
363 assert(min_bucket
== hs
->min_bucket
);
367 squares
+= hs
->squares
;
368 samples
+= hs
->samples
;
370 while (bucket_size
> hs
->bucket_size
)
372 while (bucket_size
< hs
->bucket_size
)
375 for (uint32_t i
= 0; i
< b_size
; i
++)
376 cvec
[i
] += hs
->cvec
[i
];
383 Formula::Formula(Temp r
)
385 root
= r
.getNodePtr();
391 Formula::operator=(Temp r
)
393 assert(!root
&& "Can't change formulas");
394 root
= r
.getNodePtr();
401 Formula::operator+=(Temp r
)
404 root
= NodePtr(new BinaryNode
<std::plus
<Result
> >(root
, r
));
406 root
= r
.getNodePtr();
415 Formula::operator/=(Temp r
)
418 root
= NodePtr(new BinaryNode
<std::divides
<Result
> >(root
, r
));
425 Formula::result(VResult
&vec
) const
428 vec
= root
->result();
432 Formula::total() const
434 return root
? root
->total() : 0.0;
438 Formula::size() const
452 Formula::zero() const
456 for (VResult::size_type i
= 0; i
< vec
.size(); ++i
)
465 return root
? root
->str() : "";
468 Handler resetHandler
= NULL
;
469 Handler dumpHandler
= NULL
;
472 registerHandlers(Handler reset_handler
, Handler dump_handler
)
474 resetHandler
= reset_handler
;
475 dumpHandler
= dump_handler
;
478 CallbackQueue dumpQueue
;
479 CallbackQueue resetQueue
;
484 resetQueue
.process();
494 registerResetCallback(Callback
*cb
)
499 bool _enabled
= false;
511 fatal("Stats are already enabled");
522 fatal("No registered Stats::dump handler");
531 fatal("No registered Stats::reset handler");
535 registerDumpCallback(Callback
*cb
)