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