/*
 * Copyright (c) 2004-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "cpu/o3/decode.hh"

template<class Impl>
SimpleDecode<Impl>::SimpleDecode(Params &params)
    : renameToDecodeDelay(params.renameToDecodeDelay),
      iewToDecodeDelay(params.iewToDecodeDelay),
      commitToDecodeDelay(params.commitToDecodeDelay),
      fetchToDecodeDelay(params.fetchToDecodeDelay),
      decodeWidth(params.decodeWidth),
      numInst(0)
{
    DPRINTF(Decode, "Decode: decodeWidth=%i.\n", decodeWidth);
    _status = Idle;
}

template <class Impl>
void
SimpleDecode<Impl>::regStats()
{
    decodeIdleCycles
        .name(name() + ".decodeIdleCycles")
        .desc("Number of cycles decode is idle")
        .prereq(decodeIdleCycles);
    decodeBlockedCycles
        .name(name() + ".decodeBlockedCycles")
        .desc("Number of cycles decode is blocked")
        .prereq(decodeBlockedCycles);
    decodeUnblockCycles
        .name(name() + ".decodeUnblockCycles")
        .desc("Number of cycles decode is unblocking")
        .prereq(decodeUnblockCycles);
    decodeSquashCycles
        .name(name() + ".decodeSquashCycles")
        .desc("Number of cycles decode is squashing")
        .prereq(decodeSquashCycles);
    decodeBranchMispred
        .name(name() + ".decodeBranchMispred")
        .desc("Number of times decode detected a branch misprediction")
        .prereq(decodeBranchMispred);
    decodeControlMispred
        .name(name() + ".decodeControlMispred")
        .desc("Number of times decode detected an instruction incorrectly"
              " predicted as a control")
        .prereq(decodeControlMispred);
    decodeDecodedInsts
        .name(name() + ".decodeDecodedInsts")
        .desc("Number of instructions handled by decode")
        .prereq(decodeDecodedInsts);
    decodeSquashedInsts
        .name(name() + ".decodeSquashedInsts")
        .desc("Number of squashed instructions handled by decode")
        .prereq(decodeSquashedInsts);
}

template<class Impl>
void
SimpleDecode<Impl>::setCPU(FullCPU *cpu_ptr)
{
    DPRINTF(Decode, "Decode: Setting CPU pointer.\n");
    cpu = cpu_ptr;
}

template<class Impl>
void
SimpleDecode<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
{
    DPRINTF(Decode, "Decode: Setting time buffer pointer.\n");
    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>
void
SimpleDecode<Impl>::setDecodeQueue(TimeBuffer<DecodeStruct> *dq_ptr)
{
    DPRINTF(Decode, "Decode: Setting decode queue pointer.\n");
    decodeQueue = dq_ptr;

    // Setup wire to write information to proper place in decode queue.
    toRename = decodeQueue->getWire(0);
}

template<class Impl>
void
SimpleDecode<Impl>::setFetchQueue(TimeBuffer<FetchStruct> *fq_ptr)
{
    DPRINTF(Decode, "Decode: Setting fetch queue pointer.\n");
    fetchQueue = fq_ptr;

    // Setup wire to read information from fetch queue.
    fromFetch = fetchQueue->getWire(-fetchToDecodeDelay);
}

template<class Impl>
inline bool
SimpleDecode<Impl>::fetchInstsValid()
{
    return fromFetch->size > 0;
}

template<class Impl>
void
SimpleDecode<Impl>::block()
{
    DPRINTF(Decode, "Decode: Blocking.\n");

    // Set the status to Blocked.
    _status = Blocked;

    // Add the current inputs to the skid buffer so they can be
    // reprocessed when this stage unblocks.
    skidBuffer.push(*fromFetch);

    // Note that this stage only signals previous stages to stall when
    // it is the cause of the stall originates at this stage.  Otherwise
    // the previous stages are expected to check all possible stall signals.
}

template<class Impl>
inline void
SimpleDecode<Impl>::unblock()
{
    DPRINTF(Decode, "Decode: Unblocking, going to remove "
            "instructions from skid buffer.\n");
    // Remove the now processed instructions from the skid buffer.
    skidBuffer.pop();

    // If there's still information in the skid buffer, then
    // continue to tell previous stages to stall.  They will be
    // able to restart once the skid buffer is empty.
    if (!skidBuffer.empty()) {
        toFetch->decodeInfo.stall = true;
    } else {
        DPRINTF(Decode, "Decode: Finished unblocking.\n");
        _status = Running;
    }
}

// This squash is specifically for when Decode detects a PC-relative branch
// was predicted incorrectly.
template<class Impl>
void
SimpleDecode<Impl>::squash(DynInstPtr &inst)
{
    DPRINTF(Decode, "Decode: Squashing due to incorrect branch prediction "
                    "detected at decode.\n");
    Addr new_PC = inst->readNextPC();

    toFetch->decodeInfo.branchMispredict = true;
    toFetch->decodeInfo.doneSeqNum = inst->seqNum;
    toFetch->decodeInfo.predIncorrect = true;
    toFetch->decodeInfo.squash = true;
    toFetch->decodeInfo.nextPC = new_PC;
    toFetch->decodeInfo.branchTaken = true;

    // Set status to squashing.
    _status = Squashing;

    // Clear the skid buffer in case it has any data in it.
    while (!skidBuffer.empty()) {
        skidBuffer.pop();
    }

    // Squash instructions up until this one
    // Slightly unrealistic!
    cpu->removeInstsUntil(inst->seqNum);
}

template<class Impl>
void
SimpleDecode<Impl>::squash()
{
    DPRINTF(Decode, "Decode: Squashing.\n");
    // Set status to squashing.
    _status = Squashing;

    // Maybe advance the time buffer?  Not sure what to do in the normal
    // case.

    // Clear the skid buffer in case it has any data in it.
    while (!skidBuffer.empty())
    {
        skidBuffer.pop();
    }
}

template<class Impl>
void
SimpleDecode<Impl>::tick()
{
    // Decode should try to execute as many instructions as its bandwidth
    // will allow, as long as it is not currently blocked.
    if (_status != Blocked && _status != Squashing) {
        DPRINTF(Decode, "Decode: Not blocked, so attempting to run "
                        "stage.\n");
        // Make sure that the skid buffer has something in it if the
        // status is unblocking.
        assert(_status == Unblocking ? !skidBuffer.empty() : 1);

        decode();

        // If the status was unblocking, then instructions from the skid
        // buffer were used.  Remove those instructions and handle
        // the rest of unblocking.
        if (_status == Unblocking) {
            ++decodeUnblockCycles;

            if (fetchInstsValid()) {
                // Add the current inputs to the skid buffer so they can be
                // reprocessed when this stage unblocks.
                skidBuffer.push(*fromFetch);
            }

            unblock();
        }
    } else if (_status == Blocked) {
        ++decodeBlockedCycles;

        if (fetchInstsValid()) {
            block();
        }

        if (!fromRename->renameInfo.stall &&
            !fromIEW->iewInfo.stall &&
            !fromCommit->commitInfo.stall) {
            DPRINTF(Decode, "Decode: Stall signals cleared, going to "
                    "unblock.\n");
            _status = Unblocking;

            // Continue to tell previous stage to block until this
            // stage is done unblocking.
            toFetch->decodeInfo.stall = true;
        } else {
            DPRINTF(Decode, "Decode: Still blocked.\n");
            toFetch->decodeInfo.stall = true;
        }

        if (fromCommit->commitInfo.squash ||
            fromCommit->commitInfo.robSquashing) {
            squash();
        }
    } else if (_status == Squashing) {
        if (!fromCommit->commitInfo.squash &&
            !fromCommit->commitInfo.robSquashing) {
            _status = Running;
        } else if (fromCommit->commitInfo.squash) {
            ++decodeSquashCycles;

            squash();
        }
    }
}

template<class Impl>
void
SimpleDecode<Impl>::decode()
{
    // Check time buffer if being told to squash.
    if (fromCommit->commitInfo.squash) {
        squash();
        return;
    }

    // Check time buffer if being told to stall.
    if (fromRename->renameInfo.stall ||
        fromIEW->iewInfo.stall ||
        fromCommit->commitInfo.stall) {
        block();
        return;
    }

    // Check fetch queue to see if instructions are available.
    // If no available instructions, do nothing, unless this stage is
    // currently unblocking.
    if (!fetchInstsValid() && _status != Unblocking) {
        DPRINTF(Decode, "Decode: Nothing to do, breaking out early.\n");
        // Should I change the status to idle?
        ++decodeIdleCycles;
        return;
    }

    // Might be better to use a base DynInst * instead?
    DynInstPtr inst;

    unsigned to_rename_index = 0;

    int insts_available = _status == Unblocking ?
        skidBuffer.front().size - numInst :
        fromFetch->size;

    // Debug block...
#if 0
    if (insts_available) {
        DPRINTF(Decode, "Decode: Instructions available.\n");
    } else {
        if (_status == Unblocking && skidBuffer.empty()) {
            DPRINTF(Decode, "Decode: No instructions available, skid buffer "
                    "empty.\n");
        } else if (_status != Unblocking &&
                   !fromFetch->insts[0]) {
            DPRINTF(Decode, "Decode: No instructions available, fetch queue "
                    "empty.\n");
        } else {
            panic("Decode: No instructions available, unexpected condition!"
                  "\n");
        }
    }
#endif

    while (insts_available > 0)
    {
        DPRINTF(Decode, "Decode: Sending instruction to rename.\n");

        inst = _status == Unblocking ? skidBuffer.front().insts[numInst] :
               fromFetch->insts[numInst];

        DPRINTF(Decode, "Decode: Processing instruction %i with PC %#x\n",
                inst->seqNum, inst->readPC());

        if (inst->isSquashed()) {
            DPRINTF(Decode, "Decode: Instruction %i with PC %#x is "
                    "squashed, skipping.\n",
                    inst->seqNum, inst->readPC());

            ++decodeSquashedInsts;

            ++numInst;
            --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.
        // Isn't this handled by the inst queue?
        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[to_rename_index] = inst;

        ++(toRename->size);

        // Ensure that if it was predicted as a branch, it really is a
        // branch.
        if (inst->predTaken() && !inst->isControl()) {
            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);
            break;
        }

        // Go ahead and compute any PC-relative branches.

        if (inst->isDirectCtrl() && inst->isUncondCtrl()) {

            inst->setNextPC(inst->branchTarget());

            if (inst->mispredicted()) {
                ++decodeBranchMispred;
                // Might want to set some sort of boolean and just do
                // a check at the end
                squash(inst);
                break;
            }
        }

        // Normally can check if a direct branch has the right target
        // addr (either the immediate, or the branch PC + 4) and redirect
        // fetch if it's incorrect.

        // Increment which instruction we're looking at.
        ++numInst;
        ++to_rename_index;
        ++decodeDecodedInsts;

        --insts_available;
    }

     numInst = 0;
}
