inst_queue_impl.hh revision 2665
11689SN/A/*
21689SN/A * Copyright (c) 2004-2005 The Regents of The University of Michigan
31689SN/A * All rights reserved.
41689SN/A *
51689SN/A * Redistribution and use in source and binary forms, with or without
61689SN/A * modification, are permitted provided that the following conditions are
71689SN/A * met: redistributions of source code must retain the above copyright
81689SN/A * notice, this list of conditions and the following disclaimer;
91689SN/A * redistributions in binary form must reproduce the above copyright
101689SN/A * notice, this list of conditions and the following disclaimer in the
111689SN/A * documentation and/or other materials provided with the distribution;
121689SN/A * neither the name of the copyright holders nor the names of its
131689SN/A * contributors may be used to endorse or promote products derived from
141689SN/A * this software without specific prior written permission.
151689SN/A *
161689SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
171689SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
181689SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
191689SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
201689SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
211689SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
221689SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
231689SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
241689SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
251689SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
261689SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272665Ssaidi@eecs.umich.edu *
282665Ssaidi@eecs.umich.edu * Authors: Kevin Lim
291689SN/A */
301689SN/A
311061SN/A// Todo:
321061SN/A// Current ordering allows for 0 cycle added-to-scheduled.  Could maybe fake
331060SN/A// it; either do in reverse order, or have added instructions put into a
341060SN/A// different ready queue that, in scheduleRreadyInsts(), gets put onto the
351060SN/A// normal ready queue.  This would however give only a one cycle delay,
361060SN/A// but probably is more flexible to actually add in a delay parameter than
371060SN/A// just running it backwards.
381060SN/A
392064SN/A#include <limits>
401060SN/A#include <vector>
411060SN/A
421696SN/A#include "sim/root.hh"
431689SN/A
441717SN/A#include "cpu/o3/inst_queue.hh"
451060SN/A
461060SN/A// Either compile error or max int due to sign extension.
471689SN/A// Hack to avoid compile warnings.
482064SN/Aconst InstSeqNum MaxInstSeqNum = std::numeric_limits<InstSeqNum>::max();
491060SN/A
501061SN/Atemplate <class Impl>
511060SN/AInstructionQueue<Impl>::InstructionQueue(Params &params)
521061SN/A    : memDepUnit(params),
531061SN/A      numEntries(params.numIQEntries),
541060SN/A      intWidth(params.executeIntWidth),
551060SN/A      floatWidth(params.executeFloatWidth),
561062SN/A      branchWidth(params.executeBranchWidth),
571062SN/A      memoryWidth(params.executeMemoryWidth),
581061SN/A      totalWidth(params.issueWidth),
591060SN/A      numPhysIntRegs(params.numPhysIntRegs),
601060SN/A      numPhysFloatRegs(params.numPhysFloatRegs),
611060SN/A      commitToIEWDelay(params.commitToIEWDelay)
621060SN/A{
631060SN/A    // Initialize the number of free IQ entries.
641060SN/A    freeEntries = numEntries;
651060SN/A
661060SN/A    // Set the number of physical registers as the number of int + float
671060SN/A    numPhysRegs = numPhysIntRegs + numPhysFloatRegs;
681060SN/A
691060SN/A    DPRINTF(IQ, "IQ: There are %i physical registers.\n", numPhysRegs);
701060SN/A
711060SN/A    //Create an entry for each physical register within the
721060SN/A    //dependency graph.
731060SN/A    dependGraph = new DependencyEntry[numPhysRegs];
741060SN/A
751060SN/A    // Resize the register scoreboard.
761060SN/A    regScoreboard.resize(numPhysRegs);
771060SN/A
781060SN/A    // Initialize all the head pointers to point to NULL, and all the
791060SN/A    // entries as unready.
801060SN/A    // Note that in actuality, the registers corresponding to the logical
811060SN/A    // registers start off as ready.  However this doesn't matter for the
821060SN/A    // IQ as the instruction should have been correctly told if those
831060SN/A    // registers are ready in rename.  Thus it can all be initialized as
841060SN/A    // unready.
851060SN/A    for (int i = 0; i < numPhysRegs; ++i)
861060SN/A    {
871060SN/A        dependGraph[i].next = NULL;
881060SN/A        dependGraph[i].inst = NULL;
891060SN/A        regScoreboard[i] = false;
901060SN/A    }
911060SN/A
921060SN/A}
931060SN/A
941061SN/Atemplate <class Impl>
951060SN/Avoid
961062SN/AInstructionQueue<Impl>::regStats()
971062SN/A{
981062SN/A    iqInstsAdded
991062SN/A        .name(name() + ".iqInstsAdded")
1001062SN/A        .desc("Number of instructions added to the IQ (excludes non-spec)")
1011062SN/A        .prereq(iqInstsAdded);
1021062SN/A
1031062SN/A    iqNonSpecInstsAdded
1041062SN/A        .name(name() + ".iqNonSpecInstsAdded")
1051062SN/A        .desc("Number of non-speculative instructions added to the IQ")
1061062SN/A        .prereq(iqNonSpecInstsAdded);
1071062SN/A
1081062SN/A//    iqIntInstsAdded;
1091062SN/A
1101062SN/A    iqIntInstsIssued
1111062SN/A        .name(name() + ".iqIntInstsIssued")
1121062SN/A        .desc("Number of integer instructions issued")
1131062SN/A        .prereq(iqIntInstsIssued);
1141062SN/A
1151062SN/A//    iqFloatInstsAdded;
1161062SN/A
1171062SN/A    iqFloatInstsIssued
1181062SN/A        .name(name() + ".iqFloatInstsIssued")
1191062SN/A        .desc("Number of float instructions issued")
1201062SN/A        .prereq(iqFloatInstsIssued);
1211062SN/A
1221062SN/A//    iqBranchInstsAdded;
1231062SN/A
1241062SN/A    iqBranchInstsIssued
1251062SN/A        .name(name() + ".iqBranchInstsIssued")
1261062SN/A        .desc("Number of branch instructions issued")
1271062SN/A        .prereq(iqBranchInstsIssued);
1281062SN/A
1291062SN/A//    iqMemInstsAdded;
1301062SN/A
1311062SN/A    iqMemInstsIssued
1321062SN/A        .name(name() + ".iqMemInstsIssued")
1331062SN/A        .desc("Number of memory instructions issued")
1341062SN/A        .prereq(iqMemInstsIssued);
1351062SN/A
1361062SN/A//    iqMiscInstsAdded;
1371062SN/A
1381062SN/A    iqMiscInstsIssued
1391062SN/A        .name(name() + ".iqMiscInstsIssued")
1401062SN/A        .desc("Number of miscellaneous instructions issued")
1411062SN/A        .prereq(iqMiscInstsIssued);
1421062SN/A
1431062SN/A    iqSquashedInstsIssued
1441062SN/A        .name(name() + ".iqSquashedInstsIssued")
1451062SN/A        .desc("Number of squashed instructions issued")
1461062SN/A        .prereq(iqSquashedInstsIssued);
1471062SN/A
1481062SN/A    iqLoopSquashStalls
1491062SN/A        .name(name() + ".iqLoopSquashStalls")
1501062SN/A        .desc("Number of times issue loop had to restart due to squashed "
1511062SN/A              "inst; mainly for profiling")
1521062SN/A        .prereq(iqLoopSquashStalls);
1531062SN/A
1541062SN/A    iqSquashedInstsExamined
1551062SN/A        .name(name() + ".iqSquashedInstsExamined")
1561062SN/A        .desc("Number of squashed instructions iterated over during squash;"
1571062SN/A              " mainly for profiling")
1581062SN/A        .prereq(iqSquashedInstsExamined);
1591062SN/A
1601062SN/A    iqSquashedOperandsExamined
1611062SN/A        .name(name() + ".iqSquashedOperandsExamined")
1621062SN/A        .desc("Number of squashed operands that are examined and possibly "
1631062SN/A              "removed from graph")
1641062SN/A        .prereq(iqSquashedOperandsExamined);
1651062SN/A
1661062SN/A    iqSquashedNonSpecRemoved
1671062SN/A        .name(name() + ".iqSquashedNonSpecRemoved")
1681062SN/A        .desc("Number of squashed non-spec instructions that were removed")
1691062SN/A        .prereq(iqSquashedNonSpecRemoved);
1701062SN/A
1711062SN/A    // Tell mem dependence unit to reg stats as well.
1721062SN/A    memDepUnit.regStats();
1731062SN/A}
1741062SN/A
1751062SN/Atemplate <class Impl>
1761062SN/Avoid
1771060SN/AInstructionQueue<Impl>::setCPU(FullCPU *cpu_ptr)
1781060SN/A{
1791060SN/A    cpu = cpu_ptr;
1801060SN/A
1811060SN/A    tail = cpu->instList.begin();
1821060SN/A}
1831060SN/A
1841061SN/Atemplate <class Impl>
1851060SN/Avoid
1861060SN/AInstructionQueue<Impl>::setIssueToExecuteQueue(
1871060SN/A                        TimeBuffer<IssueStruct> *i2e_ptr)
1881060SN/A{
1891060SN/A    DPRINTF(IQ, "IQ: Set the issue to execute queue.\n");
1901060SN/A    issueToExecuteQueue = i2e_ptr;
1911060SN/A}
1921060SN/A
1931061SN/Atemplate <class Impl>
1941060SN/Avoid
1951060SN/AInstructionQueue<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
1961060SN/A{
1971060SN/A    DPRINTF(IQ, "IQ: Set the time buffer.\n");
1981060SN/A    timeBuffer = tb_ptr;
1991060SN/A
2001060SN/A    fromCommit = timeBuffer->getWire(-commitToIEWDelay);
2011060SN/A}
2021060SN/A
2031684SN/Atemplate <class Impl>
2041684SN/Aunsigned
2051684SN/AInstructionQueue<Impl>::numFreeEntries()
2061684SN/A{
2071684SN/A    return freeEntries;
2081684SN/A}
2091684SN/A
2101060SN/A// Might want to do something more complex if it knows how many instructions
2111060SN/A// will be issued this cycle.
2121061SN/Atemplate <class Impl>
2131060SN/Abool
2141060SN/AInstructionQueue<Impl>::isFull()
2151060SN/A{
2161060SN/A    if (freeEntries == 0) {
2171060SN/A        return(true);
2181060SN/A    } else {
2191060SN/A        return(false);
2201060SN/A    }
2211060SN/A}
2221060SN/A
2231061SN/Atemplate <class Impl>
2241060SN/Avoid
2251061SN/AInstructionQueue<Impl>::insert(DynInstPtr &new_inst)
2261060SN/A{
2271060SN/A    // Make sure the instruction is valid
2281060SN/A    assert(new_inst);
2291060SN/A
2301060SN/A    DPRINTF(IQ, "IQ: Adding instruction PC %#x to the IQ.\n",
2311060SN/A            new_inst->readPC());
2321060SN/A
2331060SN/A    // Check if there are any free entries.  Panic if there are none.
2341060SN/A    // Might want to have this return a fault in the future instead of
2351060SN/A    // panicing.
2361060SN/A    assert(freeEntries != 0);
2371060SN/A
2381060SN/A    // If the IQ currently has nothing in it, then there's a possibility
2391060SN/A    // that the tail iterator is invalid (might have been pointing at an
2401060SN/A    // instruction that was retired).  Reset the tail iterator.
2411060SN/A    if (freeEntries == numEntries) {
2421060SN/A        tail = cpu->instList.begin();
2431060SN/A    }
2441060SN/A
2451060SN/A    // Move the tail iterator.  Instructions may not have been issued
2461060SN/A    // to the IQ, so we may have to increment the iterator more than once.
2471060SN/A    while ((*tail) != new_inst) {
2481060SN/A        tail++;
2491060SN/A
2501060SN/A        // Make sure the tail iterator points at something legal.
2511060SN/A        assert(tail != cpu->instList.end());
2521060SN/A    }
2531060SN/A
2541060SN/A
2551060SN/A    // Decrease the number of free entries.
2561060SN/A    --freeEntries;
2571060SN/A
2581060SN/A    // Look through its source registers (physical regs), and mark any
2591060SN/A    // dependencies.
2601060SN/A    addToDependents(new_inst);
2611060SN/A
2621060SN/A    // Have this instruction set itself as the producer of its destination
2631060SN/A    // register(s).
2641060SN/A    createDependency(new_inst);
2651060SN/A
2661061SN/A    // If it's a memory instruction, add it to the memory dependency
2671061SN/A    // unit.
2681061SN/A    if (new_inst->isMemRef()) {
2691061SN/A        memDepUnit.insert(new_inst);
2701062SN/A        // Uh..forgot to look it up and put it on the proper dependency list
2711062SN/A        // if the instruction should not go yet.
2721062SN/A    } else {
2731062SN/A        // If the instruction is ready then add it to the ready list.
2741062SN/A        addIfReady(new_inst);
2751061SN/A    }
2761061SN/A
2771062SN/A    ++iqInstsAdded;
2781060SN/A
2791060SN/A    assert(freeEntries == (numEntries - countInsts()));
2801060SN/A}
2811060SN/A
2821061SN/Atemplate <class Impl>
2831061SN/Avoid
2841061SN/AInstructionQueue<Impl>::insertNonSpec(DynInstPtr &inst)
2851061SN/A{
2861061SN/A    nonSpecInsts[inst->seqNum] = inst;
2871061SN/A
2881061SN/A    // @todo: Clean up this code; can do it by setting inst as unable
2891061SN/A    // to issue, then calling normal insert on the inst.
2901061SN/A
2911061SN/A    // Make sure the instruction is valid
2921061SN/A    assert(inst);
2931061SN/A
2941061SN/A    DPRINTF(IQ, "IQ: Adding instruction PC %#x to the IQ.\n",
2951061SN/A            inst->readPC());
2961061SN/A
2971061SN/A    // Check if there are any free entries.  Panic if there are none.
2981061SN/A    // Might want to have this return a fault in the future instead of
2991061SN/A    // panicing.
3001061SN/A    assert(freeEntries != 0);
3011061SN/A
3021061SN/A    // If the IQ currently has nothing in it, then there's a possibility
3031061SN/A    // that the tail iterator is invalid (might have been pointing at an
3041061SN/A    // instruction that was retired).  Reset the tail iterator.
3051061SN/A    if (freeEntries == numEntries) {
3061061SN/A        tail = cpu->instList.begin();
3071061SN/A    }
3081061SN/A
3091061SN/A    // Move the tail iterator.  Instructions may not have been issued
3101061SN/A    // to the IQ, so we may have to increment the iterator more than once.
3111061SN/A    while ((*tail) != inst) {
3121061SN/A        tail++;
3131061SN/A
3141061SN/A        // Make sure the tail iterator points at something legal.
3151061SN/A        assert(tail != cpu->instList.end());
3161061SN/A    }
3171061SN/A
3181061SN/A    // Decrease the number of free entries.
3191061SN/A    --freeEntries;
3201061SN/A
3211061SN/A    // Have this instruction set itself as the producer of its destination
3221061SN/A    // register(s).
3231061SN/A    createDependency(inst);
3241061SN/A
3251061SN/A    // If it's a memory instruction, add it to the memory dependency
3261061SN/A    // unit.
3271061SN/A    if (inst->isMemRef()) {
3281062SN/A        memDepUnit.insertNonSpec(inst);
3291061SN/A    }
3301062SN/A
3311062SN/A    ++iqNonSpecInstsAdded;
3321061SN/A}
3331061SN/A
3341060SN/A// Slightly hack function to advance the tail iterator in the case that
3351060SN/A// the IEW stage issues an instruction that is not added to the IQ.  This
3361060SN/A// is needed in case a long chain of such instructions occurs.
3371062SN/A// I don't think this is used anymore.
3381061SN/Atemplate <class Impl>
3391060SN/Avoid
3401061SN/AInstructionQueue<Impl>::advanceTail(DynInstPtr &inst)
3411060SN/A{
3421060SN/A    // Make sure the instruction is valid
3431060SN/A    assert(inst);
3441060SN/A
3451060SN/A    DPRINTF(IQ, "IQ: Adding instruction PC %#x to the IQ.\n",
3461060SN/A            inst->readPC());
3471060SN/A
3481060SN/A    // Check if there are any free entries.  Panic if there are none.
3491060SN/A    // Might want to have this return a fault in the future instead of
3501060SN/A    // panicing.
3511060SN/A    assert(freeEntries != 0);
3521060SN/A
3531060SN/A    // If the IQ currently has nothing in it, then there's a possibility
3541060SN/A    // that the tail iterator is invalid (might have been pointing at an
3551060SN/A    // instruction that was retired).  Reset the tail iterator.
3561060SN/A    if (freeEntries == numEntries) {
3571060SN/A        tail = cpu->instList.begin();
3581060SN/A    }
3591060SN/A
3601060SN/A    // Move the tail iterator.  Instructions may not have been issued
3611060SN/A    // to the IQ, so we may have to increment the iterator more than once.
3621060SN/A    while ((*tail) != inst) {
3631060SN/A        tail++;
3641060SN/A
3651060SN/A        // Make sure the tail iterator points at something legal.
3661060SN/A        assert(tail != cpu->instList.end());
3671060SN/A    }
3681060SN/A
3691060SN/A    assert(freeEntries <= numEntries);
3701060SN/A
3711060SN/A    // Have this instruction set itself as the producer of its destination
3721060SN/A    // register(s).
3731060SN/A    createDependency(inst);
3741060SN/A}
3751060SN/A
3761060SN/A// Need to make sure the number of float and integer instructions
3771061SN/A// issued does not exceed the total issue bandwidth.
3781061SN/A// @todo: Figure out a better way to remove the squashed items from the
3791061SN/A// lists.  Checking the top item of each list to see if it's squashed
3801061SN/A// wastes time and forces jumps.
3811061SN/Atemplate <class Impl>
3821060SN/Avoid
3831060SN/AInstructionQueue<Impl>::scheduleReadyInsts()
3841060SN/A{
3851060SN/A    DPRINTF(IQ, "IQ: Attempting to schedule ready instructions from "
3861060SN/A                "the IQ.\n");
3871060SN/A
3881060SN/A    int int_issued = 0;
3891060SN/A    int float_issued = 0;
3901060SN/A    int branch_issued = 0;
3911061SN/A    int memory_issued = 0;
3921060SN/A    int squashed_issued = 0;
3931060SN/A    int total_issued = 0;
3941060SN/A
3951060SN/A    IssueStruct *i2e_info = issueToExecuteQueue->access(0);
3961060SN/A
3971060SN/A    bool insts_available = !readyBranchInsts.empty() ||
3981060SN/A        !readyIntInsts.empty() ||
3991060SN/A        !readyFloatInsts.empty() ||
4001062SN/A        !memDepUnit.empty() ||
4011061SN/A        !readyMiscInsts.empty() ||
4021060SN/A        !squashedInsts.empty();
4031060SN/A
4041060SN/A    // Note: Requires a globally defined constant.
4051060SN/A    InstSeqNum oldest_inst = MaxInstSeqNum;
4061060SN/A    InstList list_with_oldest = None;
4071060SN/A
4081060SN/A    // Temporary values.
4091061SN/A    DynInstPtr int_head_inst;
4101061SN/A    DynInstPtr float_head_inst;
4111061SN/A    DynInstPtr branch_head_inst;
4121061SN/A    DynInstPtr mem_head_inst;
4131061SN/A    DynInstPtr misc_head_inst;
4141061SN/A    DynInstPtr squashed_head_inst;
4151060SN/A
4161060SN/A    // Somewhat nasty code to look at all of the lists where issuable
4171060SN/A    // instructions are located, and choose the oldest instruction among
4181060SN/A    // those lists.  Consider a rewrite in the future.
4191060SN/A    while (insts_available && total_issued < totalWidth)
4201060SN/A    {
4211060SN/A        // Set this to false.  Each if-block is required to set it to true
4221060SN/A        // if there were instructions available this check.  This will cause
4231060SN/A        // this loop to run once more than necessary, but avoids extra calls.
4241060SN/A        insts_available = false;
4251060SN/A
4261060SN/A        oldest_inst = MaxInstSeqNum;
4271060SN/A
4281060SN/A        list_with_oldest = None;
4291060SN/A
4301060SN/A        if (!readyIntInsts.empty() &&
4311060SN/A            int_issued < intWidth) {
4321060SN/A
4331060SN/A            insts_available = true;
4341060SN/A
4351061SN/A            int_head_inst = readyIntInsts.top();
4361060SN/A
4371060SN/A            if (int_head_inst->isSquashed()) {
4381060SN/A                readyIntInsts.pop();
4391062SN/A
4401062SN/A                ++iqLoopSquashStalls;
4411062SN/A
4421060SN/A                continue;
4431060SN/A            }
4441060SN/A
4451060SN/A            oldest_inst = int_head_inst->seqNum;
4461060SN/A
4471060SN/A            list_with_oldest = Int;
4481060SN/A        }
4491060SN/A
4501060SN/A        if (!readyFloatInsts.empty() &&
4511060SN/A            float_issued < floatWidth) {
4521060SN/A
4531060SN/A            insts_available = true;
4541060SN/A
4551061SN/A            float_head_inst = readyFloatInsts.top();
4561060SN/A
4571060SN/A            if (float_head_inst->isSquashed()) {
4581060SN/A                readyFloatInsts.pop();
4591062SN/A
4601062SN/A                ++iqLoopSquashStalls;
4611062SN/A
4621060SN/A                continue;
4631060SN/A            } else if (float_head_inst->seqNum < oldest_inst) {
4641060SN/A                oldest_inst = float_head_inst->seqNum;
4651060SN/A
4661060SN/A                list_with_oldest = Float;
4671060SN/A            }
4681060SN/A        }
4691060SN/A
4701060SN/A        if (!readyBranchInsts.empty() &&
4711060SN/A            branch_issued < branchWidth) {
4721060SN/A
4731060SN/A            insts_available = true;
4741060SN/A
4751061SN/A            branch_head_inst = readyBranchInsts.top();
4761060SN/A
4771060SN/A            if (branch_head_inst->isSquashed()) {
4781060SN/A                readyBranchInsts.pop();
4791062SN/A
4801062SN/A                ++iqLoopSquashStalls;
4811062SN/A
4821060SN/A                continue;
4831060SN/A            } else if (branch_head_inst->seqNum < oldest_inst) {
4841060SN/A                oldest_inst = branch_head_inst->seqNum;
4851060SN/A
4861060SN/A                list_with_oldest = Branch;
4871060SN/A            }
4881060SN/A
4891060SN/A        }
4901060SN/A
4911062SN/A        if (!memDepUnit.empty() &&
4921061SN/A            memory_issued < memoryWidth) {
4931061SN/A
4941061SN/A            insts_available = true;
4951061SN/A
4961062SN/A            mem_head_inst = memDepUnit.top();
4971061SN/A
4981061SN/A            if (mem_head_inst->isSquashed()) {
4991062SN/A                memDepUnit.pop();
5001062SN/A
5011062SN/A                ++iqLoopSquashStalls;
5021062SN/A
5031061SN/A                continue;
5041061SN/A            } else if (mem_head_inst->seqNum < oldest_inst) {
5051061SN/A                oldest_inst = mem_head_inst->seqNum;
5061061SN/A
5071061SN/A                list_with_oldest = Memory;
5081061SN/A            }
5091061SN/A        }
5101061SN/A
5111061SN/A        if (!readyMiscInsts.empty()) {
5121061SN/A
5131061SN/A            insts_available = true;
5141061SN/A
5151061SN/A            misc_head_inst = readyMiscInsts.top();
5161061SN/A
5171061SN/A            if (misc_head_inst->isSquashed()) {
5181061SN/A                readyMiscInsts.pop();
5191062SN/A
5201062SN/A                ++iqLoopSquashStalls;
5211062SN/A
5221061SN/A                continue;
5231061SN/A            } else if (misc_head_inst->seqNum < oldest_inst) {
5241061SN/A                oldest_inst = misc_head_inst->seqNum;
5251061SN/A
5261061SN/A                list_with_oldest = Misc;
5271061SN/A            }
5281061SN/A        }
5291061SN/A
5301060SN/A        if (!squashedInsts.empty()) {
5311060SN/A
5321060SN/A            insts_available = true;
5331060SN/A
5341061SN/A            squashed_head_inst = squashedInsts.top();
5351060SN/A
5361060SN/A            if (squashed_head_inst->seqNum < oldest_inst) {
5371060SN/A                list_with_oldest = Squashed;
5381060SN/A            }
5391060SN/A
5401060SN/A        }
5411060SN/A
5421061SN/A        DynInstPtr issuing_inst = NULL;
5431060SN/A
5441060SN/A        switch (list_with_oldest) {
5451060SN/A          case None:
5461060SN/A            DPRINTF(IQ, "IQ: Not able to schedule any instructions. Issuing "
5471060SN/A                    "inst is %#x.\n", issuing_inst);
5481060SN/A            break;
5491061SN/A
5501060SN/A          case Int:
5511060SN/A            issuing_inst = int_head_inst;
5521060SN/A            readyIntInsts.pop();
5531060SN/A            ++int_issued;
5541060SN/A            DPRINTF(IQ, "IQ: Issuing integer instruction PC %#x.\n",
5551060SN/A                    issuing_inst->readPC());
5561060SN/A            break;
5571061SN/A
5581060SN/A          case Float:
5591060SN/A            issuing_inst = float_head_inst;
5601060SN/A            readyFloatInsts.pop();
5611060SN/A            ++float_issued;
5621060SN/A            DPRINTF(IQ, "IQ: Issuing float instruction PC %#x.\n",
5631060SN/A                    issuing_inst->readPC());
5641060SN/A            break;
5651061SN/A
5661060SN/A          case Branch:
5671060SN/A            issuing_inst = branch_head_inst;
5681060SN/A            readyBranchInsts.pop();
5691060SN/A            ++branch_issued;
5701060SN/A            DPRINTF(IQ, "IQ: Issuing branch instruction PC %#x.\n",
5711060SN/A                    issuing_inst->readPC());
5721060SN/A            break;
5731061SN/A
5741061SN/A          case Memory:
5751061SN/A            issuing_inst = mem_head_inst;
5761061SN/A
5771062SN/A            memDepUnit.pop();
5781061SN/A            ++memory_issued;
5791061SN/A            DPRINTF(IQ, "IQ: Issuing memory instruction PC %#x.\n",
5801061SN/A                    issuing_inst->readPC());
5811061SN/A            break;
5821061SN/A
5831061SN/A          case Misc:
5841061SN/A            issuing_inst = misc_head_inst;
5851061SN/A            readyMiscInsts.pop();
5861062SN/A
5871062SN/A            ++iqMiscInstsIssued;
5881062SN/A
5891061SN/A            DPRINTF(IQ, "IQ: Issuing a miscellaneous instruction PC %#x.\n",
5901061SN/A                    issuing_inst->readPC());
5911061SN/A            break;
5921061SN/A
5931060SN/A          case Squashed:
5941681SN/A            assert(0 && "Squashed insts should not issue any more!");
5951060SN/A            squashedInsts.pop();
5961681SN/A            // Set the squashed instruction as able to commit so that commit
5971681SN/A            // can just drop it from the ROB.  This is a bit faked.
5981060SN/A            ++squashed_issued;
5991681SN/A            ++freeEntries;
6001681SN/A
6011060SN/A            DPRINTF(IQ, "IQ: Issuing squashed instruction PC %#x.\n",
6021681SN/A                    squashed_head_inst->readPC());
6031060SN/A            break;
6041060SN/A        }
6051060SN/A
6061681SN/A        if (list_with_oldest != None && list_with_oldest != Squashed) {
6071060SN/A            i2e_info->insts[total_issued] = issuing_inst;
6081062SN/A            i2e_info->size++;
6091060SN/A
6101060SN/A            issuing_inst->setIssued();
6111060SN/A
6121060SN/A            ++freeEntries;
6131060SN/A            ++total_issued;
6141060SN/A        }
6151060SN/A
6161060SN/A        assert(freeEntries == (numEntries - countInsts()));
6171060SN/A    }
6181062SN/A
6191062SN/A    iqIntInstsIssued += int_issued;
6201062SN/A    iqFloatInstsIssued += float_issued;
6211062SN/A    iqBranchInstsIssued += branch_issued;
6221062SN/A    iqMemInstsIssued += memory_issued;
6231062SN/A    iqSquashedInstsIssued += squashed_issued;
6241060SN/A}
6251060SN/A
6261061SN/Atemplate <class Impl>
6271060SN/Avoid
6281061SN/AInstructionQueue<Impl>::scheduleNonSpec(const InstSeqNum &inst)
6291060SN/A{
6301062SN/A    DPRINTF(IQ, "IQ: Marking nonspeculative instruction with sequence "
6311062SN/A            "number %i as ready to execute.\n", inst);
6321062SN/A
6331061SN/A    non_spec_it_t inst_it = nonSpecInsts.find(inst);
6341060SN/A
6351061SN/A    assert(inst_it != nonSpecInsts.end());
6361060SN/A
6371061SN/A    // Mark this instruction as ready to issue.
6381061SN/A    (*inst_it).second->setCanIssue();
6391060SN/A
6401061SN/A    // Now schedule the instruction.
6411062SN/A    if (!(*inst_it).second->isMemRef()) {
6421062SN/A        addIfReady((*inst_it).second);
6431062SN/A    } else {
6441062SN/A        memDepUnit.nonSpecInstReady((*inst_it).second);
6451062SN/A    }
6461060SN/A
6471061SN/A    nonSpecInsts.erase(inst_it);
6481060SN/A}
6491060SN/A
6501061SN/Atemplate <class Impl>
6511061SN/Avoid
6521684SN/AInstructionQueue<Impl>::wakeDependents(DynInstPtr &completed_inst)
6531684SN/A{
6541684SN/A    DPRINTF(IQ, "IQ: Waking dependents of completed instruction.\n");
6551684SN/A    //Look at the physical destination register of the DynInst
6561684SN/A    //and look it up on the dependency graph.  Then mark as ready
6571684SN/A    //any instructions within the instruction queue.
6581684SN/A    DependencyEntry *curr;
6591684SN/A
6601684SN/A    // Tell the memory dependence unit to wake any dependents on this
6611684SN/A    // instruction if it is a memory instruction.
6621684SN/A
6631684SN/A    if (completed_inst->isMemRef()) {
6641684SN/A        memDepUnit.wakeDependents(completed_inst);
6651684SN/A    }
6661684SN/A
6671684SN/A    for (int dest_reg_idx = 0;
6681684SN/A         dest_reg_idx < completed_inst->numDestRegs();
6691684SN/A         dest_reg_idx++)
6701684SN/A    {
6711684SN/A        PhysRegIndex dest_reg =
6721684SN/A            completed_inst->renamedDestRegIdx(dest_reg_idx);
6731684SN/A
6741684SN/A        // Special case of uniq or control registers.  They are not
6751684SN/A        // handled by the IQ and thus have no dependency graph entry.
6761684SN/A        // @todo Figure out a cleaner way to handle this.
6771684SN/A        if (dest_reg >= numPhysRegs) {
6781684SN/A            continue;
6791684SN/A        }
6801684SN/A
6811684SN/A        DPRINTF(IQ, "IQ: Waking any dependents on register %i.\n",
6821684SN/A                (int) dest_reg);
6831684SN/A
6841684SN/A        //Maybe abstract this part into a function.
6851684SN/A        //Go through the dependency chain, marking the registers as ready
6861684SN/A        //within the waiting instructions.
6871684SN/A        while (dependGraph[dest_reg].next) {
6881684SN/A
6891684SN/A            curr = dependGraph[dest_reg].next;
6901684SN/A
6911684SN/A            DPRINTF(IQ, "IQ: Waking up a dependent instruction, PC%#x.\n",
6921684SN/A                    curr->inst->readPC());
6931684SN/A
6941684SN/A            // Might want to give more information to the instruction
6951684SN/A            // so that it knows which of its source registers is ready.
6961684SN/A            // However that would mean that the dependency graph entries
6971684SN/A            // would need to hold the src_reg_idx.
6981684SN/A            curr->inst->markSrcRegReady();
6991684SN/A
7001684SN/A            addIfReady(curr->inst);
7011684SN/A
7021684SN/A            dependGraph[dest_reg].next = curr->next;
7031684SN/A
7041684SN/A            DependencyEntry::mem_alloc_counter--;
7051684SN/A
7061684SN/A            curr->inst = NULL;
7071684SN/A
7081684SN/A            delete curr;
7091684SN/A        }
7101684SN/A
7111684SN/A        // Reset the head node now that all of its dependents have been woken
7121684SN/A        // up.
7131684SN/A        dependGraph[dest_reg].next = NULL;
7141684SN/A        dependGraph[dest_reg].inst = NULL;
7151684SN/A
7161684SN/A        // Mark the scoreboard as having that register ready.
7171684SN/A        regScoreboard[dest_reg] = true;
7181684SN/A    }
7191684SN/A}
7201684SN/A
7211684SN/Atemplate <class Impl>
7221684SN/Avoid
7231061SN/AInstructionQueue<Impl>::violation(DynInstPtr &store,
7241061SN/A                                  DynInstPtr &faulting_load)
7251061SN/A{
7261061SN/A    memDepUnit.violation(store, faulting_load);
7271061SN/A}
7281061SN/A
7291061SN/Atemplate <class Impl>
7301060SN/Avoid
7311060SN/AInstructionQueue<Impl>::squash()
7321060SN/A{
7331060SN/A    DPRINTF(IQ, "IQ: Starting to squash instructions in the IQ.\n");
7341060SN/A
7351060SN/A    // Read instruction sequence number of last instruction out of the
7361060SN/A    // time buffer.
7371060SN/A    squashedSeqNum = fromCommit->commitInfo.doneSeqNum;
7381060SN/A
7391060SN/A    // Setup the squash iterator to point to the tail.
7401060SN/A    squashIt = tail;
7411060SN/A
7421681SN/A    // Call doSquash if there are insts in the IQ
7431681SN/A    if (freeEntries != numEntries) {
7441681SN/A        doSquash();
7451681SN/A    }
7461061SN/A
7471061SN/A    // Also tell the memory dependence unit to squash.
7481061SN/A    memDepUnit.squash(squashedSeqNum);
7491060SN/A}
7501060SN/A
7511061SN/Atemplate <class Impl>
7521061SN/Avoid
7531061SN/AInstructionQueue<Impl>::doSquash()
7541061SN/A{
7551061SN/A    // Make sure the squash iterator isn't pointing to nothing.
7561061SN/A    assert(squashIt != cpu->instList.end());
7571061SN/A    // Make sure the squashed sequence number is valid.
7581061SN/A    assert(squashedSeqNum != 0);
7591061SN/A
7601061SN/A    DPRINTF(IQ, "IQ: Squashing instructions in the IQ.\n");
7611061SN/A
7621061SN/A    // Squash any instructions younger than the squashed sequence number
7631061SN/A    // given.
7641061SN/A    while ((*squashIt)->seqNum > squashedSeqNum) {
7651061SN/A        DynInstPtr squashed_inst = (*squashIt);
7661061SN/A
7671061SN/A        // Only handle the instruction if it actually is in the IQ and
7681061SN/A        // hasn't already been squashed in the IQ.
7691061SN/A        if (!squashed_inst->isIssued() &&
7701061SN/A            !squashed_inst->isSquashedInIQ()) {
7711062SN/A
7721061SN/A            // Remove the instruction from the dependency list.
7731061SN/A            // Hack for now: These below don't add themselves to the
7741061SN/A            // dependency list, so don't try to remove them.
7751681SN/A            if (!squashed_inst->isNonSpeculative()/* &&
7761681SN/A                                                     !squashed_inst->isStore()*/
7771681SN/A                ) {
7781061SN/A
7791061SN/A                for (int src_reg_idx = 0;
7801681SN/A                     src_reg_idx < squashed_inst->numSrcRegs();
7811061SN/A                     src_reg_idx++)
7821061SN/A                {
7831061SN/A                    PhysRegIndex src_reg =
7841061SN/A                        squashed_inst->renamedSrcRegIdx(src_reg_idx);
7851061SN/A
7861061SN/A                    // Only remove it from the dependency graph if it was
7871061SN/A                    // placed there in the first place.
7881061SN/A                    // HACK: This assumes that instructions woken up from the
7891061SN/A                    // dependency chain aren't informed that a specific src
7901061SN/A                    // register has become ready.  This may not always be true
7911061SN/A                    // in the future.
7921061SN/A                    if (!squashed_inst->isReadySrcRegIdx(src_reg_idx) &&
7931061SN/A                        src_reg < numPhysRegs) {
7941061SN/A                        dependGraph[src_reg].remove(squashed_inst);
7951061SN/A                    }
7961062SN/A
7971062SN/A                    ++iqSquashedOperandsExamined;
7981061SN/A                }
7991062SN/A
8001062SN/A                // Might want to remove producers as well.
8011062SN/A            } else {
8021681SN/A                nonSpecInsts[squashed_inst->seqNum] = NULL;
8031681SN/A
8041062SN/A                nonSpecInsts.erase(squashed_inst->seqNum);
8051062SN/A
8061062SN/A                ++iqSquashedNonSpecRemoved;
8071061SN/A            }
8081061SN/A
8091061SN/A            // Might want to also clear out the head of the dependency graph.
8101061SN/A
8111061SN/A            // Mark it as squashed within the IQ.
8121061SN/A            squashed_inst->setSquashedInIQ();
8131061SN/A
8141681SN/A//            squashedInsts.push(squashed_inst);
8151681SN/A            squashed_inst->setIssued();
8161681SN/A            squashed_inst->setCanCommit();
8171681SN/A
8181681SN/A            ++freeEntries;
8191061SN/A
8201061SN/A            DPRINTF(IQ, "IQ: Instruction PC %#x squashed.\n",
8211061SN/A                    squashed_inst->readPC());
8221061SN/A        }
8231061SN/A
8241061SN/A        --squashIt;
8251062SN/A        ++iqSquashedInstsExamined;
8261061SN/A    }
8271681SN/A
8281681SN/A    assert(freeEntries <= numEntries);
8291681SN/A
8301681SN/A    if (freeEntries == numEntries) {
8311681SN/A        tail = cpu->instList.end();
8321681SN/A    }
8331681SN/A
8341061SN/A}
8351061SN/A
8361061SN/Atemplate <class Impl>
8371060SN/Avoid
8381060SN/AInstructionQueue<Impl>::stopSquash()
8391060SN/A{
8401060SN/A    // Clear up the squash variables to ensure that squashing doesn't
8411060SN/A    // get called improperly.
8421060SN/A    squashedSeqNum = 0;
8431060SN/A
8441060SN/A    squashIt = cpu->instList.end();
8451060SN/A}
8461060SN/A
8471061SN/Atemplate <class Impl>
8481060SN/Avoid
8491684SN/AInstructionQueue<Impl>::DependencyEntry::insert(DynInstPtr &new_inst)
8501060SN/A{
8511684SN/A    //Add this new, dependent instruction at the head of the dependency
8521684SN/A    //chain.
8531060SN/A
8541684SN/A    // First create the entry that will be added to the head of the
8551684SN/A    // dependency chain.
8561684SN/A    DependencyEntry *new_entry = new DependencyEntry;
8571684SN/A    new_entry->next = this->next;
8581684SN/A    new_entry->inst = new_inst;
8591061SN/A
8601684SN/A    // Then actually add it to the chain.
8611684SN/A    this->next = new_entry;
8621684SN/A
8631684SN/A    ++mem_alloc_counter;
8641684SN/A}
8651684SN/A
8661684SN/Atemplate <class Impl>
8671684SN/Avoid
8681684SN/AInstructionQueue<Impl>::DependencyEntry::remove(DynInstPtr &inst_to_remove)
8691684SN/A{
8701684SN/A    DependencyEntry *prev = this;
8711684SN/A    DependencyEntry *curr = this->next;
8721684SN/A
8731684SN/A    // Make sure curr isn't NULL.  Because this instruction is being
8741684SN/A    // removed from a dependency list, it must have been placed there at
8751684SN/A    // an earlier time.  The dependency chain should not be empty,
8761684SN/A    // unless the instruction dependent upon it is already ready.
8771684SN/A    if (curr == NULL) {
8781684SN/A        return;
8791061SN/A    }
8801061SN/A
8811684SN/A    // Find the instruction to remove within the dependency linked list.
8821684SN/A    while(curr->inst != inst_to_remove)
8831060SN/A    {
8841684SN/A        prev = curr;
8851684SN/A        curr = curr->next;
8861060SN/A
8871684SN/A        assert(curr != NULL);
8881684SN/A    }
8891060SN/A
8901684SN/A    // Now remove this instruction from the list.
8911684SN/A    prev->next = curr->next;
8921060SN/A
8931684SN/A    --mem_alloc_counter;
8941060SN/A
8951684SN/A    // Could push this off to the destructor of DependencyEntry
8961684SN/A    curr->inst = NULL;
8971060SN/A
8981684SN/A    delete curr;
8991060SN/A}
9001060SN/A
9011061SN/Atemplate <class Impl>
9021060SN/Abool
9031061SN/AInstructionQueue<Impl>::addToDependents(DynInstPtr &new_inst)
9041060SN/A{
9051060SN/A    // Loop through the instruction's source registers, adding
9061060SN/A    // them to the dependency list if they are not ready.
9071060SN/A    int8_t total_src_regs = new_inst->numSrcRegs();
9081060SN/A    bool return_val = false;
9091060SN/A
9101060SN/A    for (int src_reg_idx = 0;
9111060SN/A         src_reg_idx < total_src_regs;
9121060SN/A         src_reg_idx++)
9131060SN/A    {
9141060SN/A        // Only add it to the dependency graph if it's not ready.
9151060SN/A        if (!new_inst->isReadySrcRegIdx(src_reg_idx)) {
9161060SN/A            PhysRegIndex src_reg = new_inst->renamedSrcRegIdx(src_reg_idx);
9171060SN/A
9181060SN/A            // Check the IQ's scoreboard to make sure the register
9191060SN/A            // hasn't become ready while the instruction was in flight
9201060SN/A            // between stages.  Only if it really isn't ready should
9211060SN/A            // it be added to the dependency graph.
9221061SN/A            if (src_reg >= numPhysRegs) {
9231061SN/A                continue;
9241061SN/A            } else if (regScoreboard[src_reg] == false) {
9251060SN/A                DPRINTF(IQ, "IQ: Instruction PC %#x has src reg %i that "
9261060SN/A                        "is being added to the dependency chain.\n",
9271060SN/A                        new_inst->readPC(), src_reg);
9281060SN/A
9291060SN/A                dependGraph[src_reg].insert(new_inst);
9301060SN/A
9311060SN/A                // Change the return value to indicate that something
9321060SN/A                // was added to the dependency graph.
9331060SN/A                return_val = true;
9341060SN/A            } else {
9351060SN/A                DPRINTF(IQ, "IQ: Instruction PC %#x has src reg %i that "
9361060SN/A                        "became ready before it reached the IQ.\n",
9371060SN/A                        new_inst->readPC(), src_reg);
9381060SN/A                // Mark a register ready within the instruction.
9391060SN/A                new_inst->markSrcRegReady();
9401060SN/A            }
9411060SN/A        }
9421060SN/A    }
9431060SN/A
9441060SN/A    return return_val;
9451060SN/A}
9461060SN/A
9471061SN/Atemplate <class Impl>
9481060SN/Avoid
9491061SN/AInstructionQueue<Impl>::createDependency(DynInstPtr &new_inst)
9501060SN/A{
9511060SN/A    //Actually nothing really needs to be marked when an
9521060SN/A    //instruction becomes the producer of a register's value,
9531060SN/A    //but for convenience a ptr to the producing instruction will
9541060SN/A    //be placed in the head node of the dependency links.
9551060SN/A    int8_t total_dest_regs = new_inst->numDestRegs();
9561060SN/A
9571060SN/A    for (int dest_reg_idx = 0;
9581060SN/A         dest_reg_idx < total_dest_regs;
9591060SN/A         dest_reg_idx++)
9601060SN/A    {
9611061SN/A        PhysRegIndex dest_reg = new_inst->renamedDestRegIdx(dest_reg_idx);
9621061SN/A
9631061SN/A        // Instructions that use the misc regs will have a reg number
9641061SN/A        // higher than the normal physical registers.  In this case these
9651061SN/A        // registers are not renamed, and there is no need to track
9661061SN/A        // dependencies as these instructions must be executed at commit.
9671061SN/A        if (dest_reg >= numPhysRegs) {
9681061SN/A            continue;
9691060SN/A        }
9701060SN/A
9711061SN/A        dependGraph[dest_reg].inst = new_inst;
9721062SN/A
9731681SN/A        if (dependGraph[dest_reg].next) {
9741681SN/A            dumpDependGraph();
9751681SN/A            panic("IQ: Dependency graph not empty!");
9761681SN/A        }
9771062SN/A
9781060SN/A        // Mark the scoreboard to say it's not yet ready.
9791060SN/A        regScoreboard[dest_reg] = false;
9801060SN/A    }
9811060SN/A}
9821060SN/A
9831061SN/Atemplate <class Impl>
9841060SN/Avoid
9851061SN/AInstructionQueue<Impl>::addIfReady(DynInstPtr &inst)
9861060SN/A{
9871060SN/A    //If the instruction now has all of its source registers
9881060SN/A    // available, then add it to the list of ready instructions.
9891060SN/A    if (inst->readyToIssue()) {
9901061SN/A
9911060SN/A        //Add the instruction to the proper ready list.
9921061SN/A        if (inst->isControl()) {
9931061SN/A
9941061SN/A            DPRINTF(IQ, "IQ: Branch instruction is ready to issue, "
9951061SN/A                    "putting it onto the ready list, PC %#x.\n",
9961061SN/A                    inst->readPC());
9971061SN/A            readyBranchInsts.push(inst);
9981061SN/A
9991061SN/A        } else if (inst->isMemRef()) {
10001061SN/A
10011061SN/A            DPRINTF(IQ, "IQ: Checking if memory instruction can issue.\n");
10021061SN/A
10031062SN/A            // Message to the mem dependence unit that this instruction has
10041062SN/A            // its registers ready.
10051062SN/A
10061062SN/A            memDepUnit.regsReady(inst);
10071062SN/A
10081062SN/A#if 0
10091061SN/A            if (memDepUnit.readyToIssue(inst)) {
10101061SN/A                DPRINTF(IQ, "IQ: Memory instruction is ready to issue, "
10111061SN/A                        "putting it onto the ready list, PC %#x.\n",
10121061SN/A                        inst->readPC());
10131061SN/A                readyMemInsts.push(inst);
10141062SN/A            } else {
10151062SN/A                // Make dependent on the store.
10161062SN/A                // Will need some way to get the store instruction it should
10171062SN/A                // be dependent upon; then when the store issues it can
10181062SN/A                // put the instruction on the ready list.
10191062SN/A                // Yet another tree?
10201062SN/A                assert(0 && "Instruction has no way to actually issue");
10211061SN/A            }
10221062SN/A#endif
10231061SN/A
10241061SN/A        } else if (inst->isInteger()) {
10251061SN/A
10261060SN/A            DPRINTF(IQ, "IQ: Integer instruction is ready to issue, "
10271060SN/A                    "putting it onto the ready list, PC %#x.\n",
10281060SN/A                    inst->readPC());
10291061SN/A            readyIntInsts.push(inst);
10301061SN/A
10311060SN/A        } else if (inst->isFloating()) {
10321061SN/A
10331060SN/A            DPRINTF(IQ, "IQ: Floating instruction is ready to issue, "
10341060SN/A                    "putting it onto the ready list, PC %#x.\n",
10351060SN/A                    inst->readPC());
10361061SN/A            readyFloatInsts.push(inst);
10371061SN/A
10381061SN/A        } else {
10391061SN/A            DPRINTF(IQ, "IQ: Miscellaneous instruction is ready to issue, "
10401061SN/A                    "putting it onto the ready list, PC %#x..\n",
10411060SN/A                    inst->readPC());
10421061SN/A
10431061SN/A            readyMiscInsts.push(inst);
10441060SN/A        }
10451060SN/A    }
10461060SN/A}
10471060SN/A
10481681SN/A/*
10491681SN/A * Caution, this function must not be called prior to tail being updated at
10501681SN/A * least once, otherwise it will fail the assertion.  This is because
10511681SN/A * instList.begin() actually changes upon the insertion of an element into the
10521681SN/A * list when the list is empty.
10531681SN/A */
10541061SN/Atemplate <class Impl>
10551061SN/Aint
10561061SN/AInstructionQueue<Impl>::countInsts()
10571061SN/A{
10581061SN/A    ListIt count_it = cpu->instList.begin();
10591061SN/A    int total_insts = 0;
10601061SN/A
10611681SN/A    if (tail == cpu->instList.end())
10621681SN/A        return 0;
10631681SN/A
10641061SN/A    while (count_it != tail) {
10651061SN/A        if (!(*count_it)->isIssued()) {
10661061SN/A            ++total_insts;
10671061SN/A        }
10681061SN/A
10691061SN/A        ++count_it;
10701061SN/A
10711061SN/A        assert(count_it != cpu->instList.end());
10721061SN/A    }
10731061SN/A
10741061SN/A    // Need to count the tail iterator as well.
10751061SN/A    if (count_it != cpu->instList.end() &&
10761061SN/A        (*count_it) &&
10771061SN/A        !(*count_it)->isIssued()) {
10781061SN/A        ++total_insts;
10791061SN/A    }
10801061SN/A
10811061SN/A    return total_insts;
10821061SN/A}
10831061SN/A
10841061SN/Atemplate <class Impl>
10851061SN/Avoid
10861681SN/AInstructionQueue<Impl>::dumpDependGraph()
10871681SN/A{
10881681SN/A    DependencyEntry *curr;
10891681SN/A
10901681SN/A    for (int i = 0; i < numPhysRegs; ++i)
10911681SN/A    {
10921681SN/A        curr = &dependGraph[i];
10931681SN/A
10941681SN/A        if (curr->inst) {
10951681SN/A            cprintf("dependGraph[%i]: producer: %#x consumer: ", i,
10961681SN/A                    curr->inst->readPC());
10971681SN/A        } else {
10981681SN/A            cprintf("dependGraph[%i]: No producer. consumer: ", i);
10991681SN/A        }
11001681SN/A
11011681SN/A        while (curr->next != NULL) {
11021681SN/A            curr = curr->next;
11031681SN/A
11041681SN/A            cprintf("%#x ", curr->inst->readPC());
11051681SN/A        }
11061681SN/A
11071681SN/A        cprintf("\n");
11081681SN/A    }
11091681SN/A}
11101681SN/A
11111681SN/Atemplate <class Impl>
11121681SN/Avoid
11131061SN/AInstructionQueue<Impl>::dumpLists()
11141061SN/A{
11151061SN/A    cprintf("Ready integer list size: %i\n", readyIntInsts.size());
11161061SN/A
11171061SN/A    cprintf("Ready float list size: %i\n", readyFloatInsts.size());
11181061SN/A
11191061SN/A    cprintf("Ready branch list size: %i\n", readyBranchInsts.size());
11201061SN/A
11211061SN/A    cprintf("Ready misc list size: %i\n", readyMiscInsts.size());
11221061SN/A
11231061SN/A    cprintf("Squashed list size: %i\n", squashedInsts.size());
11241061SN/A
11251061SN/A    cprintf("Non speculative list size: %i\n", nonSpecInsts.size());
11261061SN/A
11271061SN/A    non_spec_it_t non_spec_it = nonSpecInsts.begin();
11281061SN/A
11291061SN/A    cprintf("Non speculative list: ");
11301061SN/A
11311061SN/A    while (non_spec_it != nonSpecInsts.end()) {
11321061SN/A        cprintf("%#x ", (*non_spec_it).second->readPC());
11331061SN/A        ++non_spec_it;
11341061SN/A    }
11351061SN/A
11361061SN/A    cprintf("\n");
11371061SN/A
11381061SN/A}
1139