commit_impl.hh

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

HH
1,375
字号
                    oldpc = PC[tid];                    cpu->system->pcEventQueue.service(thread[tid]->getTC());                    count++;                } while (oldpc != PC[tid]);                if (count > 1) {                    DPRINTF(Commit,                            "PC skip function event, stopping commit\n");                    break;                }            } else {                DPRINTF(Commit, "Unable to commit head instruction PC:%#x "                        "[tid:%i] [sn:%i].\n",                        head_inst->readPC(), tid ,head_inst->seqNum);                break;            }        }    }    DPRINTF(CommitRate, "%i\n", num_committed);    numCommittedDist.sample(num_committed);    if (num_committed == commitWidth) {        commitEligibleSamples++;    }}template <class Impl>boolDefaultCommit<Impl>::commitHead(DynInstPtr &head_inst, unsigned inst_num){    assert(head_inst);    int tid = head_inst->threadNumber;    // If the instruction is not executed yet, then it will need extra    // handling.  Signal backwards that it should be executed.    if (!head_inst->isExecuted()) {        // Keep this number correct.  We have not yet actually executed        // and committed this instruction.        thread[tid]->funcExeInst--;        if (head_inst->isNonSpeculative() ||            head_inst->isStoreConditional() ||            head_inst->isMemBarrier() ||            head_inst->isWriteBarrier()) {            DPRINTF(Commit, "Encountered a barrier or non-speculative "                    "instruction [sn:%lli] at the head of the ROB, PC %#x.\n",                    head_inst->seqNum, head_inst->readPC());            if (inst_num > 0 || iewStage->hasStoresToWB()) {                DPRINTF(Commit, "Waiting for all stores to writeback.\n");                return false;            }            toIEW->commitInfo[tid].nonSpecSeqNum = head_inst->seqNum;            // Change the instruction so it won't try to commit again until            // it is executed.            head_inst->clearCanCommit();            ++commitNonSpecStalls;            return false;        } else if (head_inst->isLoad()) {            if (inst_num > 0 || iewStage->hasStoresToWB()) {                DPRINTF(Commit, "Waiting for all stores to writeback.\n");                return false;            }            assert(head_inst->uncacheable());            DPRINTF(Commit, "[sn:%lli]: Uncached load, PC %#x.\n",                    head_inst->seqNum, head_inst->readPC());            // Send back the non-speculative instruction's sequence            // number.  Tell the lsq to re-execute the load.            toIEW->commitInfo[tid].nonSpecSeqNum = head_inst->seqNum;            toIEW->commitInfo[tid].uncached = true;            toIEW->commitInfo[tid].uncachedLoad = head_inst;            head_inst->clearCanCommit();            return false;        } else {            panic("Trying to commit un-executed instruction "                  "of unknown type!\n");        }    }    if (head_inst->isThreadSync()) {        // Not handled for now.        panic("Thread sync instructions are not handled yet.\n");    }    // Check if the instruction caused a fault.  If so, trap.    Fault inst_fault = head_inst->getFault();    // Stores mark themselves as completed.    if (!head_inst->isStore() && inst_fault == NoFault) {        head_inst->setCompleted();    }#if USE_CHECKER    // Use checker prior to updating anything due to traps or PC    // based events.    if (cpu->checker) {        cpu->checker->verify(head_inst);    }#endif    // DTB will sometimes need the machine instruction for when    // faults happen.  So we will set it here, prior to the DTB    // possibly needing it for its fault.    thread[tid]->setInst(        static_cast<TheISA::MachInst>(head_inst->staticInst->machInst));    if (inst_fault != NoFault) {        DPRINTF(Commit, "Inst [sn:%lli] PC %#x has a fault\n",                head_inst->seqNum, head_inst->readPC());        if (iewStage->hasStoresToWB() || inst_num > 0) {            DPRINTF(Commit, "Stores outstanding, fault must wait.\n");            return false;        }        head_inst->setCompleted();#if USE_CHECKER        if (cpu->checker && head_inst->isStore()) {            cpu->checker->verify(head_inst);        }#endif        assert(!thread[tid]->inSyscall);        // Mark that we're in state update mode so that the trap's        // execution doesn't generate extra squashes.        thread[tid]->inSyscall = true;        // Execute the trap.  Although it's slightly unrealistic in        // terms of timing (as it doesn't wait for the full timing of        // the trap event to complete before updating state), it's        // needed to update the state as soon as possible.  This        // prevents external agents from changing any specific state        // that the trap need.        cpu->trap(inst_fault, tid);        // Exit state update mode to avoid accidental updating.        thread[tid]->inSyscall = false;        commitStatus[tid] = TrapPending;        if (head_inst->traceData) {            head_inst->traceData->setFetchSeq(head_inst->seqNum);            head_inst->traceData->setCPSeq(thread[tid]->numInst);            head_inst->traceData->dump();            delete head_inst->traceData;            head_inst->traceData = NULL;        }        // Generate trap squash event.        generateTrapEvent(tid);//        warn("%lli fault (%d) handled @ PC %08p", curTick, inst_fault->name(), head_inst->readPC());        return false;    }    updateComInstStats(head_inst);#if FULL_SYSTEM    if (thread[tid]->profile) {//        bool usermode = TheISA::inUserMode(thread[tid]->getTC());//        thread[tid]->profilePC = usermode ? 1 : head_inst->readPC();        thread[tid]->profilePC = head_inst->readPC();        ProfileNode *node = thread[tid]->profile->consume(thread[tid]->getTC(),                                                          head_inst->staticInst);        if (node)            thread[tid]->profileNode = node;    }#endif    if (head_inst->traceData) {        head_inst->traceData->setFetchSeq(head_inst->seqNum);        head_inst->traceData->setCPSeq(thread[tid]->numInst);        head_inst->traceData->dump();        delete head_inst->traceData;        head_inst->traceData = NULL;    }    // Update the commit rename map    for (int i = 0; i < head_inst->numDestRegs(); i++) {        renameMap[tid]->setEntry(head_inst->flattenedDestRegIdx(i),                                 head_inst->renamedDestRegIdx(i));    }    if (head_inst->isCopy())        panic("Should not commit any copy instructions!");    // Finally clear the head ROB entry.    rob->retireHead(tid);    // If this was a store, record it for this cycle.    if (head_inst->isStore())        committedStores[tid] = true;    // Return true to indicate that we have committed an instruction.    return true;}template <class Impl>voidDefaultCommit<Impl>::getInsts(){    DPRINTF(Commit, "Getting instructions from Rename stage.\n");    // Read any renamed instructions and place them into the ROB.    int insts_to_process = std::min((int)renameWidth, fromRename->size);    for (int inst_num = 0; inst_num < insts_to_process; ++inst_num) {        DynInstPtr inst;        inst = fromRename->insts[inst_num];        int tid = inst->threadNumber;        if (!inst->isSquashed() &&            commitStatus[tid] != ROBSquashing &&            commitStatus[tid] != TrapPending) {            changedROBNumEntries[tid] = true;            DPRINTF(Commit, "Inserting PC %#x [sn:%i] [tid:%i] into ROB.\n",                    inst->readPC(), inst->seqNum, tid);            rob->insertInst(inst);            assert(rob->getThreadEntries(tid) <= rob->getMaxEntries(tid));            youngestSeqNum[tid] = inst->seqNum;        } else {            DPRINTF(Commit, "Instruction PC %#x [sn:%i] [tid:%i] was "                    "squashed, skipping.\n",                    inst->readPC(), inst->seqNum, tid);        }    }}template <class Impl>voidDefaultCommit<Impl>::skidInsert(){    DPRINTF(Commit, "Attempting to any instructions from rename into "            "skidBuffer.\n");    for (int inst_num = 0; inst_num < fromRename->size; ++inst_num) {        DynInstPtr inst = fromRename->insts[inst_num];        if (!inst->isSquashed()) {            DPRINTF(Commit, "Inserting PC %#x [sn:%i] [tid:%i] into ",                    "skidBuffer.\n", inst->readPC(), inst->seqNum,                    inst->threadNumber);            skidBuffer.push(inst);        } else {            DPRINTF(Commit, "Instruction PC %#x [sn:%i] [tid:%i] was "                    "squashed, skipping.\n",                    inst->readPC(), inst->seqNum, inst->threadNumber);        }    }}template <class Impl>voidDefaultCommit<Impl>::markCompletedInsts(){    // Grab completed insts out of the IEW instruction queue, and mark    // instructions completed within the ROB.    for (int inst_num = 0;         inst_num < fromIEW->size && fromIEW->insts[inst_num];         ++inst_num)    {        if (!fromIEW->insts[inst_num]->isSquashed()) {            DPRINTF(Commit, "[tid:%i]: Marking PC %#x, [sn:%lli] ready "                    "within ROB.\n",                    fromIEW->insts[inst_num]->threadNumber,                    fromIEW->insts[inst_num]->readPC(),                    fromIEW->insts[inst_num]->seqNum);            // Mark the instruction as ready to commit.            fromIEW->insts[inst_num]->setCanCommit();        }    }}template <class Impl>boolDefaultCommit<Impl>::robDoneSquashing(){    std::list<unsigned>::iterator threads = activeThreads->begin();    std::list<unsigned>::iterator end = activeThreads->end();    while (threads != end) {        unsigned tid = *threads++;        if (!rob->isDoneSquashing(tid))            return false;    }    return true;}template <class Impl>voidDefaultCommit<Impl>::updateComInstStats(DynInstPtr &inst){    unsigned thread = inst->threadNumber;    //    //  Pick off the software prefetches    //#ifdef TARGET_ALPHA    if (inst->isDataPrefetch()) {        statComSwp[thread]++;    } else {        statComInst[thread]++;    }#else    statComInst[thread]++;#endif    //    //  Control Instructions    //    if (inst->isControl())        statComBranches[thread]++;    //    //  Memory references    //    if (inst->isMemRef()) {        statComRefs[thread]++;        if (inst->isLoad()) {            statComLoads[thread]++;        }    }    if (inst->isMemBarrier()) {        statComMembars[thread]++;    }}//////////////////////////////////////////                                    ////  SMT COMMIT POLICY MAINTAINED HERE ////                                    //////////////////////////////////////////template <class Impl>intDefaultCommit<Impl>::getCommittingThread(){    if (numThreads > 1) {        switch (commitPolicy) {          case Aggressive:            //If Policy is Aggressive, commit will call            //this function multiple times per            //cycle            return oldestReady();          case RoundRobin:            return roundRobin();          case OldestReady:            return oldestReady();          default:            return -1;        }    } else {        assert(!activeThreads->empty());        int tid = activeThreads->front();        if (commitStatus[tid] == Running ||            commitStatus[tid] == Idle ||            commitStatus[tid] == FetchTrapPending) {            return tid;        } else {            return -1;        }    }}template<class Impl>intDefaultCommit<Impl>::roundRobin(){    std::list<unsigned>::iterator pri_iter = priority_list.begin();    std::list<unsigned>::iterator end      = priority_list.end();    while (pri_iter != end) {        unsigned tid = *pri_iter;        if (commitStatus[tid] == Running ||            commitStatus[tid] == Idle ||            commitStatus[tid] == FetchTrapPending) {            if (rob->isHeadReady(tid)) {                priority_list.erase(pri_iter);                priority_list.push_back(tid);                return tid;            }        }        pri_iter++;    }    return -1;}template<class Impl>intDefaultCommit<Impl>::oldestReady(){    unsigned oldest = 0;    bool first = true;    std::list<unsigned>::iterator threads = activeThreads->begin();    std::list<unsigned>::iterator end = activeThreads->end();    while (threads != end) {        unsigned tid = *threads++;        if (!rob->isEmpty(tid) &&            (commitStatus[tid] == Running ||             commitStatus[tid] == Idle ||             commitStatus[tid] == FetchTrapPending)) {            if (rob->isHeadReady(tid)) {                DynInstPtr head_inst = rob->readHeadInst(tid);                if (first) {                    oldest = tid;                    first = false;                } else if (head_inst->seqNum < oldest) {                    oldest = tid;                }            }        }    }    if (!first) {        return oldest;    } else {        return -1;    }}

⌨️ 快捷键说明

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