cpu_impl.hh
来自「M5,一个功能强大的多处理器系统模拟器.很多针对处理器架构,性能的研究都使用它作」· HH 代码 · 共 484 行 · 第 1/2 页
HH
484 行
/* * Copyright (c) 2006 * The Regents of The University of Michigan * All Rights Reserved * * This code is part of the M5 simulator. * * Permission is granted to use, copy, create derivative works and * redistribute this software and such derivative works for any * purpose, so long as the copyright notice above, this grant of * permission, and the disclaimer below appear in all copies made; and * so long as the name of The University of Michigan is not used in * any advertising or publicity pertaining to the use or distribution * of this software without specific, written prior authorization. * * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE * UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND * WITHOUT WARRANTY BY THE UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER * EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE. THE REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE * LIABLE FOR ANY DAMAGES, INCLUDING DIRECT, SPECIAL, INDIRECT, * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM * ARISING OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH * DAMAGES. * * Authors: Kevin T. Lim */#include <list>#include <string>#include "base/refcnt.hh"#include "cpu/base_dyn_inst.hh"#include "cpu/checker/cpu.hh"#include "cpu/simple_thread.hh"#include "cpu/thread_context.hh"#include "cpu/static_inst.hh"#include "sim/sim_object.hh"#include "sim/stats.hh"#if FULL_SYSTEM#include "arch/vtophys.hh"#endif // FULL_SYSTEMusing namespace std;//The CheckerCPU does alpha onlyusing namespace AlphaISA;template <class DynInstPtr>voidChecker<DynInstPtr>::verify(DynInstPtr &completed_inst){ DynInstPtr inst; // Either check this instruction, or add it to a list of // instructions waiting to be checked. Instructions must be // checked in program order, so if a store has committed yet not // completed, there may be some instructions that are waiting // behind it that have completed and must be checked. if (!instList.empty()) { if (youngestSN < completed_inst->seqNum) { DPRINTF(Checker, "Adding instruction [sn:%lli] PC:%#x to list.\n", completed_inst->seqNum, completed_inst->readPC()); instList.push_back(completed_inst); youngestSN = completed_inst->seqNum; } if (!instList.front()->isCompleted()) { return; } else { inst = instList.front(); instList.pop_front(); } } else { if (!completed_inst->isCompleted()) { if (youngestSN < completed_inst->seqNum) { DPRINTF(Checker, "Adding instruction [sn:%lli] PC:%#x to list.\n", completed_inst->seqNum, completed_inst->readPC()); instList.push_back(completed_inst); youngestSN = completed_inst->seqNum; } return; } else { if (youngestSN < completed_inst->seqNum) { inst = completed_inst; youngestSN = completed_inst->seqNum; } else { return; } } } 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. while (1) { DPRINTF(Checker, "Processing instruction [sn:%lli] PC:%#x.\n", inst->seqNum, inst->readPC()); unverifiedResult.integer = inst->readIntResult(); unverifiedReq = inst->req; unverifiedMemData = inst->memData; numCycles++; Fault fault = NoFault; // maintain $r0 semantics thread->setIntReg(ZeroReg, 0);#ifdef TARGET_ALPHA thread->setFloatRegDouble(ZeroReg, 0.0);#endif // TARGET_ALPHA // Check if any recent PC changes match up with anything we // expect to happen. This is mostly to check if traps or // PC-based events have occurred in both the checker and CPU. if (changedPC) { DPRINTF(Checker, "Changed PC recently to %#x\n", thread->readPC()); if (willChangePC) { if (newPC == thread->readPC()) { DPRINTF(Checker, "Changed PC matches expected PC\n"); } else { warn("%lli: Changed PC does not match expected PC, " "changed: %#x, expected: %#x", curTick, thread->readPC(), newPC); CheckerCPU::handleError(); } willChangePC = false; } changedPC = false; } if (changedNextPC) { DPRINTF(Checker, "Changed NextPC recently to %#x\n", thread->readNextPC()); changedNextPC = false; } // Try to fetch the instruction#if FULL_SYSTEM#define IFETCH_FLAGS(pc) ((pc) & 1) ? PHYSICAL : 0#else#define IFETCH_FLAGS(pc) 0#endif uint64_t fetch_PC = thread->readPC() & ~3; // set up memory request for instruction fetch memReq = new Request(inst->threadNumber, fetch_PC, sizeof(uint32_t), IFETCH_FLAGS(thread->readPC()), fetch_PC, thread->readCpuId(), inst->threadNumber); bool succeeded = translateInstReq(memReq); if (!succeeded) { if (inst->getFault() == NoFault) { // In this case the instruction was not a dummy // instruction carrying an ITB fault. In the single // threaded case the ITB should still be able to // translate this instruction; in the SMT case it's // possible that its ITB entry was kicked out. warn("%lli: Instruction PC %#x was not found in the ITB!", curTick, thread->readPC()); handleError(inst); // go to the next instruction thread->setPC(thread->readNextPC()); thread->setNextPC(thread->readNextPC() + sizeof(MachInst)); break; } else { // The instruction is carrying an ITB fault. Handle // the fault and see if our results match the CPU on // the next tick(). fault = inst->getFault(); } } if (fault == NoFault) { PacketPtr pkt = new Packet(memReq, Packet::ReadReq, Packet::Broadcast); pkt->dataStatic(&machInst); icachePort->sendFunctional(pkt); delete pkt; // keep an instruction count numInst++; // decode the instruction machInst = gtoh(machInst); // Checks that the instruction matches what we expected it to be. // Checks both the machine instruction and the PC. validateInst(inst);#if THE_ISA == ALPHA_ISA curStaticInst = StaticInst::decode(makeExtMI(machInst, thread->readPC()));#elif THE_ISA == SPARC_ISA curStaticInst = StaticInst::decode(makeExtMI(machInst, thread->getTC()));#endif#if FULL_SYSTEM thread->setInst(machInst);#endif // FULL_SYSTEM fault = inst->getFault(); } // Discard fetch's memReq. delete memReq; memReq = NULL; // Either the instruction was a fault and we should process the fault, // or we should just go ahead execute the instruction. This assumes // that the instruction is properly marked as a fault. if (fault == NoFault) { thread->funcExeInst++; if (!inst->isUnverifiable()) fault = curStaticInst->execute(this, NULL); // Checks to make sure instrution results are correct. validateExecution(inst); if (curStaticInst->isLoad()) { ++numLoad; } } if (fault != NoFault) {#if FULL_SYSTEM fault->invoke(tc); willChangePC = true;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?