changedPC = willChangePC = changedNextPC = false;
exitOnError = p->exitOnError;
+ updateOnError = p->updateOnError;
#if FULL_SYSTEM
itb = p->itb;
dtb = p->dtb;
{
cpuXC->translateDataReadReq(req);
- if (req->vaddr != unverifiedReq->vaddr) {
+ if (!unverifiedReq) {
+ warn("%lli: Request virtual addresses do not match! Inst: N/A, "
+ "checker: %#x",
+ curTick, req->vaddr);
+ return;
+ } else if (req->vaddr != unverifiedReq->vaddr) {
warn("%lli: Request virtual addresses do not match! Inst: %#x, "
"checker: %#x",
curTick, unverifiedReq->vaddr, req->vaddr);
{
cpuXC->translateDataWriteReq(req);
- if (req->vaddr != unverifiedReq->vaddr) {
+ if (!unverifiedReq) {
+ warn("%lli: Request virtual addresses do not match! Inst: N/A, "
+ "checker: %#x",
+ curTick, req->vaddr);
+ return;
+ } else if (req->vaddr != unverifiedReq->vaddr) {
warn("%lli: Request virtual addresses do not match! Inst: %#x, "
"checker: %#x",
curTick, unverifiedReq->vaddr, req->vaddr);
}
}
+ unverifiedInst = inst;
+
// Try to check all instructions that are completed, ending if we
// run out of instructions to check or if an instruction is not
// yet completed.
cpuXC->setPC(cpuXC->readNextPC());
cpuXC->setNextPC(cpuXC->readNextPC() + sizeof(MachInst));
- return;
+ break;
} else {
// The instruction is carrying an ITB fault. Handle
// the fault and see if our results match the CPU on
cpuXC->func_exe_inst++;
- fault = curStaticInst->execute(this, NULL);
+ if (!inst->isUnverifiable())
+ fault = curStaticInst->execute(this, NULL);
// Checks to make sure instrution results are correct.
validateExecution(inst);
break;
}
}
+ unverifiedInst = NULL;
}
template <class DynInstPtr>
void
Checker<DynInstPtr>::validateState()
{
+ if (updateThisCycle) {
+ warn("%lli: Instruction PC %#x results didn't match up, copying all "
+ "registers from main CPU", unverifiedInst->readPC());
+ // Heavy-weight copying of all registers
+ cpuXC->copyArchRegs(unverifiedInst->xcBase());
+ updateThisCycle = false;
+ }
}
template <class DynInstPtr>
Process *process;
#endif
bool exitOnError;
+ bool updateOnError;
};
public:
void syscall() { }
#endif
- void handleError()
- {
- if (exitOnError)
- panic("Checker found error!");
- }
+ virtual void handleError() = 0;
+
bool checkFlags(MemReqPtr &req);
ExecContext *xcBase() { return xcProxy; }
uint64_t newPC;
bool changedNextPC;
bool exitOnError;
+ bool updateOnError;
InstSeqNum youngestSN;
};
{
public:
Checker(Params *p)
- : CheckerCPU(p)
+ : CheckerCPU(p), updateThisCycle(false), unverifiedInst(NULL)
{ }
void switchOut(Sampler *s);
void validateExecution(DynInstPtr &inst);
void validateState();
+ virtual void handleError()
+ {
+ if (exitOnError)
+ panic("Checker found error!");
+ else if (updateOnError)
+ updateThisCycle = true;
+ }
+
+ bool updateThisCycle;
+
+ DynInstPtr unverifiedInst;
+
std::list<DynInstPtr> instList;
typedef typename std::list<DynInstPtr>::iterator InstListIt;
void dumpInsts();
Param<bool> defer_registration;
Param<bool> exitOnError;
+ Param<bool> updateOnError;
Param<bool> function_trace;
Param<Tick> function_trace_start;
INIT_PARAM(defer_registration, "defer system registration (for sampling)"),
INIT_PARAM(exitOnError, "exit on error"),
+ INIT_PARAM(updateOnError, "Update the checker with the main CPU's state on error"),
INIT_PARAM(function_trace, "Enable function trace"),
INIT_PARAM(function_trace_start, "Cycle to start function trace")
params->max_loads_any_thread = 0;
params->max_loads_all_threads = 0;
params->exitOnError = exitOnError;
+ params->updateOnError = updateOnError;
params->deferRegistration = defer_registration;
params->functionTrace = function_trace;
params->functionTraceStart = function_trace_start;