iew_impl.hh

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

HH
1,585
字号
    }}template<class Impl>voidDefaultIEW<Impl>::squash(unsigned tid){    DPRINTF(IEW, "[tid:%i]: Squashing all instructions.\n",            tid);    // Tell the IQ to start squashing.    instQueue.squash(tid);    // Tell the LDSTQ to start squashing.    ldstQueue.squash(fromCommit->commitInfo[tid].doneSeqNum, tid);    updatedQueues = true;    // Clear the skid buffer in case it has any data in it.    DPRINTF(IEW, "[tid:%i]: Removing skidbuffer instructions until [sn:%i].\n",            tid, fromCommit->commitInfo[tid].doneSeqNum);    while (!skidBuffer[tid].empty()) {        if (skidBuffer[tid].front()->isLoad() ||            skidBuffer[tid].front()->isStore() ) {            toRename->iewInfo[tid].dispatchedToLSQ++;        }        toRename->iewInfo[tid].dispatched++;        skidBuffer[tid].pop();    }    emptyRenameInsts(tid);}template<class Impl>voidDefaultIEW<Impl>::squashDueToBranch(DynInstPtr &inst, unsigned tid){    DPRINTF(IEW, "[tid:%i]: Squashing from a specific instruction, PC: %#x "            "[sn:%i].\n", tid, inst->readPC(), inst->seqNum);    toCommit->squash[tid] = true;    toCommit->squashedSeqNum[tid] = inst->seqNum;    toCommit->mispredPC[tid] = inst->readPC();    toCommit->branchMispredict[tid] = true;#if ISA_HAS_DELAY_SLOT    int instSize = sizeof(TheISA::MachInst);    toCommit->branchTaken[tid] =        !(inst->readNextPC() + instSize == inst->readNextNPC() &&          (inst->readNextPC() == inst->readPC() + instSize ||           inst->readNextPC() == inst->readPC() + 2 * instSize));#else    toCommit->branchTaken[tid] = inst->readNextPC() !=        (inst->readPC() + sizeof(TheISA::MachInst));#endif    toCommit->nextPC[tid] = inst->readNextPC();    toCommit->nextNPC[tid] = inst->readNextNPC();    toCommit->nextMicroPC[tid] = inst->readNextMicroPC();    toCommit->includeSquashInst[tid] = false;    wroteToTimeBuffer = true;}template<class Impl>voidDefaultIEW<Impl>::squashDueToMemOrder(DynInstPtr &inst, unsigned tid){    DPRINTF(IEW, "[tid:%i]: Squashing from a specific instruction, "            "PC: %#x [sn:%i].\n", tid, inst->readPC(), inst->seqNum);    toCommit->squash[tid] = true;    toCommit->squashedSeqNum[tid] = inst->seqNum;    toCommit->nextPC[tid] = inst->readNextPC();    toCommit->nextNPC[tid] = inst->readNextNPC();    toCommit->branchMispredict[tid] = false;    toCommit->includeSquashInst[tid] = false;    wroteToTimeBuffer = true;}template<class Impl>voidDefaultIEW<Impl>::squashDueToMemBlocked(DynInstPtr &inst, unsigned tid){    DPRINTF(IEW, "[tid:%i]: Memory blocked, squashing load and younger insts, "            "PC: %#x [sn:%i].\n", tid, inst->readPC(), inst->seqNum);    toCommit->squash[tid] = true;    toCommit->squashedSeqNum[tid] = inst->seqNum;    toCommit->nextPC[tid] = inst->readPC();    toCommit->nextNPC[tid] = inst->readNextPC();    toCommit->branchMispredict[tid] = false;    // Must include the broadcasted SN in the squash.    toCommit->includeSquashInst[tid] = true;    ldstQueue.setLoadBlockedHandled(tid);    wroteToTimeBuffer = true;}template<class Impl>voidDefaultIEW<Impl>::block(unsigned tid){    DPRINTF(IEW, "[tid:%u]: Blocking.\n", tid);    if (dispatchStatus[tid] != Blocked &&        dispatchStatus[tid] != Unblocking) {        toRename->iewBlock[tid] = true;        wroteToTimeBuffer = true;    }    // Add the current inputs to the skid buffer so they can be    // reprocessed when this stage unblocks.    skidInsert(tid);    dispatchStatus[tid] = Blocked;}template<class Impl>voidDefaultIEW<Impl>::unblock(unsigned tid){    DPRINTF(IEW, "[tid:%i]: Reading instructions out of the skid "            "buffer %u.\n",tid, tid);    // If the skid bufffer is empty, signal back to previous stages to unblock.    // Also switch status to running.    if (skidBuffer[tid].empty()) {        toRename->iewUnblock[tid] = true;        wroteToTimeBuffer = true;        DPRINTF(IEW, "[tid:%i]: Done unblocking.\n",tid);        dispatchStatus[tid] = Running;    }}template<class Impl>voidDefaultIEW<Impl>::wakeDependents(DynInstPtr &inst){    instQueue.wakeDependents(inst);}template<class Impl>voidDefaultIEW<Impl>::rescheduleMemInst(DynInstPtr &inst){    instQueue.rescheduleMemInst(inst);}template<class Impl>voidDefaultIEW<Impl>::replayMemInst(DynInstPtr &inst){    instQueue.replayMemInst(inst);}template<class Impl>voidDefaultIEW<Impl>::instToCommit(DynInstPtr &inst){    // This function should not be called after writebackInsts in a    // single cycle.  That will cause problems with an instruction    // being added to the queue to commit without being processed by    // writebackInsts prior to being sent to commit.    // First check the time slot that this instruction will write    // to.  If there are free write ports at the time, then go ahead    // and write the instruction to that time.  If there are not,    // keep looking back to see where's the first time there's a    // free slot.    while ((*iewQueue)[wbCycle].insts[wbNumInst]) {        ++wbNumInst;        if (wbNumInst == wbWidth) {            ++wbCycle;            wbNumInst = 0;        }        assert((wbCycle * wbWidth + wbNumInst) <= wbMax);    }    DPRINTF(IEW, "Current wb cycle: %i, width: %i, numInst: %i\nwbActual:%i\n",            wbCycle, wbWidth, wbNumInst, wbCycle * wbWidth + wbNumInst);    // Add finished instruction to queue to commit.    (*iewQueue)[wbCycle].insts[wbNumInst] = inst;    (*iewQueue)[wbCycle].size++;}template <class Impl>unsignedDefaultIEW<Impl>::validInstsFromRename(){    unsigned inst_count = 0;    for (int i=0; i<fromRename->size; i++) {        if (!fromRename->insts[i]->isSquashed())            inst_count++;    }    return inst_count;}template<class Impl>voidDefaultIEW<Impl>::skidInsert(unsigned tid){    DynInstPtr inst = NULL;    while (!insts[tid].empty()) {        inst = insts[tid].front();        insts[tid].pop();        DPRINTF(Decode,"[tid:%i]: Inserting [sn:%lli] PC:%#x into "                "dispatch skidBuffer %i\n",tid, inst->seqNum,                inst->readPC(),tid);        skidBuffer[tid].push(inst);    }    assert(skidBuffer[tid].size() <= skidBufferMax &&           "Skidbuffer Exceeded Max Size");}template<class Impl>intDefaultIEW<Impl>::skidCount(){    int max=0;    std::list<unsigned>::iterator threads = activeThreads->begin();    std::list<unsigned>::iterator end = activeThreads->end();    while (threads != end) {        unsigned tid = *threads++;        unsigned thread_count = skidBuffer[tid].size();        if (max < thread_count)            max = thread_count;    }    return max;}template<class Impl>boolDefaultIEW<Impl>::skidsEmpty(){    std::list<unsigned>::iterator threads = activeThreads->begin();    std::list<unsigned>::iterator end = activeThreads->end();    while (threads != end) {        unsigned tid = *threads++;        if (!skidBuffer[tid].empty())            return false;    }    return true;}template <class Impl>voidDefaultIEW<Impl>::updateStatus(){    bool any_unblocking = false;    std::list<unsigned>::iterator threads = activeThreads->begin();    std::list<unsigned>::iterator end = activeThreads->end();    while (threads != end) {        unsigned tid = *threads++;        if (dispatchStatus[tid] == Unblocking) {            any_unblocking = true;            break;        }    }    // If there are no ready instructions waiting to be scheduled by the IQ,    // and there's no stores waiting to write back, and dispatch is not    // unblocking, then there is no internal activity for the IEW stage.    if (_status == Active && !instQueue.hasReadyInsts() &&        !ldstQueue.willWB() && !any_unblocking) {        DPRINTF(IEW, "IEW switching to idle\n");        deactivateStage();        _status = Inactive;    } else if (_status == Inactive && (instQueue.hasReadyInsts() ||                                       ldstQueue.willWB() ||                                       any_unblocking)) {        // Otherwise there is internal activity.  Set to active.        DPRINTF(IEW, "IEW switching to active\n");        activateStage();        _status = Active;    }}template <class Impl>voidDefaultIEW<Impl>::resetEntries(){    instQueue.resetEntries();    ldstQueue.resetEntries();}template <class Impl>voidDefaultIEW<Impl>::readStallSignals(unsigned tid){    if (fromCommit->commitBlock[tid]) {        stalls[tid].commit = true;    }    if (fromCommit->commitUnblock[tid]) {        assert(stalls[tid].commit);        stalls[tid].commit = false;    }}template <class Impl>boolDefaultIEW<Impl>::checkStall(unsigned tid){    bool ret_val(false);    if (stalls[tid].commit) {        DPRINTF(IEW,"[tid:%i]: Stall from Commit stage detected.\n",tid);        ret_val = true;    } else if (instQueue.isFull(tid)) {        DPRINTF(IEW,"[tid:%i]: Stall: IQ  is full.\n",tid);        ret_val = true;    } else if (ldstQueue.isFull(tid)) {        DPRINTF(IEW,"[tid:%i]: Stall: LSQ is full\n",tid);        if (ldstQueue.numLoads(tid) > 0 ) {            DPRINTF(IEW,"[tid:%i]: LSQ oldest load: [sn:%i] \n",                    tid,ldstQueue.getLoadHeadSeqNum(tid));        }        if (ldstQueue.numStores(tid) > 0) {            DPRINTF(IEW,"[tid:%i]: LSQ oldest store: [sn:%i] \n",                    tid,ldstQueue.getStoreHeadSeqNum(tid));        }        ret_val = true;    } else if (ldstQueue.isStalled(tid)) {        DPRINTF(IEW,"[tid:%i]: Stall: LSQ stall detected.\n",tid);        ret_val = true;    }    return ret_val;}template <class Impl>voidDefaultIEW<Impl>::checkSignalsAndUpdate(unsigned tid){    // Check if there's a squash signal, squash if there is    // Check stall signals, block if there is.    // If status was Blocked    //     if so then go to unblocking    // If status was Squashing    //     check if squashing is not high.  Switch to running this cycle.    readStallSignals(tid);    if (fromCommit->commitInfo[tid].squash) {        squash(tid);        if (dispatchStatus[tid] == Blocked ||            dispatchStatus[tid] == Unblocking) {            toRename->iewUnblock[tid] = true;            wroteToTimeBuffer = true;        }        dispatchStatus[tid] = Squashing;        fetchRedirect[tid] = false;        return;    }    if (fromCommit->commitInfo[tid].robSquashing) {        DPRINTF(IEW, "[tid:%i]: ROB is still squashing.\n", tid);        dispatchStatus[tid] = Squashing;        emptyRenameInsts(tid);

⌨️ 快捷键说明

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