mem-cache: Avoid write merging if there are reads in between
[gem5.git] / src / sim / stat_control.cc
1 /*
2 * Copyright (c) 2012 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) 2004-2005 The Regents of The University of Michigan
15 * Copyright (c) 2013 Advanced Micro Devices, Inc.
16 * Copyright (c) 2013 Mark D. Hill and David A. Wood
17 * All rights reserved.
18 *
19 * Redistribution and use in source and binary forms, with or without
20 * modification, are permitted provided that the following conditions are
21 * met: redistributions of source code must retain the above copyright
22 * notice, this list of conditions and the following disclaimer;
23 * redistributions in binary form must reproduce the above copyright
24 * notice, this list of conditions and the following disclaimer in the
25 * documentation and/or other materials provided with the distribution;
26 * neither the name of the copyright holders nor the names of its
27 * contributors may be used to endorse or promote products derived from
28 * this software without specific prior written permission.
29 *
30 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
31 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
32 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
33 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
34 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
35 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
36 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
37 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
38 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
39 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
40 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 *
42 * Authors: Nathan Binkert
43 * Sascha Bischoff
44 */
45
46 // This file will contain default statistics for the simulator that
47 // don't really belong to a specific simulator object
48
49 #include "sim/stat_control.hh"
50
51 #include <fstream>
52 #include <iostream>
53 #include <list>
54
55 #include "base/callback.hh"
56 #include "base/hostinfo.hh"
57 #include "base/statistics.hh"
58 #include "base/time.hh"
59 #include "cpu/base.hh"
60 #include "sim/global_event.hh"
61
62 using namespace std;
63
64 Stats::Formula simSeconds;
65 Stats::Value simTicks;
66 Stats::Value finalTick;
67 Stats::Value simFreq;
68
69 namespace Stats {
70
71 Time statTime(true);
72 Tick startTick;
73
74 GlobalEvent *dumpEvent;
75
76 struct SimTicksReset : public Callback
77 {
78 void process()
79 {
80 statTime.setTimer();
81 startTick = curTick();
82 }
83 };
84
85 double
86 statElapsedTime()
87 {
88 Time now;
89 now.setTimer();
90
91 Time elapsed = now - statTime;
92 return elapsed;
93 }
94
95 Tick
96 statElapsedTicks()
97 {
98 return curTick() - startTick;
99 }
100
101 Tick
102 statFinalTick()
103 {
104 return curTick();
105 }
106
107 SimTicksReset simTicksReset;
108
109 struct Global
110 {
111 Stats::Formula hostInstRate;
112 Stats::Formula hostOpRate;
113 Stats::Formula hostTickRate;
114 Stats::Value hostMemory;
115 Stats::Value hostSeconds;
116
117 Stats::Value simInsts;
118 Stats::Value simOps;
119
120 Global();
121 };
122
123 Global::Global()
124 {
125 simInsts
126 .functor(BaseCPU::numSimulatedInsts)
127 .name("sim_insts")
128 .desc("Number of instructions simulated")
129 .precision(0)
130 .prereq(simInsts)
131 ;
132
133 simOps
134 .functor(BaseCPU::numSimulatedOps)
135 .name("sim_ops")
136 .desc("Number of ops (including micro ops) simulated")
137 .precision(0)
138 .prereq(simOps)
139 ;
140
141 simSeconds
142 .name("sim_seconds")
143 .desc("Number of seconds simulated")
144 ;
145
146 simFreq
147 .scalar(SimClock::Frequency)
148 .name("sim_freq")
149 .desc("Frequency of simulated ticks")
150 ;
151
152 simTicks
153 .functor(statElapsedTicks)
154 .name("sim_ticks")
155 .desc("Number of ticks simulated")
156 ;
157
158 finalTick
159 .functor(statFinalTick)
160 .name("final_tick")
161 .desc("Number of ticks from beginning of simulation "
162 "(restored from checkpoints and never reset)")
163 ;
164
165 hostInstRate
166 .name("host_inst_rate")
167 .desc("Simulator instruction rate (inst/s)")
168 .precision(0)
169 .prereq(simInsts)
170 ;
171
172 hostOpRate
173 .name("host_op_rate")
174 .desc("Simulator op (including micro ops) rate (op/s)")
175 .precision(0)
176 .prereq(simOps)
177 ;
178
179 hostMemory
180 .functor(memUsage)
181 .name("host_mem_usage")
182 .desc("Number of bytes of host memory used")
183 .prereq(hostMemory)
184 ;
185
186 hostSeconds
187 .functor(statElapsedTime)
188 .name("host_seconds")
189 .desc("Real time elapsed on the host")
190 .precision(2)
191 ;
192
193 hostTickRate
194 .name("host_tick_rate")
195 .desc("Simulator tick rate (ticks/s)")
196 .precision(0)
197 ;
198
199 simSeconds = simTicks / simFreq;
200 hostInstRate = simInsts / hostSeconds;
201 hostOpRate = simOps / hostSeconds;
202 hostTickRate = simTicks / hostSeconds;
203
204 registerResetCallback(&simTicksReset);
205 }
206
207 void
208 initSimStats()
209 {
210 static Global global;
211 }
212
213 /**
214 * Event to dump and/or reset the statistics.
215 */
216 class StatEvent : public GlobalEvent
217 {
218 private:
219 bool dump;
220 bool reset;
221 Tick repeat;
222
223 public:
224 StatEvent(Tick _when, bool _dump, bool _reset, Tick _repeat)
225 : GlobalEvent(_when, Stat_Event_Pri, 0),
226 dump(_dump), reset(_reset), repeat(_repeat)
227 {
228 }
229
230 virtual void
231 process()
232 {
233 if (dump)
234 Stats::dump();
235
236 if (reset)
237 Stats::reset();
238
239 if (repeat) {
240 Stats::schedStatEvent(dump, reset, curTick() + repeat, repeat);
241 }
242 }
243
244 const char *description() const { return "GlobalStatEvent"; }
245 };
246
247 void
248 schedStatEvent(bool dump, bool reset, Tick when, Tick repeat)
249 {
250 // simQuantum is being added to the time when the stats would be
251 // dumped so as to ensure that this event happens only after the next
252 // sync amongst the event queues. Asingle event queue simulation
253 // should remain unaffected.
254 dumpEvent = new StatEvent(when + simQuantum, dump, reset, repeat);
255 }
256
257 void
258 periodicStatDump(Tick period)
259 {
260 /*
261 * If the period is set to 0, then we do not want to dump periodically,
262 * thus we deschedule the event. Else, if the period is not 0, but the event
263 * has already been scheduled, we need to get rid of the old event before we
264 * create a new one, as the old event will no longer be moved forward in the
265 * event that we resume from a checkpoint.
266 */
267 if (dumpEvent != NULL && (period == 0 || dumpEvent->scheduled())) {
268 // Event should AutoDelete, so we do not need to free it.
269 dumpEvent->deschedule();
270 }
271
272 /*
273 * If the period is not 0, we schedule the event. If this is called with a
274 * period that is less than the current tick, then we shift the first dump
275 * by curTick. This ensures that we do not schedule the event is the past.
276 */
277 if (period != 0) {
278 // Schedule the event
279 if (period >= curTick()) {
280 schedStatEvent(true, true, (Tick)period, (Tick)period);
281 } else {
282 schedStatEvent(true, true, (Tick)period + curTick(), (Tick)period);
283 }
284 }
285 }
286
287 void
288 updateEvents()
289 {
290 /*
291 * If the dumpEvent has been scheduled, but is scheduled in the past, then
292 * we need to shift the event to be at a valid point in time. Therefore, we
293 * shift the event by curTick.
294 */
295 if (dumpEvent != NULL &&
296 (dumpEvent->scheduled() && dumpEvent->when() < curTick())) {
297 // shift by curTick() and reschedule
298 Tick _when = dumpEvent->when();
299 dumpEvent->reschedule(_when + curTick());
300 }
301 }
302
303 } // namespace Stats