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 ITB; 53 class DTB; 54} 55class Processor; 56class PhysicalMemory; 57 58class RemoteGDB; 59class GDBListener; 60 61#else 62 63class Process; 64 65#endif // FULL_SYSTEM 66template <class> 67class BaseDynInst; 68class ThreadContext; 69class MemInterface; 70class Checkpoint; 71class 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 */ 89class 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 struct Params : public BaseCPU::Params 100 { 101#if FULL_SYSTEM 102 TheISA::ITB *itb; 103 TheISA::DTB *dtb; 104#else 105 Process *process; 106#endif 107 bool exitOnError; 108 bool updateOnError; 109 bool warnOnlyOnLoadError; 110 }; 111 112 public: 113 CheckerCPU(Params *p); 114 virtual ~CheckerCPU(); 115 116 Process *process; 117 118 void setSystem(System *system); 119 120 System *systemPtr; 121 122 void setIcachePort(Port *icache_port); 123 124 Port *icachePort; 125 126 void setDcachePort(Port *dcache_port); 127 128 Port *dcachePort; 129 130 virtual Port *getPort(const std::string &name, int idx) 131 { 132 panic("Not supported on checker!"); 133 return NULL; 134 } 135 136 public: 137 // Primary thread being run. 138 SimpleThread *thread; 139 140 ThreadContext *tc; 141 142 TheISA::ITB *itb; 143 TheISA::DTB *dtb; 144 145#if FULL_SYSTEM 146 Addr dbg_vtophys(Addr addr); 147#endif 148 149 union Result { 150 uint64_t integer; 151// float fp; 152 double dbl; 153 }; 154 155 Result result; 156 157 // current instruction 158 MachInst machInst; 159 160 // Pointer to the one memory request. 161 RequestPtr memReq; 162 163 StaticInstPtr curStaticInst; 164 165 // number of simulated instructions 166 Counter numInst; 167 Counter startNumInst; 168 169 std::queue<int> miscRegIdxs; 170 171 virtual Counter totalInstructions() const 172 { 173 return 0; 174 } 175 176 // number of simulated loads 177 Counter numLoad; 178 Counter startNumLoad; 179 180 virtual void serialize(std::ostream &os); 181 virtual void unserialize(Checkpoint *cp, const std::string §ion); 182 183 template <class T> 184 Fault read(Addr addr, T &data, unsigned flags); 185 186 template <class T> 187 Fault write(T data, Addr addr, unsigned flags, uint64_t *res); 188 189 // These functions are only used in CPU models that split 190 // effective address computation from the actual memory access. 191 void setEA(Addr EA) { panic("SimpleCPU::setEA() not implemented\n"); } 192 Addr getEA() { panic("SimpleCPU::getEA() not implemented\n"); } 193 194 void prefetch(Addr addr, unsigned flags) 195 { 196 // need to do this... 197 } 198 199 void writeHint(Addr addr, int size, unsigned flags) 200 { 201 // need to do this... 202 } 203 204 Fault copySrcTranslate(Addr src); 205 206 Fault copy(Addr dest); 207 208 // The register accessor methods provide the index of the 209 // instruction's operand (e.g., 0 or 1), not the architectural 210 // register index, to simplify the implementation of register 211 // renaming. We find the architectural register index by indexing 212 // into the instruction's own operand index table. Note that a 213 // raw pointer to the StaticInst is provided instead of a 214 // ref-counted StaticInstPtr to redice overhead. This is fine as 215 // long as these methods don't copy the pointer into any long-term 216 // storage (which is pretty hard to imagine they would have reason 217 // to do). 218
| 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 ITB; 53 class DTB; 54} 55class Processor; 56class PhysicalMemory; 57 58class RemoteGDB; 59class GDBListener; 60 61#else 62 63class Process; 64 65#endif // FULL_SYSTEM 66template <class> 67class BaseDynInst; 68class ThreadContext; 69class MemInterface; 70class Checkpoint; 71class 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 */ 89class 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 struct Params : public BaseCPU::Params 100 { 101#if FULL_SYSTEM 102 TheISA::ITB *itb; 103 TheISA::DTB *dtb; 104#else 105 Process *process; 106#endif 107 bool exitOnError; 108 bool updateOnError; 109 bool warnOnlyOnLoadError; 110 }; 111 112 public: 113 CheckerCPU(Params *p); 114 virtual ~CheckerCPU(); 115 116 Process *process; 117 118 void setSystem(System *system); 119 120 System *systemPtr; 121 122 void setIcachePort(Port *icache_port); 123 124 Port *icachePort; 125 126 void setDcachePort(Port *dcache_port); 127 128 Port *dcachePort; 129 130 virtual Port *getPort(const std::string &name, int idx) 131 { 132 panic("Not supported on checker!"); 133 return NULL; 134 } 135 136 public: 137 // Primary thread being run. 138 SimpleThread *thread; 139 140 ThreadContext *tc; 141 142 TheISA::ITB *itb; 143 TheISA::DTB *dtb; 144 145#if FULL_SYSTEM 146 Addr dbg_vtophys(Addr addr); 147#endif 148 149 union Result { 150 uint64_t integer; 151// float fp; 152 double dbl; 153 }; 154 155 Result result; 156 157 // current instruction 158 MachInst machInst; 159 160 // Pointer to the one memory request. 161 RequestPtr memReq; 162 163 StaticInstPtr curStaticInst; 164 165 // number of simulated instructions 166 Counter numInst; 167 Counter startNumInst; 168 169 std::queue<int> miscRegIdxs; 170 171 virtual Counter totalInstructions() const 172 { 173 return 0; 174 } 175 176 // number of simulated loads 177 Counter numLoad; 178 Counter startNumLoad; 179 180 virtual void serialize(std::ostream &os); 181 virtual void unserialize(Checkpoint *cp, const std::string §ion); 182 183 template <class T> 184 Fault read(Addr addr, T &data, unsigned flags); 185 186 template <class T> 187 Fault write(T data, Addr addr, unsigned flags, uint64_t *res); 188 189 // These functions are only used in CPU models that split 190 // effective address computation from the actual memory access. 191 void setEA(Addr EA) { panic("SimpleCPU::setEA() not implemented\n"); } 192 Addr getEA() { panic("SimpleCPU::getEA() not implemented\n"); } 193 194 void prefetch(Addr addr, unsigned flags) 195 { 196 // need to do this... 197 } 198 199 void writeHint(Addr addr, int size, unsigned flags) 200 { 201 // need to do this... 202 } 203 204 Fault copySrcTranslate(Addr src); 205 206 Fault copy(Addr dest); 207 208 // The register accessor methods provide the index of the 209 // instruction's operand (e.g., 0 or 1), not the architectural 210 // register index, to simplify the implementation of register 211 // renaming. We find the architectural register index by indexing 212 // into the instruction's own operand index table. Note that a 213 // raw pointer to the StaticInst is provided instead of a 214 // ref-counted StaticInstPtr to redice overhead. This is fine as 215 // long as these methods don't copy the pointer into any long-term 216 // storage (which is pretty hard to imagine they would have reason 217 // to do). 218
|
219 uint64_t readIntReg(const StaticInst *si, int idx)
| 219 uint64_t readIntRegOperand(const StaticInst *si, int idx)
|
220 { 221 return thread->readIntReg(si->srcRegIdx(idx)); 222 } 223
| 220 { 221 return thread->readIntReg(si->srcRegIdx(idx)); 222 } 223
|
224 FloatReg readFloatReg(const StaticInst *si, int idx, int width)
| 224 FloatReg readFloatRegOperand(const StaticInst *si, int idx, int width)
|
225 { 226 int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; 227 return thread->readFloatReg(reg_idx, width); 228 } 229
| 225 { 226 int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; 227 return thread->readFloatReg(reg_idx, width); 228 } 229
|
230 FloatReg readFloatReg(const StaticInst *si, int idx)
| 230 FloatReg readFloatRegOperand(const StaticInst *si, int idx)
|
231 { 232 int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; 233 return thread->readFloatReg(reg_idx); 234 } 235
| 231 { 232 int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; 233 return thread->readFloatReg(reg_idx); 234 } 235
|
236 FloatRegBits readFloatRegBits(const StaticInst *si, int idx, int width)
| 236 FloatRegBits readFloatRegOperandBits(const StaticInst *si, int idx, 237 int width)
|
237 { 238 int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; 239 return thread->readFloatRegBits(reg_idx, width); 240 } 241
| 238 { 239 int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; 240 return thread->readFloatRegBits(reg_idx, width); 241 } 242
|
242 FloatRegBits readFloatRegBits(const StaticInst *si, int idx)
| 243 FloatRegBits readFloatRegOperandBits(const StaticInst *si, int idx)
|
243 { 244 int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; 245 return thread->readFloatRegBits(reg_idx); 246 } 247
| 244 { 245 int reg_idx = si->srcRegIdx(idx) - TheISA::FP_Base_DepTag; 246 return thread->readFloatRegBits(reg_idx); 247 } 248
|
248 void setIntReg(const StaticInst *si, int idx, uint64_t val)
| 249 void setIntRegOperand(const StaticInst *si, int idx, uint64_t val)
|
249 { 250 thread->setIntReg(si->destRegIdx(idx), val); 251 result.integer = val; 252 } 253
| 250 { 251 thread->setIntReg(si->destRegIdx(idx), val); 252 result.integer = val; 253 } 254
|
254 void setFloatReg(const StaticInst *si, int idx, FloatReg val, int width)
| 255 void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val, 256 int width)
|
255 { 256 int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; 257 thread->setFloatReg(reg_idx, val, width); 258 switch(width) { 259 case 32: 260 result.dbl = (double)val; 261 break; 262 case 64: 263 result.dbl = val; 264 break; 265 }; 266 } 267
| 257 { 258 int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; 259 thread->setFloatReg(reg_idx, val, width); 260 switch(width) { 261 case 32: 262 result.dbl = (double)val; 263 break; 264 case 64: 265 result.dbl = val; 266 break; 267 }; 268 } 269
|
268 void setFloatReg(const StaticInst *si, int idx, FloatReg val)
| 270 void setFloatRegOperand(const StaticInst *si, int idx, FloatReg val)
|
269 { 270 int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; 271 thread->setFloatReg(reg_idx, val); 272 result.dbl = (double)val; 273 } 274
| 271 { 272 int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; 273 thread->setFloatReg(reg_idx, val); 274 result.dbl = (double)val; 275 } 276
|
275 void setFloatRegBits(const StaticInst *si, int idx, FloatRegBits val, 276 int width)
| 277 void setFloatRegOperandBits(const StaticInst *si, int idx, 278 FloatRegBits val, int width)
|
277 { 278 int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; 279 thread->setFloatRegBits(reg_idx, val, width); 280 result.integer = val; 281 } 282
| 279 { 280 int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; 281 thread->setFloatRegBits(reg_idx, val, width); 282 result.integer = val; 283 } 284
|
283 void setFloatRegBits(const StaticInst *si, int idx, FloatRegBits val)
| 285 void setFloatRegOperandBits(const StaticInst *si, int idx, 286 FloatRegBits val)
|
284 { 285 int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; 286 thread->setFloatRegBits(reg_idx, val); 287 result.integer = val; 288 } 289 290 uint64_t readPC() { return thread->readPC(); } 291 292 uint64_t readNextPC() { return thread->readNextPC(); } 293 294 void setNextPC(uint64_t val) { 295 thread->setNextPC(val); 296 } 297 298 MiscReg readMiscReg(int misc_reg) 299 { 300 return thread->readMiscReg(misc_reg); 301 } 302 303 MiscReg readMiscRegWithEffect(int misc_reg) 304 { 305 return thread->readMiscRegWithEffect(misc_reg); 306 } 307 308 void setMiscReg(int misc_reg, const MiscReg &val) 309 { 310 result.integer = val; 311 miscRegIdxs.push(misc_reg); 312 return thread->setMiscReg(misc_reg, val); 313 } 314 315 void setMiscRegWithEffect(int misc_reg, const MiscReg &val) 316 { 317 miscRegIdxs.push(misc_reg); 318 return thread->setMiscRegWithEffect(misc_reg, val); 319 } 320 321 void recordPCChange(uint64_t val) { changedPC = true; newPC = val; } 322 void recordNextPCChange(uint64_t val) { changedNextPC = true; } 323 324 bool translateInstReq(Request *req); 325 void translateDataWriteReq(Request *req); 326 void translateDataReadReq(Request *req); 327 328#if FULL_SYSTEM 329 Fault hwrei() { return thread->hwrei(); } 330 void ev5_trap(Fault fault) { fault->invoke(tc); } 331 bool simPalCheck(int palFunc) { return thread->simPalCheck(palFunc); } 332#else 333 // Assume that the normal CPU's call to syscall was successful. 334 // The checker's state would have already been updated by the syscall. 335 void syscall(uint64_t callnum) { } 336#endif 337 338 void handleError() 339 { 340 if (exitOnError) 341 dumpAndExit(); 342 } 343 344 bool checkFlags(Request *req); 345 346 void dumpAndExit(); 347 348 ThreadContext *tcBase() { return tc; } 349 SimpleThread *threadBase() { return thread; } 350 351 Result unverifiedResult; 352 Request *unverifiedReq; 353 uint8_t *unverifiedMemData; 354 355 bool changedPC; 356 bool willChangePC; 357 uint64_t newPC; 358 bool changedNextPC; 359 bool exitOnError; 360 bool updateOnError; 361 bool warnOnlyOnLoadError; 362 363 InstSeqNum youngestSN; 364}; 365 366/** 367 * Templated Checker class. This Checker class is templated on the 368 * DynInstPtr of the instruction type that will be verified. Proper 369 * template instantiations of the Checker must be placed at the bottom 370 * of checker/cpu.cc. 371 */ 372template <class DynInstPtr> 373class Checker : public CheckerCPU 374{ 375 public: 376 Checker(Params *p) 377 : CheckerCPU(p), updateThisCycle(false), unverifiedInst(NULL) 378 { } 379 380 void switchOut(); 381 void takeOverFrom(BaseCPU *oldCPU); 382 383 void verify(DynInstPtr &inst); 384 385 void validateInst(DynInstPtr &inst); 386 void validateExecution(DynInstPtr &inst); 387 void validateState(); 388 389 void copyResult(DynInstPtr &inst); 390 391 private: 392 void handleError(DynInstPtr &inst) 393 { 394 if (exitOnError) { 395 dumpAndExit(inst); 396 } else if (updateOnError) { 397 updateThisCycle = true; 398 } 399 } 400 401 void dumpAndExit(DynInstPtr &inst); 402 403 bool updateThisCycle; 404 405 DynInstPtr unverifiedInst; 406 407 std::list<DynInstPtr> instList; 408 typedef typename std::list<DynInstPtr>::iterator InstListIt; 409 void dumpInsts(); 410}; 411 412#endif // __CPU_CHECKER_CPU_HH__
| 287 { 288 int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag; 289 thread->setFloatRegBits(reg_idx, val); 290 result.integer = val; 291 } 292 293 uint64_t readPC() { return thread->readPC(); } 294 295 uint64_t readNextPC() { return thread->readNextPC(); } 296 297 void setNextPC(uint64_t val) { 298 thread->setNextPC(val); 299 } 300 301 MiscReg readMiscReg(int misc_reg) 302 { 303 return thread->readMiscReg(misc_reg); 304 } 305 306 MiscReg readMiscRegWithEffect(int misc_reg) 307 { 308 return thread->readMiscRegWithEffect(misc_reg); 309 } 310 311 void setMiscReg(int misc_reg, const MiscReg &val) 312 { 313 result.integer = val; 314 miscRegIdxs.push(misc_reg); 315 return thread->setMiscReg(misc_reg, val); 316 } 317 318 void setMiscRegWithEffect(int misc_reg, const MiscReg &val) 319 { 320 miscRegIdxs.push(misc_reg); 321 return thread->setMiscRegWithEffect(misc_reg, val); 322 } 323 324 void recordPCChange(uint64_t val) { changedPC = true; newPC = val; } 325 void recordNextPCChange(uint64_t val) { changedNextPC = true; } 326 327 bool translateInstReq(Request *req); 328 void translateDataWriteReq(Request *req); 329 void translateDataReadReq(Request *req); 330 331#if FULL_SYSTEM 332 Fault hwrei() { return thread->hwrei(); } 333 void ev5_trap(Fault fault) { fault->invoke(tc); } 334 bool simPalCheck(int palFunc) { return thread->simPalCheck(palFunc); } 335#else 336 // Assume that the normal CPU's call to syscall was successful. 337 // The checker's state would have already been updated by the syscall. 338 void syscall(uint64_t callnum) { } 339#endif 340 341 void handleError() 342 { 343 if (exitOnError) 344 dumpAndExit(); 345 } 346 347 bool checkFlags(Request *req); 348 349 void dumpAndExit(); 350 351 ThreadContext *tcBase() { return tc; } 352 SimpleThread *threadBase() { return thread; } 353 354 Result unverifiedResult; 355 Request *unverifiedReq; 356 uint8_t *unverifiedMemData; 357 358 bool changedPC; 359 bool willChangePC; 360 uint64_t newPC; 361 bool changedNextPC; 362 bool exitOnError; 363 bool updateOnError; 364 bool warnOnlyOnLoadError; 365 366 InstSeqNum youngestSN; 367}; 368 369/** 370 * Templated Checker class. This Checker class is templated on the 371 * DynInstPtr of the instruction type that will be verified. Proper 372 * template instantiations of the Checker must be placed at the bottom 373 * of checker/cpu.cc. 374 */ 375template <class DynInstPtr> 376class Checker : public CheckerCPU 377{ 378 public: 379 Checker(Params *p) 380 : CheckerCPU(p), updateThisCycle(false), unverifiedInst(NULL) 381 { } 382 383 void switchOut(); 384 void takeOverFrom(BaseCPU *oldCPU); 385 386 void verify(DynInstPtr &inst); 387 388 void validateInst(DynInstPtr &inst); 389 void validateExecution(DynInstPtr &inst); 390 void validateState(); 391 392 void copyResult(DynInstPtr &inst); 393 394 private: 395 void handleError(DynInstPtr &inst) 396 { 397 if (exitOnError) { 398 dumpAndExit(inst); 399 } else if (updateOnError) { 400 updateThisCycle = true; 401 } 402 } 403 404 void dumpAndExit(DynInstPtr &inst); 405 406 bool updateThisCycle; 407 408 DynInstPtr unverifiedInst; 409 410 std::list<DynInstPtr> instList; 411 typedef typename std::list<DynInstPtr>::iterator InstListIt; 412 void dumpInsts(); 413}; 414 415#endif // __CPU_CHECKER_CPU_HH__
|