From: Kevin Lim Date: Fri, 16 Jun 2006 17:10:47 +0000 (-0400) Subject: Checker updates. X-Git-Tag: m5_2.0_beta1~36^2~59^2~5^2~4 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=720e6c4145726d310aa19fed4f48bf6a8e32912e;p=gem5.git Checker updates. 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 --- diff --git a/src/cpu/checker/cpu.cc b/src/cpu/checker/cpu.cc index 6971ab37f..99189a896 100644 --- a/src/cpu/checker/cpu.cc +++ b/src/cpu/checker/cpu.cc @@ -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 void -Checker::tick(DynInstPtr &completed_inst) +Checker::verify(DynInstPtr &completed_inst) { DynInstPtr inst; @@ -485,7 +494,7 @@ Checker::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::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::validateInst(DynInstPtr &inst) warn("%lli: Changed PCs recently, may not be an error", curTick); } else { - handleError(); + handleError(inst); } } @@ -686,7 +695,7 @@ Checker::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 void Checker::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::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::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::validateState() { } +template +void +Checker::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 +void +Checker::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 void Checker::dumpInsts() diff --git a/src/cpu/checker/cpu.hh b/src/cpu/checker/cpu.hh index c9986d228..785387e60 100644 --- a/src/cpu/checker/cpu.hh +++ b/src/cpu/checker/cpu.hh @@ -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 instList; typedef typename std::list::iterator InstListIt; void dumpInsts(); diff --git a/src/cpu/checker/cpu_builder.cc b/src/cpu/checker/cpu_builder.cc index 3b7583294..3c43ab503 100644 --- a/src/cpu/checker/cpu_builder.cc +++ b/src/cpu/checker/cpu_builder.cc @@ -77,6 +77,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(OzoneChecker) Param defer_registration; Param exitOnError; + Param warnOnlyOnLoadError; Param function_trace; Param 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; diff --git a/src/cpu/checker/o3_cpu_builder.cc b/src/cpu/checker/o3_cpu_builder.cc index 59a6c7158..534a5e28c 100644 --- a/src/cpu/checker/o3_cpu_builder.cc +++ b/src/cpu/checker/o3_cpu_builder.cc @@ -75,6 +75,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(O3Checker) Param defer_registration; Param exitOnError; + Param warnOnlyOnLoadError; Param function_trace; Param 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; diff --git a/src/cpu/o3/commit_impl.hh b/src/cpu/o3/commit_impl.hh index b0c8bee77..a18271918 100644 --- a/src/cpu/o3/commit_impl.hh +++ b/src/cpu/o3/commit_impl.hh @@ -975,7 +975,7 @@ DefaultCommit::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::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); diff --git a/src/cpu/o3/lsq_unit_impl.hh b/src/cpu/o3/lsq_unit_impl.hh index b48d7fb74..6e201ea5f 100644 --- a/src/cpu/o3/lsq_unit_impl.hh +++ b/src/cpu/o3/lsq_unit_impl.hh @@ -789,7 +789,7 @@ LSQUnit::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::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); } }