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