inst_queue_impl.hh
来自「linux下基于c++的处理器仿真平台。具有处理器流水线」· HH 代码 · 共 1,139 行 · 第 1/3 页
HH
1,139 行
template <class Impl>voidInstructionQueue<Impl>::scheduleReadyInsts(){ DPRINTF(IQ, "IQ: Attempting to schedule ready instructions from " "the IQ.\n"); int int_issued = 0; int float_issued = 0; int branch_issued = 0; int memory_issued = 0; int squashed_issued = 0; int total_issued = 0; IssueStruct *i2e_info = issueToExecuteQueue->access(0); bool insts_available = !readyBranchInsts.empty() || !readyIntInsts.empty() || !readyFloatInsts.empty() || !memDepUnit.empty() || !readyMiscInsts.empty() || !squashedInsts.empty(); // Note: Requires a globally defined constant. InstSeqNum oldest_inst = MaxInstSeqNum; InstList list_with_oldest = None; // Temporary values. DynInstPtr int_head_inst; DynInstPtr float_head_inst; DynInstPtr branch_head_inst; DynInstPtr mem_head_inst; DynInstPtr misc_head_inst; DynInstPtr squashed_head_inst; // Somewhat nasty code to look at all of the lists where issuable // instructions are located, and choose the oldest instruction among // those lists. Consider a rewrite in the future. while (insts_available && total_issued < totalWidth) { // Set this to false. Each if-block is required to set it to true // if there were instructions available this check. This will cause // this loop to run once more than necessary, but avoids extra calls. insts_available = false; oldest_inst = MaxInstSeqNum; list_with_oldest = None; if (!readyIntInsts.empty() && int_issued < intWidth) { insts_available = true; int_head_inst = readyIntInsts.top(); if (int_head_inst->isSquashed()) { readyIntInsts.pop(); ++iqLoopSquashStalls; continue; } oldest_inst = int_head_inst->seqNum; list_with_oldest = Int; } if (!readyFloatInsts.empty() && float_issued < floatWidth) { insts_available = true; float_head_inst = readyFloatInsts.top(); if (float_head_inst->isSquashed()) { readyFloatInsts.pop(); ++iqLoopSquashStalls; continue; } else if (float_head_inst->seqNum < oldest_inst) { oldest_inst = float_head_inst->seqNum; list_with_oldest = Float; } } if (!readyBranchInsts.empty() && branch_issued < branchWidth) { insts_available = true; branch_head_inst = readyBranchInsts.top(); if (branch_head_inst->isSquashed()) { readyBranchInsts.pop(); ++iqLoopSquashStalls; continue; } else if (branch_head_inst->seqNum < oldest_inst) { oldest_inst = branch_head_inst->seqNum; list_with_oldest = Branch; } } if (!memDepUnit.empty() && memory_issued < memoryWidth) { insts_available = true; mem_head_inst = memDepUnit.top(); if (mem_head_inst->isSquashed()) { memDepUnit.pop(); ++iqLoopSquashStalls; continue; } else if (mem_head_inst->seqNum < oldest_inst) { oldest_inst = mem_head_inst->seqNum; list_with_oldest = Memory; } } if (!readyMiscInsts.empty()) { insts_available = true; misc_head_inst = readyMiscInsts.top(); if (misc_head_inst->isSquashed()) { readyMiscInsts.pop(); ++iqLoopSquashStalls; continue; } else if (misc_head_inst->seqNum < oldest_inst) { oldest_inst = misc_head_inst->seqNum; list_with_oldest = Misc; } } if (!squashedInsts.empty()) { insts_available = true; squashed_head_inst = squashedInsts.top(); if (squashed_head_inst->seqNum < oldest_inst) { list_with_oldest = Squashed; } } DynInstPtr issuing_inst = NULL; switch (list_with_oldest) { case None: DPRINTF(IQ, "IQ: Not able to schedule any instructions. Issuing " "inst is %#x.\n", issuing_inst); break; case Int: issuing_inst = int_head_inst; readyIntInsts.pop(); ++int_issued; DPRINTF(IQ, "IQ: Issuing integer instruction PC %#x.\n", issuing_inst->readPC()); break; case Float: issuing_inst = float_head_inst; readyFloatInsts.pop(); ++float_issued; DPRINTF(IQ, "IQ: Issuing float instruction PC %#x.\n", issuing_inst->readPC()); break; case Branch: issuing_inst = branch_head_inst; readyBranchInsts.pop(); ++branch_issued; DPRINTF(IQ, "IQ: Issuing branch instruction PC %#x.\n", issuing_inst->readPC()); break; case Memory: issuing_inst = mem_head_inst; memDepUnit.pop(); ++memory_issued; DPRINTF(IQ, "IQ: Issuing memory instruction PC %#x.\n", issuing_inst->readPC()); break; case Misc: issuing_inst = misc_head_inst; readyMiscInsts.pop(); ++iqMiscInstsIssued; DPRINTF(IQ, "IQ: Issuing a miscellaneous instruction PC %#x.\n", issuing_inst->readPC()); break; case Squashed: assert(0 && "Squashed insts should not issue any more!"); squashedInsts.pop(); // Set the squashed instruction as able to commit so that commit // can just drop it from the ROB. This is a bit faked. ++squashed_issued; ++freeEntries; DPRINTF(IQ, "IQ: Issuing squashed instruction PC %#x.\n", squashed_head_inst->readPC()); break; } if (list_with_oldest != None && list_with_oldest != Squashed) { i2e_info->insts[total_issued] = issuing_inst; i2e_info->size++; issuing_inst->setIssued(); ++freeEntries; ++total_issued; } assert(freeEntries == (numEntries - countInsts())); } iqIntInstsIssued += int_issued; iqFloatInstsIssued += float_issued; iqBranchInstsIssued += branch_issued; iqMemInstsIssued += memory_issued; iqSquashedInstsIssued += squashed_issued;}template <class Impl>void InstructionQueue<Impl>::scheduleNonSpec(const InstSeqNum &inst){ DPRINTF(IQ, "IQ: Marking nonspeculative instruction with sequence " "number %i as ready to execute.\n", inst); non_spec_it_t inst_it = nonSpecInsts.find(inst); assert(inst_it != nonSpecInsts.end()); // Mark this instruction as ready to issue. (*inst_it).second->setCanIssue(); // Now schedule the instruction. if (!(*inst_it).second->isMemRef()) { addIfReady((*inst_it).second); } else { memDepUnit.nonSpecInstReady((*inst_it).second); } nonSpecInsts.erase(inst_it);}template <class Impl>voidInstructionQueue<Impl>::wakeDependents(DynInstPtr &completed_inst){ DPRINTF(IQ, "IQ: Waking dependents of completed instruction.\n"); //Look at the physical destination register of the DynInst //and look it up on the dependency graph. Then mark as ready //any instructions within the instruction queue. DependencyEntry *curr; // Tell the memory dependence unit to wake any dependents on this // instruction if it is a memory instruction. if (completed_inst->isMemRef()) { memDepUnit.wakeDependents(completed_inst); } for (int dest_reg_idx = 0; dest_reg_idx < completed_inst->numDestRegs(); dest_reg_idx++) { PhysRegIndex dest_reg = completed_inst->renamedDestRegIdx(dest_reg_idx); // Special case of uniq or control registers. They are not // handled by the IQ and thus have no dependency graph entry. // @todo Figure out a cleaner way to handle this. if (dest_reg >= numPhysRegs) { continue; } DPRINTF(IQ, "IQ: Waking any dependents on register %i.\n", (int) dest_reg); //Maybe abstract this part into a function. //Go through the dependency chain, marking the registers as ready //within the waiting instructions. while (dependGraph[dest_reg].next) { curr = dependGraph[dest_reg].next; DPRINTF(IQ, "IQ: Waking up a dependent instruction, PC%#x.\n", curr->inst->readPC()); // Might want to give more information to the instruction // so that it knows which of its source registers is ready. // However that would mean that the dependency graph entries // would need to hold the src_reg_idx. curr->inst->markSrcRegReady(); addIfReady(curr->inst); dependGraph[dest_reg].next = curr->next; DependencyEntry::mem_alloc_counter--; curr->inst = NULL; delete curr; } // Reset the head node now that all of its dependents have been woken // up. dependGraph[dest_reg].next = NULL; dependGraph[dest_reg].inst = NULL; // Mark the scoreboard as having that register ready. regScoreboard[dest_reg] = true; }}template <class Impl>voidInstructionQueue<Impl>::violation(DynInstPtr &store, DynInstPtr &faulting_load){ memDepUnit.violation(store, faulting_load);}template <class Impl>voidInstructionQueue<Impl>::squash(){ DPRINTF(IQ, "IQ: Starting to squash instructions in the IQ.\n"); // Read instruction sequence number of last instruction out of the // time buffer. squashedSeqNum = fromCommit->commitInfo.doneSeqNum; // Setup the squash iterator to point to the tail. squashIt = tail; // Call doSquash if there are insts in the IQ if (freeEntries != numEntries) { doSquash(); } // Also tell the memory dependence unit to squash. memDepUnit.squash(squashedSeqNum);}template <class Impl>voidInstructionQueue<Impl>::doSquash(){ // Make sure the squash iterator isn't pointing to nothing. assert(squashIt != cpu->instList.end()); // Make sure the squashed sequence number is valid. assert(squashedSeqNum != 0); DPRINTF(IQ, "IQ: Squashing instructions in the IQ.\n");
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?