Merge ktlim@zizzer:/bk/newmem
[gem5.git] / src / cpu / checker / cpu.hh
1 /*
2 * Copyright (c) 2006 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
29 #ifndef __CPU_CHECKER_CPU_HH__
30 #define __CPU_CHECKER_CPU_HH__
31
32 #include <list>
33 #include <queue>
34 #include <map>
35
36 #include "arch/types.hh"
37 #include "base/statistics.hh"
38 #include "config/full_system.hh"
39 #include "cpu/base.hh"
40 #include "cpu/base_dyn_inst.hh"
41 #include "cpu/cpu_exec_context.hh"
42 #include "cpu/pc_event.hh"
43 #include "cpu/static_inst.hh"
44 #include "sim/eventq.hh"
45
46 // forward declarations
47 #if FULL_SYSTEM
48 class Processor;
49 class AlphaITB;
50 class AlphaDTB;
51 class PhysicalMemory;
52
53 class RemoteGDB;
54 class GDBListener;
55
56 #else
57
58 class Process;
59
60 #endif // FULL_SYSTEM
61 template <class>
62 class BaseDynInst;
63 class ExecContext;
64 class MemInterface;
65 class Checkpoint;
66 class Request;
67 class Sampler;
68
69 class CheckerCPU : public BaseCPU
70 {
71 protected:
72 typedef TheISA::MachInst MachInst;
73 typedef TheISA::FloatReg FloatReg;
74 typedef TheISA::FloatRegBits FloatRegBits;
75 typedef TheISA::MiscReg MiscReg;
76 public:
77 // main simulation loop (one cycle)
78 virtual void init();
79
80 struct Params : public BaseCPU::Params
81 {
82 #if FULL_SYSTEM
83 AlphaITB *itb;
84 AlphaDTB *dtb;
85 FunctionalMemory *mem;
86 #else
87 Process *process;
88 #endif
89 bool exitOnError;
90 };
91
92 public:
93 CheckerCPU(Params *p);
94 virtual ~CheckerCPU();
95
96 void setMemory(MemObject *mem);
97
98 MemObject *memPtr;
99
100 #if FULL_SYSTEM
101 void setSystem(System *system);
102
103 System *systemPtr;
104 #endif
105 public:
106 // execution context
107 CPUExecContext *cpuXC;
108
109 ExecContext *xcProxy;
110
111 AlphaITB *itb;
112 AlphaDTB *dtb;
113
114 #if FULL_SYSTEM
115 Addr dbg_vtophys(Addr addr);
116 #endif
117
118 union Result {
119 uint64_t integer;
120 float fp;
121 double dbl;
122 };
123
124 Result result;
125
126 // current instruction
127 MachInst machInst;
128
129 // Refcounted pointer to the one memory request.
130 Request *memReq;
131
132 StaticInstPtr curStaticInst;
133
134 // number of simulated instructions
135 Counter numInst;
136 Counter startNumInst;
137
138 std::queue<int> miscRegIdxs;
139
140 virtual Counter totalInstructions() const
141 {
142 return numInst - startNumInst;
143 }
144
145 // number of simulated loads
146 Counter numLoad;
147 Counter startNumLoad;
148
149 virtual void serialize(std::ostream &os);
150 virtual void unserialize(Checkpoint *cp, const std::string &section);
151
152 template <class T>
153 Fault read(Addr addr, T &data, unsigned flags);
154
155 template <class T>
156 Fault write(T data, Addr addr, unsigned flags, uint64_t *res);
157
158 // These functions are only used in CPU models that split
159 // effective address computation from the actual memory access.
160 void setEA(Addr EA) { panic("SimpleCPU::setEA() not implemented\n"); }
161 Addr getEA() { panic("SimpleCPU::getEA() not implemented\n"); }
162
163 void prefetch(Addr addr, unsigned flags)
164 {
165 // need to do this...
166 }
167
168 void writeHint(Addr addr, int size, unsigned flags)
169 {
170 // need to do this...
171 }
172
173 Fault copySrcTranslate(Addr src);
174
175 Fault copy(Addr dest);
176
177 // The register accessor methods provide the index of the
178 // instruction's operand (e.g., 0 or 1), not the architectural
179 // register index, to simplify the implementation of register
180 // renaming. We find the architectural register index by indexing
181 // into the instruction's own operand index table. Note that a
182 // raw pointer to the StaticInst is provided instead of a
183 // ref-counted StaticInstPtr to redice overhead. This is fine as
184 // long as these methods don't copy the pointer into any long-term
185 // storage (which is pretty hard to imagine they would have reason
186 // to do).
187
188 uint64_t readIntReg(const StaticInst *si, int idx)
189 {
190 return cpuXC->readIntReg(si->srcRegIdx(idx));
191 }
192
193 FloatReg readFloatReg(const StaticInst *si, int idx, int width)
194 {
195 int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
196 return cpuXC->readFloatReg(reg_idx, width);
197 }
198
199 FloatReg readFloatReg(const StaticInst *si, int idx)
200 {
201 int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
202 return cpuXC->readFloatReg(reg_idx);
203 }
204
205 FloatRegBits readFloatRegBits(const StaticInst *si, int idx, int width)
206 {
207 int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
208 return cpuXC->readFloatRegBits(reg_idx, width);
209 }
210
211 FloatRegBits readFloatRegBits(const StaticInst *si, int idx)
212 {
213 int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
214 return cpuXC->readFloatRegBits(reg_idx);
215 }
216
217 void setIntReg(const StaticInst *si, int idx, uint64_t val)
218 {
219 cpuXC->setIntReg(si->destRegIdx(idx), val);
220 result.integer = val;
221 }
222
223 void setFloatReg(const StaticInst *si, int idx, FloatReg val, int width)
224 {
225 int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
226 cpuXC->setFloatReg(reg_idx, val, width);
227 switch(width) {
228 case 32:
229 result.fp = val;
230 break;
231 case 64:
232 result.dbl = val;
233 break;
234 };
235 }
236
237 void setFloatReg(const StaticInst *si, int idx, FloatReg val)
238 {
239 int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
240 cpuXC->setFloatReg(reg_idx, val);
241 result.fp = val;
242 }
243
244 void setFloatRegBits(const StaticInst *si, int idx, FloatRegBits val,
245 int width)
246 {
247 int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
248 cpuXC->setFloatRegBits(reg_idx, val, width);
249 result.integer = val;
250 }
251
252 void setFloatRegBits(const StaticInst *si, int idx, FloatRegBits val)
253 {
254 int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
255 cpuXC->setFloatRegBits(reg_idx, val);
256 result.integer = val;
257 }
258
259 uint64_t readPC() { return cpuXC->readPC(); }
260
261 uint64_t readNextPC() { return cpuXC->readNextPC(); }
262
263 void setNextPC(uint64_t val) {
264 cpuXC->setNextPC(val);
265 }
266
267 MiscReg readMiscReg(int misc_reg)
268 {
269 return cpuXC->readMiscReg(misc_reg);
270 }
271
272 MiscReg readMiscRegWithEffect(int misc_reg, Fault &fault)
273 {
274 return cpuXC->readMiscRegWithEffect(misc_reg, fault);
275 }
276
277 Fault setMiscReg(int misc_reg, const MiscReg &val)
278 {
279 result.integer = val;
280 miscRegIdxs.push(misc_reg);
281 return cpuXC->setMiscReg(misc_reg, val);
282 }
283
284 Fault setMiscRegWithEffect(int misc_reg, const MiscReg &val)
285 {
286 miscRegIdxs.push(misc_reg);
287 return cpuXC->setMiscRegWithEffect(misc_reg, val);
288 }
289
290 void recordPCChange(uint64_t val) { changedPC = true; }
291 void recordNextPCChange(uint64_t val) { changedNextPC = true; }
292
293 bool translateInstReq(Request *req);
294 void translateDataWriteReq(Request *req);
295 void translateDataReadReq(Request *req);
296
297 #if FULL_SYSTEM
298 Fault hwrei() { return cpuXC->hwrei(); }
299 int readIntrFlag() { return cpuXC->readIntrFlag(); }
300 void setIntrFlag(int val) { cpuXC->setIntrFlag(val); }
301 bool inPalMode() { return cpuXC->inPalMode(); }
302 void ev5_trap(Fault fault) { fault->invoke(xcProxy); }
303 bool simPalCheck(int palFunc) { return cpuXC->simPalCheck(palFunc); }
304 #else
305 // Assume that the normal CPU's call to syscall was successful.
306 // The checker's state would have already been updated by the syscall.
307 void syscall(uint64_t callnum) { }
308 #endif
309
310 void handleError()
311 {
312 if (exitOnError)
313 panic("Checker found error!");
314 }
315 bool checkFlags(Request *req);
316
317 ExecContext *xcBase() { return xcProxy; }
318 CPUExecContext *cpuXCBase() { return cpuXC; }
319
320 Result unverifiedResult;
321 Request *unverifiedReq;
322
323 bool changedPC;
324 bool willChangePC;
325 uint64_t newPC;
326 bool changedNextPC;
327 bool exitOnError;
328
329 InstSeqNum youngestSN;
330 };
331
332 template <class DynInstPtr>
333 class Checker : public CheckerCPU
334 {
335 public:
336 Checker(Params *p)
337 : CheckerCPU(p)
338 { }
339
340 void switchOut(Sampler *s);
341 void takeOverFrom(BaseCPU *oldCPU);
342
343 void tick(DynInstPtr &inst);
344
345 void validateInst(DynInstPtr &inst);
346 void validateExecution(DynInstPtr &inst);
347 void validateState();
348
349 std::list<DynInstPtr> instList;
350 typedef typename std::list<DynInstPtr>::iterator InstListIt;
351 void dumpInsts();
352 };
353
354 #endif // __CPU_CHECKER_CPU_HH__