rename_impl.hh

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

HH
1,362
字号
        if (resumeUnblocking) {            block(tid);            resumeUnblocking = false;            toDecode->renameUnblock[tid] = false;        }    }    if (renameStatus[tid] == Running ||        renameStatus[tid] == Idle) {        DPRINTF(Rename, "[tid:%u]: Not blocked, so attempting to run "                "stage.\n", tid);        renameInsts(tid);    } else if (renameStatus[tid] == Unblocking) {        renameInsts(tid);        if (validInsts()) {            // Add the current inputs to the skid buffer so they can be            // reprocessed when this stage unblocks.            skidInsert(tid);        }        // If we switched over to blocking, then there's a potential for        // an overall status change.        status_change = unblock(tid) || status_change || blockThisCycle;    }}template <class Impl>voidDefaultRename<Impl>::renameInsts(unsigned tid){    // Instructions can be either in the skid buffer or the queue of    // instructions coming from decode, depending on the status.    int insts_available = renameStatus[tid] == Unblocking ?        skidBuffer[tid].size() : insts[tid].size();    // Check the decode queue to see if instructions are available.    // If there are no available instructions to rename, then do nothing.    if (insts_available == 0) {        DPRINTF(Rename, "[tid:%u]: Nothing to do, breaking out early.\n",                tid);        // Should I change status to idle?        ++renameIdleCycles;        return;    } else if (renameStatus[tid] == Unblocking) {        ++renameUnblockCycles;    } else if (renameStatus[tid] == Running) {        ++renameRunCycles;    }    DynInstPtr inst;    // Will have to do a different calculation for the number of free    // entries.    int free_rob_entries = calcFreeROBEntries(tid);    int free_iq_entries  = calcFreeIQEntries(tid);    int free_lsq_entries = calcFreeLSQEntries(tid);    int min_free_entries = free_rob_entries;    FullSource source = ROB;    if (free_iq_entries < min_free_entries) {        min_free_entries = free_iq_entries;        source = IQ;    }    if (free_lsq_entries < min_free_entries) {        min_free_entries = free_lsq_entries;        source = LSQ;    }    // Check if there's any space left.    if (min_free_entries <= 0) {        DPRINTF(Rename, "[tid:%u]: Blocking due to no free ROB/IQ/LSQ "                "entries.\n"                "ROB has %i free entries.\n"                "IQ has %i free entries.\n"                "LSQ has %i free entries.\n",                tid,                free_rob_entries,                free_iq_entries,                free_lsq_entries);        blockThisCycle = true;        block(tid);        incrFullStat(source);        return;    } else if (min_free_entries < insts_available) {        DPRINTF(Rename, "[tid:%u]: Will have to block this cycle."                "%i insts available, but only %i insts can be "                "renamed due to ROB/IQ/LSQ limits.\n",                tid, insts_available, min_free_entries);        insts_available = min_free_entries;        blockThisCycle = true;        incrFullStat(source);    }    InstQueue &insts_to_rename = renameStatus[tid] == Unblocking ?        skidBuffer[tid] : insts[tid];    DPRINTF(Rename, "[tid:%u]: %i available instructions to "            "send iew.\n", tid, insts_available);    DPRINTF(Rename, "[tid:%u]: %i insts pipelining from Rename | %i insts "            "dispatched to IQ last cycle.\n",            tid, instsInProgress[tid], fromIEW->iewInfo[tid].dispatched);    // Handle serializing the next instruction if necessary.    if (serializeOnNextInst[tid]) {        if (emptyROB[tid] && instsInProgress[tid] == 0) {            // ROB already empty; no need to serialize.            serializeOnNextInst[tid] = false;        } else if (!insts_to_rename.empty()) {            insts_to_rename.front()->setSerializeBefore();        }    }    int renamed_insts = 0;    while (insts_available > 0 &&  toIEWIndex < renameWidth) {        DPRINTF(Rename, "[tid:%u]: Sending instructions to IEW.\n", tid);        assert(!insts_to_rename.empty());        inst = insts_to_rename.front();        insts_to_rename.pop_front();        if (renameStatus[tid] == Unblocking) {            DPRINTF(Rename,"[tid:%u]: Removing [sn:%lli] PC:%#x from rename "                    "skidBuffer\n",                    tid, inst->seqNum, inst->readPC());        }        if (inst->isSquashed()) {            DPRINTF(Rename, "[tid:%u]: instruction %i with PC %#x is "                    "squashed, skipping.\n",                    tid, inst->seqNum, inst->readPC());            ++renameSquashedInsts;            // Decrement how many instructions are available.            --insts_available;            continue;        }        DPRINTF(Rename, "[tid:%u]: Processing instruction [sn:%lli] with "                "PC %#x.\n",                tid, inst->seqNum, inst->readPC());        // Handle serializeAfter/serializeBefore instructions.        // serializeAfter marks the next instruction as serializeBefore.        // serializeBefore makes the instruction wait in rename until the ROB        // is empty.        // In this model, IPR accesses are serialize before        // instructions, and store conditionals are serialize after        // instructions.  This is mainly due to lack of support for        // out-of-order operations of either of those classes of        // instructions.        if ((inst->isIprAccess() || inst->isSerializeBefore()) &&            !inst->isSerializeHandled()) {            DPRINTF(Rename, "Serialize before instruction encountered.\n");            if (!inst->isTempSerializeBefore()) {                renamedSerializing++;                inst->setSerializeHandled();            } else {                renamedTempSerializing++;            }            // Change status over to SerializeStall so that other stages know            // what this is blocked on.            renameStatus[tid] = SerializeStall;            serializeInst[tid] = inst;            blockThisCycle = true;            break;        } else if ((inst->isStoreConditional() || inst->isSerializeAfter()) &&                   !inst->isSerializeHandled()) {            DPRINTF(Rename, "Serialize after instruction encountered.\n");            renamedSerializing++;            inst->setSerializeHandled();            serializeAfter(insts_to_rename, tid);        }        // Check here to make sure there are enough destination registers        // to rename to.  Otherwise block.        if (renameMap[tid]->numFreeEntries() < inst->numDestRegs()) {            DPRINTF(Rename, "Blocking due to lack of free "                    "physical registers to rename to.\n");            blockThisCycle = true;            insts_to_rename.push_front(inst);            ++renameFullRegistersEvents;            break;        }        renameSrcRegs(inst, inst->threadNumber);        renameDestRegs(inst, inst->threadNumber);        ++renamed_insts;        // Put instruction in rename queue.        toIEW->insts[toIEWIndex] = inst;        ++(toIEW->size);        // Increment which instruction we're on.        ++toIEWIndex;        // Decrement how many instructions are available.        --insts_available;    }    instsInProgress[tid] += renamed_insts;    renameRenamedInsts += renamed_insts;    // If we wrote to the time buffer, record this.    if (toIEWIndex) {        wroteToTimeBuffer = true;    }    // Check if there's any instructions left that haven't yet been renamed.    // If so then block.    if (insts_available) {        blockThisCycle = true;    }    if (blockThisCycle) {        block(tid);        toDecode->renameUnblock[tid] = false;    }}template<class Impl>voidDefaultRename<Impl>::skidInsert(unsigned tid){    DynInstPtr inst = NULL;    while (!insts[tid].empty()) {        inst = insts[tid].front();        insts[tid].pop_front();        assert(tid == inst->threadNumber);        DPRINTF(Rename, "[tid:%u]: Inserting [sn:%lli] PC:%#x into Rename "                "skidBuffer\n", tid, inst->seqNum, inst->readPC());        ++renameSkidInsts;        skidBuffer[tid].push_back(inst);    }    if (skidBuffer[tid].size() > skidBufferMax)    {        typename InstQueue::iterator it;        warn("Skidbuffer contents:\n");        for(it = skidBuffer[tid].begin(); it != skidBuffer[tid].end(); it++)        {            warn("[tid:%u]: %s [sn:%i].\n", tid,                    (*it)->staticInst->disassemble(inst->readPC()),                    (*it)->seqNum);        }        panic("Skidbuffer Exceeded Max Size");    }}template <class Impl>voidDefaultRename<Impl>::sortInsts(){    int insts_from_decode = fromDecode->size;#ifdef DEBUG    for (int i=0; i < numThreads; i++)        assert(insts[i].empty());#endif    for (int i = 0; i < insts_from_decode; ++i) {        DynInstPtr inst = fromDecode->insts[i];        insts[inst->threadNumber].push_back(inst);    }}template<class Impl>boolDefaultRename<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>voidDefaultRename<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 (renameStatus[tid] == Unblocking) {            any_unblocking = true;            break;        }    }    // Rename will have activity if it's unblocking.    if (any_unblocking) {        if (_status == Inactive) {            _status = Active;            DPRINTF(Activity, "Activating stage.\n");            cpu->activateStage(O3CPU::RenameIdx);        }    } else {        // If it's not unblocking, then rename will not have any internal        // activity.  Switch it to inactive.        if (_status == Active) {            _status = Inactive;            DPRINTF(Activity, "Deactivating stage.\n");            cpu->deactivateStage(O3CPU::RenameIdx);        }    }}template <class Impl>boolDefaultRename<Impl>::block(unsigned tid){    DPRINTF(Rename, "[tid:%u]: Blocking.\n", tid);    // Add the current inputs onto the skid buffer, so they can be    // reprocessed when this stage unblocks.    skidInsert(tid);    // Only signal backwards to block if the previous stages do not think    // rename is already blocked.    if (renameStatus[tid] != Blocked) {        // If resumeUnblocking is set, we unblocked during the squash,        // but now we're have unblocking status. We need to tell earlier        // stages to block.        if (resumeUnblocking || renameStatus[tid] != Unblocking) {            toDecode->renameBlock[tid] = true;            toDecode->renameUnblock[tid] = false;            wroteToTimeBuffer = true;        }        // Rename can not go from SerializeStall to Blocked, otherwise        // it would not know to complete the serialize stall.        if (renameStatus[tid] != SerializeStall) {            // Set status to Blocked.            renameStatus[tid] = Blocked;            return true;        }    }    return false;}template <class Impl>boolDefaultRename<Impl>::unblock(unsigned tid){    DPRINTF(Rename, "[tid:%u]: Trying to unblock.\n", tid);    // Rename is done unblocking if the skid buffer is empty.    if (skidBuffer[tid].empty() && renameStatus[tid] != SerializeStall) {        DPRINTF(Rename, "[tid:%u]: Done unblocking.\n", tid);        toDecode->renameUnblock[tid] = true;        wroteToTimeBuffer = true;        renameStatus[tid] = Running;        return true;    }    return false;}template <class Impl>voidDefaultRename<Impl>::doSquash(const InstSeqNum &squashed_seq_num, unsigned tid){    typename std::list<RenameHistory>::iterator hb_it =        historyBuffer[tid].begin();    // After a syscall squashes everything, the history buffer may be empty    // but the ROB may still be squashing instructions.    if (historyBuffer[tid].empty()) {        return;    }    // Go through the most recent instructions, undoing the mappings    // they did and freeing up the registers.    while (!historyBuffer[tid].empty() &&           (*hb_it).instSeqNum > squashed_seq_num) {        assert(hb_it != historyBuffer[tid].end());        DPRINTF(Rename, "[tid:%u]: Removing history entry with sequence "                "number %i.\n", tid, (*hb_it).instSeqNum);        // Tell the rename map to set the architected register to the        // previous physical register that it was renamed to.        renameMap[tid]->setEntry(hb_it->archReg, hb_it->prevPhysReg);        // Put the renamed physical register back on the free list.        freeList->addReg(hb_it->newPhysReg);        // Be sure to mark its register as ready if it's a misc register.        if (hb_it->newPhysReg >= maxPhysicalRegs) {            scoreboard->setReg(hb_it->newPhysReg);        }        historyBuffer[tid].erase(hb_it++);        ++renameUndoneMaps;    }}template<class Impl>voidDefaultRename<Impl>::removeFromHistory(InstSeqNum inst_seq_num, unsigned tid){    DPRINTF(Rename, "[tid:%u]: Removing a committed instruction from the "

⌨️ 快捷键说明

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