Checker updates.
authorKevin Lim <ktlim@umich.edu>
Fri, 16 Jun 2006 17:10:47 +0000 (13:10 -0400)
committerKevin Lim <ktlim@umich.edu>
Fri, 16 Jun 2006 17:10:47 +0000 (13:10 -0400)
src/cpu/checker/cpu.cc:
src/cpu/checker/cpu.hh:
    Updates for checker.  Output more informative messages on error.  Rename some functions.  Add in option to warn (and not exit) on load results being incorrect.
src/cpu/checker/cpu_builder.cc:
src/cpu/checker/o3_cpu_builder.cc:
    Add in parameter to warn (and not exit) on load result errors.
src/cpu/o3/commit_impl.hh:
src/cpu/o3/lsq_unit_impl.hh:
    Renamed checker functin.

--HG--
extra : convert_revision : d7aa28b8462691d20600f97a7213e2acd91c5665

src/cpu/checker/cpu.cc
src/cpu/checker/cpu.hh
src/cpu/checker/cpu_builder.cc
src/cpu/checker/o3_cpu_builder.cc
src/cpu/o3/commit_impl.hh
src/cpu/o3/lsq_unit_impl.hh

index 6971ab37fdfb1290fa32babc412f7704aa33ae60..99189a8966069b718185526629d07a653c113de5 100644 (file)
@@ -78,6 +78,7 @@ CheckerCPU::CheckerCPU(Params *p)
     changedPC = willChangePC = changedNextPC = false;
 
     exitOnError = p->exitOnError;
+    warnOnlyOnLoadError = p->warnOnlyOnLoadError;
 #if FULL_SYSTEM
     itb = p->itb;
     dtb = p->dtb;
@@ -409,9 +410,17 @@ CheckerCPU::checkFlags(Request *req)
     }
 }
 
+void
+CheckerCPU::dumpAndExit()
+{
+    warn("%lli: Checker PC:%#x, next PC:%#x",
+         curTick, thread->readPC(), thread->readNextPC());
+    panic("Checker found an error!");
+}
+
 template <class DynInstPtr>
 void
-Checker<DynInstPtr>::tick(DynInstPtr &completed_inst)
+Checker<DynInstPtr>::verify(DynInstPtr &completed_inst)
 {
     DynInstPtr inst;
 
@@ -485,7 +494,7 @@ Checker<DynInstPtr>::tick(DynInstPtr &completed_inst)
                     warn("%lli: Changed PC does not match expected PC, "
                          "changed: %#x, expected: %#x",
                          curTick, thread->readPC(), newPC);
-                    handleError();
+                    CheckerCPU::handleError();
                 }
                 willChangePC = false;
             }
@@ -524,7 +533,7 @@ Checker<DynInstPtr>::tick(DynInstPtr &completed_inst)
                 // possible that its ITB entry was kicked out.
                 warn("%lli: Instruction PC %#x was not found in the ITB!",
                      curTick, thread->readPC());
-                handleError();
+                handleError(inst);
 
                 // go to the next instruction
                 thread->setPC(thread->readNextPC());
@@ -676,7 +685,7 @@ Checker<DynInstPtr>::validateInst(DynInstPtr &inst)
             warn("%lli: Changed PCs recently, may not be an error",
                  curTick);
         } else {
-            handleError();
+            handleError(inst);
         }
     }
 
@@ -686,7 +695,7 @@ Checker<DynInstPtr>::validateInst(DynInstPtr &inst)
         warn("%lli: Binary instructions do not match! Inst: %#x, "
              "checker: %#x",
              curTick, mi, machInst);
-        handleError();
+        handleError(inst);
     }
 }
 
@@ -694,25 +703,33 @@ template <class DynInstPtr>
 void
 Checker<DynInstPtr>::validateExecution(DynInstPtr &inst)
 {
+    bool result_mismatch = false;
     if (inst->numDestRegs()) {
         // @todo: Support more destination registers.
         if (inst->isUnverifiable()) {
             // Unverifiable instructions assume they were executed
             // properly by the CPU. Grab the result from the
             // instruction and write it to the register.
-            RegIndex idx = inst->destRegIdx(0);
-            if (idx < TheISA::FP_Base_DepTag) {
-                thread->setIntReg(idx, inst->readIntResult());
-            } else if (idx < TheISA::Fpcr_DepTag) {
-                thread->setFloatRegBits(idx, inst->readIntResult());
-            } else {
-                thread->setMiscReg(idx, inst->readIntResult());
-            }
+            copyResult(inst);
         } else if (result.integer != inst->readIntResult()) {
-            warn("%lli: Instruction results do not match! (Values may not "
-                 "actually be integers) Inst: %#x, checker: %#x",
-                 curTick, inst->readIntResult(), result.integer);
-            handleError();
+            result_mismatch = true;
+        }
+    }
+
+    if (result_mismatch) {
+        warn("%lli: Instruction results do not match! (Values may not "
+             "actually be integers) Inst: %#x, checker: %#x",
+             curTick, inst->readIntResult(), result.integer);
+
+        // It's useful to verify load values from memory, but in MP
+        // systems the value obtained at execute may be different than
+        // the value obtained at completion.  Similarly DMA can
+        // present the same problem on even UP systems.  Thus there is
+        // the option to only warn on loads having a result error.
+        if (inst->isLoad() && warnOnlyOnLoadError) {
+            copyResult(inst);
+        } else {
+            handleError(inst);
         }
     }
 
@@ -720,7 +737,7 @@ Checker<DynInstPtr>::validateExecution(DynInstPtr &inst)
         warn("%lli: Instruction next PCs do not match! Inst: %#x, "
              "checker: %#x",
              curTick, inst->readNextPC(), thread->readNextPC());
-        handleError();
+        handleError(inst);
     }
 
     // Checking side effect registers can be difficult if they are not
@@ -739,7 +756,7 @@ Checker<DynInstPtr>::validateExecution(DynInstPtr &inst)
                  curTick, misc_reg_idx,
                  inst->tcBase()->readMiscReg(misc_reg_idx),
                  thread->readMiscReg(misc_reg_idx));
-            handleError();
+            handleError(inst);
         }
     }
 }
@@ -750,6 +767,36 @@ Checker<DynInstPtr>::validateState()
 {
 }
 
+template <class DynInstPtr>
+void
+Checker<DynInstPtr>::copyResult(DynInstPtr &inst)
+{
+    RegIndex idx = inst->destRegIdx(0);
+    if (idx < TheISA::FP_Base_DepTag) {
+        thread->setIntReg(idx, inst->readIntResult());
+    } else if (idx < TheISA::Fpcr_DepTag) {
+        thread->setFloatRegBits(idx, inst->readIntResult());
+    } else {
+        thread->setMiscReg(idx, inst->readIntResult());
+    }
+}
+
+template <class DynInstPtr>
+void
+Checker<DynInstPtr>::dumpAndExit(DynInstPtr &inst)
+{
+    cprintf("Error detected, instruction information:\n");
+    cprintf("PC:%#x, nextPC:%#x\n[sn:%lli]\n[tid:%i]\n"
+            "Completed:%i\n",
+            inst->readPC(),
+            inst->readNextPC(),
+            inst->seqNum,
+            inst->threadNumber,
+            inst->isCompleted());
+    inst->dump();
+    CheckerCPU::dumpAndExit();
+}
+
 template <class DynInstPtr>
 void
 Checker<DynInstPtr>::dumpInsts()
index c9986d228b451105d93d18c1ce451c650624070c..785387e600f07a74d0417f2a25d145e66913d50e 100644 (file)
@@ -103,6 +103,7 @@ class CheckerCPU : public BaseCPU
         Process *process;
 #endif
         bool exitOnError;
+        bool warnOnlyOnLoadError;
     };
 
   public:
@@ -335,10 +336,13 @@ class CheckerCPU : public BaseCPU
     void handleError()
     {
         if (exitOnError)
-            panic("Checker found error!");
+            dumpAndExit();
     }
+
     bool checkFlags(Request *req);
 
+    void dumpAndExit();
+
     ThreadContext *tcBase() { return tc; }
     SimpleThread *threadBase() { return thread; }
 
@@ -351,6 +355,7 @@ class CheckerCPU : public BaseCPU
     uint64_t newPC;
     bool changedNextPC;
     bool exitOnError;
+    bool warnOnlyOnLoadError;
 
     InstSeqNum youngestSN;
 };
@@ -372,12 +377,23 @@ class Checker : public CheckerCPU
     void switchOut(Sampler *s);
     void takeOverFrom(BaseCPU *oldCPU);
 
-    void tick(DynInstPtr &inst);
+    void verify(DynInstPtr &inst);
 
     void validateInst(DynInstPtr &inst);
     void validateExecution(DynInstPtr &inst);
     void validateState();
 
+    void copyResult(DynInstPtr &inst);
+
+  private:
+    void handleError(DynInstPtr &inst)
+    {
+        if (exitOnError)
+            dumpAndExit(inst);
+    }
+
+    void dumpAndExit(DynInstPtr &inst);
+
     std::list<DynInstPtr> instList;
     typedef typename std::list<DynInstPtr>::iterator InstListIt;
     void dumpInsts();
index 3b75832948b1f4d800ec1b4d925be5855f285909..3c43ab503f2dccba0c16f79e233d22efa0c4ca12 100644 (file)
@@ -77,6 +77,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(OzoneChecker)
 
     Param<bool> defer_registration;
     Param<bool> exitOnError;
+    Param<bool> warnOnlyOnLoadError;
     Param<bool> function_trace;
     Param<Tick> function_trace_start;
 
@@ -110,6 +111,8 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(OzoneChecker)
 
     INIT_PARAM(defer_registration, "defer system registration (for sampling)"),
     INIT_PARAM(exitOnError, "exit on error"),
+    INIT_PARAM_DFLT(warnOnlyOnLoadError, "warn, but don't exit, if a load "
+                    "result errors", false),
     INIT_PARAM(function_trace, "Enable function trace"),
     INIT_PARAM(function_trace_start, "Cycle to start function trace")
 
@@ -126,6 +129,7 @@ CREATE_SIM_OBJECT(OzoneChecker)
     params->max_loads_any_thread = 0;
     params->max_loads_all_threads = 0;
     params->exitOnError = exitOnError;
+    params->warnOnlyOnLoadError = warnOnlyOnLoadError;
     params->deferRegistration = defer_registration;
     params->functionTrace = function_trace;
     params->functionTraceStart = function_trace_start;
index 59a6c71585f104d0036b3c1354c11ec7fe809a8c..534a5e28c3b49595c7e8f4ad337c76785b277358 100644 (file)
@@ -75,6 +75,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(O3Checker)
 
     Param<bool> defer_registration;
     Param<bool> exitOnError;
+    Param<bool> warnOnlyOnLoadError;
     Param<bool> function_trace;
     Param<Tick> function_trace_start;
 
@@ -105,6 +106,8 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(O3Checker)
 
     INIT_PARAM(defer_registration, "defer system registration (for sampling)"),
     INIT_PARAM(exitOnError, "exit on error"),
+    INIT_PARAM_DFLT(warnOnlyOnLoadError, "warn, but don't exit, if a load "
+                    "result errors", false),
     INIT_PARAM(function_trace, "Enable function trace"),
     INIT_PARAM(function_trace_start, "Cycle to start function trace")
 
@@ -121,6 +124,7 @@ CREATE_SIM_OBJECT(O3Checker)
     params->max_loads_any_thread = 0;
     params->max_loads_all_threads = 0;
     params->exitOnError = exitOnError;
+    params->warnOnlyOnLoadError = warnOnlyOnLoadError;
     params->deferRegistration = defer_registration;
     params->functionTrace = function_trace;
     params->functionTraceStart = function_trace_start;
index b0c8bee77380e91bb9193c6e607a92e14ca09cb8..a182719184038042d9493f1f11751f45a4306ca0 100644 (file)
@@ -975,7 +975,7 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num)
     // Use checker prior to updating anything due to traps or PC
     // based events.
     if (cpu->checker) {
-        cpu->checker->tick(head_inst);
+        cpu->checker->verify(head_inst);
     }
 
     // Check if the instruction caused a fault.  If so, trap.
@@ -993,7 +993,7 @@ DefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num)
         }
 
         if (cpu->checker && head_inst->isStore()) {
-            cpu->checker->tick(head_inst);
+            cpu->checker->verify(head_inst);
         }
 
         assert(!thread[tid]->inSyscall);
index b48d7fb741bd5c1c477fd1b8a42efdaae53c4324..6e201ea5f2d5cfef0b36bc4e34a4ad2766659780 100644 (file)
@@ -789,7 +789,7 @@ LSQUnit<Impl>::storePostSend(Packet *pkt)
         // verify the value in memory for stores.
         storeQueue[storeWBIdx].inst->setCompleted();
         if (cpu->checker) {
-            cpu->checker->tick(storeQueue[storeWBIdx].inst);
+            cpu->checker->verify(storeQueue[storeWBIdx].inst);
         }
     }
 
@@ -885,7 +885,7 @@ LSQUnit<Impl>::completeStore(int store_idx)
     // may get reported twice to the checker, but the checker can
     // handle that case.
     if (cpu->checker) {
-        cpu->checker->tick(storeQueue[store_idx].inst);
+        cpu->checker->verify(storeQueue[store_idx].inst);
     }
 }