base.hh (8737:770ccf3af571) base.hh (8745:575cab0db076)
1/*
1/*
2 * Copyright (c) 2011 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) 2002-2005 The Regents of The University of Michigan
15 * Copyright (c) 2011 Regents of the University of California
16 * All rights reserved.
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions are
20 * met: redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer;
22 * redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution;
25 * neither the name of the copyright holders nor the names of its
26 * contributors may be used to endorse or promote products derived from
27 * this software without specific prior written permission.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
33 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 *
41 * Authors: Steve Reinhardt
42 * Nathan Binkert
43 * Rick Strong
44 */
45
46#ifndef __CPU_BASE_HH__
47#define __CPU_BASE_HH__
48
49#include <vector>
50
2 * Copyright (c) 2002-2005 The Regents of The University of Michigan
3 * Copyright (c) 2011 Regents of the University of California
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met: redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer;
10 * redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution;
13 * neither the name of the copyright holders nor the names of its
14 * contributors may be used to endorse or promote products derived from
15 * this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 *
29 * Authors: Steve Reinhardt
30 * Nathan Binkert
31 * Rick Strong
32 */
33
34#ifndef __CPU_BASE_HH__
35#define __CPU_BASE_HH__
36
37#include <vector>
38
39#include "arch/interrupts.hh"
51#include "arch/isa_traits.hh"
52#include "arch/microcode_rom.hh"
53#include "base/statistics.hh"
54#include "config/full_system.hh"
55#include "config/the_isa.hh"
56#include "mem/mem_object.hh"
57#include "sim/eventq.hh"
58#include "sim/insttracer.hh"
59
40#include "arch/isa_traits.hh"
41#include "arch/microcode_rom.hh"
42#include "base/statistics.hh"
43#include "config/full_system.hh"
44#include "config/the_isa.hh"
45#include "mem/mem_object.hh"
46#include "sim/eventq.hh"
47#include "sim/insttracer.hh"
48
60#if FULL_SYSTEM
61#include "arch/interrupts.hh"
62#endif
63
64struct BaseCPUParams;
49class BaseCPUParams;
65class BranchPred;
66class CheckerCPU;
67class ThreadContext;
68class System;
69class Port;
70
71namespace TheISA
72{
73 class Predecoder;
74}
75
76class CPUProgressEvent : public Event
77{
78 protected:
79 Tick _interval;
80 Counter lastNumInst;
81 BaseCPU *cpu;
82 bool _repeatEvent;
83
84 public:
85 CPUProgressEvent(BaseCPU *_cpu, Tick ival = 0);
86
87 void process();
88
89 void interval(Tick ival) { _interval = ival; }
90 Tick interval() { return _interval; }
91
92 void repeatEvent(bool repeat) { _repeatEvent = repeat; }
93
94 virtual const char *description() const;
95};
96
97class BaseCPU : public MemObject
98{
99 protected:
100 // CPU's clock period in terms of the number of ticks of curTime.
101 Tick clock;
102 // @todo remove me after debugging with legion done
103 Tick instCnt;
104 // every cpu has an id, put it in the base cpu
105 // Set at initialization, only time a cpuId might change is during a
106 // takeover (which should be done from within the BaseCPU anyway,
107 // therefore no setCpuId() method is provided
108 int _cpuId;
109
50class BranchPred;
51class CheckerCPU;
52class ThreadContext;
53class System;
54class Port;
55
56namespace TheISA
57{
58 class Predecoder;
59}
60
61class CPUProgressEvent : public Event
62{
63 protected:
64 Tick _interval;
65 Counter lastNumInst;
66 BaseCPU *cpu;
67 bool _repeatEvent;
68
69 public:
70 CPUProgressEvent(BaseCPU *_cpu, Tick ival = 0);
71
72 void process();
73
74 void interval(Tick ival) { _interval = ival; }
75 Tick interval() { return _interval; }
76
77 void repeatEvent(bool repeat) { _repeatEvent = repeat; }
78
79 virtual const char *description() const;
80};
81
82class BaseCPU : public MemObject
83{
84 protected:
85 // CPU's clock period in terms of the number of ticks of curTime.
86 Tick clock;
87 // @todo remove me after debugging with legion done
88 Tick instCnt;
89 // every cpu has an id, put it in the base cpu
90 // Set at initialization, only time a cpuId might change is during a
91 // takeover (which should be done from within the BaseCPU anyway,
92 // therefore no setCpuId() method is provided
93 int _cpuId;
94
110 /**
111 * Define a base class for the CPU ports (instruction and data)
112 * that is refined in the subclasses. This class handles the
113 * common cases, i.e. the functional accesses and the status
114 * changes and address range queries. The default behaviour for
115 * both atomic and timing access is to panic and the corresponding
116 * subclasses have to override these methods.
117 */
118 class CpuPort : public Port
119 {
120 public:
121
122 /**
123 * Create a CPU port with a name and a structural owner.
124 *
125 * @param _name port name including the owner
126 * @param _name structural owner of this port
127 */
128 CpuPort(const std::string& _name, MemObject* _owner) :
129 Port(_name, _owner)
130 { }
131
132 protected:
133
134 virtual bool recvTiming(PacketPtr pkt);
135
136 virtual Tick recvAtomic(PacketPtr pkt);
137
138 virtual void recvRetry();
139
140 void recvFunctional(PacketPtr pkt);
141
142 void recvRangeChange();
143
144 };
145
146 public:
147 /** Reads this CPU's ID. */
148 int cpuId() { return _cpuId; }
149
150// Tick currentTick;
151 inline Tick frequency() const { return SimClock::Frequency / clock; }
152 inline Tick ticks(int numCycles) const { return clock * numCycles; }
153 inline Tick curCycle() const { return curTick() / clock; }
154 inline Tick tickToCycles(Tick val) const { return val / clock; }
155 inline void workItemBegin() { numWorkItemsStarted++; }
156 inline void workItemEnd() { numWorkItemsCompleted++; }
157 // @todo remove me after debugging with legion done
158 Tick instCount() { return instCnt; }
159
160 /** The next cycle the CPU should be scheduled, given a cache
161 * access or quiesce event returning on this cycle. This function
162 * may return curTick() if the CPU should run on the current cycle.
163 */
164 Tick nextCycle();
165
166 /** The next cycle the CPU should be scheduled, given a cache
167 * access or quiesce event returning on the given Tick. This
168 * function may return curTick() if the CPU should run on the
169 * current cycle.
170 * @param begin_tick The tick that the event is completing on.
171 */
172 Tick nextCycle(Tick begin_tick);
173
174 TheISA::MicrocodeRom microcodeRom;
175
95 public:
96 /** Reads this CPU's ID. */
97 int cpuId() { return _cpuId; }
98
99// Tick currentTick;
100 inline Tick frequency() const { return SimClock::Frequency / clock; }
101 inline Tick ticks(int numCycles) const { return clock * numCycles; }
102 inline Tick curCycle() const { return curTick() / clock; }
103 inline Tick tickToCycles(Tick val) const { return val / clock; }
104 inline void workItemBegin() { numWorkItemsStarted++; }
105 inline void workItemEnd() { numWorkItemsCompleted++; }
106 // @todo remove me after debugging with legion done
107 Tick instCount() { return instCnt; }
108
109 /** The next cycle the CPU should be scheduled, given a cache
110 * access or quiesce event returning on this cycle. This function
111 * may return curTick() if the CPU should run on the current cycle.
112 */
113 Tick nextCycle();
114
115 /** The next cycle the CPU should be scheduled, given a cache
116 * access or quiesce event returning on the given Tick. This
117 * function may return curTick() if the CPU should run on the
118 * current cycle.
119 * @param begin_tick The tick that the event is completing on.
120 */
121 Tick nextCycle(Tick begin_tick);
122
123 TheISA::MicrocodeRom microcodeRom;
124
176#if FULL_SYSTEM
177 protected:
178 TheISA::Interrupts *interrupts;
179
180 public:
181 TheISA::Interrupts *
182 getInterruptController()
183 {
184 return interrupts;
185 }
186
125 protected:
126 TheISA::Interrupts *interrupts;
127
128 public:
129 TheISA::Interrupts *
130 getInterruptController()
131 {
132 return interrupts;
133 }
134
135#if FULL_SYSTEM
187 virtual void wakeup() = 0;
136 virtual void wakeup() = 0;
137#endif
188
189 void
190 postInterrupt(int int_num, int index)
191 {
192 interrupts->post(int_num, index);
138
139 void
140 postInterrupt(int int_num, int index)
141 {
142 interrupts->post(int_num, index);
143#if FULL_SYSTEM
193 wakeup();
144 wakeup();
145#endif
194 }
195
196 void
197 clearInterrupt(int int_num, int index)
198 {
199 interrupts->clear(int_num, index);
200 }
201
202 void
203 clearInterrupts()
204 {
205 interrupts->clearAll();
206 }
207
208 bool
209 checkInterrupts(ThreadContext *tc) const
210 {
211 return interrupts->checkInterrupts(tc);
212 }
213
214 class ProfileEvent : public Event
215 {
216 private:
217 BaseCPU *cpu;
218 Tick interval;
219
220 public:
221 ProfileEvent(BaseCPU *cpu, Tick interval);
222 void process();
223 };
224 ProfileEvent *profileEvent;
146 }
147
148 void
149 clearInterrupt(int int_num, int index)
150 {
151 interrupts->clear(int_num, index);
152 }
153
154 void
155 clearInterrupts()
156 {
157 interrupts->clearAll();
158 }
159
160 bool
161 checkInterrupts(ThreadContext *tc) const
162 {
163 return interrupts->checkInterrupts(tc);
164 }
165
166 class ProfileEvent : public Event
167 {
168 private:
169 BaseCPU *cpu;
170 Tick interval;
171
172 public:
173 ProfileEvent(BaseCPU *cpu, Tick interval);
174 void process();
175 };
176 ProfileEvent *profileEvent;
225#endif
226
227 protected:
228 std::vector<ThreadContext *> threadContexts;
229 std::vector<TheISA::Predecoder *> predecoders;
230
231 Trace::InstTracer * tracer;
232
233 public:
234
235 // Mask to align PCs to MachInst sized boundaries
236 static const Addr PCMask = ~((Addr)sizeof(TheISA::MachInst) - 1);
237
238 /// Provide access to the tracer pointer
239 Trace::InstTracer * getTracer() { return tracer; }
240
241 /// Notify the CPU that the indicated context is now active. The
242 /// delay parameter indicates the number of ticks to wait before
243 /// executing (typically 0 or 1).
177
178 protected:
179 std::vector<ThreadContext *> threadContexts;
180 std::vector<TheISA::Predecoder *> predecoders;
181
182 Trace::InstTracer * tracer;
183
184 public:
185
186 // Mask to align PCs to MachInst sized boundaries
187 static const Addr PCMask = ~((Addr)sizeof(TheISA::MachInst) - 1);
188
189 /// Provide access to the tracer pointer
190 Trace::InstTracer * getTracer() { return tracer; }
191
192 /// Notify the CPU that the indicated context is now active. The
193 /// delay parameter indicates the number of ticks to wait before
194 /// executing (typically 0 or 1).
244 virtual void activateContext(ThreadID thread_num, int delay) {}
195 virtual void activateContext(int thread_num, int delay) {}
245
246 /// Notify the CPU that the indicated context is now suspended.
196
197 /// Notify the CPU that the indicated context is now suspended.
247 virtual void suspendContext(ThreadID thread_num) {}
198 virtual void suspendContext(int thread_num) {}
248
249 /// Notify the CPU that the indicated context is now deallocated.
199
200 /// Notify the CPU that the indicated context is now deallocated.
250 virtual void deallocateContext(ThreadID thread_num) {}
201 virtual void deallocateContext(int thread_num) {}
251
252 /// Notify the CPU that the indicated context is now halted.
202
203 /// Notify the CPU that the indicated context is now halted.
253 virtual void haltContext(ThreadID thread_num) {}
204 virtual void haltContext(int thread_num) {}
254
255 /// Given a Thread Context pointer return the thread num
256 int findContext(ThreadContext *tc);
257
258 /// Given a thread num get tho thread context for it
259 ThreadContext *getContext(int tn) { return threadContexts[tn]; }
260
261 public:
262 typedef BaseCPUParams Params;
263 const Params *params() const
264 { return reinterpret_cast<const Params *>(_params); }
265 BaseCPU(Params *params);
266 virtual ~BaseCPU();
267
268 virtual void init();
269 virtual void startup();
270 virtual void regStats();
271
272 virtual void activateWhenReady(ThreadID tid) {};
273
274 void registerThreadContexts();
275
276 /// Prepare for another CPU to take over execution. When it is
277 /// is ready (drained pipe) it signals the sampler.
278 virtual void switchOut();
279
280 /// Take over execution from the given CPU. Used for warm-up and
281 /// sampling.
205
206 /// Given a Thread Context pointer return the thread num
207 int findContext(ThreadContext *tc);
208
209 /// Given a thread num get tho thread context for it
210 ThreadContext *getContext(int tn) { return threadContexts[tn]; }
211
212 public:
213 typedef BaseCPUParams Params;
214 const Params *params() const
215 { return reinterpret_cast<const Params *>(_params); }
216 BaseCPU(Params *params);
217 virtual ~BaseCPU();
218
219 virtual void init();
220 virtual void startup();
221 virtual void regStats();
222
223 virtual void activateWhenReady(ThreadID tid) {};
224
225 void registerThreadContexts();
226
227 /// Prepare for another CPU to take over execution. When it is
228 /// is ready (drained pipe) it signals the sampler.
229 virtual void switchOut();
230
231 /// Take over execution from the given CPU. Used for warm-up and
232 /// sampling.
282 virtual void takeOverFrom(BaseCPU *);
233 virtual void takeOverFrom(BaseCPU *, Port *ic, Port *dc);
283
284 /**
285 * Number of threads we're actually simulating (<= SMT_MAX_THREADS).
286 * This is a constant for the duration of the simulation.
287 */
288 ThreadID numThreads;
289
290 /**
291 * Vector of per-thread instruction-based event queues. Used for
292 * scheduling events based on number of instructions committed by
293 * a particular thread.
294 */
295 EventQueue **comInstEventQueue;
296
297 /**
298 * Vector of per-thread load-based event queues. Used for
299 * scheduling events based on number of loads committed by
300 *a particular thread.
301 */
302 EventQueue **comLoadEventQueue;
303
304 System *system;
305
306 Tick phase;
307
234
235 /**
236 * Number of threads we're actually simulating (<= SMT_MAX_THREADS).
237 * This is a constant for the duration of the simulation.
238 */
239 ThreadID numThreads;
240
241 /**
242 * Vector of per-thread instruction-based event queues. Used for
243 * scheduling events based on number of instructions committed by
244 * a particular thread.
245 */
246 EventQueue **comInstEventQueue;
247
248 /**
249 * Vector of per-thread load-based event queues. Used for
250 * scheduling events based on number of loads committed by
251 *a particular thread.
252 */
253 EventQueue **comLoadEventQueue;
254
255 System *system;
256
257 Tick phase;
258
308#if FULL_SYSTEM
309 /**
310 * Serialize this object to the given output stream.
311 * @param os The stream to serialize to.
312 */
313 virtual void serialize(std::ostream &os);
314
315 /**
316 * Reconstruct the state of this object from a checkpoint.
317 * @param cp The checkpoint use.
318 * @param section The section name of this object
319 */
320 virtual void unserialize(Checkpoint *cp, const std::string &section);
321
259 /**
260 * Serialize this object to the given output stream.
261 * @param os The stream to serialize to.
262 */
263 virtual void serialize(std::ostream &os);
264
265 /**
266 * Reconstruct the state of this object from a checkpoint.
267 * @param cp The checkpoint use.
268 * @param section The section name of this object
269 */
270 virtual void unserialize(Checkpoint *cp, const std::string &section);
271
322#endif
323
324 /**
325 * Return pointer to CPU's branch predictor (NULL if none).
326 * @return Branch predictor pointer.
327 */
328 virtual BranchPred *getBranchPred() { return NULL; };
329
330 virtual Counter totalInstructions() const = 0;
331
332 // Function tracing
333 private:
334 bool functionTracingEnabled;
335 std::ostream *functionTraceStream;
336 Addr currentFunctionStart;
337 Addr currentFunctionEnd;
338 Tick functionEntryTick;
339 void enableFunctionTrace();
340 void traceFunctionsInternal(Addr pc);
341
272 /**
273 * Return pointer to CPU's branch predictor (NULL if none).
274 * @return Branch predictor pointer.
275 */
276 virtual BranchPred *getBranchPred() { return NULL; };
277
278 virtual Counter totalInstructions() const = 0;
279
280 // Function tracing
281 private:
282 bool functionTracingEnabled;
283 std::ostream *functionTraceStream;
284 Addr currentFunctionStart;
285 Addr currentFunctionEnd;
286 Tick functionEntryTick;
287 void enableFunctionTrace();
288 void traceFunctionsInternal(Addr pc);
289
342 private:
343 static std::vector<BaseCPU *> cpuList; //!< Static global cpu list
344
345 public:
290 protected:
346 void traceFunctions(Addr pc)
347 {
348 if (functionTracingEnabled)
349 traceFunctionsInternal(pc);
350 }
351
291 void traceFunctions(Addr pc)
292 {
293 if (functionTracingEnabled)
294 traceFunctionsInternal(pc);
295 }
296
297 private:
298 static std::vector<BaseCPU *> cpuList; //!< Static global cpu list
299
300 public:
352 static int numSimulatedCPUs() { return cpuList.size(); }
353 static Counter numSimulatedInstructions()
354 {
355 Counter total = 0;
356
357 int size = cpuList.size();
358 for (int i = 0; i < size; ++i)
359 total += cpuList[i]->totalInstructions();
360
361 return total;
362 }
363
364 public:
365 // Number of CPU cycles simulated
366 Stats::Scalar numCycles;
367 Stats::Scalar numWorkItemsStarted;
368 Stats::Scalar numWorkItemsCompleted;
369};
370
371#endif // __CPU_BASE_HH__
301 static int numSimulatedCPUs() { return cpuList.size(); }
302 static Counter numSimulatedInstructions()
303 {
304 Counter total = 0;
305
306 int size = cpuList.size();
307 for (int i = 0; i < size; ++i)
308 total += cpuList[i]->totalInstructions();
309
310 return total;
311 }
312
313 public:
314 // Number of CPU cycles simulated
315 Stats::Scalar numCycles;
316 Stats::Scalar numWorkItemsStarted;
317 Stats::Scalar numWorkItemsCompleted;
318};
319
320#endif // __CPU_BASE_HH__