summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cpu/checker/cpu.cc85
-rw-r--r--src/cpu/checker/cpu.hh20
-rw-r--r--src/cpu/checker/cpu_builder.cc4
-rw-r--r--src/cpu/checker/o3_cpu_builder.cc4
-rw-r--r--src/cpu/o3/commit_impl.hh4
-rw-r--r--src/cpu/o3/lsq_unit_impl.hh4
6 files changed, 96 insertions, 25 deletions
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 <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);
}
}
}
@@ -752,6 +769,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()
{
int num = 0;
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<DynInstPtr> instList;
typedef typename std::list<DynInstPtr>::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<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;
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<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;
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<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);
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<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);
}
}