rename_impl.hh

来自「linux下基于c++的处理器仿真平台。具有处理器流水线」· HH 代码 · 共 758 行 · 第 1/2 页

HH
758
字号
template <class Impl>inline voidSimpleRename<Impl>::renameDestRegs(DynInstPtr &inst){    typename SimpleRenameMap::RenameInfo rename_result;    unsigned num_dest_regs = inst->numDestRegs();        // If it's an instruction with no destination registers, then put    // a placeholder within the history buffer.  It might be better    // to not put it in the history buffer at all (other than branches,    // which always need at least a place holder), and differentiate    // between instructions with and without destination registers    // when getting from commit the instructions that committed.    if (num_dest_regs == 0) {        RenameHistory hb_entry(inst->seqNum);                historyBuffer.push_front(hb_entry);                DPRINTF(Rename, "Rename: Adding placeholder instruction to "                "history buffer, sequence number %lli.\n",                 inst->seqNum);        ++renameHBPlaceHolders;    } else {        // Rename the destination registers.        for (int dest_idx = 0; dest_idx < num_dest_regs; dest_idx++)        {            RegIndex dest_reg = inst->destRegIdx(dest_idx);                    // Get the physical register that the destination will be            // renamed to.            rename_result = renameMap->rename(dest_reg);            DPRINTF(Rename, "Rename: Renaming arch reg %i to physical "                    "reg %i.\n", (int)dest_reg,                     (int)rename_result.first);                    // Record the rename information so that a history can be kept.            RenameHistory hb_entry(inst->seqNum, dest_reg,                                    rename_result.first,                                   rename_result.second);                    historyBuffer.push_front(hb_entry);                    DPRINTF(Rename, "Rename: Adding instruction to history buffer, "                    "sequence number %lli.\n",                     (*historyBuffer.begin()).instSeqNum);                    // Tell the instruction to rename the appropriate destination            // register (dest_idx) to the new physical register             // (rename_result.first), and record the previous physical            // register that the same logical register was renamed to            // (rename_result.second).            inst->renameDestReg(dest_idx,                                 rename_result.first,                                 rename_result.second);            ++renameRenamedOperands;        }    }}template <class Impl>inline intSimpleRename<Impl>::calcFreeROBEntries(){     return fromCommit->commitInfo.freeROBEntries -         renameWidth * iewToRenameDelay; }template <class Impl>inline intSimpleRename<Impl>::calcFreeIQEntries(){    return fromIEW->iewInfo.freeIQEntries - renameWidth * iewToRenameDelay;}template<class Impl>voidSimpleRename<Impl>::tick(){    // Rename will need to try to rename as many instructions as it    // has bandwidth, unless it is blocked.    // Check if _status is BarrierStall.  If so, then check if the number    // of free ROB entries is equal to the number of total ROB entries.    // Once equal then wake this stage up.  Set status to unblocking maybe.    if (_status != Blocked && _status != Squashing) {        DPRINTF(Rename, "Rename: Status is not blocked, will attempt to "                        "run stage.\n");        // Make sure that the skid buffer has something in it if the        // status is unblocking.        assert(_status == Unblocking ? !skidBuffer.empty() : 1);        rename();                // If the status was unblocking, then instructions from the skid        // buffer were used.  Remove those instructions and handle        // the rest of unblocking.        if (_status == Unblocking) {            ++renameUnblockCycles;            if (fromDecode->size > 0) {                // Add the current inputs onto the skid buffer, so they can be                // reprocessed when this stage unblocks.                skidBuffer.push(*fromDecode);            }            unblock();        }    } else if (_status == Blocked) {        ++renameBlockCycles;        // If stage is blocked and still receiving valid instructions,        // make sure to store them in the skid buffer.        if (fromDecode->size > 0) {            block();            // Continue to tell previous stage to stall.            toDecode->renameInfo.stall = true;        }        if (!fromIEW->iewInfo.stall &&            !fromCommit->commitInfo.stall &&            calcFreeROBEntries() > 0 &&            calcFreeIQEntries() > 0 &&            renameMap->numFreeEntries() > 0) {                        // Need to be sure to check all blocking conditions above.            // If they have cleared, then start unblocking.            DPRINTF(Rename, "Rename: Stall signals cleared, going to "                    "unblock.\n");            _status = Unblocking;            // Continue to tell previous stage to block until this stage            // is done unblocking.            toDecode->renameInfo.stall = true;        } else {            // Otherwise no conditions have changed.  Tell previous            // stage to continue blocking.            toDecode->renameInfo.stall = true;        }        if (fromCommit->commitInfo.squash ||            fromCommit->commitInfo.robSquashing) {            squash();            return;        }    } else if (_status == Squashing) {        ++renameSquashCycles;        if (fromCommit->commitInfo.squash) {            squash();        } else if (!fromCommit->commitInfo.squash &&                   !fromCommit->commitInfo.robSquashing) {            DPRINTF(Rename, "Rename: Done squashing, going to running.\n");            _status = Running;            rename();        } else {            doSquash();        }    }    // Ugly code, revamp all of the tick() functions eventually.    if (fromCommit->commitInfo.doneSeqNum != 0 && _status != Squashing) {#if !FULL_SYSTEM        if (!fromCommit->commitInfo.squash) {            removeFromHistory(fromCommit->commitInfo.doneSeqNum);        }#else        removeFromHistory(fromCommit->commitInfo.doneSeqNum);#endif    }}template<class Impl>voidSimpleRename<Impl>::rename(){    // Check if any of the stages ahead of rename are telling rename    // to squash.  The squash() function will also take care of fixing up    // the rename map and the free list.    if (fromCommit->commitInfo.squash ||        fromCommit->commitInfo.robSquashing) {        DPRINTF(Rename, "Rename: Receiving signal from Commit to squash.\n");        squash();        return;    }    // Check if time buffer is telling this stage to stall.    if (fromIEW->iewInfo.stall ||        fromCommit->commitInfo.stall) {        DPRINTF(Rename, "Rename: Receiving signal from IEW/Commit to "                        "stall.\n");      	block();        return;    }    // Check if the current status is squashing.  If so, set its status    // to running and resume execution the next cycle.    if (_status == Squashing) {        DPRINTF(Rename, "Rename: Done squashing.\n");        _status = Running;        return;    }    // Check the decode queue to see if instructions are available.    // If there are no available instructions to rename, then do nothing.    // Or, if the stage is currently unblocking, then go ahead and run it.    if (fromDecode->size == 0 && _status != Unblocking) {        DPRINTF(Rename, "Rename: Nothing to do, breaking out early.\n");        // Should I change status to idle?        return;    }    ////////////////////////////////////    // Actual rename part.    ////////////////////////////////////        DynInstPtr inst;        // If we're unblocking, then we may be in the middle of an instruction    // group.  Subtract off numInst to get the proper number of instructions    // left.    int insts_available = _status == Unblocking ?         skidBuffer.front().size - numInst :        fromDecode->size;    bool block_this_cycle = false;    // Will have to do a different calculation for the number of free    // entries.  Number of free entries recorded on this cycle -     // renameWidth * renameToDecodeDelay    int free_rob_entries = calcFreeROBEntries();    int free_iq_entries = calcFreeIQEntries();    int min_iq_rob = min(free_rob_entries, free_iq_entries);    unsigned to_iew_index = 0;    // Check if there's any space left.    if (min_iq_rob <= 0) {        DPRINTF(Rename, "Rename: Blocking due to no free ROB or IQ "                "entries.\n"                "Rename: ROB has %d free entries.\n"                "Rename: IQ has %d free entries.\n",                 free_rob_entries,                free_iq_entries);        block();        // Tell previous stage to stall.        toDecode->renameInfo.stall = true;        if (free_rob_entries <= 0) {            ++renameROBFullEvents;        } else {            ++renameIQFullEvents;        }                return;    } else if (min_iq_rob < insts_available) {        DPRINTF(Rename, "Rename: Will have to block this cycle.  Only "                "%i insts can be renamed due to IQ/ROB limits.\n",                min_iq_rob);        insts_available = min_iq_rob;        block_this_cycle = true;        if (free_rob_entries < free_iq_entries) {            ++renameROBFullEvents;        } else {            ++renameIQFullEvents;        }    }        while (insts_available > 0) {        DPRINTF(Rename, "Rename: Sending instructions to iew.\n");        // Get the next instruction either from the skid buffer or the        // decode queue.        inst = _status == Unblocking ? skidBuffer.front().insts[numInst] :                fromDecode->insts[numInst];        if (inst->isSquashed()) {            DPRINTF(Rename, "Rename: instruction %i with PC %#x is "                    "squashed, skipping.\n",                    inst->seqNum, inst->readPC());            // Go to the next instruction.            ++numInst;            ++renameSquashedInsts;                        // Decrement how many instructions are available.            --insts_available;            continue;        }                    DPRINTF(Rename, "Rename: Processing instruction %i with PC %#x.\n",                inst->seqNum, inst->readPC());        // If it's a trap instruction, then it needs to wait here within        // rename until the ROB is empty.  Needs a way to detect that the        // ROB is empty.  Maybe an event?        // Would be nice if it could be avoided putting this into a        // specific stage and instead just put it into the AlphaFullCPU.        // Might not really be feasible though...        // (EXCB, TRAPB)        if (inst->isSerializing()) {            panic("Rename: Serializing instruction encountered.\n");            DPRINTF(Rename, "Rename: Serializing instruction "                            "encountered.\n");                        // Change status over to BarrierStall so that other stages know            // what this is blocked on.            _status = BarrierStall;            block_this_cycle = true;            break;        }        // Check here to make sure there are enough destination registers        // to rename to.  Otherwise block.        if (renameMap->numFreeEntries() < inst->numDestRegs())        {            DPRINTF(Rename, "Rename: Blocking due to lack of free "                            "physical registers to rename to.\n");            // Need some sort of event based on a register being freed.            block_this_cycle = true;            ++renameFullRegistersEvents;            break;        }        renameSrcRegs(inst);        renameDestRegs(inst);        // Put instruction in rename queue.        toIEW->insts[to_iew_index] = inst;        ++(toIEW->size);        // Decrease the number of free ROB and IQ entries.        --free_rob_entries;        --free_iq_entries;                // Increment which instruction we're on.        ++to_iew_index;        ++numInst;        ++renameRenamedInsts;        // Decrement how many instructions are available.        --insts_available;    }    // Check if there's any instructions left that haven't yet been renamed.    // If so then block.    if (block_this_cycle) {        block();        toDecode->renameInfo.stall = true;    } else {        // If we had a successful rename and didn't have to exit early, then        // reset numInst so it will refer to the correct instruction on next        // run.        numInst = 0;    }}

⌨️ 快捷键说明

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