/*
 * Copyright (c) 2013-2014,2018-2020 ARM Limited
 * All rights reserved
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * 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/minor/execute.hh"

#include <functional>

#include "cpu/minor/cpu.hh"
#include "cpu/minor/exec_context.hh"
#include "cpu/minor/fetch1.hh"
#include "cpu/minor/lsq.hh"
#include "cpu/op_class.hh"
#include "debug/Activity.hh"
#include "debug/Branch.hh"
#include "debug/Drain.hh"
#include "debug/ExecFaulting.hh"
#include "debug/MinorExecute.hh"
#include "debug/MinorInterrupt.hh"
#include "debug/MinorMem.hh"
#include "debug/MinorTrace.hh"
#include "debug/PCEvent.hh"

namespace gem5
{

GEM5_DEPRECATED_NAMESPACE(Minor, minor);
namespace minor
{

Execute::Execute(const std::string &name_,
    MinorCPU &cpu_,
    const BaseMinorCPUParams &params,
    Latch<ForwardInstData>::Output inp_,
    Latch<BranchData>::Input out_) :
    Named(name_),
    inp(inp_),
    out(out_),
    cpu(cpu_),
    issueLimit(params.executeIssueLimit),
    memoryIssueLimit(params.executeMemoryIssueLimit),
    commitLimit(params.executeCommitLimit),
    memoryCommitLimit(params.executeMemoryCommitLimit),
    processMoreThanOneInput(params.executeCycleInput),
    fuDescriptions(*params.executeFuncUnits),
    numFuncUnits(fuDescriptions.funcUnits.size()),
    setTraceTimeOnCommit(params.executeSetTraceTimeOnCommit),
    setTraceTimeOnIssue(params.executeSetTraceTimeOnIssue),
    allowEarlyMemIssue(params.executeAllowEarlyMemoryIssue),
    noCostFUIndex(fuDescriptions.funcUnits.size() + 1),
    lsq(name_ + ".lsq", name_ + ".dcache_port",
        cpu_, *this,
        params.executeMaxAccessesInMemory,
        params.executeMemoryWidth,
        params.executeLSQRequestsQueueSize,
        params.executeLSQTransfersQueueSize,
        params.executeLSQStoreBufferSize,
        params.executeLSQMaxStoreBufferStoresPerCycle),
    executeInfo(params.numThreads,
            ExecuteThreadInfo(params.executeCommitLimit)),
    interruptPriority(0),
    issuePriority(0),
    commitPriority(0)
{
    if (commitLimit < 1) {
        fatal("%s: executeCommitLimit must be >= 1 (%d)\n", name_,
            commitLimit);
    }

    if (issueLimit < 1) {
        fatal("%s: executeCommitLimit must be >= 1 (%d)\n", name_,
            issueLimit);
    }

    if (memoryIssueLimit < 1) {
        fatal("%s: executeMemoryIssueLimit must be >= 1 (%d)\n", name_,
            memoryIssueLimit);
    }

    if (memoryCommitLimit > commitLimit) {
        fatal("%s: executeMemoryCommitLimit (%d) must be <="
            " executeCommitLimit (%d)\n",
            name_, memoryCommitLimit, commitLimit);
    }

    if (params.executeInputBufferSize < 1) {
        fatal("%s: executeInputBufferSize must be >= 1 (%d)\n", name_,
        params.executeInputBufferSize);
    }

    if (params.executeInputBufferSize < 1) {
        fatal("%s: executeInputBufferSize must be >= 1 (%d)\n", name_,
        params.executeInputBufferSize);
    }

    /* This should be large enough to count all the in-FU instructions
     *  which need to be accounted for in the inFlightInsts
     *  queue */
    unsigned int total_slots = 0;

    /* Make FUPipelines for each MinorFU */
    for (unsigned int i = 0; i < numFuncUnits; i++) {
        std::ostringstream fu_name;
        MinorFU *fu_description = fuDescriptions.funcUnits[i];

        /* Note the total number of instruction slots (for sizing
         *  the inFlightInst queue) and the maximum latency of any FU
         *  (for sizing the activity recorder) */
        total_slots += fu_description->opLat;

        fu_name << name_ << ".fu." << i;

        FUPipeline *fu = new FUPipeline(fu_name.str(), *fu_description, cpu);

        funcUnits.push_back(fu);
    }

    /** Check that there is a functional unit for all operation classes */
    for (int op_class = No_OpClass + 1; op_class < Num_OpClasses; op_class++) {
        bool found_fu = false;
        unsigned int fu_index = 0;

        while (fu_index < numFuncUnits && !found_fu)
        {
            if (funcUnits[fu_index]->provides(
                static_cast<OpClass>(op_class)))
            {
                found_fu = true;
            }
            fu_index++;
        }

        if (!found_fu) {
            warn("No functional unit for OpClass %s\n",
                enums::OpClassStrings[op_class]);
        }
    }

    /* Per-thread structures */
    for (ThreadID tid = 0; tid < params.numThreads; tid++) {
        std::string tid_str = std::to_string(tid);

        /* Input Buffers */
        inputBuffer.push_back(
            InputBuffer<ForwardInstData>(
                name_ + ".inputBuffer" + tid_str, "insts",
                params.executeInputBufferSize));

        const auto &regClasses = cpu.threads[tid]->getIsaPtr()->regClasses();

        /* Scoreboards */
        scoreboard.emplace_back(name_ + ".scoreboard" + tid_str, regClasses);

        /* In-flight instruction records */
        executeInfo[tid].inFlightInsts =  new Queue<QueuedInst,
            ReportTraitsAdaptor<QueuedInst> >(
            name_ + ".inFlightInsts" + tid_str, "insts", total_slots);

        executeInfo[tid].inFUMemInsts = new Queue<QueuedInst,
            ReportTraitsAdaptor<QueuedInst> >(
            name_ + ".inFUMemInsts" + tid_str, "insts", total_slots);
    }
}

const ForwardInstData *
Execute::getInput(ThreadID tid)
{
    /* Get a line from the inputBuffer to work with */
    if (!inputBuffer[tid].empty()) {
        const ForwardInstData &head = inputBuffer[tid].front();

        return (head.isBubble() ? NULL : &(inputBuffer[tid].front()));
    } else {
        return NULL;
    }
}

void
Execute::popInput(ThreadID tid)
{
    if (!inputBuffer[tid].empty())
        inputBuffer[tid].pop();

    executeInfo[tid].inputIndex = 0;
}

void
Execute::tryToBranch(MinorDynInstPtr inst, Fault fault, BranchData &branch)
{
    ThreadContext *thread = cpu.getContext(inst->id.threadId);
    const std::unique_ptr<PCStateBase> pc_before(inst->pc->clone());
    std::unique_ptr<PCStateBase> target(thread->pcState().clone());

    /* Force a branch for SerializeAfter/SquashAfter instructions
     * at the end of micro-op sequence when we're not suspended */
    bool force_branch = thread->status() != ThreadContext::Suspended &&
        !inst->isFault() &&
        inst->isLastOpInInst() &&
        (inst->staticInst->isSerializeAfter() ||
         inst->staticInst->isSquashAfter());

    DPRINTF(Branch, "tryToBranch before: %s after: %s%s\n",
        *pc_before, *target, (force_branch ? " (forcing)" : ""));

    /* Will we change the PC to something other than the next instruction? */
    bool must_branch = *pc_before != *target ||
        fault != NoFault ||
        force_branch;

    /* The reason for the branch data we're about to generate, set below */
    BranchData::Reason reason = BranchData::NoBranch;

    if (fault == NoFault) {
        inst->staticInst->advancePC(*target);
        thread->pcState(*target);

        DPRINTF(Branch, "Advancing current PC from: %s to: %s\n",
            *pc_before, *target);
    }

    if (inst->predictedTaken && !force_branch) {
        /* Predicted to branch */
        if (!must_branch) {
            /* No branch was taken, change stream to get us back to the
             *  intended PC value */
            DPRINTF(Branch, "Predicted a branch from 0x%x to 0x%x but"
                " none happened inst: %s\n",
                inst->pc->instAddr(), inst->predictedTarget->instAddr(),
                *inst);

            reason = BranchData::BadlyPredictedBranch;
        } else if (*inst->predictedTarget == *target) {
            /* Branch prediction got the right target, kill the branch and
             *  carry on.
             *  Note that this information to the branch predictor might get
             *  overwritten by a "real" branch during this cycle */
            DPRINTF(Branch, "Predicted a branch from 0x%x to 0x%x correctly"
                " inst: %s\n",
                inst->pc->instAddr(), inst->predictedTarget->instAddr(),
                *inst);

            reason = BranchData::CorrectlyPredictedBranch;
        } else {
            /* Branch prediction got the wrong target */
            DPRINTF(Branch, "Predicted a branch from 0x%x to 0x%x"
                    " but got the wrong target (actual: 0x%x) inst: %s\n",
                    inst->pc->instAddr(), inst->predictedTarget->instAddr(),
                    target->instAddr(), *inst);

            reason = BranchData::BadlyPredictedBranchTarget;
        }
    } else if (must_branch) {
        /* Unpredicted branch */
        DPRINTF(Branch, "Unpredicted branch from 0x%x to 0x%x inst: %s\n",
            inst->pc->instAddr(), target->instAddr(), *inst);

        reason = BranchData::UnpredictedBranch;
    } else {
        /* No branch at all */
        reason = BranchData::NoBranch;
    }

    updateBranchData(inst->id.threadId, reason, inst, *target, branch);
}

void
Execute::updateBranchData(
    ThreadID tid,
    BranchData::Reason reason,
    MinorDynInstPtr inst, const PCStateBase &target,
    BranchData &branch)
{
    if (reason != BranchData::NoBranch) {
        /* Bump up the stream sequence number on a real branch*/
        if (BranchData::isStreamChange(reason))
            executeInfo[tid].streamSeqNum++;

        /* Branches (even mis-predictions) don't change the predictionSeqNum,
         *  just the streamSeqNum */
        branch = BranchData(reason, tid,
            executeInfo[tid].streamSeqNum,
            /* Maintaining predictionSeqNum if there's no inst is just a
             * courtesy and looks better on minorview */
            (inst->isBubble() ? executeInfo[tid].lastPredictionSeqNum
                : inst->id.predictionSeqNum),
            target, inst);

        DPRINTF(Branch, "Branch data signalled: %s\n", branch);
    }
}

void
Execute::handleMemResponse(MinorDynInstPtr inst,
    LSQ::LSQRequestPtr response, BranchData &branch, Fault &fault)
{
    ThreadID thread_id = inst->id.threadId;
    ThreadContext *thread = cpu.getContext(thread_id);

    ExecContext context(cpu, *cpu.threads[thread_id], *this, inst);

    PacketPtr packet = response->packet;

    bool is_load = inst->staticInst->isLoad();
    bool is_store = inst->staticInst->isStore();
    bool is_atomic = inst->staticInst->isAtomic();
    bool is_prefetch = inst->staticInst->isDataPrefetch();

    /* If true, the trace's predicate value will be taken from the exec
     *  context predicate, otherwise, it will be set to false */
    bool use_context_predicate = true;

    if (inst->translationFault != NoFault) {
        /* Invoke memory faults. */
        DPRINTF(MinorMem, "Completing fault from DTLB access: %s\n",
            inst->translationFault->name());

        if (inst->staticInst->isPrefetch()) {
            DPRINTF(MinorMem, "Not taking fault on prefetch: %s\n",
                inst->translationFault->name());

            /* Don't assign to fault */
        } else {
            /* Take the fault raised during the TLB/memory access */
            fault = inst->translationFault;

            fault->invoke(thread, inst->staticInst);
        }
    } else if (!packet) {
        DPRINTF(MinorMem, "Completing failed request inst: %s\n",
            *inst);
        use_context_predicate = false;
        if (!context.readMemAccPredicate())
            inst->staticInst->completeAcc(nullptr, &context, inst->traceData);
    } else if (packet->isError()) {
        DPRINTF(MinorMem, "Trying to commit error response: %s\n",
            *inst);

        fatal("Received error response packet for inst: %s\n", *inst);
    } else if (is_store || is_load || is_prefetch || is_atomic) {
        assert(packet);

        DPRINTF(MinorMem, "Memory response inst: %s addr: 0x%x size: %d\n",
            *inst, packet->getAddr(), packet->getSize());

        if (is_load && packet->getSize() > 0) {
            DPRINTF(MinorMem, "Memory data[0]: 0x%x\n",
                static_cast<unsigned int>(packet->getConstPtr<uint8_t>()[0]));
        }

        /* Complete the memory access instruction */
        fault = inst->staticInst->completeAcc(packet, &context,
            inst->traceData);

        if (fault != NoFault) {
            /* Invoke fault created by instruction completion */
            DPRINTF(MinorMem, "Fault in memory completeAcc: %s\n",
                fault->name());
            fault->invoke(thread, inst->staticInst);
        } else {
            /* Stores need to be pushed into the store buffer to finish
             *  them off */
            if (response->needsToBeSentToStoreBuffer())
                lsq.sendStoreToStoreBuffer(response);
        }
    } else {
        fatal("There should only ever be reads, "
            "writes or faults at this point\n");
    }

    lsq.popResponse(response);

    if (inst->traceData) {
        inst->traceData->setPredicate((use_context_predicate ?
            context.readPredicate() : false));
    }

    doInstCommitAccounting(inst);

    /* Generate output to account for branches */
    tryToBranch(inst, fault, branch);
}

bool
Execute::isInterrupted(ThreadID thread_id) const
{
    return cpu.checkInterrupts(thread_id);
}

bool
Execute::takeInterrupt(ThreadID thread_id, BranchData &branch)
{
    DPRINTF(MinorInterrupt, "Considering interrupt status from PC: %s\n",
        cpu.getContext(thread_id)->pcState());

    Fault interrupt = cpu.getInterruptController(thread_id)->getInterrupt();

    if (interrupt != NoFault) {
        /* The interrupt *must* set pcState */
        cpu.getInterruptController(thread_id)->updateIntrInfo();
        interrupt->invoke(cpu.getContext(thread_id));

        assert(!lsq.accessesInFlight());

        DPRINTF(MinorInterrupt, "Invoking interrupt: %s to PC: %s\n",
            interrupt->name(), cpu.getContext(thread_id)->pcState());

        /* Assume that an interrupt *must* cause a branch.  Assert this? */

        updateBranchData(thread_id, BranchData::Interrupt,
            MinorDynInst::bubble(), cpu.getContext(thread_id)->pcState(),
            branch);
    }

    return interrupt != NoFault;
}

bool
Execute::executeMemRefInst(MinorDynInstPtr inst, BranchData &branch,
    bool &passed_predicate, Fault &fault)
{
    bool issued = false;

    /* Set to true if the mem op. is issued and sent to the mem system */
    passed_predicate = false;

    if (!lsq.canRequest()) {
        /* Not acting on instruction yet as the memory
         * queues are full */
        issued = false;
    } else {
        ThreadContext *thread = cpu.getContext(inst->id.threadId);
        std::unique_ptr<PCStateBase> old_pc(thread->pcState().clone());

        ExecContext context(cpu, *cpu.threads[inst->id.threadId], *this, inst);

        DPRINTF(MinorExecute, "Initiating memRef inst: %s\n", *inst);

        Fault init_fault = inst->staticInst->initiateAcc(&context,
            inst->traceData);

        if (inst->inLSQ) {
            if (init_fault != NoFault) {
                assert(inst->translationFault != NoFault);
                // Translation faults are dealt with in handleMemResponse()
                init_fault = NoFault;
            } else {
                // If we have a translation fault then it got suppressed  by
                // initateAcc()
                inst->translationFault = NoFault;
            }
        }

        if (init_fault != NoFault) {
            DPRINTF(MinorExecute, "Fault on memory inst: %s"
                " initiateAcc: %s\n", *inst, init_fault->name());
            fault = init_fault;
        } else {
            /* Only set this if the instruction passed its
             * predicate */
            if (!context.readMemAccPredicate()) {
                DPRINTF(MinorMem, "No memory access for inst: %s\n", *inst);
                assert(context.readPredicate());
            }
            passed_predicate = context.readPredicate();

            /* Set predicate in tracing */
            if (inst->traceData)
                inst->traceData->setPredicate(passed_predicate);

            /* If the instruction didn't pass its predicate
             * or it is a predicated vector instruction and the
             * associated predicate register is all-false (and so will not
             * progress from here)  Try to branch to correct and branch
             * mis-prediction. */
            if (!inst->inLSQ) {
                /* Leave it up to commit to handle the fault */
                lsq.pushFailedRequest(inst);
                inst->inLSQ = true;
            }
        }

        /* Restore thread PC */
        thread->pcState(*old_pc);
        issued = true;
    }

    return issued;
}

/** Increment a cyclic buffer index for indices [0, cycle_size-1] */
inline unsigned int
cyclicIndexInc(unsigned int index, unsigned int cycle_size)
{
    unsigned int ret = index + 1;

    if (ret == cycle_size)
        ret = 0;

    return ret;
}

/** Decrement a cyclic buffer index for indices [0, cycle_size-1] */
inline unsigned int
cyclicIndexDec(unsigned int index, unsigned int cycle_size)
{
    int ret = index - 1;

    if (ret < 0)
        ret = cycle_size - 1;

    return ret;
}

unsigned int
Execute::issue(ThreadID thread_id)
{
    const ForwardInstData *insts_in = getInput(thread_id);
    ExecuteThreadInfo &thread = executeInfo[thread_id];

    /* Early termination if we have no instructions */
    if (!insts_in)
        return 0;

    /* Start from the first FU */
    unsigned int fu_index = 0;

    /* Remains true while instructions are still being issued.  If any
     *  instruction fails to issue, this is set to false and we exit issue.
     *  This strictly enforces in-order issue.  For other issue behaviours,
     *  a more complicated test in the outer while loop below is needed. */
    bool issued = true;

    /* Number of insts issues this cycle to check for issueLimit */
    unsigned num_insts_issued = 0;

    /* Number of memory ops issues this cycle to check for memoryIssueLimit */
    unsigned num_mem_insts_issued = 0;

    /* Number of instructions discarded this cycle in order to enforce a
     *  discardLimit. @todo, add that parameter? */
    unsigned num_insts_discarded = 0;

    do {
        MinorDynInstPtr inst = insts_in->insts[thread.inputIndex];
        Fault fault = inst->fault;
        bool discarded = false;
        bool issued_mem_ref = false;

        if (inst->isBubble()) {
            /* Skip */
            issued = true;
        } else if (cpu.getContext(thread_id)->status() ==
            ThreadContext::Suspended)
        {
            DPRINTF(MinorExecute, "Discarding inst: %s from suspended"
                " thread\n", *inst);

            issued = true;
            discarded = true;
        } else if (inst->id.streamSeqNum != thread.streamSeqNum) {
            DPRINTF(MinorExecute, "Discarding inst: %s as its stream"
                " state was unexpected, expected: %d\n",
                *inst, thread.streamSeqNum);
            issued = true;
            discarded = true;
        } else {
            /* Try and issue an instruction into an FU, assume we didn't and
             * fix that in the loop */
            issued = false;

            /* Try FU from 0 each instruction */
            fu_index = 0;

            /* Try and issue a single instruction stepping through the
             *  available FUs */
            do {
                FUPipeline *fu = funcUnits[fu_index];

                DPRINTF(MinorExecute, "Trying to issue inst: %s to FU: %d\n",
                    *inst, fu_index);

                /* Does the examined fu have the OpClass-related capability
                 *  needed to execute this instruction?  Faults can always
                 *  issue to any FU but probably should just 'live' in the
                 *  inFlightInsts queue rather than having an FU. */
                bool fu_is_capable = (!inst->isFault() ?
                    fu->provides(inst->staticInst->opClass()) : true);

                if (inst->isNoCostInst()) {
                    /* Issue free insts. to a fake numbered FU */
                    fu_index = noCostFUIndex;

                    /* And start the countdown on activity to allow
                     *  this instruction to get to the end of its FU */
                    cpu.activityRecorder->activity();

                    /* Mark the destinations for this instruction as
                     *  busy */
                    scoreboard[thread_id].markupInstDests(inst, cpu.curCycle() +
                        Cycles(0), cpu.getContext(thread_id), false);

                    DPRINTF(MinorExecute, "Issuing %s to %d\n", inst->id, noCostFUIndex);
                    inst->fuIndex = noCostFUIndex;
                    inst->extraCommitDelay = Cycles(0);
                    inst->extraCommitDelayExpr = NULL;

                    /* Push the instruction onto the inFlight queue so
                     *  it can be committed in order */
                    QueuedInst fu_inst(inst);
                    thread.inFlightInsts->push(fu_inst);

                    issued = true;

                } else if (!fu_is_capable || fu->alreadyPushed()) {
                    /* Skip */
                    if (!fu_is_capable) {
                        DPRINTF(MinorExecute, "Can't issue as FU: %d isn't"
                            " capable\n", fu_index);
                    } else {
                        DPRINTF(MinorExecute, "Can't issue as FU: %d is"
                            " already busy\n", fu_index);
                    }
                } else if (fu->stalled) {
                    DPRINTF(MinorExecute, "Can't issue inst: %s into FU: %d,"
                        " it's stalled\n",
                        *inst, fu_index);
                } else if (!fu->canInsert()) {
                    DPRINTF(MinorExecute, "Can't issue inst: %s to busy FU"
                        " for another: %d cycles\n",
                        *inst, fu->cyclesBeforeInsert());
                } else {
                    MinorFUTiming *timing = (!inst->isFault() ?
                        fu->findTiming(inst->staticInst) : NULL);

                    const std::vector<Cycles> *src_latencies =
                        (timing ? &(timing->srcRegsRelativeLats)
                            : NULL);

                    const std::vector<bool> *cant_forward_from_fu_indices =
                        &(fu->cantForwardFromFUIndices);

                    if (timing && timing->suppress) {
                        DPRINTF(MinorExecute, "Can't issue inst: %s as extra"
                            " decoding is suppressing it\n",
                            *inst);
                    } else if (!scoreboard[thread_id].canInstIssue(inst,
                        src_latencies, cant_forward_from_fu_indices,
                        cpu.curCycle(), cpu.getContext(thread_id)))
                    {
                        DPRINTF(MinorExecute, "Can't issue inst: %s yet\n",
                            *inst);
                    } else {
                        /* Can insert the instruction into this FU */
                        DPRINTF(MinorExecute, "Issuing inst: %s"
                            " into FU %d\n", *inst,
                            fu_index);

                        Cycles extra_dest_retire_lat = Cycles(0);
                        TimingExpr *extra_dest_retire_lat_expr = NULL;
                        Cycles extra_assumed_lat = Cycles(0);

                        /* Add the extraCommitDelay and extraAssumeLat to
                         *  the FU pipeline timings */
                        if (timing) {
                            extra_dest_retire_lat =
                                timing->extraCommitLat;
                            extra_dest_retire_lat_expr =
                                timing->extraCommitLatExpr;
                            extra_assumed_lat =
                                timing->extraAssumedLat;
                        }

                        issued_mem_ref = inst->isMemRef();

                        QueuedInst fu_inst(inst);

                        /* Decorate the inst with FU details */
                        inst->fuIndex = fu_index;
                        inst->extraCommitDelay = extra_dest_retire_lat;
                        inst->extraCommitDelayExpr =
                            extra_dest_retire_lat_expr;

                        if (issued_mem_ref) {
                            /* Remember which instruction this memory op
                             *  depends on so that initiateAcc can be called
                             *  early */
                            if (allowEarlyMemIssue) {
                                inst->instToWaitFor =
                                    scoreboard[thread_id].execSeqNumToWaitFor(inst,
                                        cpu.getContext(thread_id));

                                if (lsq.getLastMemBarrier(thread_id) >
                                    inst->instToWaitFor)
                                {
                                    DPRINTF(MinorExecute, "A barrier will"
                                        " cause a delay in mem ref issue of"
                                        " inst: %s until after inst"
                                        " %d(exec)\n", *inst,
                                        lsq.getLastMemBarrier(thread_id));

                                    inst->instToWaitFor =
                                        lsq.getLastMemBarrier(thread_id);
                                } else {
                                    DPRINTF(MinorExecute, "Memory ref inst:"
                                        " %s must wait for inst %d(exec)"
                                        " before issuing\n",
                                        *inst, inst->instToWaitFor);
                                }

                                inst->canEarlyIssue = true;
                            }
                            /* Also queue this instruction in the memory ref
                             *  queue to ensure in-order issue to the LSQ */
                            DPRINTF(MinorExecute, "Pushing mem inst: %s\n",
                                *inst);
                            thread.inFUMemInsts->push(fu_inst);
                        }

                        /* Issue to FU */
                        fu->push(fu_inst);
                        /* And start the countdown on activity to allow
                         *  this instruction to get to the end of its FU */
                        cpu.activityRecorder->activity();

                        /* Mark the destinations for this instruction as
                         *  busy */
                        scoreboard[thread_id].markupInstDests(inst, cpu.curCycle() +
                            fu->description.opLat +
                            extra_dest_retire_lat +
                            extra_assumed_lat,
                            cpu.getContext(thread_id),
                            issued_mem_ref && extra_assumed_lat == Cycles(0));

                        /* Push the instruction onto the inFlight queue so
                         *  it can be committed in order */
                        thread.inFlightInsts->push(fu_inst);

                        issued = true;
                    }
                }

                fu_index++;
            } while (fu_index != numFuncUnits && !issued);

            if (!issued)
                DPRINTF(MinorExecute, "Didn't issue inst: %s\n", *inst);
        }

        if (issued) {
            /* Generate MinorTrace's MinorInst lines.  Do this at commit
             *  to allow better instruction annotation? */
            if (debug::MinorTrace && !inst->isBubble()) {
                inst->minorTraceInst(*this);
            }

            /* Mark up barriers in the LSQ */
            if (!discarded && inst->isInst() &&
                inst->staticInst->isFullMemBarrier())
            {
                DPRINTF(MinorMem, "Issuing memory barrier inst: %s\n", *inst);
                lsq.issuedMemBarrierInst(inst);
            }

            if (inst->traceData && setTraceTimeOnIssue) {
                inst->traceData->setWhen(curTick());
            }

            if (issued_mem_ref)
                num_mem_insts_issued++;

            if (discarded) {
                num_insts_discarded++;
            } else if (!inst->isBubble()) {
                num_insts_issued++;

                if (num_insts_issued == issueLimit)
                    DPRINTF(MinorExecute, "Reached inst issue limit\n");
            }

            thread.inputIndex++;
            DPRINTF(MinorExecute, "Stepping to next inst inputIndex: %d\n",
                thread.inputIndex);
        }

        /* Got to the end of a line */
        if (thread.inputIndex == insts_in->width()) {
            popInput(thread_id);
            /* Set insts_in to null to force us to leave the surrounding
             *  loop */
            insts_in = NULL;

            if (processMoreThanOneInput) {
                DPRINTF(MinorExecute, "Wrapping\n");
                insts_in = getInput(thread_id);
            }
        }
    } while (insts_in && thread.inputIndex < insts_in->width() &&
        /* We still have instructions */
        fu_index != numFuncUnits && /* Not visited all FUs */
        issued && /* We've not yet failed to issue an instruction */
        num_insts_issued != issueLimit && /* Still allowed to issue */
        num_mem_insts_issued != memoryIssueLimit);

    return num_insts_issued;
}

bool
Execute::tryPCEvents(ThreadID thread_id)
{
    ThreadContext *thread = cpu.getContext(thread_id);
    unsigned int num_pc_event_checks = 0;

    /* Handle PC events on instructions */
    Addr oldPC;
    do {
        oldPC = thread->pcState().instAddr();
        cpu.threads[thread_id]->pcEventQueue.service(oldPC, thread);
        num_pc_event_checks++;
    } while (oldPC != thread->pcState().instAddr());

    if (num_pc_event_checks > 1) {
        DPRINTF(PCEvent, "Acting on PC Event to PC: %s\n",
            thread->pcState());
    }

    return num_pc_event_checks > 1;
}

void
Execute::doInstCommitAccounting(MinorDynInstPtr inst)
{
    assert(!inst->isFault());

    MinorThread *thread = cpu.threads[inst->id.threadId];

    /* Increment the many and various inst and op counts in the
     *  thread and system */
    if (!inst->staticInst->isMicroop() || inst->staticInst->isLastMicroop())
    {
        thread->numInst++;
        thread->threadStats.numInsts++;
        cpu.stats.numInsts++;

        /* Act on events related to instruction counts */
        thread->comInstEventQueue.serviceEvents(thread->numInst);
    }
    thread->numOp++;
    thread->threadStats.numOps++;
    cpu.stats.numOps++;
    cpu.stats.committedInstType[inst->id.threadId]
                               [inst->staticInst->opClass()]++;

    /** Add a count for every control instruction */
    if (inst->staticInst->isControl()) {
        if (inst->staticInst->isReturn()) {
            cpu.stats.committedControl[inst->id.threadId]
                        [gem5::StaticInstFlags::Flags::IsReturn]++;
        }
        if (inst->staticInst->isCall()) {
            cpu.stats.committedControl[inst->id.threadId]
                        [gem5::StaticInstFlags::Flags::IsCall]++;
        }
        if (inst->staticInst->isDirectCtrl()) {
            cpu.stats.committedControl[inst->id.threadId]
                        [gem5::StaticInstFlags::Flags::IsDirectControl]++;
        }
        if (inst->staticInst->isIndirectCtrl()) {
            cpu.stats.committedControl[inst->id.threadId]
                        [gem5::StaticInstFlags::Flags::IsIndirectControl]++;
        }
        if (inst->staticInst->isCondCtrl()) {
            cpu.stats.committedControl[inst->id.threadId]
                        [gem5::StaticInstFlags::Flags::IsCondControl]++;
        }
        if (inst->staticInst->isUncondCtrl()) {
            cpu.stats.committedControl[inst->id.threadId]
                        [gem5::StaticInstFlags::Flags::IsUncondControl]++;

        }
        cpu.stats.committedControl[inst->id.threadId]
                        [gem5::StaticInstFlags::Flags::IsControl]++;
    }



    /* Set the CP SeqNum to the numOps commit number */
    if (inst->traceData)
        inst->traceData->setCPSeq(thread->numOp);

    cpu.probeInstCommit(inst->staticInst, inst->pc->instAddr());
}

bool
Execute::commitInst(MinorDynInstPtr inst, bool early_memory_issue,
    BranchData &branch, Fault &fault, bool &committed,
    bool &completed_mem_issue)
{
    ThreadID thread_id = inst->id.threadId;
    ThreadContext *thread = cpu.getContext(thread_id);

    bool completed_inst = true;
    fault = NoFault;

    /* Is the thread for this instruction suspended?  In that case, just
     *  stall as long as there are no pending interrupts */
    if (thread->status() == ThreadContext::Suspended &&
        !isInterrupted(thread_id))
    {
        panic("We should never hit the case where we try to commit from a "
              "suspended thread as the streamSeqNum should not match");
    } else if (inst->isFault()) {
        ExecContext context(cpu, *cpu.threads[thread_id], *this, inst);

        DPRINTF(MinorExecute, "Fault inst reached Execute: %s\n",
            inst->fault->name());

        fault = inst->fault;
        inst->fault->invoke(thread, NULL);

        tryToBranch(inst, fault, branch);
    } else if (inst->staticInst->isMemRef()) {
        /* Memory accesses are executed in two parts:
         *  executeMemRefInst -- calculates the EA and issues the access
         *      to memory.  This is done here.
         *  handleMemResponse -- handles the response packet, done by
         *      Execute::commit
         *
         *  While the memory access is in its FU, the EA is being
         *  calculated.  At the end of the FU, when it is ready to
         *  'commit' (in this function), the access is presented to the
         *  memory queues.  When a response comes back from memory,
         *  Execute::commit will commit it.
         */
        bool predicate_passed = false;
        bool completed_mem_inst = executeMemRefInst(inst, branch,
            predicate_passed, fault);

        if (completed_mem_inst && fault != NoFault) {
            if (early_memory_issue) {
                DPRINTF(MinorExecute, "Fault in early executing inst: %s\n",
                    fault->name());
                /* Don't execute the fault, just stall the instruction
                 *  until it gets to the head of inFlightInsts */
                inst->canEarlyIssue = false;
                /* Not completed as we'll come here again to pick up
                 * the fault when we get to the end of the FU */
                completed_inst = false;
            } else {
                DPRINTF(MinorExecute, "Fault in execute: %s\n",
                    fault->name());
                fault->invoke(thread, NULL);

                tryToBranch(inst, fault, branch);
                completed_inst = true;
            }
        } else {
            completed_inst = completed_mem_inst;
        }
        completed_mem_issue = completed_inst;
    } else if (inst->isInst() && inst->staticInst->isFullMemBarrier() &&
        !lsq.canPushIntoStoreBuffer())
    {
        DPRINTF(MinorExecute, "Can't commit data barrier inst: %s yet as"
            " there isn't space in the store buffer\n", *inst);

        completed_inst = false;
    } else if (inst->isInst() && inst->staticInst->isQuiesce()
            && !branch.isBubble()){
        /* This instruction can suspend, need to be able to communicate
         * backwards, so no other branches may evaluate this cycle*/
        completed_inst = false;
    } else {
        ExecContext context(cpu, *cpu.threads[thread_id], *this, inst);

        DPRINTF(MinorExecute, "Committing inst: %s\n", *inst);

        fault = inst->staticInst->execute(&context,
            inst->traceData);

        /* Set the predicate for tracing and dump */
        if (inst->traceData)
            inst->traceData->setPredicate(context.readPredicate());

        committed = true;

        if (fault != NoFault) {
            if (inst->traceData) {
                if (debug::ExecFaulting) {
                    inst->traceData->setFaulting(true);
                } else {
                    delete inst->traceData;
                    inst->traceData = NULL;
                }
            }

            DPRINTF(MinorExecute, "Fault in execute of inst: %s fault: %s\n",
                *inst, fault->name());
            fault->invoke(thread, inst->staticInst);
        }

        doInstCommitAccounting(inst);
        tryToBranch(inst, fault, branch);
    }

    if (completed_inst) {
        /* Keep a copy of this instruction's predictionSeqNum just in case
         * we need to issue a branch without an instruction (such as an
         * interrupt) */
        executeInfo[thread_id].lastPredictionSeqNum = inst->id.predictionSeqNum;

        /* Check to see if this instruction suspended the current thread. */
        if (!inst->isFault() &&
            thread->status() == ThreadContext::Suspended &&
            branch.isBubble() && /* It didn't branch too */
            !isInterrupted(thread_id)) /* Don't suspend if we have
                interrupts */
        {
            auto &resume_pc = cpu.getContext(thread_id)->pcState();

            assert(resume_pc.microPC() == 0);

            DPRINTF(MinorInterrupt, "Suspending thread: %d from Execute"
                " inst: %s\n", thread_id, *inst);

            cpu.stats.numFetchSuspends++;

            updateBranchData(thread_id, BranchData::SuspendThread, inst,
                resume_pc, branch);
        }
    }

    return completed_inst;
}

void
Execute::commit(ThreadID thread_id, bool only_commit_microops, bool discard,
    BranchData &branch)
{
    Fault fault = NoFault;
    Cycles now = cpu.curCycle();
    ExecuteThreadInfo &ex_info = executeInfo[thread_id];

    /**
     * Try and execute as many instructions from the end of FU pipelines as
     *  possible.  This *doesn't* include actually advancing the pipelines.
     *
     * We do this by looping on the front of the inFlightInsts queue for as
     *  long as we can find the desired instruction at the end of the
     *  functional unit it was issued to without seeing a branch or a fault.
     *  In this function, these terms are used:
     *      complete -- The instruction has finished its passage through
     *          its functional unit and its fate has been decided
     *          (committed, discarded, issued to the memory system)
     *      commit -- The instruction is complete(d), not discarded and has
     *          its effects applied to the CPU state
     *      discard(ed) -- The instruction is complete but not committed
     *          as its streamSeqNum disagrees with the current
     *          Execute::streamSeqNum
     *
     *  Commits are also possible from two other places:
     *
     *  1) Responses returning from the LSQ
     *  2) Mem ops issued to the LSQ ('committed' from the FUs) earlier
     *      than their position in the inFlightInsts queue, but after all
     *      their dependencies are resolved.
     */

    /* Has an instruction been completed?  Once this becomes false, we stop
     *  trying to complete instructions. */
    bool completed_inst = true;

    /* Number of insts committed this cycle to check against commitLimit */
    unsigned int num_insts_committed = 0;

    /* Number of memory access instructions committed to check against
     *  memCommitLimit */
    unsigned int num_mem_refs_committed = 0;

    if (only_commit_microops && !ex_info.inFlightInsts->empty()) {
        DPRINTF(MinorInterrupt, "Only commit microops %s %d\n",
            *(ex_info.inFlightInsts->front().inst),
            ex_info.lastCommitWasEndOfMacroop);
    }

    while (!ex_info.inFlightInsts->empty() && /* Some more instructions to process */
        !branch.isStreamChange() && /* No real branch */
        fault == NoFault && /* No faults */
        completed_inst && /* Still finding instructions to execute */
        num_insts_committed != commitLimit /* Not reached commit limit */
        )
    {
        if (only_commit_microops) {
            DPRINTF(MinorInterrupt, "Committing tail of insts before"
                " interrupt: %s\n",
                *(ex_info.inFlightInsts->front().inst));
        }

        QueuedInst *head_inflight_inst = &(ex_info.inFlightInsts->front());

        InstSeqNum head_exec_seq_num =
            head_inflight_inst->inst->id.execSeqNum;

        /* The instruction we actually process if completed_inst
         *  remains true to the end of the loop body.
         *  Start by considering the the head of the in flight insts queue */
        MinorDynInstPtr inst = head_inflight_inst->inst;

        bool committed_inst = false;
        bool discard_inst = false;
        bool completed_mem_ref = false;
        bool issued_mem_ref = false;
        bool early_memory_issue = false;

        /* Must set this again to go around the loop */
        completed_inst = false;

        /* If we're just completing a macroop before an interrupt or drain,
         *  can we stil commit another microop (rather than a memory response)
         *  without crosing into the next full instruction? */
        bool can_commit_insts = !ex_info.inFlightInsts->empty() &&
            !(only_commit_microops && ex_info.lastCommitWasEndOfMacroop);

        /* Can we find a mem response for this inst */
        LSQ::LSQRequestPtr mem_response =
            (inst->inLSQ ? lsq.findResponse(inst) : NULL);

        DPRINTF(MinorExecute, "Trying to commit canCommitInsts: %d\n",
            can_commit_insts);

        /* Test for PC events after every instruction */
        if (isInbetweenInsts(thread_id) && tryPCEvents(thread_id)) {
            ThreadContext *thread = cpu.getContext(thread_id);

            /* Branch as there was a change in PC */
            updateBranchData(thread_id, BranchData::UnpredictedBranch,
                MinorDynInst::bubble(), thread->pcState(), branch);
        } else if (mem_response &&
            num_mem_refs_committed < memoryCommitLimit)
        {
            /* Try to commit from the memory responses next */
            discard_inst = inst->id.streamSeqNum !=
                           ex_info.streamSeqNum || discard;

            DPRINTF(MinorExecute, "Trying to commit mem response: %s\n",
                *inst);

            /* Complete or discard the response */
            if (discard_inst) {
                DPRINTF(MinorExecute, "Discarding mem inst: %s as its"
                    " stream state was unexpected, expected: %d\n",
                    *inst, ex_info.streamSeqNum);

                lsq.popResponse(mem_response);
            } else {
                handleMemResponse(inst, mem_response, branch, fault);
                committed_inst = true;
            }

            completed_mem_ref = true;
            completed_inst = true;
        } else if (can_commit_insts) {
            /* If true, this instruction will, subject to timing tweaks,
             *  be considered for completion.  try_to_commit flattens
             *  the `if' tree a bit and allows other tests for inst
             *  commit to be inserted here. */
            bool try_to_commit = false;

            /* Try and issue memory ops early if they:
             *  - Can push a request into the LSQ
             *  - Have reached the end of their FUs
             *  - Have had all their dependencies satisfied
             *  - Are from the right stream
             *
             *  For any other case, leave it to the normal instruction
             *  issue below to handle them.
             */
            if (!ex_info.inFUMemInsts->empty() && lsq.canRequest()) {
                DPRINTF(MinorExecute, "Trying to commit from mem FUs\n");

                const MinorDynInstPtr head_mem_ref_inst =
                    ex_info.inFUMemInsts->front().inst;
                FUPipeline *fu = funcUnits[head_mem_ref_inst->fuIndex];
                const MinorDynInstPtr &fu_inst = fu->front().inst;

                /* Use this, possibly out of order, inst as the one
                 *  to 'commit'/send to the LSQ */
                if (!fu_inst->isBubble() &&
                    !fu_inst->inLSQ &&
                    fu_inst->canEarlyIssue &&
                    ex_info.streamSeqNum == fu_inst->id.streamSeqNum &&
                    head_exec_seq_num > fu_inst->instToWaitFor)
                {
                    DPRINTF(MinorExecute, "Issuing mem ref early"
                        " inst: %s instToWaitFor: %d\n",
                        *(fu_inst), fu_inst->instToWaitFor);

                    inst = fu_inst;
                    try_to_commit = true;
                    early_memory_issue = true;
                    completed_inst = true;
                }
            }

            /* Try and commit FU-less insts */
            if (!completed_inst && inst->isNoCostInst()) {
                DPRINTF(MinorExecute, "Committing no cost inst: %s", *inst);

                try_to_commit = true;
                completed_inst = true;
            }

            /* Try to issue from the ends of FUs and the inFlightInsts
             *  queue */
            if (!completed_inst && !inst->inLSQ) {
                DPRINTF(MinorExecute, "Trying to commit from FUs\n");

                /* Try to commit from a functional unit */
                /* Is the head inst of the expected inst's FU actually the
                 *  expected inst? */
                QueuedInst &fu_inst =
                    funcUnits[inst->fuIndex]->front();
                InstSeqNum fu_inst_seq_num = fu_inst.inst->id.execSeqNum;

                if (fu_inst.inst->isBubble()) {
                    /* No instruction ready */
                    completed_inst = false;
                } else if (fu_inst_seq_num != head_exec_seq_num) {
                    /* Past instruction: we must have already executed it
                     * in the same cycle and so the head inst isn't
                     * actually at the end of its pipeline
                     * Future instruction: handled above and only for
                     * mem refs on their way to the LSQ */
                } else if (fu_inst.inst->id == inst->id)  {
                    /* All instructions can be committed if they have the
                     *  right execSeqNum and there are no in-flight
                     *  mem insts before us */
                    try_to_commit = true;
                    completed_inst = true;
                }
            }

            if (try_to_commit) {
                discard_inst = inst->id.streamSeqNum !=
                    ex_info.streamSeqNum || discard;

                /* Is this instruction discardable as its streamSeqNum
                 *  doesn't match? */
                if (!discard_inst) {
                    /* Try to commit or discard a non-memory instruction.
                     *  Memory ops are actually 'committed' from this FUs
                     *  and 'issued' into the memory system so we need to
                     *  account for them later (commit_was_mem_issue gets
                     *  set) */
                    if (inst->extraCommitDelayExpr) {
                        DPRINTF(MinorExecute, "Evaluating expression for"
                            " extra commit delay inst: %s\n", *inst);

                        ThreadContext *thread = cpu.getContext(thread_id);

                        TimingExprEvalContext context(inst->staticInst,
                            thread, NULL);

                        uint64_t extra_delay = inst->extraCommitDelayExpr->
                            eval(context);

                        DPRINTF(MinorExecute, "Extra commit delay expr"
                            " result: %d\n", extra_delay);

                        if (extra_delay < 128) {
                            inst->extraCommitDelay += Cycles(extra_delay);
                        } else {
                            DPRINTF(MinorExecute, "Extra commit delay was"
                                " very long: %d\n", extra_delay);
                        }
                        inst->extraCommitDelayExpr = NULL;
                    }

                    /* Move the extraCommitDelay from the instruction
                     *  into the minimumCommitCycle */
                    if (inst->extraCommitDelay != Cycles(0)) {
                        inst->minimumCommitCycle = cpu.curCycle() +
                            inst->extraCommitDelay;
                        inst->extraCommitDelay = Cycles(0);
                    }

                    /* @todo Think about making lastMemBarrier be
                     *  MAX_UINT_64 to avoid using 0 as a marker value */
                    if (!inst->isFault() && inst->isMemRef() &&
                        lsq.getLastMemBarrier(thread_id) <
                            inst->id.execSeqNum &&
                        lsq.getLastMemBarrier(thread_id) != 0)
                    {
                        DPRINTF(MinorExecute, "Not committing inst: %s yet"
                            " as there are incomplete barriers in flight\n",
                            *inst);
                        completed_inst = false;
                    } else if (inst->minimumCommitCycle > now) {
                        DPRINTF(MinorExecute, "Not committing inst: %s yet"
                            " as it wants to be stalled for %d more cycles\n",
                            *inst, inst->minimumCommitCycle - now);
                        completed_inst = false;
                    } else {
                        completed_inst = commitInst(inst,
                            early_memory_issue, branch, fault,
                            committed_inst, issued_mem_ref);
                    }
                } else {
                    /* Discard instruction */
                    completed_inst = true;
                }

                if (completed_inst) {
                    /* Allow the pipeline to advance.  If the FU head
                     *  instruction wasn't the inFlightInsts head
                     *  but had already been committed, it would have
                     *  unstalled the pipeline before here */
                    if (inst->fuIndex != noCostFUIndex) {
                        DPRINTF(MinorExecute, "Unstalling %d for inst %s\n", inst->fuIndex, inst->id);
                        funcUnits[inst->fuIndex]->stalled = false;
                    }
                }
            }
        } else {
            DPRINTF(MinorExecute, "No instructions to commit\n");
            completed_inst = false;
        }

        /* All discardable instructions must also be 'completed' by now */
        assert(!(discard_inst && !completed_inst));

        /* Instruction committed but was discarded due to streamSeqNum
         *  mismatch */
        if (discard_inst) {
            DPRINTF(MinorExecute, "Discarding inst: %s as its stream"
                " state was unexpected, expected: %d\n",
                *inst, ex_info.streamSeqNum);

            if (fault == NoFault)
                cpu.stats.numDiscardedOps++;
        }

        /* Mark the mem inst as being in the LSQ */
        if (issued_mem_ref) {
            inst->fuIndex = 0;
            inst->inLSQ = true;
        }

        /* Pop issued (to LSQ) and discarded mem refs from the inFUMemInsts
         *  as they've *definitely* exited the FUs */
        if (completed_inst && inst->isMemRef()) {
            /* The MemRef could have been discarded from the FU or the memory
             *  queue, so just check an FU instruction */
            if (!ex_info.inFUMemInsts->empty() &&
                ex_info.inFUMemInsts->front().inst == inst)
            {
                ex_info.inFUMemInsts->pop();
            }
        }

        if (completed_inst && !(issued_mem_ref && fault == NoFault)) {
            /* Note that this includes discarded insts */
            DPRINTF(MinorExecute, "Completed inst: %s\n", *inst);

            /* Got to the end of a full instruction? */
            ex_info.lastCommitWasEndOfMacroop = inst->isFault() ||
                inst->isLastOpInInst();

            /* lastPredictionSeqNum is kept as a convenience to prevent its
             *  value from changing too much on the minorview display */
            ex_info.lastPredictionSeqNum = inst->id.predictionSeqNum;

            /* Finished with the inst, remove it from the inst queue and
             *  clear its dependencies */
            ex_info.inFlightInsts->pop();

            /* Complete barriers in the LSQ/move to store buffer */
            if (inst->isInst() && inst->staticInst->isFullMemBarrier()) {
                DPRINTF(MinorMem, "Completing memory barrier"
                    " inst: %s committed: %d\n", *inst, committed_inst);
                lsq.completeMemBarrierInst(inst, committed_inst);
            }

            scoreboard[thread_id].clearInstDests(inst, inst->isMemRef());
        }

        /* Handle per-cycle instruction counting */
        if (committed_inst) {
            bool is_no_cost_inst = inst->isNoCostInst();

            /* Don't show no cost instructions as having taken a commit
             *  slot */
            if (debug::MinorTrace && !is_no_cost_inst)
                ex_info.instsBeingCommitted.insts[num_insts_committed] = inst;

            if (!is_no_cost_inst)
                num_insts_committed++;

            if (num_insts_committed == commitLimit)
                DPRINTF(MinorExecute, "Reached inst commit limit\n");

            /* Re-set the time of the instruction if that's required for
             * tracing */
            if (inst->traceData) {
                if (setTraceTimeOnCommit)
                    inst->traceData->setWhen(curTick());
                inst->traceData->dump();
            }

            if (completed_mem_ref)
                num_mem_refs_committed++;

            if (num_mem_refs_committed == memoryCommitLimit)
                DPRINTF(MinorExecute, "Reached mem ref commit limit\n");
        }
    }
}

bool
Execute::isInbetweenInsts(ThreadID thread_id) const
{
    return executeInfo[thread_id].lastCommitWasEndOfMacroop &&
        !lsq.accessesInFlight();
}

void
Execute::evaluate()
{
    if (!inp.outputWire->isBubble())
        inputBuffer[inp.outputWire->threadId].setTail(*inp.outputWire);

    BranchData &branch = *out.inputWire;

    unsigned int num_issued = 0;

    /* Do all the cycle-wise activities for dcachePort here to potentially
     *  free up input spaces in the LSQ's requests queue */
    lsq.step();

    /* Check interrupts first.  Will halt commit if interrupt found */
    bool interrupted = false;
    ThreadID interrupt_tid = checkInterrupts(branch, interrupted);

    if (interrupt_tid != InvalidThreadID) {
        /* Signalling an interrupt this cycle, not issuing/committing from
         * any other threads */
    } else if (!branch.isBubble()) {
        /* It's important that this is here to carry Fetch1 wakeups to Fetch1
         *  without overwriting them */
        DPRINTF(MinorInterrupt, "Execute skipping a cycle to allow old"
            " branch to complete\n");
    } else {
        ThreadID commit_tid = getCommittingThread();

        if (commit_tid != InvalidThreadID) {
            ExecuteThreadInfo& commit_info = executeInfo[commit_tid];

            DPRINTF(MinorExecute, "Attempting to commit [tid:%d]\n",
                    commit_tid);
            /* commit can set stalled flags observable to issue and so *must* be
             *  called first */
            if (commit_info.drainState != NotDraining) {
                if (commit_info.drainState == DrainCurrentInst) {
                    /* Commit only micro-ops, don't kill anything else */
                    commit(commit_tid, true, false, branch);

                    if (isInbetweenInsts(commit_tid))
                        setDrainState(commit_tid, DrainHaltFetch);

                    /* Discard any generated branch */
                    branch = BranchData::bubble();
                } else if (commit_info.drainState == DrainAllInsts) {
                    /* Kill all instructions */
                    while (getInput(commit_tid))
                        popInput(commit_tid);
                    commit(commit_tid, false, true, branch);
                }
            } else {
                /* Commit micro-ops only if interrupted.  Otherwise, commit
                 *  anything you like */
                DPRINTF(MinorExecute, "Committing micro-ops for interrupt[tid:%d]\n",
                        commit_tid);
                bool only_commit_microops = interrupted &&
                                            hasInterrupt(commit_tid);
                commit(commit_tid, only_commit_microops, false, branch);
            }

            /* Halt fetch, but don't do it until we have the current instruction in
             *  the bag */
            if (commit_info.drainState == DrainHaltFetch) {
                updateBranchData(commit_tid, BranchData::HaltFetch,
                        MinorDynInst::bubble(),
                        cpu.getContext(commit_tid)->pcState(), branch);

                cpu.wakeupOnEvent(Pipeline::ExecuteStageId);
                setDrainState(commit_tid, DrainAllInsts);
            }
        }
        ThreadID issue_tid = getIssuingThread();
        /* This will issue merrily even when interrupted in the sure and
         *  certain knowledge that the interrupt with change the stream */
        if (issue_tid != InvalidThreadID) {
            DPRINTF(MinorExecute, "Attempting to issue [tid:%d]\n",
                    issue_tid);
            num_issued = issue(issue_tid);
        }

    }

    /* Run logic to step functional units + decide if we are active on the next
     * clock cycle */
    std::vector<MinorDynInstPtr> next_issuable_insts;
    bool can_issue_next = false;

    for (ThreadID tid = 0; tid < cpu.numThreads; tid++) {
        /* Find the next issuable instruction for each thread and see if it can
           be issued */
        if (getInput(tid)) {
            unsigned int input_index = executeInfo[tid].inputIndex;
            MinorDynInstPtr inst = getInput(tid)->insts[input_index];
            if (inst->isFault()) {
                can_issue_next = true;
            } else if (!inst->isBubble()) {
                next_issuable_insts.push_back(inst);
            }
        }
    }

    bool becoming_stalled = true;

    /* Advance the pipelines and note whether they still need to be
     * advanced */
    for (unsigned int i = 0; i < numFuncUnits; i++) {
        FUPipeline *fu = funcUnits[i];
        fu->advance();

        /* If we need to tick again, the pipeline will have been left or set
         * to be unstalled */
        if (fu->occupancy !=0 && !fu->stalled)
            becoming_stalled = false;

        /* Could we possibly issue the next instruction from any thread?
         * This is quite an expensive test and is only used to determine
         * if the CPU should remain active, only run it if we aren't sure
         * we are active next cycle yet */
        for (auto inst : next_issuable_insts) {
            if (!fu->stalled && fu->provides(inst->staticInst->opClass()) &&
                scoreboard[inst->id.threadId].canInstIssue(inst,
                    NULL, NULL, cpu.curCycle() + Cycles(1),
                    cpu.getContext(inst->id.threadId))) {
                can_issue_next = true;
                break;
            }
        }
    }

    bool head_inst_might_commit = false;

    /* Could the head in flight insts be committed */
    for (auto const &info : executeInfo) {
        if (!info.inFlightInsts->empty()) {
            const QueuedInst &head_inst = info.inFlightInsts->front();

            if (head_inst.inst->isNoCostInst()) {
                head_inst_might_commit = true;
            } else {
                FUPipeline *fu = funcUnits[head_inst.inst->fuIndex];
                if ((fu->stalled &&
                     fu->front().inst->id == head_inst.inst->id) ||
                     lsq.findResponse(head_inst.inst))
                {
                    head_inst_might_commit = true;
                    break;
                }
            }
        }
    }

    DPRINTF(Activity, "Need to tick num issued insts: %s%s%s%s%s%s\n",
       (num_issued != 0 ? " (issued some insts)" : ""),
       (becoming_stalled ? "(becoming stalled)" : "(not becoming stalled)"),
       (can_issue_next ? " (can issued next inst)" : ""),
       (head_inst_might_commit ? "(head inst might commit)" : ""),
       (lsq.needsToTick() ? " (LSQ needs to tick)" : ""),
       (interrupted ? " (interrupted)" : ""));

    bool need_to_tick =
       num_issued != 0 || /* Issued some insts this cycle */
       !becoming_stalled || /* Some FU pipelines can still move */
       can_issue_next || /* Can still issue a new inst */
       head_inst_might_commit || /* Could possible commit the next inst */
       lsq.needsToTick() || /* Must step the dcache port */
       interrupted; /* There are pending interrupts */

    if (!need_to_tick) {
        DPRINTF(Activity, "The next cycle might be skippable as there are no"
            " advanceable FUs\n");
    }

    /* Wake up if we need to tick again */
    if (need_to_tick)
        cpu.wakeupOnEvent(Pipeline::ExecuteStageId);

    /* Note activity of following buffer */
    if (!branch.isBubble())
        cpu.activityRecorder->activity();

    /* Make sure the input (if any left) is pushed */
    if (!inp.outputWire->isBubble())
        inputBuffer[inp.outputWire->threadId].pushTail();
}

ThreadID
Execute::checkInterrupts(BranchData& branch, bool& interrupted)
{
    ThreadID tid = interruptPriority;
    /* Evaluate interrupts in round-robin based upon service */
    do {
        /* Has an interrupt been signalled?  This may not be acted on
         *  straighaway so this is different from took_interrupt */
        bool thread_interrupted = false;

        if (FullSystem && cpu.getInterruptController(tid)) {
            /* This is here because it seems that after drainResume the
             * interrupt controller isn't always set */
            thread_interrupted = executeInfo[tid].drainState == NotDraining &&
                isInterrupted(tid);
            interrupted = interrupted || thread_interrupted;
        } else {
            DPRINTF(MinorInterrupt, "No interrupt controller\n");
        }
        DPRINTF(MinorInterrupt, "[tid:%d] thread_interrupted?=%d isInbetweenInsts?=%d\n",
                tid, thread_interrupted, isInbetweenInsts(tid));
        /* Act on interrupts */
        if (thread_interrupted && isInbetweenInsts(tid)) {
            if (takeInterrupt(tid, branch)) {
                interruptPriority = tid;
                return tid;
            }
        } else {
            tid = (tid + 1) % cpu.numThreads;
        }
    } while (tid != interruptPriority);

    return InvalidThreadID;
}

bool
Execute::hasInterrupt(ThreadID thread_id)
{
    if (FullSystem && cpu.getInterruptController(thread_id)) {
        return executeInfo[thread_id].drainState == NotDraining &&
               isInterrupted(thread_id);
    }

    return false;
}

void
Execute::minorTrace() const
{
    std::ostringstream insts;
    std::ostringstream stalled;

    executeInfo[0].instsBeingCommitted.reportData(insts);
    lsq.minorTrace();
    inputBuffer[0].minorTrace();
    scoreboard[0].minorTrace();

    /* Report functional unit stalling in one string */
    unsigned int i = 0;
    while (i < numFuncUnits)
    {
        stalled << (funcUnits[i]->stalled ? '1' : 'E');
        i++;
        if (i != numFuncUnits)
            stalled << ',';
    }

    minor::minorTrace("insts=%s inputIndex=%d streamSeqNum=%d"
        " stalled=%s drainState=%d isInbetweenInsts=%d\n",
        insts.str(), executeInfo[0].inputIndex, executeInfo[0].streamSeqNum,
        stalled.str(), executeInfo[0].drainState, isInbetweenInsts(0));

    std::for_each(funcUnits.begin(), funcUnits.end(),
        std::mem_fn(&FUPipeline::minorTrace));

    executeInfo[0].inFlightInsts->minorTrace();
    executeInfo[0].inFUMemInsts->minorTrace();
}

inline ThreadID
Execute::getCommittingThread()
{
    std::vector<ThreadID> priority_list;

    switch (cpu.threadPolicy) {
      case enums::SingleThreaded:
          return 0;
      case enums::RoundRobin:
          priority_list = cpu.roundRobinPriority(commitPriority);
          break;
      case enums::Random:
          priority_list = cpu.randomPriority();
          break;
      default:
          panic("Invalid thread policy");
    }

    for (auto tid : priority_list) {
        ExecuteThreadInfo &ex_info = executeInfo[tid];
        bool can_commit_insts = !ex_info.inFlightInsts->empty();
        if (can_commit_insts) {
            QueuedInst *head_inflight_inst = &(ex_info.inFlightInsts->front());
            MinorDynInstPtr inst = head_inflight_inst->inst;

            can_commit_insts = can_commit_insts &&
                (!inst->inLSQ || (lsq.findResponse(inst) != NULL));

            if (!inst->inLSQ) {
                bool can_transfer_mem_inst = false;
                if (!ex_info.inFUMemInsts->empty() && lsq.canRequest()) {
                    const MinorDynInstPtr head_mem_ref_inst =
                        ex_info.inFUMemInsts->front().inst;
                    FUPipeline *fu = funcUnits[head_mem_ref_inst->fuIndex];
                    const MinorDynInstPtr &fu_inst = fu->front().inst;
                    can_transfer_mem_inst =
                        !fu_inst->isBubble() &&
                         fu_inst->id.threadId == tid &&
                         !fu_inst->inLSQ &&
                         fu_inst->canEarlyIssue &&
                         inst->id.execSeqNum > fu_inst->instToWaitFor;
                }

                bool can_execute_fu_inst = inst->fuIndex == noCostFUIndex;
                if (can_commit_insts && !can_transfer_mem_inst &&
                        inst->fuIndex != noCostFUIndex)
                {
                    QueuedInst& fu_inst = funcUnits[inst->fuIndex]->front();
                    can_execute_fu_inst = !fu_inst.inst->isBubble() &&
                        fu_inst.inst->id == inst->id;
                }

                can_commit_insts = can_commit_insts &&
                    (can_transfer_mem_inst || can_execute_fu_inst);
            }
        }


        if (can_commit_insts) {
            commitPriority = tid;
            return tid;
        }
    }

    return InvalidThreadID;
}

inline ThreadID
Execute::getIssuingThread()
{
    std::vector<ThreadID> priority_list;

    switch (cpu.threadPolicy) {
      case enums::SingleThreaded:
          return 0;
      case enums::RoundRobin:
          priority_list = cpu.roundRobinPriority(issuePriority);
          break;
      case enums::Random:
          priority_list = cpu.randomPriority();
          break;
      default:
          panic("Invalid thread scheduling policy.");
    }

    for (auto tid : priority_list) {
        if (getInput(tid)) {
            issuePriority = tid;
            return tid;
        }
    }

    return InvalidThreadID;
}

void
Execute::drainResume()
{
    DPRINTF(Drain, "MinorExecute drainResume\n");

    for (ThreadID tid = 0; tid < cpu.numThreads; tid++) {
        setDrainState(tid, NotDraining);
    }

    cpu.wakeupOnEvent(Pipeline::ExecuteStageId);
}

std::ostream &operator <<(std::ostream &os, Execute::DrainState state)
{
    switch (state)
    {
        case Execute::NotDraining:
          os << "NotDraining";
          break;
        case Execute::DrainCurrentInst:
          os << "DrainCurrentInst";
          break;
        case Execute::DrainHaltFetch:
          os << "DrainHaltFetch";
          break;
        case Execute::DrainAllInsts:
          os << "DrainAllInsts";
          break;
        default:
          os << "Drain-" << static_cast<int>(state);
          break;
    }

    return os;
}

void
Execute::setDrainState(ThreadID thread_id, DrainState state)
{
    DPRINTF(Drain, "setDrainState[%d]: %s\n", thread_id, state);
    executeInfo[thread_id].drainState = state;
}

unsigned int
Execute::drain()
{
    DPRINTF(Drain, "MinorExecute drain\n");

    for (ThreadID tid = 0; tid < cpu.numThreads; tid++) {
        if (executeInfo[tid].drainState == NotDraining) {
            cpu.wakeupOnEvent(Pipeline::ExecuteStageId);

            /* Go to DrainCurrentInst if we're between microops
             * or waiting on an unbufferable memory operation.
             * Otherwise we can go straight to DrainHaltFetch
             */
            if (isInbetweenInsts(tid))
                setDrainState(tid, DrainHaltFetch);
            else
                setDrainState(tid, DrainCurrentInst);
        }
    }
    return (isDrained() ? 0 : 1);
}

bool
Execute::isDrained()
{
    if (!lsq.isDrained())
        return false;

    for (ThreadID tid = 0; tid < cpu.numThreads; tid++) {
        if (!inputBuffer[tid].empty() ||
            !executeInfo[tid].inFlightInsts->empty()) {

            return false;
        }
    }

    return true;
}

Execute::~Execute()
{
    for (unsigned int i = 0; i < numFuncUnits; i++)
        delete funcUnits[i];

    for (ThreadID tid = 0; tid < cpu.numThreads; tid++)
        delete executeInfo[tid].inFlightInsts;
}

bool
Execute::instIsRightStream(MinorDynInstPtr inst)
{
    return inst->id.streamSeqNum == executeInfo[inst->id.threadId].streamSeqNum;
}

bool
Execute::instIsHeadInst(MinorDynInstPtr inst)
{
    bool ret = false;

    if (!executeInfo[inst->id.threadId].inFlightInsts->empty())
        ret = executeInfo[inst->id.threadId].inFlightInsts->front().inst->id == inst->id;

    return ret;
}

MinorCPU::MinorCPUPort &
Execute::getDcachePort()
{
    return lsq.getDcachePort();
}

} // namespace minor
} // namespace gem5
