cpu.cc
来自「M5,一个功能强大的多处理器系统模拟器.很多针对处理器架构,性能的研究都使用它作」· CC 代码 · 共 1,477 行 · 第 1/3 页
CC
1,477 行
/* * Copyright (c) 2004, 2005, 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 * Korey L. Sewell */#include "config/full_system.hh"#include "config/use_checker.hh"#include "cpu/activity.hh"#include "cpu/simple_thread.hh"#include "cpu/thread_context.hh"#include "cpu/o3/isa_specific.hh"#include "cpu/o3/cpu.hh"#include "enums/MemoryMode.hh"#include "sim/core.hh"#include "sim/stat_control.hh"#if FULL_SYSTEM#include "cpu/quiesce_event.hh"#include "sim/system.hh"#else#include "sim/process.hh"#endif#if USE_CHECKER#include "cpu/checker/cpu.hh"#endifusing namespace TheISA;BaseO3CPU::BaseO3CPU(Params *params) : BaseCPU(params), cpu_id(0){}voidBaseO3CPU::regStats(){ BaseCPU::regStats();}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() const{ return "FullO3CPU tick";}template <class Impl>FullO3CPU<Impl>::ActivateThreadEvent::ActivateThreadEvent() : Event(&mainEventQueue, CPU_Switch_Pri){}template <class Impl>voidFullO3CPU<Impl>::ActivateThreadEvent::init(int thread_num, FullO3CPU<Impl> *thread_cpu){ tid = thread_num; cpu = thread_cpu;}template <class Impl>voidFullO3CPU<Impl>::ActivateThreadEvent::process(){ cpu->activateThread(tid);}template <class Impl>const char *FullO3CPU<Impl>::ActivateThreadEvent::description() const{ return "FullO3CPU \"Activate Thread\"";}template <class Impl>FullO3CPU<Impl>::DeallocateContextEvent::DeallocateContextEvent() : Event(&mainEventQueue, CPU_Tick_Pri), tid(0), remove(false), cpu(NULL){}template <class Impl>voidFullO3CPU<Impl>::DeallocateContextEvent::init(int thread_num, FullO3CPU<Impl> *thread_cpu){ tid = thread_num; cpu = thread_cpu; remove = false;}template <class Impl>voidFullO3CPU<Impl>::DeallocateContextEvent::process(){ cpu->deactivateThread(tid); if (remove) cpu->removeThread(tid);}template <class Impl>const char *FullO3CPU<Impl>::DeallocateContextEvent::description() const{ return "FullO3CPU \"Deallocate Context\"";}template <class Impl>FullO3CPU<Impl>::FullO3CPU(O3CPU *o3_cpu, Params *params) : BaseO3CPU(params), itb(params->itb), dtb(params->dtb), tickEvent(this), removeInstsThisCycle(false), fetch(o3_cpu, params), decode(o3_cpu, params), rename(o3_cpu, params), iew(o3_cpu, params), commit(o3_cpu, params), regFile(o3_cpu, params->numPhysIntRegs, params->numPhysFloatRegs), freeList(params->numberOfThreads, TheISA::NumIntRegs, params->numPhysIntRegs, TheISA::NumFloatRegs, params->numPhysFloatRegs), rob(o3_cpu, params->numROBEntries, params->squashWidth, params->smtROBPolicy, params->smtROBThreshold, params->numberOfThreads), scoreboard(params->numberOfThreads, TheISA::NumIntRegs, params->numPhysIntRegs, TheISA::NumFloatRegs, params->numPhysFloatRegs, TheISA::NumMiscRegs * number_of_threads, TheISA::ZeroReg), timeBuffer(params->backComSize, params->forwardComSize), fetchQueue(params->backComSize, params->forwardComSize), decodeQueue(params->backComSize, params->forwardComSize), renameQueue(params->backComSize, params->forwardComSize), iewQueue(params->backComSize, params->forwardComSize), activityRec(NumStages, params->backComSize + params->forwardComSize, params->activity), globalSeqNum(1),#if FULL_SYSTEM system(params->system), physmem(system->physmem),#endif // FULL_SYSTEM drainCount(0), deferRegistration(params->deferRegistration), numThreads(number_of_threads){ if (!deferRegistration) { _status = Running; } else { _status = Idle; }#if USE_CHECKER if (params->checker) { BaseCPU *temp_checker = params->checker; checker = dynamic_cast<Checker<DynInstPtr> *>(temp_checker);#if FULL_SYSTEM checker->setSystem(params->system);#endif } else { checker = NULL; }#endif // USE_CHECKER#if !FULL_SYSTEM thread.resize(number_of_threads); tids.resize(number_of_threads);#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. // Set up Pointers to the activeThreads list for each stage fetch.setActiveThreads(&activeThreads); decode.setActiveThreads(&activeThreads); rename.setActiveThreads(&activeThreads); iew.setActiveThreads(&activeThreads); commit.setActiveThreads(&activeThreads); // 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); commit.setFetchQueue(&fetchQueue); decode.setDecodeQueue(&decodeQueue); rename.setDecodeQueue(&decodeQueue); rename.setRenameQueue(&renameQueue); iew.setRenameQueue(&renameQueue); iew.setIEWQueue(&iewQueue); commit.setIEWQueue(&iewQueue); commit.setRenameQueue(&renameQueue); commit.setIEWStage(&iew); rename.setIEWStage(&iew); rename.setCommitStage(&commit);#if !FULL_SYSTEM int active_threads = params->workload.size(); if (active_threads > Impl::MaxThreads) { panic("Workload Size too large. Increase the 'MaxThreads'" "constant in your O3CPU impl. file (e.g. o3/alpha/impl.hh) or " "edit your workload size."); }#else int active_threads = 1;#endif //Make Sure That this a Valid Architeture assert(params->numPhysIntRegs >= numThreads * TheISA::NumIntRegs); assert(params->numPhysFloatRegs >= numThreads * TheISA::NumFloatRegs); rename.setScoreboard(&scoreboard); iew.setScoreboard(&scoreboard); // Setup the rename map for whichever stages need it. PhysRegIndex lreg_idx = 0; PhysRegIndex freg_idx = params->numPhysIntRegs; //Index to 1 after int regs for (int tid=0; tid < numThreads; tid++) { bool bindRegs = (tid <= active_threads - 1); commitRenameMap[tid].init(TheISA::NumIntRegs, params->numPhysIntRegs, lreg_idx, //Index for Logical. Regs TheISA::NumFloatRegs, params->numPhysFloatRegs, freg_idx, //Index for Float Regs TheISA::NumMiscRegs, TheISA::ZeroReg, TheISA::ZeroReg, tid, false); renameMap[tid].init(TheISA::NumIntRegs, params->numPhysIntRegs, lreg_idx, //Index for Logical. Regs TheISA::NumFloatRegs, params->numPhysFloatRegs, freg_idx, //Index for Float Regs TheISA::NumMiscRegs, TheISA::ZeroReg, TheISA::ZeroReg, tid, bindRegs); activateThreadEvent[tid].init(tid, this); deallocateContextEvent[tid].init(tid, this); } rename.setRenameMap(renameMap); commit.setRenameMap(commitRenameMap); // Give renameMap & rename stage access to the freeList; for (int i=0; i < numThreads; i++) { renameMap[i].setFreeList(&freeList); } rename.setFreeList(&freeList); // Setup the ROB for whichever stages need it. commit.setROB(&rob); lastRunningCycle = curTick; lastActivatedCycle = -1; // Give renameMap & rename stage access to the freeList; //for (int i=0; i < numThreads; i++) { //globalSeqNum[i] = 1; //} contextSwitch = false;}template <class Impl>FullO3CPU<Impl>::~FullO3CPU(){}template <class Impl>voidFullO3CPU<Impl>::fullCPURegStats(){ BaseO3CPU::regStats(); // Register any of the O3CPU's stats here. timesIdled .name(name() + ".timesIdled") .desc("Number of times that the entire CPU went into an idle state and" " unscheduled itself") .prereq(timesIdled); idleCycles .name(name() + ".idleCycles") .desc("Total number of cycles that the CPU has spent unscheduled due " "to idling") .prereq(idleCycles); // Number of Instructions simulated // -------------------------------- // Should probably be in Base CPU but need templated // MaxThreads so put in here instead committedInsts .init(numThreads) .name(name() + ".committedInsts") .desc("Number of Instructions Simulated"); totalCommittedInsts .name(name() + ".committedInsts_total") .desc("Number of Instructions Simulated"); cpi .name(name() + ".cpi") .desc("CPI: Cycles Per Instruction") .precision(6); cpi = numCycles / committedInsts; totalCpi .name(name() + ".cpi_total") .desc("CPI: Total CPI of All Threads") .precision(6); totalCpi = numCycles / totalCommittedInsts; ipc .name(name() + ".ipc") .desc("IPC: Instructions Per Cycle") .precision(6); ipc = committedInsts / numCycles; totalIpc .name(name() + ".ipc_total") .desc("IPC: Total IPC of All Threads") .precision(6); totalIpc = totalCommittedInsts / numCycles;}template <class Impl>Port *FullO3CPU<Impl>::getPort(const std::string &if_name, int idx){ if (if_name == "dcache_port") return iew.getDcachePort(); else if (if_name == "icache_port") return fetch.getIcachePort(); else panic("No Such Port\n");}template <class Impl>voidFullO3CPU<Impl>::tick(){ DPRINTF(O3CPU, "\n\nFullO3CPU: Ticking main, FullO3CPU.\n"); ++numCycles;// activity = false; //Tick each of the stages fetch.tick(); decode.tick(); rename.tick(); iew.tick(); commit.tick();#if !FULL_SYSTEM doContextSwitch();#endif // Now advance the time buffers timeBuffer.advance(); fetchQueue.advance(); decodeQueue.advance(); renameQueue.advance(); iewQueue.advance(); activityRec.advance(); if (removeInstsThisCycle) { cleanUpRemovedInsts(); } if (!tickEvent.scheduled()) { if (_status == SwitchedOut || getState() == SimObject::Drained) { DPRINTF(O3CPU, "Switched out!\n"); // increment stat lastRunningCycle = curTick; } else if (!activityRec.active() || _status == Idle) { DPRINTF(O3CPU, "Idle!\n"); lastRunningCycle = curTick; timesIdled++; } else { tickEvent.schedule(nextCycle(curTick + ticks(1))); DPRINTF(O3CPU, "Scheduling next tick!\n"); } }#if !FULL_SYSTEM updateThreadPriority();#endif}template <class Impl>voidFullO3CPU<Impl>::init(){ if (!deferRegistration) { registerThreadContexts(); } // Set inSyscall so that the CPU doesn't squash when initially // setting up registers. for (int i = 0; i < number_of_threads; ++i) thread[i]->inSyscall = true; for (int tid=0; tid < number_of_threads; tid++) {#if FULL_SYSTEM ThreadContext *src_tc = threadContexts[tid];#else
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?