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 *
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"
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;
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
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
125 protected:
126 TheISA::Interrupts *interrupts;
127
128 public:
129 TheISA::Interrupts *
130 getInterruptController()
131 {
132 return interrupts;
133 }
134
135#if FULL_SYSTEM
136 virtual void wakeup() = 0;
137#endif
138
139 void
140 postInterrupt(int int_num, int index)
141 {
142 interrupts->post(int_num, index);
143#if FULL_SYSTEM
144 wakeup();
145#endif
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
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) {}
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) {}
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) {}
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) {}
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);
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
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
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:
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:
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__