summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cpu/checker/cpu.cc30
-rw-r--r--cpu/checker/cpu.hh23
-rw-r--r--cpu/checker/cpu_builder.cc3
3 files changed, 46 insertions, 10 deletions
diff --git a/cpu/checker/cpu.cc b/cpu/checker/cpu.cc
index 41ff6e769..f195c8842 100644
--- a/cpu/checker/cpu.cc
+++ b/cpu/checker/cpu.cc
@@ -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>
diff --git a/cpu/checker/cpu.hh b/cpu/checker/cpu.hh
index 9fcd1037f..f48d1135a 100644
--- a/cpu/checker/cpu.hh
+++ b/cpu/checker/cpu.hh
@@ -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();
diff --git a/cpu/checker/cpu_builder.cc b/cpu/checker/cpu_builder.cc
index d80daef97..802944e47 100644
--- a/cpu/checker/cpu_builder.cc
+++ b/cpu/checker/cpu_builder.cc
@@ -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;