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 + -
显示快捷键?