inst_queue_impl.hh
来自「linux下基于c++的处理器仿真平台。具有处理器流水线」· HH 代码 · 共 1,139 行 · 第 1/3 页
HH
1,139 行
// Squash any instructions younger than the squashed sequence number // given. while ((*squashIt)->seqNum > squashedSeqNum) { DynInstPtr squashed_inst = (*squashIt); // Only handle the instruction if it actually is in the IQ and // hasn't already been squashed in the IQ. if (!squashed_inst->isIssued() && !squashed_inst->isSquashedInIQ()) { // Remove the instruction from the dependency list. // Hack for now: These below don't add themselves to the // dependency list, so don't try to remove them. if (!squashed_inst->isNonSpeculative()/* && !squashed_inst->isStore()*/ ) { for (int src_reg_idx = 0; src_reg_idx < squashed_inst->numSrcRegs(); src_reg_idx++) { PhysRegIndex src_reg = squashed_inst->renamedSrcRegIdx(src_reg_idx); // Only remove it from the dependency graph if it was // placed there in the first place. // HACK: This assumes that instructions woken up from the // dependency chain aren't informed that a specific src // register has become ready. This may not always be true // in the future. if (!squashed_inst->isReadySrcRegIdx(src_reg_idx) && src_reg < numPhysRegs) { dependGraph[src_reg].remove(squashed_inst); } ++iqSquashedOperandsExamined; } // Might want to remove producers as well. } else { nonSpecInsts[squashed_inst->seqNum] = NULL; nonSpecInsts.erase(squashed_inst->seqNum); ++iqSquashedNonSpecRemoved; } // Might want to also clear out the head of the dependency graph. // Mark it as squashed within the IQ. squashed_inst->setSquashedInIQ();// squashedInsts.push(squashed_inst); squashed_inst->setIssued(); squashed_inst->setCanCommit(); ++freeEntries; DPRINTF(IQ, "IQ: Instruction PC %#x squashed.\n", squashed_inst->readPC()); } --squashIt; ++iqSquashedInstsExamined; } assert(freeEntries <= numEntries); if (freeEntries == numEntries) { tail = cpu->instList.end(); }}template <class Impl>voidInstructionQueue<Impl>::stopSquash(){ // Clear up the squash variables to ensure that squashing doesn't // get called improperly. squashedSeqNum = 0; squashIt = cpu->instList.end();}template <class Impl>voidInstructionQueue<Impl>::DependencyEntry::insert(DynInstPtr &new_inst){ //Add this new, dependent instruction at the head of the dependency //chain. // First create the entry that will be added to the head of the // dependency chain. DependencyEntry *new_entry = new DependencyEntry; new_entry->next = this->next; new_entry->inst = new_inst; // Then actually add it to the chain. this->next = new_entry; ++mem_alloc_counter;}template <class Impl>voidInstructionQueue<Impl>::DependencyEntry::remove(DynInstPtr &inst_to_remove){ DependencyEntry *prev = this; DependencyEntry *curr = this->next; // Make sure curr isn't NULL. Because this instruction is being // removed from a dependency list, it must have been placed there at // an earlier time. The dependency chain should not be empty, // unless the instruction dependent upon it is already ready. if (curr == NULL) { return; } // Find the instruction to remove within the dependency linked list. while(curr->inst != inst_to_remove) { prev = curr; curr = curr->next; assert(curr != NULL); } // Now remove this instruction from the list. prev->next = curr->next; --mem_alloc_counter; // Could push this off to the destructor of DependencyEntry curr->inst = NULL; delete curr;}template <class Impl>boolInstructionQueue<Impl>::addToDependents(DynInstPtr &new_inst){ // Loop through the instruction's source registers, adding // them to the dependency list if they are not ready. int8_t total_src_regs = new_inst->numSrcRegs(); bool return_val = false; for (int src_reg_idx = 0; src_reg_idx < total_src_regs; src_reg_idx++) { // Only add it to the dependency graph if it's not ready. if (!new_inst->isReadySrcRegIdx(src_reg_idx)) { PhysRegIndex src_reg = new_inst->renamedSrcRegIdx(src_reg_idx); // Check the IQ's scoreboard to make sure the register // hasn't become ready while the instruction was in flight // between stages. Only if it really isn't ready should // it be added to the dependency graph. if (src_reg >= numPhysRegs) { continue; } else if (regScoreboard[src_reg] == false) { DPRINTF(IQ, "IQ: Instruction PC %#x has src reg %i that " "is being added to the dependency chain.\n", new_inst->readPC(), src_reg); dependGraph[src_reg].insert(new_inst); // Change the return value to indicate that something // was added to the dependency graph. return_val = true; } else { DPRINTF(IQ, "IQ: Instruction PC %#x has src reg %i that " "became ready before it reached the IQ.\n", new_inst->readPC(), src_reg); // Mark a register ready within the instruction. new_inst->markSrcRegReady(); } } } return return_val;}template <class Impl>voidInstructionQueue<Impl>::createDependency(DynInstPtr &new_inst){ //Actually nothing really needs to be marked when an //instruction becomes the producer of a register's value, //but for convenience a ptr to the producing instruction will //be placed in the head node of the dependency links. int8_t total_dest_regs = new_inst->numDestRegs(); for (int dest_reg_idx = 0; dest_reg_idx < total_dest_regs; dest_reg_idx++) { PhysRegIndex dest_reg = new_inst->renamedDestRegIdx(dest_reg_idx); // Instructions that use the misc regs will have a reg number // higher than the normal physical registers. In this case these // registers are not renamed, and there is no need to track // dependencies as these instructions must be executed at commit. if (dest_reg >= numPhysRegs) { continue; } dependGraph[dest_reg].inst = new_inst; if (dependGraph[dest_reg].next) { dumpDependGraph(); panic("IQ: Dependency graph not empty!"); } // Mark the scoreboard to say it's not yet ready. regScoreboard[dest_reg] = false; }}template <class Impl>voidInstructionQueue<Impl>::addIfReady(DynInstPtr &inst){ //If the instruction now has all of its source registers // available, then add it to the list of ready instructions. if (inst->readyToIssue()) { //Add the instruction to the proper ready list. if (inst->isControl()) { DPRINTF(IQ, "IQ: Branch instruction is ready to issue, " "putting it onto the ready list, PC %#x.\n", inst->readPC()); readyBranchInsts.push(inst); } else if (inst->isMemRef()) { DPRINTF(IQ, "IQ: Checking if memory instruction can issue.\n"); // Message to the mem dependence unit that this instruction has // its registers ready. memDepUnit.regsReady(inst);#if 0 if (memDepUnit.readyToIssue(inst)) { DPRINTF(IQ, "IQ: Memory instruction is ready to issue, " "putting it onto the ready list, PC %#x.\n", inst->readPC()); readyMemInsts.push(inst); } else { // Make dependent on the store. // Will need some way to get the store instruction it should // be dependent upon; then when the store issues it can // put the instruction on the ready list. // Yet another tree? assert(0 && "Instruction has no way to actually issue"); }#endif } else if (inst->isInteger()) { DPRINTF(IQ, "IQ: Integer instruction is ready to issue, " "putting it onto the ready list, PC %#x.\n", inst->readPC()); readyIntInsts.push(inst); } else if (inst->isFloating()) { DPRINTF(IQ, "IQ: Floating instruction is ready to issue, " "putting it onto the ready list, PC %#x.\n", inst->readPC()); readyFloatInsts.push(inst); } else { DPRINTF(IQ, "IQ: Miscellaneous instruction is ready to issue, " "putting it onto the ready list, PC %#x..\n", inst->readPC()); readyMiscInsts.push(inst); } }}/* * Caution, this function must not be called prior to tail being updated at * least once, otherwise it will fail the assertion. This is because * instList.begin() actually changes upon the insertion of an element into the * list when the list is empty. */template <class Impl>intInstructionQueue<Impl>::countInsts(){ ListIt count_it = cpu->instList.begin(); int total_insts = 0; if (tail == cpu->instList.end()) return 0; while (count_it != tail) { if (!(*count_it)->isIssued()) { ++total_insts; } ++count_it; assert(count_it != cpu->instList.end()); } // Need to count the tail iterator as well. if (count_it != cpu->instList.end() && (*count_it) && !(*count_it)->isIssued()) { ++total_insts; } return total_insts;}template <class Impl>voidInstructionQueue<Impl>::dumpDependGraph(){ DependencyEntry *curr; for (int i = 0; i < numPhysRegs; ++i) { curr = &dependGraph[i]; if (curr->inst) { cprintf("dependGraph[%i]: producer: %#x consumer: ", i, curr->inst->readPC()); } else { cprintf("dependGraph[%i]: No producer. consumer: ", i); } while (curr->next != NULL) { curr = curr->next; cprintf("%#x ", curr->inst->readPC()); } cprintf("\n"); }}template <class Impl>voidInstructionQueue<Impl>::dumpLists(){ cprintf("Ready integer list size: %i\n", readyIntInsts.size()); cprintf("Ready float list size: %i\n", readyFloatInsts.size()); cprintf("Ready branch list size: %i\n", readyBranchInsts.size()); cprintf("Ready misc list size: %i\n", readyMiscInsts.size()); cprintf("Squashed list size: %i\n", squashedInsts.size()); cprintf("Non speculative list size: %i\n", nonSpecInsts.size()); non_spec_it_t non_spec_it = nonSpecInsts.begin(); cprintf("Non speculative list: "); while (non_spec_it != nonSpecInsts.end()) { cprintf("%#x ", (*non_spec_it).second->readPC()); ++non_spec_it; } cprintf("\n");}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?