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 + -
显示快捷键?