decode_impl.hh

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

HH
758
字号
                inst->seqNum, inst->readPC(), inst->threadNumber);        skidBuffer[tid].push(inst);    }    // @todo: Eventually need to enforce this by not letting a thread    // fetch past its skidbuffer    assert(skidBuffer[tid].size() <= skidBufferMax);}template<class Impl>boolDefaultDecode<Impl>::skidsEmpty(){    std::list<unsigned>::iterator threads = activeThreads->begin();    std::list<unsigned>::iterator end = activeThreads->end();    while (threads != end) {        unsigned tid = *threads++;        if (!skidBuffer[tid].empty())            return false;    }    return true;}template<class Impl>voidDefaultDecode<Impl>::updateStatus(){    bool any_unblocking = false;    std::list<unsigned>::iterator threads = activeThreads->begin();    std::list<unsigned>::iterator end = activeThreads->end();    while (threads != end) {        unsigned tid = *threads++;        if (decodeStatus[tid] == Unblocking) {            any_unblocking = true;            break;        }    }    // Decode will have activity if it's unblocking.    if (any_unblocking) {        if (_status == Inactive) {            _status = Active;            DPRINTF(Activity, "Activating stage.\n");            cpu->activateStage(O3CPU::DecodeIdx);        }    } else {        // If it's not unblocking, then decode will not have any internal        // activity.  Switch it to inactive.        if (_status == Active) {            _status = Inactive;            DPRINTF(Activity, "Deactivating stage.\n");            cpu->deactivateStage(O3CPU::DecodeIdx);        }    }}template <class Impl>voidDefaultDecode<Impl>::sortInsts(){    int insts_from_fetch = fromFetch->size;#ifdef DEBUG    for (int i=0; i < numThreads; i++)        assert(insts[i].empty());#endif    for (int i = 0; i < insts_from_fetch; ++i) {        insts[fromFetch->insts[i]->threadNumber].push(fromFetch->insts[i]);    }}template<class Impl>voidDefaultDecode<Impl>::readStallSignals(unsigned tid){    if (fromRename->renameBlock[tid]) {        stalls[tid].rename = true;    }    if (fromRename->renameUnblock[tid]) {        assert(stalls[tid].rename);        stalls[tid].rename = false;    }    if (fromIEW->iewBlock[tid]) {        stalls[tid].iew = true;    }    if (fromIEW->iewUnblock[tid]) {        assert(stalls[tid].iew);        stalls[tid].iew = false;    }    if (fromCommit->commitBlock[tid]) {        stalls[tid].commit = true;    }    if (fromCommit->commitUnblock[tid]) {        assert(stalls[tid].commit);        stalls[tid].commit = false;    }}template <class Impl>boolDefaultDecode<Impl>::checkSignalsAndUpdate(unsigned tid){    // Check if there's a squash signal, squash if there is.    // Check stall signals, block if necessary.    // If status was blocked    //     Check if stall conditions have passed    //         if so then go to unblocking    // If status was Squashing    //     check if squashing is not high.  Switch to running this cycle.    // Update the per thread stall statuses.    readStallSignals(tid);    // Check squash signals from commit.    if (fromCommit->commitInfo[tid].squash) {        DPRINTF(Decode, "[tid:%u]: Squashing instructions due to squash "                "from commit.\n", tid);        squash(tid);        return true;    }    // Check ROB squash signals from commit.    if (fromCommit->commitInfo[tid].robSquashing) {        DPRINTF(Decode, "[tid:%u]: ROB is still squashing.\n", tid);        // Continue to squash.        decodeStatus[tid] = Squashing;        return true;    }    if (checkStall(tid)) {        return block(tid);    }    if (decodeStatus[tid] == Blocked) {        DPRINTF(Decode, "[tid:%u]: Done blocking, switching to unblocking.\n",                tid);        decodeStatus[tid] = Unblocking;        unblock(tid);        return true;    }    if (decodeStatus[tid] == Squashing) {        // Switch status to running if decode isn't being told to block or        // squash this cycle.        DPRINTF(Decode, "[tid:%u]: Done squashing, switching to running.\n",                tid);        decodeStatus[tid] = Running;        return false;    }    // If we've reached this point, we have not gotten any signals that    // cause decode to change its status.  Decode remains the same as before.    return false;}template<class Impl>voidDefaultDecode<Impl>::tick(){    wroteToTimeBuffer = false;    bool status_change = false;    toRenameIndex = 0;    std::list<unsigned>::iterator threads = activeThreads->begin();    std::list<unsigned>::iterator end = activeThreads->end();    sortInsts();    //Check stall and squash signals.    while (threads != end) {        unsigned tid = *threads++;        DPRINTF(Decode,"Processing [tid:%i]\n",tid);        status_change =  checkSignalsAndUpdate(tid) || status_change;        decode(status_change, tid);    }    if (status_change) {        updateStatus();    }    if (wroteToTimeBuffer) {        DPRINTF(Activity, "Activity this cycle.\n");        cpu->activityThisCycle();    }}template<class Impl>voidDefaultDecode<Impl>::decode(bool &status_change, unsigned tid){    // If status is Running or idle,    //     call decodeInsts()    // If status is Unblocking,    //     buffer any instructions coming from fetch    //     continue trying to empty skid buffer    //     check if stall conditions have passed    if (decodeStatus[tid] == Blocked) {        ++decodeBlockedCycles;    } else if (decodeStatus[tid] == Squashing) {        ++decodeSquashCycles;    }    // Decode should try to decode as many instructions as its bandwidth    // will allow, as long as it is not currently blocked.    if (decodeStatus[tid] == Running ||        decodeStatus[tid] == Idle) {        DPRINTF(Decode, "[tid:%u]: Not blocked, so attempting to run "                "stage.\n",tid);        decodeInsts(tid);    } else if (decodeStatus[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.        decodeInsts(tid);        if (fetchInstsValid()) {            // Add the current inputs to the skid buffer so they can be            // reprocessed when this stage unblocks.            skidInsert(tid);        }        status_change = unblock(tid) || status_change;    }}template <class Impl>voidDefaultDecode<Impl>::decodeInsts(unsigned tid){    // Instructions can come either from the skid buffer or the list of    // instructions coming from fetch, depending on decode's status.    int insts_available = decodeStatus[tid] == Unblocking ?        skidBuffer[tid].size() : insts[tid].size();    if (insts_available == 0) {        DPRINTF(Decode, "[tid:%u] Nothing to do, breaking out"                " early.\n",tid);        // Should I change the status to idle?        ++decodeIdleCycles;        return;    } else if (decodeStatus[tid] == Unblocking) {        DPRINTF(Decode, "[tid:%u] Unblocking, removing insts from skid "                "buffer.\n",tid);        ++decodeUnblockCycles;    } else if (decodeStatus[tid] == Running) {        ++decodeRunCycles;    }    DynInstPtr inst;    std::queue<DynInstPtr>        &insts_to_decode = decodeStatus[tid] == Unblocking ?        skidBuffer[tid] : insts[tid];    DPRINTF(Decode, "[tid:%u]: Sending instruction to rename.\n",tid);    while (insts_available > 0 && toRenameIndex < decodeWidth) {        assert(!insts_to_decode.empty());        inst = insts_to_decode.front();        insts_to_decode.pop();        DPRINTF(Decode, "[tid:%u]: Processing instruction [sn:%lli] with "                "PC %#x\n",                tid, inst->seqNum, inst->readPC());        if (inst->isSquashed()) {            DPRINTF(Decode, "[tid:%u]: Instruction %i with PC %#x is "                    "squashed, skipping.\n",                    tid, inst->seqNum, inst->readPC());            ++decodeSquashedInsts;            --insts_available;            continue;        }        // Also check if instructions have no source registers.  Mark        // them as ready to issue at any time.  Not sure if this check        // should exist here or at a later stage; however it doesn't matter        // too much for function correctness.        if (inst->numSrcRegs() == 0) {            inst->setCanIssue();        }        // This current instruction is valid, so add it into the decode        // queue.  The next instruction may not be valid, so check to        // see if branches were predicted correctly.        toRename->insts[toRenameIndex] = inst;        ++(toRename->size);        ++toRenameIndex;        ++decodeDecodedInsts;        --insts_available;        // Ensure that if it was predicted as a branch, it really is a        // branch.        if (inst->readPredTaken() && !inst->isControl()) {            DPRINTF(Decode, "PredPC : %#x != NextPC: %#x\n",                    inst->readPredPC(), inst->readNextPC() + 4);            panic("Instruction predicted as a branch!");            ++decodeControlMispred;            // Might want to set some sort of boolean and just do            // a check at the end            squash(inst, inst->threadNumber);            break;        }        // Go ahead and compute any PC-relative branches.        if (inst->isDirectCtrl() && inst->isUncondCtrl()) {            ++decodeBranchResolved;            if (inst->branchTarget() != inst->readPredPC()) {                ++decodeBranchMispred;                // Might want to set some sort of boolean and just do                // a check at the end                squash(inst, inst->threadNumber);                Addr target = inst->branchTarget();                //The micro pc after an instruction level branch should be 0                inst->setPredTarg(target, target + sizeof(TheISA::MachInst), 0);                break;            }        }    }    // If we didn't process all instructions, then we will need to block    // and put all those instructions into the skid buffer.    if (!insts_to_decode.empty()) {        block(tid);    }    // Record that decode has written to the time buffer for activity    // tracking.    if (toRenameIndex) {        wroteToTimeBuffer = true;    }}

⌨️ 快捷键说明

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