iew_impl.hh

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

HH
1,585
字号
        DPRINTF(IEW, "Execute: Processing PC %#x, [tid:%i] [sn:%i].\n",                inst->readPC(), inst->threadNumber,inst->seqNum);        // Check if the instruction is squashed; if so then skip it        if (inst->isSquashed()) {            DPRINTF(IEW, "Execute: Instruction was squashed.\n");            // Consider this instruction executed so that commit can go            // ahead and retire the instruction.            inst->setExecuted();            // Not sure if I should set this here or just let commit try to            // commit any squashed instructions.  I like the latter a bit more.            inst->setCanCommit();            ++iewExecSquashedInsts;            decrWb(inst->seqNum);            continue;        }        Fault fault = NoFault;        // Execute instruction.        // Note that if the instruction faults, it will be handled        // at the commit stage.        if (inst->isMemRef() &&            (!inst->isDataPrefetch() && !inst->isInstPrefetch())) {            DPRINTF(IEW, "Execute: Calculating address for memory "                    "reference.\n");            // Tell the LDSTQ to execute this instruction (if it is a load).            if (inst->isLoad()) {                // Loads will mark themselves as executed, and their writeback                // event adds the instruction to the queue to commit                fault = ldstQueue.executeLoad(inst);            } else if (inst->isStore()) {                fault = ldstQueue.executeStore(inst);                // If the store had a fault then it may not have a mem req                if (!inst->isStoreConditional() && fault == NoFault) {                    inst->setExecuted();                    instToCommit(inst);                } else if (fault != NoFault) {                    // If the instruction faulted, then we need to send it along to commit                    // without the instruction completing.                    DPRINTF(IEW, "Store has fault %s! [sn:%lli]\n",                            fault->name(), inst->seqNum);                    // Send this instruction to commit, also make sure iew stage                    // realizes there is activity.                    inst->setExecuted();                    instToCommit(inst);                    activityThisCycle();                }                // Store conditionals will mark themselves as                // executed, and their writeback event will add the                // instruction to the queue to commit.            } else {                panic("Unexpected memory type!\n");            }        } else {            inst->execute();            inst->setExecuted();            instToCommit(inst);        }        updateExeInstStats(inst);        // Check if branch prediction was correct, if not then we need        // to tell commit to squash in flight instructions.  Only        // handle this if there hasn't already been something that        // redirects fetch in this group of instructions.        // This probably needs to prioritize the redirects if a different        // scheduler is used.  Currently the scheduler schedules the oldest        // instruction first, so the branch resolution order will be correct.        unsigned tid = inst->threadNumber;        if (!fetchRedirect[tid] ||            toCommit->squashedSeqNum[tid] > inst->seqNum) {            if (inst->mispredicted()) {                fetchRedirect[tid] = true;                DPRINTF(IEW, "Execute: Branch mispredict detected.\n");                DPRINTF(IEW, "Predicted target was %#x, %#x.\n",                        inst->readPredPC(), inst->readPredNPC());                DPRINTF(IEW, "Execute: Redirecting fetch to PC: %#x,"                        " NPC: %#x.\n", inst->readNextPC(),                        inst->readNextNPC());                // If incorrect, then signal the ROB that it must be squashed.                squashDueToBranch(inst, tid);                if (inst->readPredTaken()) {                    predictedTakenIncorrect++;                } else {                    predictedNotTakenIncorrect++;                }            } else if (ldstQueue.violation(tid)) {                assert(inst->isMemRef());                // If there was an ordering violation, then get the                // DynInst that caused the violation.  Note that this                // clears the violation signal.                DynInstPtr violator;                violator = ldstQueue.getMemDepViolator(tid);                DPRINTF(IEW, "LDSTQ detected a violation.  Violator PC: "                        "%#x, inst PC: %#x.  Addr is: %#x.\n",                        violator->readPC(), inst->readPC(), inst->physEffAddr);                // Ensure the violating instruction is older than                // current squash/*                if (fetchRedirect[tid] &&                    violator->seqNum >= toCommit->squashedSeqNum[tid] + 1)                    continue;*/                fetchRedirect[tid] = true;                // Tell the instruction queue that a violation has occured.                instQueue.violation(inst, violator);                // Squash.                squashDueToMemOrder(inst,tid);                ++memOrderViolationEvents;            } else if (ldstQueue.loadBlocked(tid) &&                       !ldstQueue.isLoadBlockedHandled(tid)) {                fetchRedirect[tid] = true;                DPRINTF(IEW, "Load operation couldn't execute because the "                        "memory system is blocked.  PC: %#x [sn:%lli]\n",                        inst->readPC(), inst->seqNum);                squashDueToMemBlocked(inst, tid);            }        } else {            // Reset any state associated with redirects that will not            // be used.            if (ldstQueue.violation(tid)) {                assert(inst->isMemRef());                DynInstPtr violator = ldstQueue.getMemDepViolator(tid);                DPRINTF(IEW, "LDSTQ detected a violation.  Violator PC: "                        "%#x, inst PC: %#x.  Addr is: %#x.\n",                        violator->readPC(), inst->readPC(), inst->physEffAddr);                DPRINTF(IEW, "Violation will not be handled because "                        "already squashing\n");                ++memOrderViolationEvents;            }            if (ldstQueue.loadBlocked(tid) &&                !ldstQueue.isLoadBlockedHandled(tid)) {                DPRINTF(IEW, "Load operation couldn't execute because the "                        "memory system is blocked.  PC: %#x [sn:%lli]\n",                        inst->readPC(), inst->seqNum);                DPRINTF(IEW, "Blocked load will not be handled because "                        "already squashing\n");                ldstQueue.setLoadBlockedHandled(tid);            }        }    }    // Update and record activity if we processed any instructions.    if (inst_num) {        if (exeStatus == Idle) {            exeStatus = Running;        }        updatedQueues = true;        cpu->activityThisCycle();    }    // Need to reset this in case a writeback event needs to write into the    // iew queue.  That way the writeback event will write into the correct    // spot in the queue.    wbNumInst = 0;}template <class Impl>voidDefaultIEW<Impl>::writebackInsts(){    // Loop through the head of the time buffer and wake any    // dependents.  These instructions are about to write back.  Also    // mark scoreboard that this instruction is finally complete.    // Either have IEW have direct access to scoreboard, or have this    // as part of backwards communication.    for (int inst_num = 0; inst_num < wbWidth &&             toCommit->insts[inst_num]; inst_num++) {        DynInstPtr inst = toCommit->insts[inst_num];        int tid = inst->threadNumber;        DPRINTF(IEW, "Sending instructions to commit, [sn:%lli] PC %#x.\n",                inst->seqNum, inst->readPC());        iewInstsToCommit[tid]++;        // Some instructions will be sent to commit without having        // executed because they need commit to handle them.        // E.g. Uncached loads have not actually executed when they        // are first sent to commit.  Instead commit must tell the LSQ        // when it's ready to execute the uncached load.        if (!inst->isSquashed() && inst->isExecuted() && inst->getFault() == NoFault) {            int dependents = instQueue.wakeDependents(inst);            for (int i = 0; i < inst->numDestRegs(); i++) {                //mark as Ready                DPRINTF(IEW,"Setting Destination Register %i\n",                        inst->renamedDestRegIdx(i));                scoreboard->setReg(inst->renamedDestRegIdx(i));            }            if (dependents) {                producerInst[tid]++;                consumerInst[tid]+= dependents;            }            writebackCount[tid]++;        }        decrWb(inst->seqNum);    }}template<class Impl>voidDefaultIEW<Impl>::tick(){    wbNumInst = 0;    wbCycle = 0;    wroteToTimeBuffer = false;    updatedQueues = false;    sortInsts();    // Free function units marked as being freed this cycle.    fuPool->processFreeUnits();    std::list<unsigned>::iterator threads = activeThreads->begin();    std::list<unsigned>::iterator end = activeThreads->end();    // Check stall and squash signals, dispatch any instructions.    while (threads != end) {        unsigned tid = *threads++;        DPRINTF(IEW,"Issue: Processing [tid:%i]\n",tid);        checkSignalsAndUpdate(tid);        dispatch(tid);    }    if (exeStatus != Squashing) {        executeInsts();        writebackInsts();        // Have the instruction queue try to schedule any ready instructions.        // (In actuality, this scheduling is for instructions that will        // be executed next cycle.)        instQueue.scheduleReadyInsts();        // Also should advance its own time buffers if the stage ran.        // Not the best place for it, but this works (hopefully).        issueToExecQueue.advance();    }    bool broadcast_free_entries = false;    if (updatedQueues || exeStatus == Running || updateLSQNextCycle) {        exeStatus = Idle;        updateLSQNextCycle = false;        broadcast_free_entries = true;    }    // Writeback any stores using any leftover bandwidth.    ldstQueue.writebackStores();    // Check the committed load/store signals to see if there's a load    // or store to commit.  Also check if it's being told to execute a    // nonspeculative instruction.    // This is pretty inefficient...    threads = activeThreads->begin();    while (threads != end) {        unsigned tid = (*threads++);        DPRINTF(IEW,"Processing [tid:%i]\n",tid);        // Update structures based on instructions committed.        if (fromCommit->commitInfo[tid].doneSeqNum != 0 &&            !fromCommit->commitInfo[tid].squash &&            !fromCommit->commitInfo[tid].robSquashing) {            ldstQueue.commitStores(fromCommit->commitInfo[tid].doneSeqNum,tid);            ldstQueue.commitLoads(fromCommit->commitInfo[tid].doneSeqNum,tid);            updateLSQNextCycle = true;            instQueue.commit(fromCommit->commitInfo[tid].doneSeqNum,tid);        }        if (fromCommit->commitInfo[tid].nonSpecSeqNum != 0) {            //DPRINTF(IEW,"NonspecInst from thread %i",tid);            if (fromCommit->commitInfo[tid].uncached) {                instQueue.replayMemInst(fromCommit->commitInfo[tid].uncachedLoad);                fromCommit->commitInfo[tid].uncachedLoad->setAtCommit();            } else {                instQueue.scheduleNonSpec(                    fromCommit->commitInfo[tid].nonSpecSeqNum);            }        }        if (broadcast_free_entries) {            toFetch->iewInfo[tid].iqCount =                instQueue.getCount(tid);            toFetch->iewInfo[tid].ldstqCount =                ldstQueue.getCount(tid);            toRename->iewInfo[tid].usedIQ = true;            toRename->iewInfo[tid].freeIQEntries =                instQueue.numFreeEntries();            toRename->iewInfo[tid].usedLSQ = true;            toRename->iewInfo[tid].freeLSQEntries =                ldstQueue.numFreeEntries(tid);            wroteToTimeBuffer = true;        }        DPRINTF(IEW, "[tid:%i], Dispatch dispatched %i instructions.\n",                tid, toRename->iewInfo[tid].dispatched);    }    DPRINTF(IEW, "IQ has %i free entries (Can schedule: %i).  "            "LSQ has %i free entries.\n",            instQueue.numFreeEntries(), instQueue.hasReadyInsts(),            ldstQueue.numFreeEntries());    updateStatus();    if (wroteToTimeBuffer) {        DPRINTF(Activity, "Activity this cycle.\n");        cpu->activityThisCycle();    }}template <class Impl>voidDefaultIEW<Impl>::updateExeInstStats(DynInstPtr &inst){    int thread_number = inst->threadNumber;    //    //  Pick off the software prefetches    //#ifdef TARGET_ALPHA    if (inst->isDataPrefetch())        iewExecutedSwp[thread_number]++;    else        iewIewExecutedcutedInsts++;#else    iewExecutedInsts++;#endif    //    //  Control operations    //    if (inst->isControl())        iewExecutedBranches[thread_number]++;    //    //  Memory operations    //    if (inst->isMemRef()) {        iewExecutedRefs[thread_number]++;        if (inst->isLoad()) {            iewExecLoadInsts[thread_number]++;        }    }}

⌨️ 快捷键说明

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