includes: sort all includes
[gem5.git] / src / cpu / simple / base.hh
1 /*
2 * Copyright (c) 2002-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
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.
15 *
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.
27 *
28 * Authors: Steve Reinhardt
29 * Dave Greene
30 * Nathan Binkert
31 */
32
33 #ifndef __CPU_SIMPLE_BASE_HH__
34 #define __CPU_SIMPLE_BASE_HH__
35
36 #include "arch/predecoder.hh"
37 #include "base/statistics.hh"
38 #include "config/full_system.hh"
39 #include "config/the_isa.hh"
40 #include "cpu/base.hh"
41 #include "cpu/pc_event.hh"
42 #include "cpu/simple_thread.hh"
43 #include "cpu/static_inst.hh"
44 #include "mem/packet.hh"
45 #include "mem/port.hh"
46 #include "mem/request.hh"
47 #include "sim/eventq.hh"
48 #include "sim/system.hh"
49
50 // forward declarations
51 #if FULL_SYSTEM
52 class Processor;
53 namespace TheISA
54 {
55 class ITB;
56 class DTB;
57 }
58 class MemObject;
59
60 #else
61
62 class Process;
63
64 #endif // FULL_SYSTEM
65
66 namespace TheISA
67 {
68 class Predecoder;
69 }
70 class ThreadContext;
71 class Checkpoint;
72
73 namespace Trace {
74 class InstRecord;
75 }
76
77 class BaseSimpleCPUParams;
78
79
80 class BaseSimpleCPU : public BaseCPU
81 {
82 protected:
83 typedef TheISA::MiscReg MiscReg;
84 typedef TheISA::FloatReg FloatReg;
85 typedef TheISA::FloatRegBits FloatRegBits;
86
87 protected:
88 Trace::InstRecord *traceData;
89
90 inline void checkPcEventQueue() {
91 Addr oldpc, pc = thread->instAddr();
92 do {
93 oldpc = pc;
94 system->pcEventQueue.service(tc);
95 pc = thread->instAddr();
96 } while (oldpc != pc);
97 }
98
99 public:
100 void wakeup();
101
102 void zero_fill_64(Addr addr) {
103 static int warned = 0;
104 if (!warned) {
105 warn ("WH64 is not implemented");
106 warned = 1;
107 }
108 };
109
110 public:
111 BaseSimpleCPU(BaseSimpleCPUParams *params);
112 virtual ~BaseSimpleCPU();
113
114 public:
115 /** SimpleThread object, provides all the architectural state. */
116 SimpleThread *thread;
117
118 /** ThreadContext object, provides an interface for external
119 * objects to modify this thread's state.
120 */
121 ThreadContext *tc;
122 protected:
123
124 enum Status {
125 Idle,
126 Running,
127 ITBWaitResponse,
128 IcacheRetry,
129 IcacheWaitResponse,
130 IcacheWaitSwitch,
131 DTBWaitResponse,
132 DcacheRetry,
133 DcacheWaitResponse,
134 DcacheWaitSwitch,
135 SwitchedOut
136 };
137
138 Status _status;
139
140 public:
141
142 #if FULL_SYSTEM
143 Addr dbg_vtophys(Addr addr);
144
145 bool interval_stats;
146 #endif
147
148 // current instruction
149 TheISA::MachInst inst;
150
151 // The predecoder
152 TheISA::Predecoder predecoder;
153
154 StaticInstPtr curStaticInst;
155 StaticInstPtr curMacroStaticInst;
156
157 //This is the offset from the current pc that fetch should be performed at
158 Addr fetchOffset;
159 //This flag says to stay at the current pc. This is useful for
160 //instructions which go beyond MachInst boundaries.
161 bool stayAtPC;
162
163 void checkForInterrupts();
164 void setupFetchRequest(Request *req);
165 void preExecute();
166 void postExecute();
167 void advancePC(Fault fault);
168
169 virtual void deallocateContext(int thread_num);
170 virtual void haltContext(int thread_num);
171
172 // statistics
173 virtual void regStats();
174 virtual void resetStats();
175
176 // number of simulated instructions
177 Counter numInst;
178 Counter startNumInst;
179 Stats::Scalar numInsts;
180
181 void countInst()
182 {
183 numInst++;
184 numInsts++;
185 system->totalNumInsts++;
186 thread->funcExeInst++;
187 }
188
189 virtual Counter totalInstructions() const
190 {
191 return numInst - startNumInst;
192 }
193
194 //number of integer alu accesses
195 Stats::Scalar numIntAluAccesses;
196
197 //number of float alu accesses
198 Stats::Scalar numFpAluAccesses;
199
200 //number of function calls/returns
201 Stats::Scalar numCallsReturns;
202
203 //conditional control instructions;
204 Stats::Scalar numCondCtrlInsts;
205
206 //number of int instructions
207 Stats::Scalar numIntInsts;
208
209 //number of float instructions
210 Stats::Scalar numFpInsts;
211
212 //number of integer register file accesses
213 Stats::Scalar numIntRegReads;
214 Stats::Scalar numIntRegWrites;
215
216 //number of float register file accesses
217 Stats::Scalar numFpRegReads;
218 Stats::Scalar numFpRegWrites;
219
220 // number of simulated memory references
221 Stats::Scalar numMemRefs;
222 Stats::Scalar numLoadInsts;
223 Stats::Scalar numStoreInsts;
224
225 // number of idle cycles
226 Stats::Formula numIdleCycles;
227
228 // number of busy cycles
229 Stats::Formula numBusyCycles;
230
231 // number of simulated loads
232 Counter numLoad;
233 Counter startNumLoad;
234
235 // number of idle cycles
236 Stats::Average notIdleFraction;
237 Stats::Formula idleFraction;
238
239 // number of cycles stalled for I-cache responses
240 Stats::Scalar icacheStallCycles;
241 Counter lastIcacheStall;
242
243 // number of cycles stalled for I-cache retries
244 Stats::Scalar icacheRetryCycles;
245 Counter lastIcacheRetry;
246
247 // number of cycles stalled for D-cache responses
248 Stats::Scalar dcacheStallCycles;
249 Counter lastDcacheStall;
250
251 // number of cycles stalled for D-cache retries
252 Stats::Scalar dcacheRetryCycles;
253 Counter lastDcacheRetry;
254
255 virtual void serialize(std::ostream &os);
256 virtual void unserialize(Checkpoint *cp, const std::string &section);
257
258 // These functions are only used in CPU models that split
259 // effective address computation from the actual memory access.
260 void setEA(Addr EA) { panic("BaseSimpleCPU::setEA() not implemented\n"); }
261 Addr getEA() { panic("BaseSimpleCPU::getEA() not implemented\n");
262 M5_DUMMY_RETURN}
263
264 // The register accessor methods provide the index of the
265 // instruction's operand (e.g., 0 or 1), not the architectural
266 // register index, to simplify the implementation of register
267 // renaming. We find the architectural register index by indexing
268 // into the instruction's own operand index table. Note that a
269 // raw pointer to the StaticInst is provided instead of a
270 // ref-counted StaticInstPtr to redice overhead. This is fine as
271 // long as these methods don't copy the pointer into any long-term
272 // storage (which is pretty hard to imagine they would have reason
273 // to do).
274
275 uint64_t readIntRegOperand(const StaticInst *si, int idx)
276 {
277 numIntRegReads++;
278 return thread->readIntReg(si->srcRegIdx(idx));
279 }
280
281 FloatReg readFloatRegOperand(const StaticInst *si, int idx)
282 {
283 numFpRegReads++;
284 int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
285 return thread->readFloatReg(reg_idx);
286 }
287
288 FloatRegBits readFloatRegOperandBits(const StaticInst *si, int idx)
289 {
290 numFpRegReads++;
291 int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
292 return thread->readFloatRegBits(reg_idx);
293 }
294
295 void setIntRegOperand(const StaticInst *si, int idx, uint64_t val)
296 {
297 numIntRegWrites++;
298 thread->setIntReg(si->destRegIdx(idx), val);
299 }
300
301 void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val)
302 {
303 numFpRegWrites++;
304 int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
305 thread->setFloatReg(reg_idx, val);
306 }
307
308 void setFloatRegOperandBits(const StaticInst *si, int idx,
309 FloatRegBits val)
310 {
311 numFpRegWrites++;
312 int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
313 thread->setFloatRegBits(reg_idx, val);
314 }
315
316 bool readPredicate() { return thread->readPredicate(); }
317 void setPredicate(bool val)
318 {
319 thread->setPredicate(val);
320 if (traceData) {
321 traceData->setPredicate(val);
322 }
323 }
324 TheISA::PCState pcState() { return thread->pcState(); }
325 void pcState(const TheISA::PCState &val) { thread->pcState(val); }
326 Addr instAddr() { return thread->instAddr(); }
327 Addr nextInstAddr() { return thread->nextInstAddr(); }
328 MicroPC microPC() { return thread->microPC(); }
329
330 MiscReg readMiscRegNoEffect(int misc_reg)
331 {
332 return thread->readMiscRegNoEffect(misc_reg);
333 }
334
335 MiscReg readMiscReg(int misc_reg)
336 {
337 numIntRegReads++;
338 return thread->readMiscReg(misc_reg);
339 }
340
341 void setMiscReg(int misc_reg, const MiscReg &val)
342 {
343 numIntRegWrites++;
344 return thread->setMiscReg(misc_reg, val);
345 }
346
347 MiscReg readMiscRegOperand(const StaticInst *si, int idx)
348 {
349 numIntRegReads++;
350 int reg_idx = si->srcRegIdx(idx) - TheISA::Ctrl_Base_DepTag;
351 return thread->readMiscReg(reg_idx);
352 }
353
354 void setMiscRegOperand(
355 const StaticInst *si, int idx, const MiscReg &val)
356 {
357 numIntRegWrites++;
358 int reg_idx = si->destRegIdx(idx) - TheISA::Ctrl_Base_DepTag;
359 return thread->setMiscReg(reg_idx, val);
360 }
361
362 void demapPage(Addr vaddr, uint64_t asn)
363 {
364 thread->demapPage(vaddr, asn);
365 }
366
367 void demapInstPage(Addr vaddr, uint64_t asn)
368 {
369 thread->demapInstPage(vaddr, asn);
370 }
371
372 void demapDataPage(Addr vaddr, uint64_t asn)
373 {
374 thread->demapDataPage(vaddr, asn);
375 }
376
377 unsigned readStCondFailures() {
378 return thread->readStCondFailures();
379 }
380
381 void setStCondFailures(unsigned sc_failures) {
382 thread->setStCondFailures(sc_failures);
383 }
384
385 MiscReg readRegOtherThread(int regIdx, ThreadID tid = InvalidThreadID)
386 {
387 panic("Simple CPU models do not support multithreaded "
388 "register access.\n");
389 }
390
391 void setRegOtherThread(int regIdx, const MiscReg &val,
392 ThreadID tid = InvalidThreadID)
393 {
394 panic("Simple CPU models do not support multithreaded "
395 "register access.\n");
396 }
397
398 //Fault CacheOp(uint8_t Op, Addr EA);
399
400 #if FULL_SYSTEM
401 Fault hwrei() { return thread->hwrei(); }
402 bool simPalCheck(int palFunc) { return thread->simPalCheck(palFunc); }
403 #else
404 void syscall(int64_t callnum) { thread->syscall(callnum); }
405 #endif
406
407 bool misspeculating() { return thread->misspeculating(); }
408 ThreadContext *tcBase() { return tc; }
409 };
410
411 #endif // __CPU_SIMPLE_BASE_HH__