cpu.cc
来自「linux下基于c++的处理器仿真平台。具有处理器流水线」· CC 代码 · 共 561 行
CC
561 行
/* * Copyright (c) 2004, 2005 * The Regents of The University of Michigan * All Rights Reserved * * This code is part of the M5 simulator, developed by Nathan Binkert, * Erik Hallnor, Steve Raasch, and Steve Reinhardt, with contributions * from Ron Dreslinski, Dave Greene, Lisa Hsu, Kevin Lim, Ali Saidi, * and Andrew Schultz. * * 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. */#include "config/full_system.hh"#if FULL_SYSTEM#include "sim/system.hh"#else#include "sim/process.hh"#endif#include "sim/root.hh"#include "cpu/o3/alpha_dyn_inst.hh"#include "cpu/o3/alpha_impl.hh"#include "cpu/o3/cpu.hh"#include "cpu/exec_context.hh"using namespace std;BaseFullCPU::BaseFullCPU(Params ¶ms) : BaseCPU(¶ms), cpu_id(0){}template <class Impl>FullO3CPU<Impl>::TickEvent::TickEvent(FullO3CPU<Impl> *c) : Event(&mainEventQueue, CPU_Tick_Pri), cpu(c){}template <class Impl>voidFullO3CPU<Impl>::TickEvent::process(){ cpu->tick();}template <class Impl>const char *FullO3CPU<Impl>::TickEvent::description(){ return "FullO3CPU tick event";}//Call constructor to all the pipeline stages heretemplate <class Impl>FullO3CPU<Impl>::FullO3CPU(Params ¶ms)#if FULL_SYSTEM : BaseFullCPU(params),#else : BaseFullCPU(params),#endif // FULL_SYSTEM tickEvent(this), fetch(params), decode(params), rename(params), iew(params), commit(params), regFile(params.numPhysIntRegs, params.numPhysFloatRegs), freeList(Impl::ISA::NumIntRegs, params.numPhysIntRegs, Impl::ISA::NumFloatRegs, params.numPhysFloatRegs), renameMap(Impl::ISA::NumIntRegs, params.numPhysIntRegs, Impl::ISA::NumFloatRegs, params.numPhysFloatRegs, Impl::ISA::NumMiscRegs, Impl::ISA::ZeroReg, Impl::ISA::ZeroReg + Impl::ISA::NumIntRegs), rob(params.numROBEntries, params.squashWidth), // What to pass to these time buffers? // For now just have these time buffers be pretty big. timeBuffer(5, 5), fetchQueue(5, 5), decodeQueue(5, 5), renameQueue(5, 5), iewQueue(5, 5), xc(NULL), globalSeqNum(1),#if FULL_SYSTEM system(params.system), memCtrl(system->memctrl), physmem(system->physmem), itb(params.itb), dtb(params.dtb), mem(params.mem),#else // Hardcoded for a single thread!! mem(params.workload[0]->getMemory()),#endif // FULL_SYSTEM icacheInterface(params.icacheInterface), dcacheInterface(params.dcacheInterface), deferRegistration(params.defReg), numInsts(0), funcExeInst(0){ _status = Idle;#if !FULL_SYSTEM thread.resize(this->number_of_threads);#endif for (int i = 0; i < this->number_of_threads; ++i) {#if FULL_SYSTEM assert(i == 0); system->execContexts[i] = new ExecContext(this, i, system, itb, dtb, mem); // initialize CPU, including PC TheISA::initCPU(&system->execContexts[i]->regs); execContexts.push_back(system->execContexts[i]);#else if (i < params.workload.size()) { DPRINTF(FullCPU, "FullCPU: Workload[%i]'s starting PC is %#x, " "process is %#x", i, params.workload[i]->prog_entry, thread[i]); thread[i] = new ExecContext(this, i, params.workload[i], i); } assert(params.workload[i]->getMemory() != NULL); assert(mem != NULL); execContexts.push_back(thread[i]);#endif // !FULL_SYSTEM } // Note that this is a hack so that my code which still uses xc-> will // still work. I should remove this eventually#if FULL_SYSTEM xc = system->execContexts[0];#else xc = thread[0];#endif // The stages also need their CPU pointer setup. However this must be // done at the upper level CPU because they have pointers to the upper // level CPU, and not this FullO3CPU. // Give each of the stages the time buffer they will use. fetch.setTimeBuffer(&timeBuffer); decode.setTimeBuffer(&timeBuffer); rename.setTimeBuffer(&timeBuffer); iew.setTimeBuffer(&timeBuffer); commit.setTimeBuffer(&timeBuffer); // Also setup each of the stages' queues. fetch.setFetchQueue(&fetchQueue); decode.setFetchQueue(&fetchQueue); decode.setDecodeQueue(&decodeQueue); rename.setDecodeQueue(&decodeQueue); rename.setRenameQueue(&renameQueue); iew.setRenameQueue(&renameQueue); iew.setIEWQueue(&iewQueue); commit.setIEWQueue(&iewQueue); commit.setRenameQueue(&renameQueue); // Setup the rename map for whichever stages need it. rename.setRenameMap(&renameMap); iew.setRenameMap(&renameMap); // Setup the free list for whichever stages need it. rename.setFreeList(&freeList); renameMap.setFreeList(&freeList); // Setup the ROB for whichever stages need it. commit.setROB(&rob);}template <class Impl>FullO3CPU<Impl>::~FullO3CPU(){}template <class Impl>voidFullO3CPU<Impl>::fullCPURegStats(){ // Register any of the FullCPU's stats here.}template <class Impl>voidFullO3CPU<Impl>::tick(){ DPRINTF(FullCPU, "\n\nFullCPU: Ticking main, FullO3CPU.\n"); //Tick each of the stages if they're actually running. //Will want to figure out a way to unschedule itself if they're all //going to be idle for a long time. fetch.tick(); decode.tick(); rename.tick(); iew.tick(); commit.tick(); // Now advance the time buffers, unless the stage is stalled. timeBuffer.advance(); fetchQueue.advance(); decodeQueue.advance(); renameQueue.advance(); iewQueue.advance(); if (_status == Running && !tickEvent.scheduled()) tickEvent.schedule(curTick + 1);}template <class Impl>voidFullO3CPU<Impl>::init(){ if(!deferRegistration) { this->registerExecContexts(); // Need to do a copy of the xc->regs into the CPU's regfile so // that it can start properly.#if FULL_SYSTEM ExecContext *src_xc = system->execContexts[0];#else ExecContext *src_xc = thread[0];#endif // First loop through the integer registers. for (int i = 0; i < Impl::ISA::NumIntRegs; ++i) { regFile.intRegFile[i] = src_xc->regs.intRegFile[i]; } // Then loop through the floating point registers. for (int i = 0; i < Impl::ISA::NumFloatRegs; ++i) { regFile.floatRegFile[i].d = src_xc->regs.floatRegFile.d[i]; regFile.floatRegFile[i].q = src_xc->regs.floatRegFile.q[i]; } // Then loop through the misc registers. regFile.miscRegs.fpcr = src_xc->regs.miscRegs.fpcr; regFile.miscRegs.uniq = src_xc->regs.miscRegs.uniq; regFile.miscRegs.lock_flag = src_xc->regs.miscRegs.lock_flag; regFile.miscRegs.lock_addr = src_xc->regs.miscRegs.lock_addr; // Then finally set the PC and the next PC. regFile.pc = src_xc->regs.pc; regFile.npc = src_xc->regs.npc; }}template <class Impl>void FullO3CPU<Impl>::activateContext(int thread_num, int delay){ // Needs to set each stage to running as well. scheduleTickEvent(delay); _status = Running;}template <class Impl>void FullO3CPU<Impl>::suspendContext(int thread_num){ panic("suspendContext unimplemented!");}template <class Impl>void FullO3CPU<Impl>::deallocateContext(int thread_num){ panic("deallocateContext unimplemented!");}template <class Impl>void FullO3CPU<Impl>::haltContext(int thread_num){ panic("haltContext unimplemented!");}template <class Impl>voidFullO3CPU<Impl>::switchOut(){ panic("FullO3CPU does not have a switch out function.\n");}template <class Impl>voidFullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU){ BaseCPU::takeOverFrom(oldCPU); assert(!tickEvent.scheduled()); // Set all status's to active, schedule the // CPU's tick event. for (int i = 0; i < execContexts.size(); ++i) { ExecContext *xc = execContexts[i]; if (xc->status() == ExecContext::Active && _status != Running) { _status = Running; tickEvent.schedule(curTick); } }}template <class Impl>InstSeqNumFullO3CPU<Impl>::getAndIncrementInstSeq(){ // Hopefully this works right. return globalSeqNum++;}template <class Impl>uint64_tFullO3CPU<Impl>::readIntReg(int reg_idx){ return regFile.readIntReg(reg_idx);}template <class Impl>float FullO3CPU<Impl>::readFloatRegSingle(int reg_idx){ return regFile.readFloatRegSingle(reg_idx);}template <class Impl>double FullO3CPU<Impl>::readFloatRegDouble(int reg_idx){ return regFile.readFloatRegDouble(reg_idx);}template <class Impl>uint64_t FullO3CPU<Impl>::readFloatRegInt(int reg_idx){ return regFile.readFloatRegInt(reg_idx);}template <class Impl>void FullO3CPU<Impl>::setIntReg(int reg_idx, uint64_t val){ regFile.setIntReg(reg_idx, val);}template <class Impl>void FullO3CPU<Impl>::setFloatRegSingle(int reg_idx, float val){ regFile.setFloatRegSingle(reg_idx, val);}template <class Impl>void FullO3CPU<Impl>::setFloatRegDouble(int reg_idx, double val){ regFile.setFloatRegDouble(reg_idx, val);}template <class Impl>void FullO3CPU<Impl>::setFloatRegInt(int reg_idx, uint64_t val){ regFile.setFloatRegInt(reg_idx, val);}template <class Impl>uint64_t FullO3CPU<Impl>::readPC(){ return regFile.readPC();}template <class Impl>voidFullO3CPU<Impl>::setNextPC(uint64_t val){ regFile.setNextPC(val);}template <class Impl>void FullO3CPU<Impl>::setPC(Addr new_PC){ regFile.setPC(new_PC);}template <class Impl>voidFullO3CPU<Impl>::addInst(DynInstPtr &inst){ instList.push_back(inst);}template <class Impl>voidFullO3CPU<Impl>::instDone(){ // Keep an instruction count. numInsts++; // Check for instruction-count-based events. comInstEventQueue[0]->serviceEvents(numInsts);}template <class Impl>voidFullO3CPU<Impl>::removeBackInst(DynInstPtr &inst){ DynInstPtr inst_to_delete; // Walk through the instruction list, removing any instructions // that were inserted after the given instruction, inst. while (instList.back() != inst) { assert(!instList.empty()); // Obtain the pointer to the instruction. inst_to_delete = instList.back(); DPRINTF(FullCPU, "FullCPU: Removing instruction %i, PC %#x\n", inst_to_delete->seqNum, inst_to_delete->readPC()); // Remove the instruction from the list. instList.pop_back(); // Mark it as squashed. inst_to_delete->setSquashed(); }}template <class Impl>voidFullO3CPU<Impl>::removeFrontInst(DynInstPtr &inst){ DynInstPtr inst_to_remove; // The front instruction should be the same one being asked to be removed. assert(instList.front() == inst); // Remove the front instruction. inst_to_remove = inst; instList.pop_front(); DPRINTF(FullCPU, "FullCPU: Removing committed instruction %#x, PC %#x\n", inst_to_remove, inst_to_remove->readPC());}template <class Impl>voidFullO3CPU<Impl>::removeInstsNotInROB(){ DPRINTF(FullCPU, "FullCPU: Deleting instructions from instruction " "list.\n"); DynInstPtr rob_tail = rob.readTailInst(); removeBackInst(rob_tail);}template <class Impl>voidFullO3CPU<Impl>::removeInstsUntil(const InstSeqNum &seq_num){ DPRINTF(FullCPU, "FullCPU: Deleting instructions from instruction " "list.\n"); DynInstPtr inst_to_delete; while (instList.back()->seqNum > seq_num) { assert(!instList.empty()); // Obtain the pointer to the instruction. inst_to_delete = instList.back(); DPRINTF(FullCPU, "FullCPU: Removing instruction %i, PC %#x\n", inst_to_delete->seqNum, inst_to_delete->readPC()); // Remove the instruction from the list. instList.back() = NULL; instList.pop_back(); // Mark it as squashed. inst_to_delete->setSquashed(); }}template <class Impl>voidFullO3CPU<Impl>::removeAllInsts(){ instList.clear();}template <class Impl>voidFullO3CPU<Impl>::dumpInsts(){ int num = 0; typename list<DynInstPtr>::iterator inst_list_it = instList.begin(); while (inst_list_it != instList.end()) { cprintf("Instruction:%i\nPC:%#x\nSN:%lli\nIssued:%i\nSquashed:%i\n\n", num, (*inst_list_it)->readPC(), (*inst_list_it)->seqNum, (*inst_list_it)->isIssued(), (*inst_list_it)->isSquashed()); inst_list_it++; ++num; }}template <class Impl>voidFullO3CPU<Impl>::wakeDependents(DynInstPtr &inst){ iew.wakeDependents(inst);}// Forward declaration of FullO3CPU.template class FullO3CPU<AlphaSimpleImpl>;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?