summaryrefslogtreecommitdiff
path: root/src/cpu/checker
diff options
context:
space:
mode:
Diffstat (limited to 'src/cpu/checker')
-rw-r--r--src/cpu/checker/cpu.hh21
-rw-r--r--src/cpu/checker/cpu_impl.hh26
2 files changed, 39 insertions, 8 deletions
diff --git a/src/cpu/checker/cpu.hh b/src/cpu/checker/cpu.hh
index 6d6ae1e0a..00b01171f 100644
--- a/src/cpu/checker/cpu.hh
+++ b/src/cpu/checker/cpu.hh
@@ -102,6 +102,7 @@ class CheckerCPU : public BaseCPU
Process *process;
#endif
bool exitOnError;
+ bool updateOnError;
bool warnOnlyOnLoadError;
};
@@ -148,7 +149,7 @@ class CheckerCPU : public BaseCPU
union Result {
uint64_t integer;
- float fp;
+// float fp;
double dbl;
};
@@ -257,7 +258,7 @@ class CheckerCPU : public BaseCPU
thread->setFloatReg(reg_idx, val, width);
switch(width) {
case 32:
- result.fp = val;
+ result.dbl = (double)val;
break;
case 64:
result.dbl = val;
@@ -269,7 +270,7 @@ class CheckerCPU : public BaseCPU
{
int reg_idx = si->destRegIdx(idx) - TheISA::FP_Base_DepTag;
thread->setFloatReg(reg_idx, val);
- result.fp = val;
+ result.dbl = (double)val;
}
void setFloatRegBits(const StaticInst *si, int idx, FloatRegBits val,
@@ -318,7 +319,7 @@ class CheckerCPU : public BaseCPU
return thread->setMiscRegWithEffect(misc_reg, val);
}
- void recordPCChange(uint64_t val) { changedPC = true; }
+ void recordPCChange(uint64_t val) { changedPC = true; newPC = val; }
void recordNextPCChange(uint64_t val) { changedNextPC = true; }
bool translateInstReq(Request *req);
@@ -360,6 +361,7 @@ class CheckerCPU : public BaseCPU
uint64_t newPC;
bool changedNextPC;
bool exitOnError;
+ bool updateOnError;
bool warnOnlyOnLoadError;
InstSeqNum youngestSN;
@@ -376,7 +378,7 @@ class Checker : public CheckerCPU
{
public:
Checker(Params *p)
- : CheckerCPU(p)
+ : CheckerCPU(p), updateThisCycle(false), unverifiedInst(NULL)
{ }
void switchOut();
@@ -393,12 +395,19 @@ class Checker : public CheckerCPU
private:
void handleError(DynInstPtr &inst)
{
- if (exitOnError)
+ if (exitOnError) {
dumpAndExit(inst);
+ } else if (updateOnError) {
+ updateThisCycle = true;
+ }
}
void dumpAndExit(DynInstPtr &inst);
+ bool updateThisCycle;
+
+ DynInstPtr unverifiedInst;
+
std::list<DynInstPtr> instList;
typedef typename std::list<DynInstPtr>::iterator InstListIt;
void dumpInsts();
diff --git a/src/cpu/checker/cpu_impl.hh b/src/cpu/checker/cpu_impl.hh
index 81f97726c..8aec79754 100644
--- a/src/cpu/checker/cpu_impl.hh
+++ b/src/cpu/checker/cpu_impl.hh
@@ -94,6 +94,8 @@ Checker<DynInstPtr>::verify(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.
@@ -171,7 +173,7 @@ Checker<DynInstPtr>::verify(DynInstPtr &completed_inst)
thread->setPC(thread->readNextPC());
thread->setNextPC(thread->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
@@ -220,7 +222,8 @@ Checker<DynInstPtr>::verify(DynInstPtr &completed_inst)
thread->funcExeInst++;
- fault = curStaticInst->execute(this, NULL);
+ if (!inst->isUnverifiable())
+ fault = curStaticInst->execute(this, NULL);
// Checks to make sure instrution results are correct.
validateExecution(inst);
@@ -289,6 +292,7 @@ Checker<DynInstPtr>::verify(DynInstPtr &completed_inst)
break;
}
}
+ unverifiedInst = NULL;
}
template <class DynInstPtr>
@@ -395,6 +399,24 @@ 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", curTick, unverifiedInst->readPC());
+ // Heavy-weight copying of all registers
+ thread->copyArchRegs(unverifiedInst->tcBase());
+ // Also advance the PC. Hopefully no PC-based events happened.
+#if THE_ISA != MIPS_ISA
+ // go to the next instruction
+ thread->setPC(thread->readNextPC());
+ thread->setNextPC(thread->readNextPC() + sizeof(MachInst));
+#else
+ // go to the next instruction
+ thread->setPC(thread->readNextPC());
+ thread->setNextPC(thread->readNextNPC());
+ thread->setNextNPC(thread->readNextNPC() + sizeof(MachInst));
+#endif
+ updateThisCycle = false;
+ }
}
template <class DynInstPtr>