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