Make checker handle not executing the same instruction as the main CPU a little better.
authorKevin Lim <ktlim@umich.edu>
Wed, 2 Aug 2006 16:06:59 +0000 (12:06 -0400)
committerKevin Lim <ktlim@umich.edu>
Wed, 2 Aug 2006 16:06:59 +0000 (12:06 -0400)
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

cpu/checker/cpu.cc
cpu/checker/cpu.hh
cpu/checker/cpu_builder.cc

index 41ff6e7696fb0e7bd24a3295d1dd5284e6499ec4..f195c8842467eac3bfb2988275b475840a1f9e33 100644 (file)
@@ -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>
index 9fcd1037f814638030c0851190ab0d1271a2cf27..f48d1135a29f099bc380925e6c12b00bbf2031be 100644 (file)
@@ -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();
index d80daef97205e8d7071f3d85be745c59ba7bfb7f..802944e47bf7617514a14efe24173d68a5ad8116 100644 (file)
@@ -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;