Make checker handle not executing the same instruction as the main CPU a little better.
Also add the option for the checker to update itself with the main CPU's state if it executes an instruction differently (so it will handle DMA timing errors properly). --HG-- extra : convert_revision : 760d11ec1a249bc75e2807d320866b5d08c2b6f2
This commit is contained in:
parent
cbfbb7bc56
commit
5be592f870
3 changed files with 46 additions and 10 deletions
|
@ -78,6 +78,7 @@ CheckerCPU::CheckerCPU(Params *p)
|
|||
changedPC = willChangePC = changedNextPC = false;
|
||||
|
||||
exitOnError = p->exitOnError;
|
||||
updateOnError = p->updateOnError;
|
||||
#if FULL_SYSTEM
|
||||
itb = p->itb;
|
||||
dtb = p->dtb;
|
||||
|
@ -350,7 +351,12 @@ CheckerCPU::translateDataReadReq(MemReqPtr &req)
|
|||
{
|
||||
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);
|
||||
|
@ -370,7 +376,12 @@ CheckerCPU::translateDataWriteReq(MemReqPtr &req)
|
|||
{
|
||||
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);
|
||||
|
@ -443,6 +454,8 @@ Checker<DynInstPtr>::tick(DynInstPtr &completed_inst)
|
|||
}
|
||||
}
|
||||
|
||||
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.
|
||||
|
@ -516,7 +529,7 @@ Checker<DynInstPtr>::tick(DynInstPtr &completed_inst)
|
|||
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
|
||||
|
@ -554,7 +567,8 @@ Checker<DynInstPtr>::tick(DynInstPtr &completed_inst)
|
|||
|
||||
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);
|
||||
|
@ -620,6 +634,7 @@ Checker<DynInstPtr>::tick(DynInstPtr &completed_inst)
|
|||
break;
|
||||
}
|
||||
}
|
||||
unverifiedInst = NULL;
|
||||
}
|
||||
|
||||
template <class DynInstPtr>
|
||||
|
@ -718,6 +733,13 @@ 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>
|
||||
|
|
|
@ -98,6 +98,7 @@ class CheckerCPU : public BaseCPU
|
|||
Process *process;
|
||||
#endif
|
||||
bool exitOnError;
|
||||
bool updateOnError;
|
||||
};
|
||||
|
||||
public:
|
||||
|
@ -294,11 +295,8 @@ class CheckerCPU : public BaseCPU
|
|||
void syscall() { }
|
||||
#endif
|
||||
|
||||
void handleError()
|
||||
{
|
||||
if (exitOnError)
|
||||
panic("Checker found error!");
|
||||
}
|
||||
virtual void handleError() = 0;
|
||||
|
||||
bool checkFlags(MemReqPtr &req);
|
||||
|
||||
ExecContext *xcBase() { return xcProxy; }
|
||||
|
@ -312,6 +310,7 @@ class CheckerCPU : public BaseCPU
|
|||
uint64_t newPC;
|
||||
bool changedNextPC;
|
||||
bool exitOnError;
|
||||
bool updateOnError;
|
||||
|
||||
InstSeqNum youngestSN;
|
||||
};
|
||||
|
@ -327,7 +326,7 @@ class Checker : public CheckerCPU
|
|||
{
|
||||
public:
|
||||
Checker(Params *p)
|
||||
: CheckerCPU(p)
|
||||
: CheckerCPU(p), updateThisCycle(false), unverifiedInst(NULL)
|
||||
{ }
|
||||
|
||||
void switchOut(Sampler *s);
|
||||
|
@ -339,6 +338,18 @@ class Checker : public CheckerCPU
|
|||
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();
|
||||
|
|
|
@ -75,6 +75,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(OzoneChecker)
|
|||
|
||||
Param<bool> defer_registration;
|
||||
Param<bool> exitOnError;
|
||||
Param<bool> updateOnError;
|
||||
Param<bool> function_trace;
|
||||
Param<Tick> function_trace_start;
|
||||
|
||||
|
@ -108,6 +109,7 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(OzoneChecker)
|
|||
|
||||
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")
|
||||
|
||||
|
@ -124,6 +126,7 @@ CREATE_SIM_OBJECT(OzoneChecker)
|
|||
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;
|
||||
|
|
Loading…
Reference in a new issue