arch-arm,cpu: Introduce a getEMI virtual method on StaticInst.
[gem5.git] / src / base / statistics.cc
1 /*
2 * Copyright (c) 2019-2020 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
41 #include "base/statistics.hh"
42
43 #include <cassert>
44 #include <list>
45 #include <map>
46 #include <string>
47 #include <utility>
48
49 #include "base/callback.hh"
50 #include "base/logging.hh"
51 #include "sim/root.hh"
52
53 namespace Stats {
54
55 // We wrap these in a function to make sure they're built in time.
56 std::list<Info *> &
57 statsList()
58 {
59 static std::list<Info *> the_list;
60 return the_list;
61 }
62
63 MapType &
64 statsMap()
65 {
66 static MapType the_map;
67 return the_map;
68 }
69
70 void
71 InfoAccess::setInfo(Group *parent, Info *info)
72 {
73 panic_if(statsMap().find(this) != statsMap().end() ||
74 _info != nullptr,
75 "shouldn't register stat twice!");
76
77 // New-style stats are reachable through the hierarchy and
78 // shouldn't be added to the global lists.
79 if (parent) {
80 _info = info;
81 return;
82 }
83
84 statsList().push_back(info);
85
86 #ifndef NDEBUG
87 std::pair<MapType::iterator, bool> result =
88 #endif
89 statsMap().insert(std::make_pair(this, info));
90 assert(result.second && "this should never fail");
91 assert(statsMap().find(this) != statsMap().end());
92 }
93
94 void
95 InfoAccess::setParams(const StorageParams *params)
96 {
97 info()->storageParams = params;
98 }
99
100 void
101 InfoAccess::setInit()
102 {
103 info()->flags.set(init);
104 }
105
106 Info *
107 InfoAccess::info()
108 {
109 if (_info) {
110 // New-style stats
111 return _info;
112 } else {
113 // Legacy stats
114 MapType::const_iterator i = statsMap().find(this);
115 assert(i != statsMap().end());
116 return (*i).second;
117 }
118 }
119
120 const Info *
121 InfoAccess::info() const
122 {
123 if (_info) {
124 // New-style stats
125 return _info;
126 } else {
127 // Legacy stats
128 MapType::const_iterator i = statsMap().find(this);
129 assert(i != statsMap().end());
130 return (*i).second;
131 }
132 }
133
134 Formula::Formula(Group *parent, const char *name, const char *desc)
135 : DataWrapVec<Formula, FormulaInfoProxy>(parent, name, desc)
136
137 {
138 }
139
140
141
142 Formula::Formula(Group *parent, const char *name, const char *desc,
143 const Temp &r)
144 : DataWrapVec<Formula, FormulaInfoProxy>(parent, name, desc)
145 {
146 *this = r;
147 }
148
149 const Formula &
150 Formula::operator=(const Temp &r)
151 {
152 assert(!root && "Can't change formulas");
153 root = r.getNodePtr();
154 setInit();
155 assert(size());
156 return *this;
157 }
158
159 const Formula &
160 Formula::operator+=(Temp r)
161 {
162 if (root)
163 root = NodePtr(new BinaryNode<std::plus<Result> >(root, r));
164 else {
165 root = r.getNodePtr();
166 setInit();
167 }
168
169 assert(size());
170 return *this;
171 }
172
173 const Formula &
174 Formula::operator/=(Temp r)
175 {
176 assert (root);
177 root = NodePtr(new BinaryNode<std::divides<Result> >(root, r));
178
179 assert(size());
180 return *this;
181 }
182
183
184 void
185 Formula::result(VResult &vec) const
186 {
187 if (root)
188 vec = root->result();
189 }
190
191 Result
192 Formula::total() const
193 {
194 return root ? root->total() : 0.0;
195 }
196
197 size_type
198 Formula::size() const
199 {
200 if (!root)
201 return 0;
202 else
203 return root->size();
204 }
205
206 void
207 Formula::reset()
208 {
209 }
210
211 bool
212 Formula::zero() const
213 {
214 VResult vec;
215 result(vec);
216 for (VResult::size_type i = 0; i < vec.size(); ++i)
217 if (vec[i] != 0.0)
218 return false;
219 return true;
220 }
221
222 std::string
223 Formula::str() const
224 {
225 return root ? root->str() : "";
226 }
227
228 Handler resetHandler = NULL;
229 Handler dumpHandler = NULL;
230
231 void
232 registerHandlers(Handler reset_handler, Handler dump_handler)
233 {
234 resetHandler = reset_handler;
235 dumpHandler = dump_handler;
236 }
237
238 CallbackQueue dumpQueue;
239 CallbackQueue resetQueue;
240
241 void
242 processResetQueue()
243 {
244 resetQueue.process();
245 }
246
247 void
248 processDumpQueue()
249 {
250 dumpQueue.process();
251 }
252
253 void
254 registerResetCallback(const std::function<void()> &callback)
255 {
256 resetQueue.push_back(callback);
257 }
258
259 bool _enabled = false;
260
261 bool
262 enabled()
263 {
264 return _enabled;
265 }
266
267 void
268 enable()
269 {
270 if (_enabled)
271 fatal("Stats are already enabled");
272
273 _enabled = true;
274 }
275
276 void
277 dump()
278 {
279 if (dumpHandler)
280 dumpHandler();
281 else
282 fatal("No registered Stats::dump handler");
283 }
284
285 void
286 reset()
287 {
288 if (resetHandler)
289 resetHandler();
290 else
291 fatal("No registered Stats::reset handler");
292 }
293
294 const Info *
295 resolve(const std::string &name)
296 {
297 const auto &it = nameMap().find(name);
298 if (it != nameMap().cend()) {
299 return it->second;
300 } else {
301 return Root::root()->resolveStat(name);
302 }
303 }
304
305 void
306 registerDumpCallback(const std::function<void()> &callback)
307 {
308 dumpQueue.push_back(callback);
309 }
310
311 } // namespace Stats
312
313 void
314 debugDumpStats()
315 {
316 Stats::dump();
317 }