iew_impl.hh

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

HH
1,585
字号
        wroteToTimeBuffer = true;        return;    }    if (checkStall(tid)) {        block(tid);        dispatchStatus[tid] = Blocked;        return;    }    if (dispatchStatus[tid] == Blocked) {        // Status from previous cycle was blocked, but there are no more stall        // conditions.  Switch over to unblocking.        DPRINTF(IEW, "[tid:%i]: Done blocking, switching to unblocking.\n",                tid);        dispatchStatus[tid] = Unblocking;        unblock(tid);        return;    }    if (dispatchStatus[tid] == Squashing) {        // Switch status to running if rename isn't being told to block or        // squash this cycle.        DPRINTF(IEW, "[tid:%i]: Done squashing, switching to running.\n",                tid);        dispatchStatus[tid] = Running;        return;    }}template <class Impl>voidDefaultIEW<Impl>::sortInsts(){    int insts_from_rename = fromRename->size;#ifdef DEBUG    for (int i = 0; i < numThreads; i++)        assert(insts[i].empty());#endif    for (int i = 0; i < insts_from_rename; ++i) {        insts[fromRename->insts[i]->threadNumber].push(fromRename->insts[i]);    }}template <class Impl>voidDefaultIEW<Impl>::emptyRenameInsts(unsigned tid){    DPRINTF(IEW, "[tid:%i]: Removing incoming rename instructions\n", tid);    while (!insts[tid].empty()) {        if (insts[tid].front()->isLoad() ||            insts[tid].front()->isStore() ) {            toRename->iewInfo[tid].dispatchedToLSQ++;        }        toRename->iewInfo[tid].dispatched++;        insts[tid].pop();    }}template <class Impl>voidDefaultIEW<Impl>::wakeCPU(){    cpu->wakeCPU();}template <class Impl>voidDefaultIEW<Impl>::activityThisCycle(){    DPRINTF(Activity, "Activity this cycle.\n");    cpu->activityThisCycle();}template <class Impl>inline voidDefaultIEW<Impl>::activateStage(){    DPRINTF(Activity, "Activating stage.\n");    cpu->activateStage(O3CPU::IEWIdx);}template <class Impl>inline voidDefaultIEW<Impl>::deactivateStage(){    DPRINTF(Activity, "Deactivating stage.\n");    cpu->deactivateStage(O3CPU::IEWIdx);}template<class Impl>voidDefaultIEW<Impl>::dispatch(unsigned tid){    // If status is Running or idle,    //     call dispatchInsts()    // If status is Unblocking,    //     buffer any instructions coming from rename    //     continue trying to empty skid buffer    //     check if stall conditions have passed    if (dispatchStatus[tid] == Blocked) {        ++iewBlockCycles;    } else if (dispatchStatus[tid] == Squashing) {        ++iewSquashCycles;    }    // Dispatch should try to dispatch as many instructions as its bandwidth    // will allow, as long as it is not currently blocked.    if (dispatchStatus[tid] == Running ||        dispatchStatus[tid] == Idle) {        DPRINTF(IEW, "[tid:%i] Not blocked, so attempting to run "                "dispatch.\n", tid);        dispatchInsts(tid);    } else if (dispatchStatus[tid] == Unblocking) {        // Make sure that the skid buffer has something in it if the        // status is unblocking.        assert(!skidsEmpty());        // If the status was unblocking, then instructions from the skid        // buffer were used.  Remove those instructions and handle        // the rest of unblocking.        dispatchInsts(tid);        ++iewUnblockCycles;        if (validInstsFromRename()) {            // Add the current inputs to the skid buffer so they can be            // reprocessed when this stage unblocks.            skidInsert(tid);        }        unblock(tid);    }}template <class Impl>voidDefaultIEW<Impl>::dispatchInsts(unsigned tid){    // Obtain instructions from skid buffer if unblocking, or queue from rename    // otherwise.    std::queue<DynInstPtr> &insts_to_dispatch =        dispatchStatus[tid] == Unblocking ?        skidBuffer[tid] : insts[tid];    int insts_to_add = insts_to_dispatch.size();    DynInstPtr inst;    bool add_to_iq = false;    int dis_num_inst = 0;    // Loop through the instructions, putting them in the instruction    // queue.    for ( ; dis_num_inst < insts_to_add &&              dis_num_inst < dispatchWidth;          ++dis_num_inst)    {        inst = insts_to_dispatch.front();        if (dispatchStatus[tid] == Unblocking) {            DPRINTF(IEW, "[tid:%i]: Issue: Examining instruction from skid "                    "buffer\n", tid);        }        // Make sure there's a valid instruction there.        assert(inst);        DPRINTF(IEW, "[tid:%i]: Issue: Adding PC %#x [sn:%lli] [tid:%i] to "                "IQ.\n",                tid, inst->readPC(), inst->seqNum, inst->threadNumber);        // Be sure to mark these instructions as ready so that the        // commit stage can go ahead and execute them, and mark        // them as issued so the IQ doesn't reprocess them.        // Check for squashed instructions.        if (inst->isSquashed()) {            DPRINTF(IEW, "[tid:%i]: Issue: Squashed instruction encountered, "                    "not adding to IQ.\n", tid);            ++iewDispSquashedInsts;            insts_to_dispatch.pop();            //Tell Rename That An Instruction has been processed            if (inst->isLoad() || inst->isStore()) {                toRename->iewInfo[tid].dispatchedToLSQ++;            }            toRename->iewInfo[tid].dispatched++;            continue;        }        // Check for full conditions.        if (instQueue.isFull(tid)) {            DPRINTF(IEW, "[tid:%i]: Issue: IQ has become full.\n", tid);            // Call function to start blocking.            block(tid);            // Set unblock to false. Special case where we are using            // skidbuffer (unblocking) instructions but then we still            // get full in the IQ.            toRename->iewUnblock[tid] = false;            ++iewIQFullEvents;            break;        } else if (ldstQueue.isFull(tid)) {            DPRINTF(IEW, "[tid:%i]: Issue: LSQ has become full.\n",tid);            // Call function to start blocking.            block(tid);            // Set unblock to false. Special case where we are using            // skidbuffer (unblocking) instructions but then we still            // get full in the IQ.            toRename->iewUnblock[tid] = false;            ++iewLSQFullEvents;            break;        }        // Otherwise issue the instruction just fine.        if (inst->isLoad()) {            DPRINTF(IEW, "[tid:%i]: Issue: Memory instruction "                    "encountered, adding to LSQ.\n", tid);            // Reserve a spot in the load store queue for this            // memory access.            ldstQueue.insertLoad(inst);            ++iewDispLoadInsts;            add_to_iq = true;            toRename->iewInfo[tid].dispatchedToLSQ++;        } else if (inst->isStore()) {            DPRINTF(IEW, "[tid:%i]: Issue: Memory instruction "                    "encountered, adding to LSQ.\n", tid);            ldstQueue.insertStore(inst);            ++iewDispStoreInsts;            if (inst->isStoreConditional()) {                // Store conditionals need to be set as "canCommit()"                // so that commit can process them when they reach the                // head of commit.                // @todo: This is somewhat specific to Alpha.                inst->setCanCommit();                instQueue.insertNonSpec(inst);                add_to_iq = false;                ++iewDispNonSpecInsts;            } else {                add_to_iq = true;            }            toRename->iewInfo[tid].dispatchedToLSQ++;        } else if (inst->isMemBarrier() || inst->isWriteBarrier()) {            // Same as non-speculative stores.            inst->setCanCommit();            instQueue.insertBarrier(inst);            add_to_iq = false;        } else if (inst->isNop()) {            DPRINTF(IEW, "[tid:%i]: Issue: Nop instruction encountered, "                    "skipping.\n", tid);            inst->setIssued();            inst->setExecuted();            inst->setCanCommit();            instQueue.recordProducer(inst);            iewExecutedNop[tid]++;            add_to_iq = false;        } else if (inst->isExecuted()) {            assert(0 && "Instruction shouldn't be executed.\n");            DPRINTF(IEW, "Issue: Executed branch encountered, "                    "skipping.\n");            inst->setIssued();            inst->setCanCommit();            instQueue.recordProducer(inst);            add_to_iq = false;        } else {            add_to_iq = true;        }        if (inst->isNonSpeculative()) {            DPRINTF(IEW, "[tid:%i]: Issue: Nonspeculative instruction "                    "encountered, skipping.\n", tid);            // Same as non-speculative stores.            inst->setCanCommit();            // Specifically insert it as nonspeculative.            instQueue.insertNonSpec(inst);            ++iewDispNonSpecInsts;            add_to_iq = false;        }        // If the instruction queue is not full, then add the        // instruction.        if (add_to_iq) {            instQueue.insert(inst);        }        insts_to_dispatch.pop();        toRename->iewInfo[tid].dispatched++;        ++iewDispatchedInsts;    }    if (!insts_to_dispatch.empty()) {        DPRINTF(IEW,"[tid:%i]: Issue: Bandwidth Full. Blocking.\n", tid);        block(tid);        toRename->iewUnblock[tid] = false;    }    if (dispatchStatus[tid] == Idle && dis_num_inst) {        dispatchStatus[tid] = Running;        updatedQueues = true;    }    dis_num_inst = 0;}template <class Impl>voidDefaultIEW<Impl>::printAvailableInsts(){    int inst = 0;    std::cout << "Available Instructions: ";    while (fromIssue->insts[inst]) {        if (inst%3==0) std::cout << "\n\t";        std::cout << "PC: " << fromIssue->insts[inst]->readPC()             << " TN: " << fromIssue->insts[inst]->threadNumber             << " SN: " << fromIssue->insts[inst]->seqNum << " | ";        inst++;    }    std::cout << "\n";}template <class Impl>voidDefaultIEW<Impl>::executeInsts(){    wbNumInst = 0;    wbCycle = 0;    std::list<unsigned>::iterator threads = activeThreads->begin();    std::list<unsigned>::iterator end = activeThreads->end();    while (threads != end) {        unsigned tid = *threads++;        fetchRedirect[tid] = false;    }    // Uncomment this if you want to see all available instructions.//    printAvailableInsts();    // Execute/writeback any instructions that are available.    int insts_to_execute = fromIssue->size;    int inst_num = 0;    for (; inst_num < insts_to_execute;          ++inst_num) {        DPRINTF(IEW, "Execute: Executing instructions from IQ.\n");        DynInstPtr inst = instQueue.getInstToExecute();

⌨️ 快捷键说明

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