decode_impl.hh

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

HH
758
字号
/* * Copyright (c) 2004, 2005, 2006 * The Regents of The University of Michigan * All Rights Reserved * * This code is part of the M5 simulator. * * Permission is granted to use, copy, create derivative works and * redistribute this software and such derivative works for any * purpose, so long as the copyright notice above, this grant of * permission, and the disclaimer below appear in all copies made; and * so long as the name of The University of Michigan is not used in * any advertising or publicity pertaining to the use or distribution * of this software without specific, written prior authorization. * * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE * UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND * WITHOUT WARRANTY BY THE UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER * EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE. THE REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE * LIABLE FOR ANY DAMAGES, INCLUDING DIRECT, SPECIAL, INDIRECT, * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM * ARISING OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH * DAMAGES. * * Authors: Kevin T. Lim */#include "cpu/o3/decode.hh"template<class Impl>DefaultDecode<Impl>::DefaultDecode(O3CPU *_cpu, Params *params)    : cpu(_cpu),      renameToDecodeDelay(params->renameToDecodeDelay),      iewToDecodeDelay(params->iewToDecodeDelay),      commitToDecodeDelay(params->commitToDecodeDelay),      fetchToDecodeDelay(params->fetchToDecodeDelay),      decodeWidth(params->decodeWidth),      numThreads(params->numberOfThreads){    _status = Inactive;    // Setup status, make sure stall signals are clear.    for (int i = 0; i < numThreads; ++i) {        decodeStatus[i] = Idle;        stalls[i].rename = false;        stalls[i].iew = false;        stalls[i].commit = false;    }    // @todo: Make into a parameter    skidBufferMax = (fetchToDecodeDelay * params->fetchWidth) + decodeWidth;}template <class Impl>std::stringDefaultDecode<Impl>::name() const{    return cpu->name() + ".decode";}template <class Impl>voidDefaultDecode<Impl>::regStats(){    decodeIdleCycles        .name(name() + ".DECODE:IdleCycles")        .desc("Number of cycles decode is idle")        .prereq(decodeIdleCycles);    decodeBlockedCycles        .name(name() + ".DECODE:BlockedCycles")        .desc("Number of cycles decode is blocked")        .prereq(decodeBlockedCycles);    decodeRunCycles        .name(name() + ".DECODE:RunCycles")        .desc("Number of cycles decode is running")        .prereq(decodeRunCycles);    decodeUnblockCycles        .name(name() + ".DECODE:UnblockCycles")        .desc("Number of cycles decode is unblocking")        .prereq(decodeUnblockCycles);    decodeSquashCycles        .name(name() + ".DECODE:SquashCycles")        .desc("Number of cycles decode is squashing")        .prereq(decodeSquashCycles);    decodeBranchResolved        .name(name() + ".DECODE:BranchResolved")        .desc("Number of times decode resolved a branch")        .prereq(decodeBranchResolved);    decodeBranchMispred        .name(name() + ".DECODE:BranchMispred")        .desc("Number of times decode detected a branch misprediction")        .prereq(decodeBranchMispred);    decodeControlMispred        .name(name() + ".DECODE:ControlMispred")        .desc("Number of times decode detected an instruction incorrectly"              " predicted as a control")        .prereq(decodeControlMispred);    decodeDecodedInsts        .name(name() + ".DECODE:DecodedInsts")        .desc("Number of instructions handled by decode")        .prereq(decodeDecodedInsts);    decodeSquashedInsts        .name(name() + ".DECODE:SquashedInsts")        .desc("Number of squashed instructions handled by decode")        .prereq(decodeSquashedInsts);}template<class Impl>voidDefaultDecode<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr){    timeBuffer = tb_ptr;    // Setup wire to write information back to fetch.    toFetch = timeBuffer->getWire(0);    // Create wires to get information from proper places in time buffer.    fromRename = timeBuffer->getWire(-renameToDecodeDelay);    fromIEW = timeBuffer->getWire(-iewToDecodeDelay);    fromCommit = timeBuffer->getWire(-commitToDecodeDelay);}template<class Impl>voidDefaultDecode<Impl>::setDecodeQueue(TimeBuffer<DecodeStruct> *dq_ptr){    decodeQueue = dq_ptr;    // Setup wire to write information to proper place in decode queue.    toRename = decodeQueue->getWire(0);}template<class Impl>voidDefaultDecode<Impl>::setFetchQueue(TimeBuffer<FetchStruct> *fq_ptr){    fetchQueue = fq_ptr;    // Setup wire to read information from fetch queue.    fromFetch = fetchQueue->getWire(-fetchToDecodeDelay);}template<class Impl>voidDefaultDecode<Impl>::setActiveThreads(std::list<unsigned> *at_ptr){    activeThreads = at_ptr;}template <class Impl>boolDefaultDecode<Impl>::drain(){    // Decode is done draining at any time.    cpu->signalDrained();    return true;}template <class Impl>voidDefaultDecode<Impl>::takeOverFrom(){    _status = Inactive;    // Be sure to reset state and clear out any old instructions.    for (int i = 0; i < numThreads; ++i) {        decodeStatus[i] = Idle;        stalls[i].rename = false;        stalls[i].iew = false;        stalls[i].commit = false;        while (!insts[i].empty())            insts[i].pop();        while (!skidBuffer[i].empty())            skidBuffer[i].pop();        branchCount[i] = 0;    }    wroteToTimeBuffer = false;}template<class Impl>boolDefaultDecode<Impl>::checkStall(unsigned tid) const{    bool ret_val = false;    if (stalls[tid].rename) {        DPRINTF(Decode,"[tid:%i]: Stall fom Rename stage detected.\n", tid);        ret_val = true;    } else if (stalls[tid].iew) {        DPRINTF(Decode,"[tid:%i]: Stall fom IEW stage detected.\n", tid);        ret_val = true;    } else if (stalls[tid].commit) {        DPRINTF(Decode,"[tid:%i]: Stall fom Commit stage detected.\n", tid);        ret_val = true;    }    return ret_val;}template<class Impl>inline boolDefaultDecode<Impl>::fetchInstsValid(){    return fromFetch->size > 0;}template<class Impl>boolDefaultDecode<Impl>::block(unsigned tid){    DPRINTF(Decode, "[tid:%u]: Blocking.\n", tid);    // Add the current inputs to the skid buffer so they can be    // reprocessed when this stage unblocks.    skidInsert(tid);    // If the decode status is blocked or unblocking then decode has not yet    // signalled fetch to unblock. In that case, there is no need to tell    // fetch to block.    if (decodeStatus[tid] != Blocked) {        // Set the status to Blocked.        decodeStatus[tid] = Blocked;        if (decodeStatus[tid] != Unblocking) {            toFetch->decodeBlock[tid] = true;            wroteToTimeBuffer = true;        }        return true;    }    return false;}template<class Impl>boolDefaultDecode<Impl>::unblock(unsigned tid){    // Decode is done unblocking only if the skid buffer is empty.    if (skidBuffer[tid].empty()) {        DPRINTF(Decode, "[tid:%u]: Done unblocking.\n", tid);        toFetch->decodeUnblock[tid] = true;        wroteToTimeBuffer = true;        decodeStatus[tid] = Running;        return true;    }    DPRINTF(Decode, "[tid:%u]: Currently unblocking.\n", tid);    return false;}template<class Impl>voidDefaultDecode<Impl>::squash(DynInstPtr &inst, unsigned tid){    DPRINTF(Decode, "[tid:%i]: Squashing due to incorrect branch prediction "            "detected at decode.\n", tid);    // Send back mispredict information.    toFetch->decodeInfo[tid].branchMispredict = true;    toFetch->decodeInfo[tid].predIncorrect = true;    toFetch->decodeInfo[tid].doneSeqNum = inst->seqNum;    toFetch->decodeInfo[tid].squash = true;    toFetch->decodeInfo[tid].nextPC = inst->branchTarget();    ///FIXME There needs to be a way to set the nextPC and nextNPC    ///explicitly for ISAs with delay slots.    toFetch->decodeInfo[tid].nextNPC =        inst->branchTarget() + sizeof(TheISA::MachInst);    toFetch->decodeInfo[tid].nextMicroPC = inst->readMicroPC();#if ISA_HAS_DELAY_SLOT    toFetch->decodeInfo[tid].branchTaken = inst->readNextNPC() !=        (inst->readNextPC() + sizeof(TheISA::MachInst));#else    toFetch->decodeInfo[tid].branchTaken =        inst->readNextPC() != (inst->readPC() + sizeof(TheISA::MachInst));#endif    InstSeqNum squash_seq_num = inst->seqNum;    // Might have to tell fetch to unblock.    if (decodeStatus[tid] == Blocked ||        decodeStatus[tid] == Unblocking) {        toFetch->decodeUnblock[tid] = 1;    }    // Set status to squashing.    decodeStatus[tid] = Squashing;    for (int i=0; i<fromFetch->size; i++) {        if (fromFetch->insts[i]->threadNumber == tid &&            fromFetch->insts[i]->seqNum > squash_seq_num) {            fromFetch->insts[i]->setSquashed();        }    }    // Clear the instruction list and skid buffer in case they have any    // insts in them.    while (!insts[tid].empty()) {        insts[tid].pop();    }    while (!skidBuffer[tid].empty()) {        skidBuffer[tid].pop();    }    // Squash instructions up until this one    cpu->removeInstsUntil(squash_seq_num, tid);}template<class Impl>unsignedDefaultDecode<Impl>::squash(unsigned tid){    DPRINTF(Decode, "[tid:%i]: Squashing.\n",tid);    if (decodeStatus[tid] == Blocked ||        decodeStatus[tid] == Unblocking) {#if !FULL_SYSTEM        // In syscall emulation, we can have both a block and a squash due        // to a syscall in the same cycle.  This would cause both signals to        // be high.  This shouldn't happen in full system.        // @todo: Determine if this still happens.        if (toFetch->decodeBlock[tid]) {            toFetch->decodeBlock[tid] = 0;        } else {            toFetch->decodeUnblock[tid] = 1;        }#else        toFetch->decodeUnblock[tid] = 1;#endif    }    // Set status to squashing.    decodeStatus[tid] = Squashing;    // Go through incoming instructions from fetch and squash them.    unsigned squash_count = 0;    for (int i=0; i<fromFetch->size; i++) {        if (fromFetch->insts[i]->threadNumber == tid) {            fromFetch->insts[i]->setSquashed();            squash_count++;        }    }    // Clear the instruction list and skid buffer in case they have any    // insts in them.    while (!insts[tid].empty()) {        insts[tid].pop();    }    while (!skidBuffer[tid].empty()) {        skidBuffer[tid].pop();    }    return squash_count;}template<class Impl>voidDefaultDecode<Impl>::skidInsert(unsigned tid){    DynInstPtr inst = NULL;    while (!insts[tid].empty()) {        inst = insts[tid].front();        insts[tid].pop();        assert(tid == inst->threadNumber);        DPRINTF(Decode,"Inserting [sn:%lli] PC:%#x into decode skidBuffer %i\n",

⌨️ 快捷键说明

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