inst_queue_impl.hh

来自「M5,一个功能强大的多处理器系统模拟器.很多针对处理器架构,性能的研究都使用它作」· HH 代码 · 共 1,409 行 · 第 1/3 页

HH
1,409
字号
    readyInsts[op_class].push(ready_inst);    // Will need to reorder the list if either a queue is not on the list,    // or it has an older instruction than last time.    if (!queueOnList[op_class]) {        addToOrderList(op_class);    } else if (readyInsts[op_class].top()->seqNum  <               (*readyIt[op_class]).oldestInst) {        listOrder.erase(readyIt[op_class]);        addToOrderList(op_class);    }    DPRINTF(IQ, "Instruction is ready to issue, putting it onto "            "the ready list, PC %#x opclass:%i [sn:%lli].\n",            ready_inst->readPC(), op_class, ready_inst->seqNum);}template <class Impl>voidInstructionQueue<Impl>::rescheduleMemInst(DynInstPtr &resched_inst){    DPRINTF(IQ, "Rescheduling mem inst [sn:%lli]\n", resched_inst->seqNum);    resched_inst->clearCanIssue();    memDepUnit[resched_inst->threadNumber].reschedule(resched_inst);}template <class Impl>voidInstructionQueue<Impl>::replayMemInst(DynInstPtr &replay_inst){    memDepUnit[replay_inst->threadNumber].replay(replay_inst);}template <class Impl>voidInstructionQueue<Impl>::completeMemInst(DynInstPtr &completed_inst){    int tid = completed_inst->threadNumber;    DPRINTF(IQ, "Completing mem instruction PC:%#x [sn:%lli]\n",            completed_inst->readPC(), completed_inst->seqNum);    ++freeEntries;    completed_inst->memOpDone = true;    memDepUnit[tid].completed(completed_inst);    count[tid]--;}template <class Impl>voidInstructionQueue<Impl>::violation(DynInstPtr &store,                                  DynInstPtr &faulting_load){    memDepUnit[store->threadNumber].violation(store, faulting_load);}template <class Impl>voidInstructionQueue<Impl>::squash(unsigned tid){    DPRINTF(IQ, "[tid:%i]: Starting to squash instructions in "            "the IQ.\n", tid);    // Read instruction sequence number of last instruction out of the    // time buffer.    squashedSeqNum[tid] = fromCommit->commitInfo[tid].doneSeqNum;    // Call doSquash if there are insts in the IQ    if (count[tid] > 0) {        doSquash(tid);    }    // Also tell the memory dependence unit to squash.    memDepUnit[tid].squash(squashedSeqNum[tid], tid);}template <class Impl>voidInstructionQueue<Impl>::doSquash(unsigned tid){    // Start at the tail.    ListIt squash_it = instList[tid].end();    --squash_it;    DPRINTF(IQ, "[tid:%i]: Squashing until sequence number %i!\n",            tid, squashedSeqNum[tid]);    // Squash any instructions younger than the squashed sequence number    // given.    while (squash_it != instList[tid].end() &&           (*squash_it)->seqNum > squashedSeqNum[tid]) {        DynInstPtr squashed_inst = (*squash_it);        // Only handle the instruction if it actually is in the IQ and        // hasn't already been squashed in the IQ.        if (squashed_inst->threadNumber != tid ||            squashed_inst->isSquashedInIQ()) {            --squash_it;            continue;        }        if (!squashed_inst->isIssued() ||            (squashed_inst->isMemRef() &&             !squashed_inst->memOpDone)) {            DPRINTF(IQ, "[tid:%i]: Instruction [sn:%lli] PC %#x "                    "squashed.\n",                    tid, squashed_inst->seqNum, squashed_inst->readPC());            // Remove the instruction from the dependency list.            if (!squashed_inst->isNonSpeculative() &&                !squashed_inst->isStoreConditional() &&                !squashed_inst->isMemBarrier() &&                !squashed_inst->isWriteBarrier()) {                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.                    // Instead of doing a linked list traversal, we                    // can just remove these squashed instructions                    // either at issue time, or when the register is                    // overwritten.  The only downside to this is it                    // leaves more room for error.                    if (!squashed_inst->isReadySrcRegIdx(src_reg_idx) &&                        src_reg < numPhysRegs) {                        dependGraph.remove(src_reg, squashed_inst);                    }                    ++iqSquashedOperandsExamined;                }            } else if (!squashed_inst->isStoreConditional() ||                       !squashed_inst->isCompleted()) {                NonSpecMapIt ns_inst_it =                    nonSpecInsts.find(squashed_inst->seqNum);                assert(ns_inst_it != nonSpecInsts.end());                if (ns_inst_it == nonSpecInsts.end()) {                    assert(squashed_inst->getFault() != NoFault);                } else {                    (*ns_inst_it).second = NULL;                    nonSpecInsts.erase(ns_inst_it);                    ++iqSquashedNonSpecRemoved;                }            }            // Might want to also clear out the head of the dependency graph.            // Mark it as squashed within the IQ.            squashed_inst->setSquashedInIQ();            // @todo: Remove this hack where several statuses are set so the            // inst will flow through the rest of the pipeline.            squashed_inst->setIssued();            squashed_inst->setCanCommit();            squashed_inst->clearInIQ();            //Update Thread IQ Count            count[squashed_inst->threadNumber]--;            ++freeEntries;        }        instList[tid].erase(squash_it--);        ++iqSquashedInstsExamined;    }}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, "Instruction PC %#x has src reg %i that "                        "is being added to the dependency chain.\n",                        new_inst->readPC(), src_reg);                dependGraph.insert(src_reg, new_inst);                // Change the return value to indicate that something                // was added to the dependency graph.                return_val = true;            } else {                DPRINTF(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(src_reg_idx);            }        }    }    return return_val;}template <class Impl>voidInstructionQueue<Impl>::addToProducers(DynInstPtr &new_inst){    // 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;        }        if (!dependGraph.empty(dest_reg)) {            dependGraph.dump();            panic("Dependency graph %i not empty!", dest_reg);        }        dependGraph.setInst(dest_reg, new_inst);        // 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->isMemRef()) {            DPRINTF(IQ, "Checking if memory instruction can issue.\n");            // Message to the mem dependence unit that this instruction has            // its registers ready.            memDepUnit[inst->threadNumber].regsReady(inst);            return;        }        OpClass op_class = inst->opClass();        DPRINTF(IQ, "Instruction is ready to issue, putting it onto "                "the ready list, PC %#x opclass:%i [sn:%lli].\n",                inst->readPC(), op_class, inst->seqNum);        readyInsts[op_class].push(inst);        // Will need to reorder the list if either a queue is not on the list,        // or it has an older instruction than last time.        if (!queueOnList[op_class]) {            addToOrderList(op_class);        } else if (readyInsts[op_class].top()->seqNum  <                   (*readyIt[op_class]).oldestInst) {            listOrder.erase(readyIt[op_class]);            addToOrderList(op_class);        }    }}template <class Impl>intInstructionQueue<Impl>::countInsts(){#if 0    //ksewell:This works but definitely could use a cleaner write    //with a more intuitive way of counting. Right now it's    //just brute force ....    // Change the #if if you want to use this method.    int total_insts = 0;    for (int i = 0; i < numThreads; ++i) {        ListIt count_it = instList[i].begin();        while (count_it != instList[i].end()) {            if (!(*count_it)->isSquashed() && !(*count_it)->isSquashedInIQ()) {                if (!(*count_it)->isIssued()) {                    ++total_insts;                } else if ((*count_it)->isMemRef() &&                           !(*count_it)->memOpDone) {                    // Loads that have not been marked as executed still count                    // towards the total instructions.                    ++total_insts;                }            }            ++count_it;        }    }    return total_insts;#else    return numEntries - freeEntries;#endif}template <class Impl>voidInstructionQueue<Impl>::dumpLists(){    for (int i = 0; i < Num_OpClasses; ++i) {        cprintf("Ready list %i size: %i\n", i, readyInsts[i].size());        cprintf("\n");    }    cprintf("Non speculative list size: %i\n", nonSpecInsts.size());    NonSpecMapIt non_spec_it = nonSpecInsts.begin();    NonSpecMapIt non_spec_end_it = nonSpecInsts.end();    cprintf("Non speculative list: ");    while (non_spec_it != non_spec_end_it) {        cprintf("%#x [sn:%lli]", (*non_spec_it).second->readPC(),                (*non_spec_it).second->seqNum);        ++non_spec_it;    }    cprintf("\n");    ListOrderIt list_order_it = listOrder.begin();    ListOrderIt list_order_end_it = listOrder.end();    int i = 1;    cprintf("List order: ");    while (list_order_it != list_order_end_it) {        cprintf("%i OpClass:%i [sn:%lli] ", i, (*list_order_it).queueType,                (*list_order_it).oldestInst);        ++list_order_it;        ++i;    }    cprintf("\n");}template <class Impl>voidInstructionQueue<Impl>::dumpInsts(){    for (int i = 0; i < numThreads; ++i) {        int num = 0;        int valid_num = 0;        ListIt inst_list_it = instList[i].begin();        while (inst_list_it != instList[i].end())        {            cprintf("Instruction:%i\n",                    num);            if (!(*inst_list_it)->isSquashed()) {                if (!(*inst_list_it)->isIssued()) {                    ++valid_num;                    cprintf("Count:%i\n", valid_num);                } else if ((*inst_list_it)->isMemRef() &&                           !(*inst_list_it)->memOpDone) {                    // Loads that have not been marked as executed                    // still count towards the total instructions.                    ++valid_num;                    cprintf("Count:%i\n", valid_num);                }            }            cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n"                    "Issued:%i\nSquashed:%i\n",                    (*inst_list_it)->readPC(),                    (*inst_list_it)->seqNum,                    (*inst_list_it)->threadNumber,                    (*inst_list_it)->isIssued(),                    (*inst_list_it)->isSquashed());            if ((*inst_list_it)->isMemRef()) {                cprintf("MemOpDone:%i\n", (*inst_list_it)->memOpDone);            }            cprintf("\n");            inst_list_it++;            ++num;        }    }    cprintf("Insts to Execute list:\n");    int num = 0;    int valid_num = 0;    ListIt inst_list_it = instsToExecute.begin();    while (inst_list_it != instsToExecute.end())    {        cprintf("Instruction:%i\n",                num);        if (!(*inst_list_it)->isSquashed()) {            if (!(*inst_list_it)->isIssued()) {                ++valid_num;                cprintf("Count:%i\n", valid_num);            } else if ((*inst_list_it)->isMemRef() &&                       !(*inst_list_it)->memOpDone) {                // Loads that have not been marked as executed                // still count towards the total instructions.                ++valid_num;                cprintf("Count:%i\n", valid_num);            }        }        cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n"                "Issued:%i\nSquashed:%i\n",                (*inst_list_it)->readPC(),                (*inst_list_it)->seqNum,                (*inst_list_it)->threadNumber,                (*inst_list_it)->isIssued(),                (*inst_list_it)->isSquashed());        if ((*inst_list_it)->isMemRef()) {            cprintf("MemOpDone:%i\n", (*inst_list_it)->memOpDone);        }        cprintf("\n");        inst_list_it++;        ++num;    }}

⌨️ 快捷键说明

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