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