arch: nuke arch/isa_specific.hh and move stuff to generated config/the_isa.hh
[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 * Authors: Kevin Lim
29 */
30
31 #ifndef __CPU_CHECKER_CPU_HH__
32 #define __CPU_CHECKER_CPU_HH__
33
34 #include <list>
35 #include <queue>
36 #include <map>
37
38 #include "arch/types.hh"
39 #include "base/statistics.hh"
40 #include "config/full_system.hh"
41 #include "cpu/base.hh"
42 #include "cpu/base_dyn_inst.hh"
43 #include "cpu/simple_thread.hh"
44 #include "cpu/pc_event.hh"
45 #include "cpu/static_inst.hh"
46 #include "sim/eventq.hh"
47
48 // forward declarations
49 #if FULL_SYSTEM
50 namespace TheISA
51 {
52 class TLB;
53 }
54 class Processor;
55 class PhysicalMemory;
56
57 class RemoteGDB;
58 class GDBListener;
59
60 #else
61
62 class Process;
63
64 #endif // FULL_SYSTEM
65 template <class>
66 class BaseDynInst;
67 class CheckerCPUParams;
68 class ThreadContext;
69 class MemInterface;
70 class Checkpoint;
71 class Request;
72
73 /**
74 * CheckerCPU class. Dynamically verifies instructions as they are
75 * completed by making sure that the instruction and its results match
76 * the independent execution of the benchmark inside the checker. The
77 * checker verifies instructions in order, regardless of the order in
78 * which instructions complete. There are certain results that can
79 * not be verified, specifically the result of a store conditional or
80 * the values of uncached accesses. In these cases, and with
81 * instructions marked as "IsUnverifiable", the checker assumes that
82 * the value from the main CPU's execution is correct and simply
83 * copies that value. It provides a CheckerThreadContext (see
84 * checker/thread_context.hh) that provides hooks for updating the
85 * Checker's state through any ThreadContext accesses. This allows the
86 * checker to be able to correctly verify instructions, even with
87 * external accesses to the ThreadContext that change state.
88 */
89 class CheckerCPU : public BaseCPU
90 {
91 protected:
92 typedef TheISA::MachInst MachInst;
93 typedef TheISA::FloatReg FloatReg;
94 typedef TheISA::FloatRegBits FloatRegBits;
95 typedef TheISA::MiscReg MiscReg;
96 public:
97 virtual void init();
98
99 public:
100 typedef CheckerCPUParams Params;
101 const Params *params() const
102 { return reinterpret_cast<const Params *>(_params); }
103 CheckerCPU(Params *p);
104 virtual ~CheckerCPU();
105
106 Process *process;
107
108 void setSystem(System *system);
109
110 System *systemPtr;
111
112 void setIcachePort(Port *icache_port);
113
114 Port *icachePort;
115
116 void setDcachePort(Port *dcache_port);
117
118 Port *dcachePort;
119
120 virtual Port *getPort(const std::string &name, int idx)
121 {
122 panic("Not supported on checker!");
123 return NULL;
124 }
125
126 public:
127 // Primary thread being run.
128 SimpleThread *thread;
129
130 ThreadContext *tc;
131
132 TheISA::TLB *itb;
133 TheISA::TLB *dtb;
134
135 #if FULL_SYSTEM
136 Addr dbg_vtophys(Addr addr);
137 #endif
138
139 union Result {
140 uint64_t integer;
141 // float fp;
142 double dbl;
143 };
144
145 Result result;
146
147 // current instruction
148 MachInst machInst;
149
150 // Pointer to the one memory request.
151 RequestPtr memReq;
152
153 StaticInstPtr curStaticInst;
154
155 // number of simulated instructions
156 Counter numInst;
157 Counter startNumInst;
158
159 std::queue<int> miscRegIdxs;
160
161 virtual Counter totalInstructions() const
162 {
163 return 0;
164 }
165
166 // number of simulated loads
167 Counter numLoad;
168 Counter startNumLoad;
169
170 virtual void serialize(std::ostream &os);
171 virtual void unserialize(Checkpoint *cp, const std::string &section);
172
173 template <class T>
174 Fault read(Addr addr, T &data, unsigned flags);
175
176 template <class T>
177 Fault write(T data, Addr addr, unsigned flags, uint64_t *res);
178
179 // These functions are only used in CPU models that split
180 // effective address computation from the actual memory access.
181 void setEA(Addr EA) { panic("SimpleCPU::setEA() not implemented\n"); }
182 Addr getEA() { panic("SimpleCPU::getEA() not implemented\n"); }
183
184 void prefetch(Addr addr, unsigned flags)
185 {
186 // need to do this...
187 }
188
189 void writeHint(Addr addr, int size, unsigned flags)
190 {
191 // need to do this...
192 }
193
194 Fault copySrcTranslate(Addr src);
195
196 Fault copy(Addr dest);
197
198 // The register accessor methods provide the index of the
199 // instruction's operand (e.g., 0 or 1), not the architectural
200 // register index, to simplify the implementation of register
201 // renaming. We find the architectural register index by indexing
202 // into the instruction's own operand index table. Note that a
203 // raw pointer to the StaticInst is provided instead of a
204 // ref-counted StaticInstPtr to redice overhead. This is fine as
205 // long as these methods don't copy the pointer into any long-term
206 // storage (which is pretty hard to imagine they would have reason
207 // to do).
208
209 uint64_t readIntRegOperand(const StaticInst *si, int idx)
210 {
211 return thread->readIntReg(si->srcRegIdx(idx));
212 }
213
214 FloatReg readFloatRegOperand(const StaticInst *si, int idx)
215 {
216 int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
217 return thread->readFloatReg(reg_idx);
218 }
219
220 FloatRegBits readFloatRegOperandBits(const StaticInst *si, int idx)
221 {
222 int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag;
223 return thread->readFloatRegBits(reg_idx);
224 }
225
226 void setIntRegOperand(const StaticInst *si, int idx, uint64_t val)
227 {
228 thread->setIntReg(si->destRegIdx(idx), val);
229 result.integer = val;
230 }
231
232 void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val)
233 {
234 int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
235 thread->setFloatReg(reg_idx, val);
236 result.dbl = (double)val;
237 }
238
239 void setFloatRegOperandBits(const StaticInst *si, int idx,
240 FloatRegBits val)
241 {
242 int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
243 thread->setFloatRegBits(reg_idx, val);
244 result.integer = val;
245 }
246
247 uint64_t readPC() { return thread->readPC(); }
248
249 uint64_t readNextPC() { return thread->readNextPC(); }
250
251 void setNextPC(uint64_t val) {
252 thread->setNextPC(val);
253 }
254
255 MiscReg readMiscRegNoEffect(int misc_reg)
256 {
257 return thread->readMiscRegNoEffect(misc_reg);
258 }
259
260 MiscReg readMiscReg(int misc_reg)
261 {
262 return thread->readMiscReg(misc_reg);
263 }
264
265 void setMiscRegNoEffect(int misc_reg, const MiscReg &val)
266 {
267 result.integer = val;
268 miscRegIdxs.push(misc_reg);
269 return thread->setMiscRegNoEffect(misc_reg, val);
270 }
271
272 void setMiscReg(int misc_reg, const MiscReg &val)
273 {
274 miscRegIdxs.push(misc_reg);
275 return thread->setMiscReg(misc_reg, val);
276 }
277
278 void recordPCChange(uint64_t val) { changedPC = true; newPC = val; }
279 void recordNextPCChange(uint64_t val) { changedNextPC = true; }
280
281 void demapPage(Addr vaddr, uint64_t asn)
282 {
283 this->itb->demapPage(vaddr, asn);
284 this->dtb->demapPage(vaddr, asn);
285 }
286
287 void demapInstPage(Addr vaddr, uint64_t asn)
288 {
289 this->itb->demapPage(vaddr, asn);
290 }
291
292 void demapDataPage(Addr vaddr, uint64_t asn)
293 {
294 this->dtb->demapPage(vaddr, asn);
295 }
296
297 #if FULL_SYSTEM
298 Fault hwrei() { return thread->hwrei(); }
299 void ev5_trap(Fault fault) { fault->invoke(tc); }
300 bool simPalCheck(int palFunc) { return thread->simPalCheck(palFunc); }
301 #else
302 // Assume that the normal CPU's call to syscall was successful.
303 // The checker's state would have already been updated by the syscall.
304 void syscall(uint64_t callnum) { }
305 #endif
306
307 void handleError()
308 {
309 if (exitOnError)
310 dumpAndExit();
311 }
312
313 bool checkFlags(Request *req);
314
315 void dumpAndExit();
316
317 ThreadContext *tcBase() { return tc; }
318 SimpleThread *threadBase() { return thread; }
319
320 Result unverifiedResult;
321 Request *unverifiedReq;
322 uint8_t *unverifiedMemData;
323
324 bool changedPC;
325 bool willChangePC;
326 uint64_t newPC;
327 bool changedNextPC;
328 bool exitOnError;
329 bool updateOnError;
330 bool warnOnlyOnLoadError;
331
332 InstSeqNum youngestSN;
333 };
334
335 /**
336 * Templated Checker class. This Checker class is templated on the
337 * DynInstPtr of the instruction type that will be verified. Proper
338 * template instantiations of the Checker must be placed at the bottom
339 * of checker/cpu.cc.
340 */
341 template <class DynInstPtr>
342 class Checker : public CheckerCPU
343 {
344 public:
345 Checker(Params *p)
346 : CheckerCPU(p), updateThisCycle(false), unverifiedInst(NULL)
347 { }
348
349 void switchOut();
350 void takeOverFrom(BaseCPU *oldCPU);
351
352 void verify(DynInstPtr &inst);
353
354 void validateInst(DynInstPtr &inst);
355 void validateExecution(DynInstPtr &inst);
356 void validateState();
357
358 void copyResult(DynInstPtr &inst);
359
360 private:
361 void handleError(DynInstPtr &inst)
362 {
363 if (exitOnError) {
364 dumpAndExit(inst);
365 } else if (updateOnError) {
366 updateThisCycle = true;
367 }
368 }
369
370 void dumpAndExit(DynInstPtr &inst);
371
372 bool updateThisCycle;
373
374 DynInstPtr unverifiedInst;
375
376 std::list<DynInstPtr> instList;
377 typedef typename std::list<DynInstPtr>::iterator InstListIt;
378 void dumpInsts();
379 };
380
381 #endif // __CPU_CHECKER_CPU_HH__