/*
 * 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.
 */

// Todo:
// Current ordering allows for 0 cycle added-to-scheduled.  Could maybe fake
// it; either do in reverse order, or have added instructions put into a
// different ready queue that, in scheduleRreadyInsts(), gets put onto the
// normal ready queue.  This would however give only a one cycle delay,
// but probably is more flexible to actually add in a delay parameter than
// just running it backwards.

#include <limits>
#include <vector>

#include "sim/root.hh"

#include "cpu/o3/inst_queue.hh"

// Either compile error or max int due to sign extension.
// Hack to avoid compile warnings.
const InstSeqNum MaxInstSeqNum = std::numeric_limits<InstSeqNum>::max();

template <class Impl>
InstructionQueue<Impl>::InstructionQueue(Params &params)
    : memDepUnit(params),
      numEntries(params.numIQEntries),
      intWidth(params.executeIntWidth),
      floatWidth(params.executeFloatWidth),
      branchWidth(params.executeBranchWidth),
      memoryWidth(params.executeMemoryWidth),
      totalWidth(params.issueWidth),
      numPhysIntRegs(params.numPhysIntRegs),
      numPhysFloatRegs(params.numPhysFloatRegs),
      commitToIEWDelay(params.commitToIEWDelay)
{
    // Initialize the number of free IQ entries.
    freeEntries = numEntries;

    // Set the number of physical registers as the number of int + float
    numPhysRegs = numPhysIntRegs + numPhysFloatRegs;

    DPRINTF(IQ, "IQ: There are %i physical registers.\n", numPhysRegs);

    //Create an entry for each physical register within the
    //dependency graph.
    dependGraph = new DependencyEntry[numPhysRegs];

    // Resize the register scoreboard.
    regScoreboard.resize(numPhysRegs);

    // Initialize all the head pointers to point to NULL, and all the
    // entries as unready.
    // Note that in actuality, the registers corresponding to the logical
    // registers start off as ready.  However this doesn't matter for the
    // IQ as the instruction should have been correctly told if those
    // registers are ready in rename.  Thus it can all be initialized as
    // unready.
    for (int i = 0; i < numPhysRegs; ++i)
    {
        dependGraph[i].next = NULL;
        dependGraph[i].inst = NULL;
        regScoreboard[i] = false;
    }

}

template <class Impl>
void
InstructionQueue<Impl>::regStats()
{
    iqInstsAdded
        .name(name() + ".iqInstsAdded")
        .desc("Number of instructions added to the IQ (excludes non-spec)")
        .prereq(iqInstsAdded);

    iqNonSpecInstsAdded
        .name(name() + ".iqNonSpecInstsAdded")
        .desc("Number of non-speculative instructions added to the IQ")
        .prereq(iqNonSpecInstsAdded);

//    iqIntInstsAdded;

    iqIntInstsIssued
        .name(name() + ".iqIntInstsIssued")
        .desc("Number of integer instructions issued")
        .prereq(iqIntInstsIssued);

//    iqFloatInstsAdded;

    iqFloatInstsIssued
        .name(name() + ".iqFloatInstsIssued")
        .desc("Number of float instructions issued")
        .prereq(iqFloatInstsIssued);

//    iqBranchInstsAdded;

    iqBranchInstsIssued
        .name(name() + ".iqBranchInstsIssued")
        .desc("Number of branch instructions issued")
        .prereq(iqBranchInstsIssued);

//    iqMemInstsAdded;

    iqMemInstsIssued
        .name(name() + ".iqMemInstsIssued")
        .desc("Number of memory instructions issued")
        .prereq(iqMemInstsIssued);

//    iqMiscInstsAdded;

    iqMiscInstsIssued
        .name(name() + ".iqMiscInstsIssued")
        .desc("Number of miscellaneous instructions issued")
        .prereq(iqMiscInstsIssued);

    iqSquashedInstsIssued
        .name(name() + ".iqSquashedInstsIssued")
        .desc("Number of squashed instructions issued")
        .prereq(iqSquashedInstsIssued);

    iqLoopSquashStalls
        .name(name() + ".iqLoopSquashStalls")
        .desc("Number of times issue loop had to restart due to squashed "
              "inst; mainly for profiling")
        .prereq(iqLoopSquashStalls);

    iqSquashedInstsExamined
        .name(name() + ".iqSquashedInstsExamined")
        .desc("Number of squashed instructions iterated over during squash;"
              " mainly for profiling")
        .prereq(iqSquashedInstsExamined);

    iqSquashedOperandsExamined
        .name(name() + ".iqSquashedOperandsExamined")
        .desc("Number of squashed operands that are examined and possibly "
              "removed from graph")
        .prereq(iqSquashedOperandsExamined);

    iqSquashedNonSpecRemoved
        .name(name() + ".iqSquashedNonSpecRemoved")
        .desc("Number of squashed non-spec instructions that were removed")
        .prereq(iqSquashedNonSpecRemoved);

    // Tell mem dependence unit to reg stats as well.
    memDepUnit.regStats();
}

template <class Impl>
void
InstructionQueue<Impl>::setCPU(FullCPU *cpu_ptr)
{
    cpu = cpu_ptr;

    tail = cpu->instList.begin();
}

template <class Impl>
void
InstructionQueue<Impl>::setIssueToExecuteQueue(
                        TimeBuffer<IssueStruct> *i2e_ptr)
{
    DPRINTF(IQ, "IQ: Set the issue to execute queue.\n");
    issueToExecuteQueue = i2e_ptr;
}

template <class Impl>
void
InstructionQueue<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
{
    DPRINTF(IQ, "IQ: Set the time buffer.\n");
    timeBuffer = tb_ptr;

    fromCommit = timeBuffer->getWire(-commitToIEWDelay);
}

template <class Impl>
unsigned
InstructionQueue<Impl>::numFreeEntries()
{
    return freeEntries;
}

// Might want to do something more complex if it knows how many instructions
// will be issued this cycle.
template <class Impl>
bool
InstructionQueue<Impl>::isFull()
{
    if (freeEntries == 0) {
        return(true);
    } else {
        return(false);
    }
}

template <class Impl>
void
InstructionQueue<Impl>::insert(DynInstPtr &new_inst)
{
    // Make sure the instruction is valid
    assert(new_inst);

    DPRINTF(IQ, "IQ: Adding instruction PC %#x to the IQ.\n",
            new_inst->readPC());

    // Check if there are any free entries.  Panic if there are none.
    // Might want to have this return a fault in the future instead of
    // panicing.
    assert(freeEntries != 0);

    // If the IQ currently has nothing in it, then there's a possibility
    // that the tail iterator is invalid (might have been pointing at an
    // instruction that was retired).  Reset the tail iterator.
    if (freeEntries == numEntries) {
        tail = cpu->instList.begin();
    }

    // Move the tail iterator.  Instructions may not have been issued
    // to the IQ, so we may have to increment the iterator more than once.
    while ((*tail) != new_inst) {
        tail++;

        // Make sure the tail iterator points at something legal.
        assert(tail != cpu->instList.end());
    }


    // Decrease the number of free entries.
    --freeEntries;

    // Look through its source registers (physical regs), and mark any
    // dependencies.
    addToDependents(new_inst);

    // Have this instruction set itself as the producer of its destination
    // register(s).
    createDependency(new_inst);

    // If it's a memory instruction, add it to the memory dependency
    // unit.
    if (new_inst->isMemRef()) {
        memDepUnit.insert(new_inst);
        // Uh..forgot to look it up and put it on the proper dependency list
        // if the instruction should not go yet.
    } else {
        // If the instruction is ready then add it to the ready list.
        addIfReady(new_inst);
    }

    ++iqInstsAdded;

    assert(freeEntries == (numEntries - countInsts()));
}

template <class Impl>
void
InstructionQueue<Impl>::insertNonSpec(DynInstPtr &inst)
{
    nonSpecInsts[inst->seqNum] = inst;

    // @todo: Clean up this code; can do it by setting inst as unable
    // to issue, then calling normal insert on the inst.

    // Make sure the instruction is valid
    assert(inst);

    DPRINTF(IQ, "IQ: Adding instruction PC %#x to the IQ.\n",
            inst->readPC());

    // Check if there are any free entries.  Panic if there are none.
    // Might want to have this return a fault in the future instead of
    // panicing.
    assert(freeEntries != 0);

    // If the IQ currently has nothing in it, then there's a possibility
    // that the tail iterator is invalid (might have been pointing at an
    // instruction that was retired).  Reset the tail iterator.
    if (freeEntries == numEntries) {
        tail = cpu->instList.begin();
    }

    // Move the tail iterator.  Instructions may not have been issued
    // to the IQ, so we may have to increment the iterator more than once.
    while ((*tail) != inst) {
        tail++;

        // Make sure the tail iterator points at something legal.
        assert(tail != cpu->instList.end());
    }

    // Decrease the number of free entries.
    --freeEntries;

    // Have this instruction set itself as the producer of its destination
    // register(s).
    createDependency(inst);

    // If it's a memory instruction, add it to the memory dependency
    // unit.
    if (inst->isMemRef()) {
        memDepUnit.insertNonSpec(inst);
    }

    ++iqNonSpecInstsAdded;
}

// Slightly hack function to advance the tail iterator in the case that
// the IEW stage issues an instruction that is not added to the IQ.  This
// is needed in case a long chain of such instructions occurs.
// I don't think this is used anymore.
template <class Impl>
void
InstructionQueue<Impl>::advanceTail(DynInstPtr &inst)
{
    // Make sure the instruction is valid
    assert(inst);

    DPRINTF(IQ, "IQ: Adding instruction PC %#x to the IQ.\n",
            inst->readPC());

    // Check if there are any free entries.  Panic if there are none.
    // Might want to have this return a fault in the future instead of
    // panicing.
    assert(freeEntries != 0);

    // If the IQ currently has nothing in it, then there's a possibility
    // that the tail iterator is invalid (might have been pointing at an
    // instruction that was retired).  Reset the tail iterator.
    if (freeEntries == numEntries) {
        tail = cpu->instList.begin();
    }

    // Move the tail iterator.  Instructions may not have been issued
    // to the IQ, so we may have to increment the iterator more than once.
    while ((*tail) != inst) {
        tail++;

        // Make sure the tail iterator points at something legal.
        assert(tail != cpu->instList.end());
    }

    assert(freeEntries <= numEntries);

    // Have this instruction set itself as the producer of its destination
    // register(s).
    createDependency(inst);
}

// Need to make sure the number of float and integer instructions
// issued does not exceed the total issue bandwidth.
// @todo: Figure out a better way to remove the squashed items from the
// lists.  Checking the top item of each list to see if it's squashed
// wastes time and forces jumps.
template <class Impl>
void
InstructionQueue<Impl>::scheduleReadyInsts()
{
    DPRINTF(IQ, "IQ: Attempting to schedule ready instructions from "
                "the IQ.\n");

    int int_issued = 0;
    int float_issued = 0;
    int branch_issued = 0;
    int memory_issued = 0;
    int squashed_issued = 0;
    int total_issued = 0;

    IssueStruct *i2e_info = issueToExecuteQueue->access(0);

    bool insts_available = !readyBranchInsts.empty() ||
        !readyIntInsts.empty() ||
        !readyFloatInsts.empty() ||
        !memDepUnit.empty() ||
        !readyMiscInsts.empty() ||
        !squashedInsts.empty();

    // Note: Requires a globally defined constant.
    InstSeqNum oldest_inst = MaxInstSeqNum;
    InstList list_with_oldest = None;

    // Temporary values.
    DynInstPtr int_head_inst;
    DynInstPtr float_head_inst;
    DynInstPtr branch_head_inst;
    DynInstPtr mem_head_inst;
    DynInstPtr misc_head_inst;
    DynInstPtr squashed_head_inst;

    // Somewhat nasty code to look at all of the lists where issuable
    // instructions are located, and choose the oldest instruction among
    // those lists.  Consider a rewrite in the future.
    while (insts_available && total_issued < totalWidth)
    {
        // Set this to false.  Each if-block is required to set it to true
        // if there were instructions available this check.  This will cause
        // this loop to run once more than necessary, but avoids extra calls.
        insts_available = false;

        oldest_inst = MaxInstSeqNum;

        list_with_oldest = None;

        if (!readyIntInsts.empty() &&
            int_issued < intWidth) {

            insts_available = true;

            int_head_inst = readyIntInsts.top();

            if (int_head_inst->isSquashed()) {
                readyIntInsts.pop();

                ++iqLoopSquashStalls;

                continue;
            }

            oldest_inst = int_head_inst->seqNum;

            list_with_oldest = Int;
        }

        if (!readyFloatInsts.empty() &&
            float_issued < floatWidth) {

            insts_available = true;

            float_head_inst = readyFloatInsts.top();

            if (float_head_inst->isSquashed()) {
                readyFloatInsts.pop();

                ++iqLoopSquashStalls;

                continue;
            } else if (float_head_inst->seqNum < oldest_inst) {
                oldest_inst = float_head_inst->seqNum;

                list_with_oldest = Float;
            }
        }

        if (!readyBranchInsts.empty() &&
            branch_issued < branchWidth) {

            insts_available = true;

            branch_head_inst = readyBranchInsts.top();

            if (branch_head_inst->isSquashed()) {
                readyBranchInsts.pop();

                ++iqLoopSquashStalls;

                continue;
            } else if (branch_head_inst->seqNum < oldest_inst) {
                oldest_inst = branch_head_inst->seqNum;

                list_with_oldest = Branch;
            }

        }

        if (!memDepUnit.empty() &&
            memory_issued < memoryWidth) {

            insts_available = true;

            mem_head_inst = memDepUnit.top();

            if (mem_head_inst->isSquashed()) {
                memDepUnit.pop();

                ++iqLoopSquashStalls;

                continue;
            } else if (mem_head_inst->seqNum < oldest_inst) {
                oldest_inst = mem_head_inst->seqNum;

                list_with_oldest = Memory;
            }
        }

        if (!readyMiscInsts.empty()) {

            insts_available = true;

            misc_head_inst = readyMiscInsts.top();

            if (misc_head_inst->isSquashed()) {
                readyMiscInsts.pop();

                ++iqLoopSquashStalls;

                continue;
            } else if (misc_head_inst->seqNum < oldest_inst) {
                oldest_inst = misc_head_inst->seqNum;

                list_with_oldest = Misc;
            }
        }

        if (!squashedInsts.empty()) {

            insts_available = true;

            squashed_head_inst = squashedInsts.top();

            if (squashed_head_inst->seqNum < oldest_inst) {
                list_with_oldest = Squashed;
            }

        }

        DynInstPtr issuing_inst = NULL;

        switch (list_with_oldest) {
          case None:
            DPRINTF(IQ, "IQ: Not able to schedule any instructions. Issuing "
                    "inst is %#x.\n", issuing_inst);
            break;

          case Int:
            issuing_inst = int_head_inst;
            readyIntInsts.pop();
            ++int_issued;
            DPRINTF(IQ, "IQ: Issuing integer instruction PC %#x.\n",
                    issuing_inst->readPC());
            break;

          case Float:
            issuing_inst = float_head_inst;
            readyFloatInsts.pop();
            ++float_issued;
            DPRINTF(IQ, "IQ: Issuing float instruction PC %#x.\n",
                    issuing_inst->readPC());
            break;

          case Branch:
            issuing_inst = branch_head_inst;
            readyBranchInsts.pop();
            ++branch_issued;
            DPRINTF(IQ, "IQ: Issuing branch instruction PC %#x.\n",
                    issuing_inst->readPC());
            break;

          case Memory:
            issuing_inst = mem_head_inst;

            memDepUnit.pop();
            ++memory_issued;
            DPRINTF(IQ, "IQ: Issuing memory instruction PC %#x.\n",
                    issuing_inst->readPC());
            break;

          case Misc:
            issuing_inst = misc_head_inst;
            readyMiscInsts.pop();

            ++iqMiscInstsIssued;

            DPRINTF(IQ, "IQ: Issuing a miscellaneous instruction PC %#x.\n",
                    issuing_inst->readPC());
            break;

          case Squashed:
            assert(0 && "Squashed insts should not issue any more!");
            squashedInsts.pop();
            // Set the squashed instruction as able to commit so that commit
            // can just drop it from the ROB.  This is a bit faked.
            ++squashed_issued;
            ++freeEntries;

            DPRINTF(IQ, "IQ: Issuing squashed instruction PC %#x.\n",
                    squashed_head_inst->readPC());
            break;
        }

        if (list_with_oldest != None && list_with_oldest != Squashed) {
            i2e_info->insts[total_issued] = issuing_inst;
            i2e_info->size++;

            issuing_inst->setIssued();

            ++freeEntries;
            ++total_issued;
        }

        assert(freeEntries == (numEntries - countInsts()));
    }

    iqIntInstsIssued += int_issued;
    iqFloatInstsIssued += float_issued;
    iqBranchInstsIssued += branch_issued;
    iqMemInstsIssued += memory_issued;
    iqSquashedInstsIssued += squashed_issued;
}

template <class Impl>
void
InstructionQueue<Impl>::scheduleNonSpec(const InstSeqNum &inst)
{
    DPRINTF(IQ, "IQ: Marking nonspeculative instruction with sequence "
            "number %i as ready to execute.\n", inst);

    non_spec_it_t inst_it = nonSpecInsts.find(inst);

    assert(inst_it != nonSpecInsts.end());

    // Mark this instruction as ready to issue.
    (*inst_it).second->setCanIssue();

    // Now schedule the instruction.
    if (!(*inst_it).second->isMemRef()) {
        addIfReady((*inst_it).second);
    } else {
        memDepUnit.nonSpecInstReady((*inst_it).second);
    }

    nonSpecInsts.erase(inst_it);
}

template <class Impl>
void
InstructionQueue<Impl>::wakeDependents(DynInstPtr &completed_inst)
{
    DPRINTF(IQ, "IQ: Waking dependents of completed instruction.\n");
    //Look at the physical destination register of the DynInst
    //and look it up on the dependency graph.  Then mark as ready
    //any instructions within the instruction queue.
    DependencyEntry *curr;

    // Tell the memory dependence unit to wake any dependents on this
    // instruction if it is a memory instruction.

    if (completed_inst->isMemRef()) {
        memDepUnit.wakeDependents(completed_inst);
    }

    for (int dest_reg_idx = 0;
         dest_reg_idx < completed_inst->numDestRegs();
         dest_reg_idx++)
    {
        PhysRegIndex dest_reg =
            completed_inst->renamedDestRegIdx(dest_reg_idx);

        // Special case of uniq or control registers.  They are not
        // handled by the IQ and thus have no dependency graph entry.
        // @todo Figure out a cleaner way to handle this.
        if (dest_reg >= numPhysRegs) {
            continue;
        }

        DPRINTF(IQ, "IQ: Waking any dependents on register %i.\n",
                (int) dest_reg);

        //Maybe abstract this part into a function.
        //Go through the dependency chain, marking the registers as ready
        //within the waiting instructions.
        while (dependGraph[dest_reg].next) {

            curr = dependGraph[dest_reg].next;

            DPRINTF(IQ, "IQ: Waking up a dependent instruction, PC%#x.\n",
                    curr->inst->readPC());

            // Might want to give more information to the instruction
            // so that it knows which of its source registers is ready.
            // However that would mean that the dependency graph entries
            // would need to hold the src_reg_idx.
            curr->inst->markSrcRegReady();

            addIfReady(curr->inst);

            dependGraph[dest_reg].next = curr->next;

            DependencyEntry::mem_alloc_counter--;

            curr->inst = NULL;

            delete curr;
        }

        // Reset the head node now that all of its dependents have been woken
        // up.
        dependGraph[dest_reg].next = NULL;
        dependGraph[dest_reg].inst = NULL;

        // Mark the scoreboard as having that register ready.
        regScoreboard[dest_reg] = true;
    }
}

template <class Impl>
void
InstructionQueue<Impl>::violation(DynInstPtr &store,
                                  DynInstPtr &faulting_load)
{
    memDepUnit.violation(store, faulting_load);
}

template <class Impl>
void
InstructionQueue<Impl>::squash()
{
    DPRINTF(IQ, "IQ: Starting to squash instructions in the IQ.\n");

    // Read instruction sequence number of last instruction out of the
    // time buffer.
    squashedSeqNum = fromCommit->commitInfo.doneSeqNum;

    // Setup the squash iterator to point to the tail.
    squashIt = tail;

    // Call doSquash if there are insts in the IQ
    if (freeEntries != numEntries) {
        doSquash();
    }

    // Also tell the memory dependence unit to squash.
    memDepUnit.squash(squashedSeqNum);
}

template <class Impl>
void
InstructionQueue<Impl>::doSquash()
{
    // Make sure the squash iterator isn't pointing to nothing.
    assert(squashIt != cpu->instList.end());
    // Make sure the squashed sequence number is valid.
    assert(squashedSeqNum != 0);

    DPRINTF(IQ, "IQ: Squashing instructions in the IQ.\n");

    // Squash any instructions younger than the squashed sequence number
    // given.
    while ((*squashIt)->seqNum > squashedSeqNum) {
        DynInstPtr squashed_inst = (*squashIt);

        // Only handle the instruction if it actually is in the IQ and
        // hasn't already been squashed in the IQ.
        if (!squashed_inst->isIssued() &&
            !squashed_inst->isSquashedInIQ()) {

            // Remove the instruction from the dependency list.
            // Hack for now: These below don't add themselves to the
            // dependency list, so don't try to remove them.
            if (!squashed_inst->isNonSpeculative()/* &&
                                                     !squashed_inst->isStore()*/
                ) {

                for (int src_reg_idx = 0;
                     src_reg_idx < squashed_inst->numSrcRegs();
                     src_reg_idx++)
                {
                    PhysRegIndex src_reg =
                        squashed_inst->renamedSrcRegIdx(src_reg_idx);

                    // Only remove it from the dependency graph if it was
                    // placed there in the first place.
                    // HACK: This assumes that instructions woken up from the
                    // dependency chain aren't informed that a specific src
                    // register has become ready.  This may not always be true
                    // in the future.
                    if (!squashed_inst->isReadySrcRegIdx(src_reg_idx) &&
                        src_reg < numPhysRegs) {
                        dependGraph[src_reg].remove(squashed_inst);
                    }

                    ++iqSquashedOperandsExamined;
                }

                // Might want to remove producers as well.
            } else {
                nonSpecInsts[squashed_inst->seqNum] = NULL;

                nonSpecInsts.erase(squashed_inst->seqNum);

                ++iqSquashedNonSpecRemoved;
            }

            // Might want to also clear out the head of the dependency graph.

            // Mark it as squashed within the IQ.
            squashed_inst->setSquashedInIQ();

//            squashedInsts.push(squashed_inst);
            squashed_inst->setIssued();
            squashed_inst->setCanCommit();

            ++freeEntries;

            DPRINTF(IQ, "IQ: Instruction PC %#x squashed.\n",
                    squashed_inst->readPC());
        }

        --squashIt;
        ++iqSquashedInstsExamined;
    }

    assert(freeEntries <= numEntries);

    if (freeEntries == numEntries) {
        tail = cpu->instList.end();
    }

}

template <class Impl>
void
InstructionQueue<Impl>::stopSquash()
{
    // Clear up the squash variables to ensure that squashing doesn't
    // get called improperly.
    squashedSeqNum = 0;

    squashIt = cpu->instList.end();
}

template <class Impl>
void
InstructionQueue<Impl>::DependencyEntry::insert(DynInstPtr &new_inst)
{
    //Add this new, dependent instruction at the head of the dependency
    //chain.

    // First create the entry that will be added to the head of the
    // dependency chain.
    DependencyEntry *new_entry = new DependencyEntry;
    new_entry->next = this->next;
    new_entry->inst = new_inst;

    // Then actually add it to the chain.
    this->next = new_entry;

    ++mem_alloc_counter;
}

template <class Impl>
void
InstructionQueue<Impl>::DependencyEntry::remove(DynInstPtr &inst_to_remove)
{
    DependencyEntry *prev = this;
    DependencyEntry *curr = this->next;

    // Make sure curr isn't NULL.  Because this instruction is being
    // removed from a dependency list, it must have been placed there at
    // an earlier time.  The dependency chain should not be empty,
    // unless the instruction dependent upon it is already ready.
    if (curr == NULL) {
        return;
    }

    // Find the instruction to remove within the dependency linked list.
    while(curr->inst != inst_to_remove)
    {
        prev = curr;
        curr = curr->next;

        assert(curr != NULL);
    }

    // Now remove this instruction from the list.
    prev->next = curr->next;

    --mem_alloc_counter;

    // Could push this off to the destructor of DependencyEntry
    curr->inst = NULL;

    delete curr;
}

template <class Impl>
bool
InstructionQueue<Impl>::addToDependents(DynInstPtr &new_inst)
{
    // Loop through the instruction's source registers, adding
    // them to the dependency list if they are not ready.
    int8_t total_src_regs = new_inst->numSrcRegs();
    bool return_val = false;

    for (int src_reg_idx = 0;
         src_reg_idx < total_src_regs;
         src_reg_idx++)
    {
        // Only add it to the dependency graph if it's not ready.
        if (!new_inst->isReadySrcRegIdx(src_reg_idx)) {
            PhysRegIndex src_reg = new_inst->renamedSrcRegIdx(src_reg_idx);

            // Check the IQ's scoreboard to make sure the register
            // hasn't become ready while the instruction was in flight
            // between stages.  Only if it really isn't ready should
            // it be added to the dependency graph.
            if (src_reg >= numPhysRegs) {
                continue;
            } else if (regScoreboard[src_reg] == false) {
                DPRINTF(IQ, "IQ: Instruction PC %#x has src reg %i that "
                        "is being added to the dependency chain.\n",
                        new_inst->readPC(), src_reg);

                dependGraph[src_reg].insert(new_inst);

                // Change the return value to indicate that something
                // was added to the dependency graph.
                return_val = true;
            } else {
                DPRINTF(IQ, "IQ: Instruction PC %#x has src reg %i that "
                        "became ready before it reached the IQ.\n",
                        new_inst->readPC(), src_reg);
                // Mark a register ready within the instruction.
                new_inst->markSrcRegReady();
            }
        }
    }

    return return_val;
}

template <class Impl>
void
InstructionQueue<Impl>::createDependency(DynInstPtr &new_inst)
{
    //Actually nothing really needs to be marked when an
    //instruction becomes the producer of a register's value,
    //but for convenience a ptr to the producing instruction will
    //be placed in the head node of the dependency links.
    int8_t total_dest_regs = new_inst->numDestRegs();

    for (int dest_reg_idx = 0;
         dest_reg_idx < total_dest_regs;
         dest_reg_idx++)
    {
        PhysRegIndex dest_reg = new_inst->renamedDestRegIdx(dest_reg_idx);

        // Instructions that use the misc regs will have a reg number
        // higher than the normal physical registers.  In this case these
        // registers are not renamed, and there is no need to track
        // dependencies as these instructions must be executed at commit.
        if (dest_reg >= numPhysRegs) {
            continue;
        }

        dependGraph[dest_reg].inst = new_inst;

        if (dependGraph[dest_reg].next) {
            dumpDependGraph();
            panic("IQ: Dependency graph not empty!");
        }

        // Mark the scoreboard to say it's not yet ready.
        regScoreboard[dest_reg] = false;
    }
}

template <class Impl>
void
InstructionQueue<Impl>::addIfReady(DynInstPtr &inst)
{
    //If the instruction now has all of its source registers
    // available, then add it to the list of ready instructions.
    if (inst->readyToIssue()) {

        //Add the instruction to the proper ready list.
        if (inst->isControl()) {

            DPRINTF(IQ, "IQ: Branch instruction is ready to issue, "
                    "putting it onto the ready list, PC %#x.\n",
                    inst->readPC());
            readyBranchInsts.push(inst);

        } else if (inst->isMemRef()) {

            DPRINTF(IQ, "IQ: Checking if memory instruction can issue.\n");

            // Message to the mem dependence unit that this instruction has
            // its registers ready.

            memDepUnit.regsReady(inst);

#if 0
            if (memDepUnit.readyToIssue(inst)) {
                DPRINTF(IQ, "IQ: Memory instruction is ready to issue, "
                        "putting it onto the ready list, PC %#x.\n",
                        inst->readPC());
                readyMemInsts.push(inst);
            } else {
                // Make dependent on the store.
                // Will need some way to get the store instruction it should
                // be dependent upon; then when the store issues it can
                // put the instruction on the ready list.
                // Yet another tree?
                assert(0 && "Instruction has no way to actually issue");
            }
#endif

        } else if (inst->isInteger()) {

            DPRINTF(IQ, "IQ: Integer instruction is ready to issue, "
                    "putting it onto the ready list, PC %#x.\n",
                    inst->readPC());
            readyIntInsts.push(inst);

        } else if (inst->isFloating()) {

            DPRINTF(IQ, "IQ: Floating instruction is ready to issue, "
                    "putting it onto the ready list, PC %#x.\n",
                    inst->readPC());
            readyFloatInsts.push(inst);

        } else {
            DPRINTF(IQ, "IQ: Miscellaneous instruction is ready to issue, "
                    "putting it onto the ready list, PC %#x..\n",
                    inst->readPC());

            readyMiscInsts.push(inst);
        }
    }
}

/*
 * Caution, this function must not be called prior to tail being updated at
 * least once, otherwise it will fail the assertion.  This is because
 * instList.begin() actually changes upon the insertion of an element into the
 * list when the list is empty.
 */
template <class Impl>
int
InstructionQueue<Impl>::countInsts()
{
    ListIt count_it = cpu->instList.begin();
    int total_insts = 0;

    if (tail == cpu->instList.end())
        return 0;

    while (count_it != tail) {
        if (!(*count_it)->isIssued()) {
            ++total_insts;
        }

        ++count_it;

        assert(count_it != cpu->instList.end());
    }

    // Need to count the tail iterator as well.
    if (count_it != cpu->instList.end() &&
        (*count_it) &&
        !(*count_it)->isIssued()) {
        ++total_insts;
    }

    return total_insts;
}

template <class Impl>
void
InstructionQueue<Impl>::dumpDependGraph()
{
    DependencyEntry *curr;

    for (int i = 0; i < numPhysRegs; ++i)
    {
        curr = &dependGraph[i];

        if (curr->inst) {
            cprintf("dependGraph[%i]: producer: %#x consumer: ", i,
                    curr->inst->readPC());
        } else {
            cprintf("dependGraph[%i]: No producer. consumer: ", i);
        }

        while (curr->next != NULL) {
            curr = curr->next;

            cprintf("%#x ", curr->inst->readPC());
        }

        cprintf("\n");
    }
}

template <class Impl>
void
InstructionQueue<Impl>::dumpLists()
{
    cprintf("Ready integer list size: %i\n", readyIntInsts.size());

    cprintf("Ready float list size: %i\n", readyFloatInsts.size());

    cprintf("Ready branch list size: %i\n", readyBranchInsts.size());

    cprintf("Ready misc list size: %i\n", readyMiscInsts.size());

    cprintf("Squashed list size: %i\n", squashedInsts.size());

    cprintf("Non speculative list size: %i\n", nonSpecInsts.size());

    non_spec_it_t non_spec_it = nonSpecInsts.begin();

    cprintf("Non speculative list: ");

    while (non_spec_it != nonSpecInsts.end()) {
        cprintf("%#x ", (*non_spec_it).second->readPC());
        ++non_spec_it;
    }

    cprintf("\n");

}