cpu_impl.hh
来自「M5,一个功能强大的多处理器系统模拟器.很多针对处理器架构,性能的研究都使用它作」· HH 代码 · 共 484 行 · 第 1/2 页
HH
484 行
newPC = thread->readPC(); DPRINTF(Checker, "Fault, PC is now %#x\n", newPC);#endif } else {#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 }#if FULL_SYSTEM // @todo: Determine if these should happen only if the // instruction hasn't faulted. In the SimpleCPU case this may // not be true, but in the O3 or Ozone case this may be true. Addr oldpc; int count = 0; do { oldpc = thread->readPC(); system->pcEventQueue.service(tc); count++; } while (oldpc != thread->readPC()); if (count > 1) { willChangePC = true; newPC = thread->readPC(); DPRINTF(Checker, "PC Event, PC is now %#x\n", newPC); }#endif // @todo: Optionally can check all registers. (Or just those // that have been modified). validateState(); if (memReq) { delete memReq; memReq = NULL; } // Continue verifying instructions if there's another completed // instruction waiting to be verified. if (instList.empty()) { break; } else if (instList.front()->isCompleted()) { inst = instList.front(); instList.pop_front(); } else { break; } } unverifiedInst = NULL;}template <class DynInstPtr>voidChecker<DynInstPtr>::switchOut(){ instList.clear();}template <class DynInstPtr>voidChecker<DynInstPtr>::takeOverFrom(BaseCPU *oldCPU){}template <class DynInstPtr>voidChecker<DynInstPtr>::validateInst(DynInstPtr &inst){ if (inst->readPC() != thread->readPC()) { warn("%lli: PCs do not match! Inst: %#x, checker: %#x", curTick, inst->readPC(), thread->readPC()); if (changedPC) { warn("%lli: Changed PCs recently, may not be an error", curTick); } else { handleError(inst); } } MachInst mi = static_cast<MachInst>(inst->staticInst->machInst); if (mi != machInst) { warn("%lli: Binary instructions do not match! Inst: %#x, " "checker: %#x", curTick, mi, machInst); handleError(inst); }}template <class DynInstPtr>voidChecker<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. copyResult(inst); } else if (result.integer != inst->readIntResult()) { 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); } } if (inst->readNextPC() != thread->readNextPC()) { warn("%lli: Instruction next PCs do not match! Inst: %#x, " "checker: %#x", curTick, inst->readNextPC(), thread->readNextPC()); handleError(inst); } // Checking side effect registers can be difficult if they are not // checked simultaneously with the execution of the instruction. // This is because other valid instructions may have modified // these registers in the meantime, and their values are not // stored within the DynInst. while (!miscRegIdxs.empty()) { int misc_reg_idx = miscRegIdxs.front(); miscRegIdxs.pop(); if (inst->tcBase()->readMiscRegNoEffect(misc_reg_idx) != thread->readMiscRegNoEffect(misc_reg_idx)) { warn("%lli: Misc reg idx %i (side effect) does not match! " "Inst: %#x, checker: %#x", curTick, misc_reg_idx, inst->tcBase()->readMiscRegNoEffect(misc_reg_idx), thread->readMiscRegNoEffect(misc_reg_idx)); handleError(inst); } }}template <class DynInstPtr>voidChecker<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>voidChecker<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->setMiscRegNoEffect(idx, inst->readIntResult()); }}template <class DynInstPtr>voidChecker<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>voidChecker<DynInstPtr>::dumpInsts(){ int num = 0; InstListIt inst_list_it = --(instList.end()); cprintf("Inst list size: %i\n", instList.size()); while (inst_list_it != instList.end()) { cprintf("Instruction:%i\n", num); cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n" "Completed:%i\n", (*inst_list_it)->readPC(), (*inst_list_it)->seqNum, (*inst_list_it)->threadNumber, (*inst_list_it)->isCompleted()); cprintf("\n"); inst_list_it--; ++num; }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?