thread_context_impl.hh

来自「M5,一个功能强大的多处理器系统模拟器.很多针对处理器架构,性能的研究都使用它作」· HH 代码 · 共 529 行

HH
529
字号
/* * 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 "arch/regfile.hh"#include "cpu/o3/thread_context.hh"#include "cpu/quiesce_event.hh"#if FULL_SYSTEMtemplate <class Impl>VirtualPort *O3ThreadContext<Impl>::getVirtPort(ThreadContext *src_tc){    if (!src_tc)        return thread->getVirtPort();    VirtualPort *vp;    vp = new VirtualPort("tc-vport", src_tc);    thread->connectToMemFunc(vp);    return vp;}template <class Impl>voidO3ThreadContext<Impl>::dumpFuncProfile(){    thread->dumpFuncProfile();}#endiftemplate <class Impl>voidO3ThreadContext<Impl>::takeOverFrom(ThreadContext *old_context){    // some things should already be set up#if FULL_SYSTEM    assert(getSystemPtr() == old_context->getSystemPtr());#else    assert(getProcessPtr() == old_context->getProcessPtr());#endif    // copy over functional state    setStatus(old_context->status());    copyArchRegs(old_context);    setCpuId(old_context->readCpuId());#if !FULL_SYSTEM    thread->funcExeInst = old_context->readFuncExeInst();#else    EndQuiesceEvent *other_quiesce = old_context->getQuiesceEvent();    if (other_quiesce) {        // Point the quiesce event's TC at this TC so that it wakes up        // the proper CPU.        other_quiesce->tc = this;    }    if (thread->quiesceEvent) {        thread->quiesceEvent->tc = this;    }    // Transfer kernel stats from one CPU to the other.    thread->kernelStats = old_context->getKernelStats();//    storeCondFailures = 0;    cpu->lockFlag = false;#endif    old_context->setStatus(ThreadContext::Unallocated);    thread->inSyscall = false;    thread->trapPending = false;}#if FULL_SYSTEMtemplate <class Impl>voidO3ThreadContext<Impl>::delVirtPort(VirtualPort *vp){    if (vp != thread->getVirtPort()) {        vp->removeConn();        delete vp;    }}#endiftemplate <class Impl>voidO3ThreadContext<Impl>::activate(int delay){    DPRINTF(O3CPU, "Calling activate on Thread Context %d\n",            getThreadNum());    if (thread->status() == ThreadContext::Active)        return;#if FULL_SYSTEM    thread->lastActivate = curTick;#endif    if (thread->status() == ThreadContext::Unallocated) {        cpu->activateWhenReady(thread->readTid());        return;    }    thread->setStatus(ThreadContext::Active);    // status() == Suspended    cpu->activateContext(thread->readTid(), delay);}template <class Impl>voidO3ThreadContext<Impl>::suspend(int delay){    DPRINTF(O3CPU, "Calling suspend on Thread Context %d\n",            getThreadNum());    if (thread->status() == ThreadContext::Suspended)        return;#if FULL_SYSTEM    thread->lastActivate = curTick;    thread->lastSuspend = curTick;#endif/*#if FULL_SYSTEM    // Don't change the status from active if there are pending interrupts    if (cpu->check_interrupts()) {        assert(status() == ThreadContext::Active);        return;    }#endif*/    thread->setStatus(ThreadContext::Suspended);    cpu->suspendContext(thread->readTid());}template <class Impl>voidO3ThreadContext<Impl>::deallocate(int delay){    DPRINTF(O3CPU, "Calling deallocate on Thread Context %d delay %d\n",            getThreadNum(), delay);    if (thread->status() == ThreadContext::Unallocated)        return;    thread->setStatus(ThreadContext::Unallocated);    cpu->deallocateContext(thread->readTid(), true, delay);}template <class Impl>voidO3ThreadContext<Impl>::halt(int delay){    DPRINTF(O3CPU, "Calling halt on Thread Context %d\n",            getThreadNum());    if (thread->status() == ThreadContext::Halted)        return;    thread->setStatus(ThreadContext::Halted);    cpu->haltContext(thread->readTid());}template <class Impl>voidO3ThreadContext<Impl>::regStats(const std::string &name){#if FULL_SYSTEM    thread->kernelStats = new TheISA::Kernel::Statistics(cpu->system);    thread->kernelStats->regStats(name + ".kern");#endif}template <class Impl>voidO3ThreadContext<Impl>::serialize(std::ostream &os){#if FULL_SYSTEM    if (thread->kernelStats)        thread->kernelStats->serialize(os);#endif}template <class Impl>voidO3ThreadContext<Impl>::unserialize(Checkpoint *cp, const std::string &section){#if FULL_SYSTEM    if (thread->kernelStats)        thread->kernelStats->unserialize(cp, section);#endif}#if FULL_SYSTEMtemplate <class Impl>TickO3ThreadContext<Impl>::readLastActivate(){    return thread->lastActivate;}template <class Impl>TickO3ThreadContext<Impl>::readLastSuspend(){    return thread->lastSuspend;}template <class Impl>voidO3ThreadContext<Impl>::profileClear(){    thread->profileClear();}template <class Impl>voidO3ThreadContext<Impl>::profileSample(){    thread->profileSample();}#endiftemplate <class Impl>TheISA::MachInstO3ThreadContext<Impl>:: getInst(){    return thread->getInst();}template <class Impl>voidO3ThreadContext<Impl>::copyArchRegs(ThreadContext *tc){    // This function will mess things up unless the ROB is empty and    // there are no instructions in the pipeline.    unsigned tid = thread->readTid();    PhysRegIndex renamed_reg;    // First loop through the integer registers.    for (int i = 0; i < TheISA::NumIntRegs; ++i) {        renamed_reg = cpu->renameMap[tid].lookup(i);        DPRINTF(O3CPU, "Copying over register %i, had data %lli, "                "now has data %lli.\n",                renamed_reg, cpu->readIntReg(renamed_reg),                tc->readIntReg(i));        cpu->setIntReg(renamed_reg, tc->readIntReg(i));    }    // Then loop through the floating point registers.    for (int i = 0; i < TheISA::NumFloatRegs; ++i) {        renamed_reg = cpu->renameMap[tid].lookup(i + TheISA::FP_Base_DepTag);        cpu->setFloatRegBits(renamed_reg,                             tc->readFloatRegBits(i));    }    // Copy the misc regs.    TheISA::copyMiscRegs(tc, this);    // Then finally set the PC, the next PC, the nextNPC, the micropc, and the    // next micropc.    cpu->setPC(tc->readPC(), tid);    cpu->setNextPC(tc->readNextPC(), tid);    cpu->setNextNPC(tc->readNextNPC(), tid);    cpu->setMicroPC(tc->readMicroPC(), tid);    cpu->setNextMicroPC(tc->readNextMicroPC(), tid);#if !FULL_SYSTEM    this->thread->funcExeInst = tc->readFuncExeInst();#endif}template <class Impl>voidO3ThreadContext<Impl>::clearArchRegs(){}template <class Impl>uint64_tO3ThreadContext<Impl>::readIntReg(int reg_idx){    reg_idx = TheISA::flattenIntIndex(this, reg_idx);    return cpu->readArchIntReg(reg_idx, thread->readTid());}template <class Impl>TheISA::FloatRegO3ThreadContext<Impl>::readFloatReg(int reg_idx, int width){    reg_idx = TheISA::flattenFloatIndex(this, reg_idx);    switch(width) {      case 32:        return cpu->readArchFloatRegSingle(reg_idx, thread->readTid());      case 64:        return cpu->readArchFloatRegDouble(reg_idx, thread->readTid());      default:        panic("Unsupported width!");        return 0;    }}template <class Impl>TheISA::FloatRegO3ThreadContext<Impl>::readFloatReg(int reg_idx){    reg_idx = TheISA::flattenFloatIndex(this, reg_idx);    return cpu->readArchFloatRegSingle(reg_idx, thread->readTid());}template <class Impl>TheISA::FloatRegBitsO3ThreadContext<Impl>::readFloatRegBits(int reg_idx, int width){    DPRINTF(Fault, "Reading floatint register through the TC!\n");    reg_idx = TheISA::flattenFloatIndex(this, reg_idx);    return cpu->readArchFloatRegInt(reg_idx, thread->readTid());}template <class Impl>TheISA::FloatRegBitsO3ThreadContext<Impl>::readFloatRegBits(int reg_idx){    reg_idx = TheISA::flattenFloatIndex(this, reg_idx);    return cpu->readArchFloatRegInt(reg_idx, thread->readTid());}template <class Impl>voidO3ThreadContext<Impl>::setIntReg(int reg_idx, uint64_t val){    reg_idx = TheISA::flattenIntIndex(this, reg_idx);    cpu->setArchIntReg(reg_idx, val, thread->readTid());    // Squash if we're not already in a state update mode.    if (!thread->trapPending && !thread->inSyscall) {        cpu->squashFromTC(thread->readTid());    }}template <class Impl>voidO3ThreadContext<Impl>::setFloatReg(int reg_idx, FloatReg val, int width){    reg_idx = TheISA::flattenFloatIndex(this, reg_idx);    switch(width) {      case 32:        cpu->setArchFloatRegSingle(reg_idx, val, thread->readTid());        break;      case 64:        cpu->setArchFloatRegDouble(reg_idx, val, thread->readTid());        break;    }    // Squash if we're not already in a state update mode.    if (!thread->trapPending && !thread->inSyscall) {        cpu->squashFromTC(thread->readTid());    }}template <class Impl>voidO3ThreadContext<Impl>::setFloatReg(int reg_idx, FloatReg val){    reg_idx = TheISA::flattenFloatIndex(this, reg_idx);    cpu->setArchFloatRegSingle(reg_idx, val, thread->readTid());    if (!thread->trapPending && !thread->inSyscall) {        cpu->squashFromTC(thread->readTid());    }}template <class Impl>voidO3ThreadContext<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val,                                             int width){    DPRINTF(Fault, "Setting floatint register through the TC!\n");    reg_idx = TheISA::flattenFloatIndex(this, reg_idx);    cpu->setArchFloatRegInt(reg_idx, val, thread->readTid());    // Squash if we're not already in a state update mode.    if (!thread->trapPending && !thread->inSyscall) {        cpu->squashFromTC(thread->readTid());    }}template <class Impl>voidO3ThreadContext<Impl>::setFloatRegBits(int reg_idx, FloatRegBits val){    reg_idx = TheISA::flattenFloatIndex(this, reg_idx);    cpu->setArchFloatRegInt(reg_idx, val, thread->readTid());    // Squash if we're not already in a state update mode.    if (!thread->trapPending && !thread->inSyscall) {        cpu->squashFromTC(thread->readTid());    }}template <class Impl>voidO3ThreadContext<Impl>::setPC(uint64_t val){    cpu->setPC(val, thread->readTid());    // Squash if we're not already in a state update mode.    if (!thread->trapPending && !thread->inSyscall) {        cpu->squashFromTC(thread->readTid());    }}template <class Impl>voidO3ThreadContext<Impl>::setNextPC(uint64_t val){    cpu->setNextPC(val, thread->readTid());    // Squash if we're not already in a state update mode.    if (!thread->trapPending && !thread->inSyscall) {        cpu->squashFromTC(thread->readTid());    }}template <class Impl>voidO3ThreadContext<Impl>::setMicroPC(uint64_t val){    cpu->setMicroPC(val, thread->readTid());    // Squash if we're not already in a state update mode.    if (!thread->trapPending && !thread->inSyscall) {        cpu->squashFromTC(thread->readTid());    }}template <class Impl>voidO3ThreadContext<Impl>::setNextMicroPC(uint64_t val){    cpu->setNextMicroPC(val, thread->readTid());    // Squash if we're not already in a state update mode.    if (!thread->trapPending && !thread->inSyscall) {        cpu->squashFromTC(thread->readTid());    }}template <class Impl>voidO3ThreadContext<Impl>::setMiscRegNoEffect(int misc_reg, const MiscReg &val){    cpu->setMiscRegNoEffect(misc_reg, val, thread->readTid());    // Squash if we're not already in a state update mode.    if (!thread->trapPending && !thread->inSyscall) {        cpu->squashFromTC(thread->readTid());    }}template <class Impl>voidO3ThreadContext<Impl>::setMiscReg(int misc_reg,                                                const MiscReg &val){    cpu->setMiscReg(misc_reg, val, thread->readTid());    // Squash if we're not already in a state update mode.    if (!thread->trapPending && !thread->inSyscall) {        cpu->squashFromTC(thread->readTid());    }}#if !FULL_SYSTEMtemplate <class Impl>TheISA::IntRegO3ThreadContext<Impl>::getSyscallArg(int i){    return cpu->getSyscallArg(i, thread->readTid());}template <class Impl>voidO3ThreadContext<Impl>::setSyscallArg(int i, IntReg val){    cpu->setSyscallArg(i, val, thread->readTid());}template <class Impl>voidO3ThreadContext<Impl>::setSyscallReturn(SyscallReturn return_value){    cpu->setSyscallReturn(return_value, thread->readTid());}#endif // FULL_SYSTEM

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?