inst_queue_impl.hh revision 1689
11689SN/A/*
22326SN/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
292831Sksewell@umich.edu// Todo:
301689SN/A// Current ordering allows for 0 cycle added-to-scheduled.  Could maybe fake
311689SN/A// it; either do in reverse order, or have added instructions put into a
322064SN/A// different ready queue that, in scheduleRreadyInsts(), gets put onto the
331060SN/A// normal ready queue.  This would however give only a one cycle delay,
341060SN/A// but probably is more flexible to actually add in a delay parameter than
351696SN/A// just running it backwards.
361689SN/A
372292SN/A#include <vector>
381717SN/A
391060SN/A#include "sim/universe.hh"
401061SN/A
412292SN/A#include "cpu/beta_cpu/inst_queue.hh"
422292SN/A
432292SN/A// Either compile error or max int due to sign extension.
442292SN/A// Hack to avoid compile warnings.
452326SN/Aconst InstSeqNum MaxInstSeqNum = 0 - 1;
461060SN/A
472292SN/Atemplate <class Impl>
482292SN/AInstructionQueue<Impl>::InstructionQueue(Params &params)
492292SN/A    : memDepUnit(params),
502292SN/A      numEntries(params.numIQEntries),
512292SN/A      intWidth(params.executeIntWidth),
522292SN/A      floatWidth(params.executeFloatWidth),
532292SN/A      branchWidth(params.executeBranchWidth),
542326SN/A      memoryWidth(params.executeMemoryWidth),
552292SN/A      totalWidth(params.issueWidth),
562292SN/A      numPhysIntRegs(params.numPhysIntRegs),
572292SN/A      numPhysFloatRegs(params.numPhysFloatRegs),
582292SN/A      commitToIEWDelay(params.commitToIEWDelay)
592292SN/A{
602292SN/A    // Initialize the number of free IQ entries.
612292SN/A    freeEntries = numEntries;
622292SN/A
632292SN/A    // Set the number of physical registers as the number of int + float
642292SN/A    numPhysRegs = numPhysIntRegs + numPhysFloatRegs;
652292SN/A
662292SN/A    DPRINTF(IQ, "IQ: There are %i physical registers.\n", numPhysRegs);
672292SN/A
682669Sktlim@umich.edu    //Create an entry for each physical register within the
692292SN/A    //dependency graph.
702292SN/A    dependGraph = new DependencyEntry[numPhysRegs];
712292SN/A
722292SN/A    // Resize the register scoreboard.
732292SN/A    regScoreboard.resize(numPhysRegs);
742292SN/A
752292SN/A    // Initialize all the head pointers to point to NULL, and all the
762292SN/A    // entries as unready.
772307SN/A    // Note that in actuality, the registers corresponding to the logical
782307SN/A    // registers start off as ready.  However this doesn't matter for the
792292SN/A    // IQ as the instruction should have been correctly told if those
801060SN/A    // registers are ready in rename.  Thus it can all be initialized as
811060SN/A    // unready.
821060SN/A    for (int i = 0; i < numPhysRegs; ++i)
831060SN/A    {
842292SN/A        dependGraph[i].next = NULL;
851060SN/A        dependGraph[i].inst = NULL;
861060SN/A        regScoreboard[i] = false;
871060SN/A    }
882326SN/A
891060SN/A}
901060SN/A
911060SN/Atemplate <class Impl>
921060SN/Avoid
932292SN/AInstructionQueue<Impl>::regStats()
942292SN/A{
952292SN/A    iqInstsAdded
962292SN/A        .name(name() + ".iqInstsAdded")
971060SN/A        .desc("Number of instructions added to the IQ (excludes non-spec)")
981060SN/A        .prereq(iqInstsAdded);
992307SN/A
1002292SN/A    iqNonSpecInstsAdded
1012980Sgblack@eecs.umich.edu        .name(name() + ".iqNonSpecInstsAdded")
1022292SN/A        .desc("Number of non-speculative instructions added to the IQ")
1032292SN/A        .prereq(iqNonSpecInstsAdded);
1042292SN/A
1052292SN/A//    iqIntInstsAdded;
1062292SN/A
1072292SN/A    iqIntInstsIssued
1082292SN/A        .name(name() + ".iqIntInstsIssued")
1092292SN/A        .desc("Number of integer instructions issued")
1102292SN/A        .prereq(iqIntInstsIssued);
1112292SN/A
1122292SN/A//    iqFloatInstsAdded;
1132292SN/A
1142292SN/A    iqFloatInstsIssued
1152292SN/A        .name(name() + ".iqFloatInstsIssued")
1162292SN/A        .desc("Number of float instructions issued")
1172292SN/A        .prereq(iqFloatInstsIssued);
1182292SN/A
1192292SN/A//    iqBranchInstsAdded;
1202292SN/A
1212292SN/A    iqBranchInstsIssued
1222292SN/A        .name(name() + ".iqBranchInstsIssued")
1232292SN/A        .desc("Number of branch instructions issued")
1242292SN/A        .prereq(iqBranchInstsIssued);
1252292SN/A
1262292SN/A//    iqMemInstsAdded;
1272831Sksewell@umich.edu
1282292SN/A    iqMemInstsIssued
1292292SN/A        .name(name() + ".iqMemInstsIssued")
1302292SN/A        .desc("Number of memory instructions issued")
1312292SN/A        .prereq(iqMemInstsIssued);
1322292SN/A
1332292SN/A//    iqMiscInstsAdded;
1342292SN/A
1352292SN/A    iqMiscInstsIssued
1362292SN/A        .name(name() + ".iqMiscInstsIssued")
1372292SN/A        .desc("Number of miscellaneous instructions issued")
1382292SN/A        .prereq(iqMiscInstsIssued);
1392292SN/A
1402292SN/A    iqSquashedInstsIssued
1412292SN/A        .name(name() + ".iqSquashedInstsIssued")
1422831Sksewell@umich.edu        .desc("Number of squashed instructions issued")
1432292SN/A        .prereq(iqSquashedInstsIssued);
1442292SN/A
1452292SN/A    iqLoopSquashStalls
1462292SN/A        .name(name() + ".iqLoopSquashStalls")
1472292SN/A        .desc("Number of times issue loop had to restart due to squashed "
1482292SN/A              "inst; mainly for profiling")
1492292SN/A        .prereq(iqLoopSquashStalls);
1502292SN/A
1512292SN/A    iqSquashedInstsExamined
1522292SN/A        .name(name() + ".iqSquashedInstsExamined")
1532326SN/A        .desc("Number of squashed instructions iterated over during squash;"
1542348SN/A              " mainly for profiling")
1552326SN/A        .prereq(iqSquashedInstsExamined);
1562326SN/A
1572348SN/A    iqSquashedOperandsExamined
1582292SN/A        .name(name() + ".iqSquashedOperandsExamined")
1592292SN/A        .desc("Number of squashed operands that are examined and possibly "
1602292SN/A              "removed from graph")
1612292SN/A        .prereq(iqSquashedOperandsExamined);
1622292SN/A
1632292SN/A    iqSquashedNonSpecRemoved
1642292SN/A        .name(name() + ".iqSquashedNonSpecRemoved")
1651060SN/A        .desc("Number of squashed non-spec instructions that were removed")
1661060SN/A        .prereq(iqSquashedNonSpecRemoved);
1671061SN/A
1681060SN/A    // Tell mem dependence unit to reg stats as well.
1691062SN/A    memDepUnit.regStats();
1701062SN/A}
1712301SN/A
1721062SN/Atemplate <class Impl>
1731062SN/Avoid
1741062SN/AInstructionQueue<Impl>::setCPU(FullCPU *cpu_ptr)
1751062SN/A{
1761062SN/A    cpu = cpu_ptr;
1771062SN/A
1781062SN/A    tail = cpu->instList.begin();
1791062SN/A}
1801062SN/A
1811062SN/Atemplate <class Impl>
1822301SN/Avoid
1832301SN/AInstructionQueue<Impl>::setIssueToExecuteQueue(
1842301SN/A                        TimeBuffer<IssueStruct> *i2e_ptr)
1852301SN/A{
1861062SN/A    DPRINTF(IQ, "IQ: Set the issue to execute queue.\n");
1871062SN/A    issueToExecuteQueue = i2e_ptr;
1881062SN/A}
1891062SN/A
1901062SN/Atemplate <class Impl>
1911062SN/Avoid
1921062SN/AInstructionQueue<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
1931062SN/A{
1941062SN/A    DPRINTF(IQ, "IQ: Set the time buffer.\n");
1951062SN/A    timeBuffer = tb_ptr;
1961062SN/A
1971062SN/A    fromCommit = timeBuffer->getWire(-commitToIEWDelay);
1981062SN/A}
1991062SN/A
2001062SN/Atemplate <class Impl>
2011062SN/Aunsigned
2021062SN/AInstructionQueue<Impl>::numFreeEntries()
2031062SN/A{
2041062SN/A    return freeEntries;
2051062SN/A}
2061062SN/A
2071062SN/A// Might want to do something more complex if it knows how many instructions
2081062SN/A// will be issued this cycle.
2091062SN/Atemplate <class Impl>
2101062SN/Abool
2111062SN/AInstructionQueue<Impl>::isFull()
2121062SN/A{
2131062SN/A    if (freeEntries == 0) {
2141062SN/A        return(true);
2151062SN/A    } else {
2161062SN/A        return(false);
2171062SN/A    }
2181062SN/A}
2191062SN/A
2201062SN/Atemplate <class Impl>
2211062SN/Avoid
2221062SN/AInstructionQueue<Impl>::insert(DynInstPtr &new_inst)
2231062SN/A{
2241062SN/A    // Make sure the instruction is valid
2251062SN/A    assert(new_inst);
2261062SN/A
2271062SN/A    DPRINTF(IQ, "IQ: Adding instruction PC %#x to the IQ.\n",
2281062SN/A            new_inst->readPC());
2291062SN/A
2301062SN/A    // Check if there are any free entries.  Panic if there are none.
2311062SN/A    // Might want to have this return a fault in the future instead of
2321062SN/A    // panicing.
2331062SN/A    assert(freeEntries != 0);
2342326SN/A
2352301SN/A    // If the IQ currently has nothing in it, then there's a possibility
2362301SN/A    // that the tail iterator is invalid (might have been pointing at an
2372301SN/A    // instruction that was retired).  Reset the tail iterator.
2382301SN/A    if (freeEntries == numEntries) {
2392301SN/A        tail = cpu->instList.begin();
2402301SN/A    }
2412326SN/A
2422301SN/A    // Move the tail iterator.  Instructions may not have been issued
2432326SN/A    // to the IQ, so we may have to increment the iterator more than once.
2442307SN/A    while ((*tail) != new_inst) {
2452301SN/A        tail++;
2462301SN/A
2472307SN/A        // Make sure the tail iterator points at something legal.
2482301SN/A        assert(tail != cpu->instList.end());
2492301SN/A    }
2502301SN/A
2512301SN/A
2522301SN/A    // Decrease the number of free entries.
2532301SN/A    --freeEntries;
2542301SN/A
2552301SN/A    // Look through its source registers (physical regs), and mark any
2562301SN/A    // dependencies.
2572301SN/A    addToDependents(new_inst);
2582301SN/A
2592301SN/A    // Have this instruction set itself as the producer of its destination
2602326SN/A    // register(s).
2612301SN/A    createDependency(new_inst);
2622301SN/A
2632301SN/A    // If it's a memory instruction, add it to the memory dependency
2642301SN/A    // unit.
2652301SN/A    if (new_inst->isMemRef()) {
2662326SN/A        memDepUnit.insert(new_inst);
2672301SN/A        // Uh..forgot to look it up and put it on the proper dependency list
2682301SN/A        // if the instruction should not go yet.
2692301SN/A    } else {
2702301SN/A        // If the instruction is ready then add it to the ready list.
2712301SN/A        addIfReady(new_inst);
2722326SN/A    }
2732301SN/A
2742301SN/A    ++iqInstsAdded;
2752301SN/A
2762301SN/A    assert(freeEntries == (numEntries - countInsts()));
2772301SN/A}
2782301SN/A
2792301SN/Atemplate <class Impl>
2802980Sgblack@eecs.umich.eduvoid
2812301SN/AInstructionQueue<Impl>::insertNonSpec(DynInstPtr &inst)
2822326SN/A{
2832301SN/A    nonSpecInsts[inst->seqNum] = inst;
2842301SN/A
2852326SN/A    // @todo: Clean up this code; can do it by setting inst as unable
2862301SN/A    // to issue, then calling normal insert on the inst.
2872301SN/A
2882301SN/A    // Make sure the instruction is valid
2892301SN/A    assert(inst);
2902326SN/A
2912727Sktlim@umich.edu    DPRINTF(IQ, "IQ: Adding instruction PC %#x to the IQ.\n",
2922326SN/A            inst->readPC());
2932301SN/A
2942301SN/A    // Check if there are any free entries.  Panic if there are none.
2952301SN/A    // Might want to have this return a fault in the future instead of
2962301SN/A    // panicing.
2972301SN/A    assert(freeEntries != 0);
2982301SN/A
2992326SN/A    // If the IQ currently has nothing in it, then there's a possibility
3002301SN/A    // that the tail iterator is invalid (might have been pointing at an
3012301SN/A    // instruction that was retired).  Reset the tail iterator.
3022326SN/A    if (freeEntries == numEntries) {
3032301SN/A        tail = cpu->instList.begin();
3042301SN/A    }
3052301SN/A
3062301SN/A    // Move the tail iterator.  Instructions may not have been issued
3072301SN/A    // to the IQ, so we may have to increment the iterator more than once.
3082301SN/A    while ((*tail) != inst) {
3092326SN/A        tail++;
3102301SN/A
3112301SN/A        // Make sure the tail iterator points at something legal.
3122301SN/A        assert(tail != cpu->instList.end());
3132301SN/A    }
3142326SN/A
3152301SN/A    // Decrease the number of free entries.
3162292SN/A    --freeEntries;
3172292SN/A
3182292SN/A    // Have this instruction set itself as the producer of its destination
3192292SN/A    // register(s).
3201062SN/A    createDependency(inst);
3211062SN/A
3221062SN/A    // If it's a memory instruction, add it to the memory dependency
3231062SN/A    // unit.
3242307SN/A    if (inst->isMemRef()) {
3251060SN/A        memDepUnit.insertNonSpec(inst);
3262307SN/A    }
3272307SN/A
3282307SN/A    ++iqNonSpecInstsAdded;
3292307SN/A}
3302307SN/A
3311060SN/A// Slightly hack function to advance the tail iterator in the case that
3322307SN/A// the IEW stage issues an instruction that is not added to the IQ.  This
3332307SN/A// is needed in case a long chain of such instructions occurs.
3342307SN/A// I don't think this is used anymore.
3352307SN/Atemplate <class Impl>
3362307SN/Avoid
3372307SN/AInstructionQueue<Impl>::advanceTail(DynInstPtr &inst)
3382307SN/A{
3392307SN/A    // Make sure the instruction is valid
3402307SN/A    assert(inst);
3412307SN/A
3422307SN/A    DPRINTF(IQ, "IQ: Adding instruction PC %#x to the IQ.\n",
3432307SN/A            inst->readPC());
3442307SN/A
3452307SN/A    // Check if there are any free entries.  Panic if there are none.
3462307SN/A    // Might want to have this return a fault in the future instead of
3472307SN/A    // panicing.
3482307SN/A    assert(freeEntries != 0);
3492307SN/A
3502307SN/A    // If the IQ currently has nothing in it, then there's a possibility
3512307SN/A    // that the tail iterator is invalid (might have been pointing at an
3522307SN/A    // instruction that was retired).  Reset the tail iterator.
3532307SN/A    if (freeEntries == numEntries) {
3542307SN/A        tail = cpu->instList.begin();
3552307SN/A    }
3561060SN/A
3571060SN/A    // Move the tail iterator.  Instructions may not have been issued
3581061SN/A    // to the IQ, so we may have to increment the iterator more than once.
3591060SN/A    while ((*tail) != inst) {
3602980Sgblack@eecs.umich.edu        tail++;
3611060SN/A
3622292SN/A        // Make sure the tail iterator points at something legal.
3632292SN/A        assert(tail != cpu->instList.end());
3642064SN/A    }
3652064SN/A
3662064SN/A    assert(freeEntries <= numEntries);
3672064SN/A
3682292SN/A    // Have this instruction set itself as the producer of its destination
3692064SN/A    // register(s).
3702292SN/A    createDependency(inst);
3711060SN/A}
3721060SN/A
3731060SN/A// Need to make sure the number of float and integer instructions
3741061SN/A// issued does not exceed the total issue bandwidth.
3751060SN/A// @todo: Figure out a better way to remove the squashed items from the
3761060SN/A// lists.  Checking the top item of each list to see if it's squashed
3771060SN/A// wastes time and forces jumps.
3782292SN/Atemplate <class Impl>
3791060SN/Avoid
3801060SN/AInstructionQueue<Impl>::scheduleReadyInsts()
3811060SN/A{
3821060SN/A    DPRINTF(IQ, "IQ: Attempting to schedule ready instructions from "
3831060SN/A                "the IQ.\n");
3841684SN/A
3852307SN/A    int int_issued = 0;
3862307SN/A    int float_issued = 0;
3872307SN/A    int branch_issued = 0;
3882307SN/A    int memory_issued = 0;
3892326SN/A    int squashed_issued = 0;
3902307SN/A    int total_issued = 0;
3912307SN/A
3922307SN/A    IssueStruct *i2e_info = issueToExecuteQueue->access(0);
3932307SN/A
3942307SN/A    bool insts_available = !readyBranchInsts.empty() ||
3952307SN/A        !readyIntInsts.empty() ||
3962307SN/A        !readyFloatInsts.empty() ||
3972307SN/A        !memDepUnit.empty() ||
3982307SN/A        !readyMiscInsts.empty() ||
3992307SN/A        !squashedInsts.empty();
4002307SN/A
4012307SN/A    // Note: Requires a globally defined constant.
4022307SN/A    InstSeqNum oldest_inst = MaxInstSeqNum;
4032307SN/A    InstList list_with_oldest = None;
4042292SN/A
4052292SN/A    // Temporary values.
4062292SN/A    DynInstPtr int_head_inst;
4072292SN/A    DynInstPtr float_head_inst;
4082292SN/A    DynInstPtr branch_head_inst;
4092292SN/A    DynInstPtr mem_head_inst;
4102292SN/A    DynInstPtr misc_head_inst;
4112292SN/A    DynInstPtr squashed_head_inst;
4122292SN/A
4132292SN/A    // Somewhat nasty code to look at all of the lists where issuable
4142292SN/A    // instructions are located, and choose the oldest instruction among
4152292SN/A    // those lists.  Consider a rewrite in the future.
4162292SN/A    while (insts_available && total_issued < totalWidth)
4172292SN/A    {
4182292SN/A        // Set this to false.  Each if-block is required to set it to true
4192292SN/A        // if there were instructions available this check.  This will cause
4202292SN/A        // this loop to run once more than necessary, but avoids extra calls.
4212292SN/A        insts_available = false;
4222980Sgblack@eecs.umich.edu
4232980Sgblack@eecs.umich.edu        oldest_inst = MaxInstSeqNum;
4242292SN/A
4252292SN/A        list_with_oldest = None;
4262292SN/A
4272292SN/A        if (!readyIntInsts.empty() &&
4282292SN/A            int_issued < intWidth) {
4292292SN/A
4302292SN/A            insts_available = true;
4312292SN/A
4322292SN/A            int_head_inst = readyIntInsts.top();
4332292SN/A
4342292SN/A            if (int_head_inst->isSquashed()) {
4352292SN/A                readyIntInsts.pop();
4361684SN/A
4371684SN/A                ++iqLoopSquashStalls;
4381684SN/A
4391684SN/A                continue;
4401684SN/A            }
4411684SN/A
4422292SN/A            oldest_inst = int_head_inst->seqNum;
4432292SN/A
4442292SN/A            list_with_oldest = Int;
4452292SN/A        }
4462292SN/A
4472292SN/A        if (!readyFloatInsts.empty() &&
4482292SN/A            float_issued < floatWidth) {
4491060SN/A
4501060SN/A            insts_available = true;
4511061SN/A
4521060SN/A            float_head_inst = readyFloatInsts.top();
4531060SN/A
4541060SN/A            if (float_head_inst->isSquashed()) {
4551060SN/A                readyFloatInsts.pop();
4561060SN/A
4571060SN/A                ++iqLoopSquashStalls;
4581060SN/A
4591060SN/A                continue;
4601060SN/A            } else if (float_head_inst->seqNum < oldest_inst) {
4611060SN/A                oldest_inst = float_head_inst->seqNum;
4621061SN/A
4632292SN/A                list_with_oldest = Float;
4642292SN/A            }
4652292SN/A        }
4662292SN/A
4672292SN/A        if (!readyBranchInsts.empty() &&
4682292SN/A            branch_issued < branchWidth) {
4692292SN/A
4702292SN/A            insts_available = true;
4712292SN/A
4722292SN/A            branch_head_inst = readyBranchInsts.top();
4732292SN/A
4742292SN/A            if (branch_head_inst->isSquashed()) {
4752292SN/A                readyBranchInsts.pop();
4762292SN/A
4772292SN/A                ++iqLoopSquashStalls;
4782292SN/A
4792292SN/A                continue;
4802292SN/A            } else if (branch_head_inst->seqNum < oldest_inst) {
4812292SN/A                oldest_inst = branch_head_inst->seqNum;
4822292SN/A
4832292SN/A                list_with_oldest = Branch;
4842292SN/A            }
4852292SN/A
4862292SN/A        }
4872292SN/A
4882292SN/A        if (!memDepUnit.empty() &&
4892292SN/A            memory_issued < memoryWidth) {
4902292SN/A
4911060SN/A            insts_available = true;
4921061SN/A
4931060SN/A            mem_head_inst = memDepUnit.top();
4941060SN/A
4951060SN/A            if (mem_head_inst->isSquashed()) {
4961060SN/A                memDepUnit.pop();
4972326SN/A
4982326SN/A                ++iqLoopSquashStalls;
4991060SN/A
5001060SN/A                continue;
5011060SN/A            } else if (mem_head_inst->seqNum < oldest_inst) {
5022292SN/A                oldest_inst = mem_head_inst->seqNum;
5031060SN/A
5042064SN/A                list_with_oldest = Memory;
5051060SN/A            }
5062292SN/A        }
5071060SN/A
5081060SN/A        if (!readyMiscInsts.empty()) {
5091060SN/A
5101060SN/A            insts_available = true;
5111060SN/A
5121060SN/A            misc_head_inst = readyMiscInsts.top();
5131060SN/A
5142326SN/A            if (misc_head_inst->isSquashed()) {
5151060SN/A                readyMiscInsts.pop();
5161061SN/A
5172292SN/A                ++iqLoopSquashStalls;
5181062SN/A
5191062SN/A                continue;
5201061SN/A            } else if (misc_head_inst->seqNum < oldest_inst) {
5211061SN/A                oldest_inst = misc_head_inst->seqNum;
5221062SN/A
5231060SN/A                list_with_oldest = Misc;
5242292SN/A            }
5252292SN/A        }
5261060SN/A
5271060SN/A        if (!squashedInsts.empty()) {
5281060SN/A
5291061SN/A            insts_available = true;
5301061SN/A
5312292SN/A            squashed_head_inst = squashedInsts.top();
5321061SN/A
5331061SN/A            if (squashed_head_inst->seqNum < oldest_inst) {
5341061SN/A                list_with_oldest = Squashed;
5351061SN/A            }
5362292SN/A
5371061SN/A        }
5382292SN/A
5391061SN/A        DynInstPtr issuing_inst = NULL;
5402326SN/A
5412326SN/A        switch (list_with_oldest) {
5422326SN/A          case None:
5432064SN/A            DPRINTF(IQ, "IQ: Not able to schedule any instructions. Issuing "
5441061SN/A                    "inst is %#x.\n", issuing_inst);
5451061SN/A            break;
5462292SN/A
5471061SN/A          case Int:
5482064SN/A            issuing_inst = int_head_inst;
5491061SN/A            readyIntInsts.pop();
5502292SN/A            ++int_issued;
5511061SN/A            DPRINTF(IQ, "IQ: Issuing integer instruction PC %#x.\n",
5521061SN/A                    issuing_inst->readPC());
5531061SN/A            break;
5542326SN/A
5551061SN/A          case Float:
5561061SN/A            issuing_inst = float_head_inst;
5571061SN/A            readyFloatInsts.pop();
5582292SN/A            ++float_issued;
5592292SN/A            DPRINTF(IQ, "IQ: Issuing float instruction PC %#x.\n",
5601061SN/A                    issuing_inst->readPC());
5611062SN/A            break;
5621062SN/A
5632292SN/A          case Branch:
5642292SN/A            issuing_inst = branch_head_inst;
5652292SN/A            readyBranchInsts.pop();
5662292SN/A            ++branch_issued;
5671061SN/A            DPRINTF(IQ, "IQ: Issuing branch instruction PC %#x.\n",
5681061SN/A                    issuing_inst->readPC());
5691061SN/A            break;
5701060SN/A
5712292SN/A          case Memory:
5721060SN/A            issuing_inst = mem_head_inst;
5732292SN/A
5741060SN/A            memDepUnit.pop();
5752292SN/A            ++memory_issued;
5762292SN/A            DPRINTF(IQ, "IQ: Issuing memory instruction PC %#x.\n",
5771060SN/A                    issuing_inst->readPC());
5782064SN/A            break;
5792333SN/A
5802333SN/A          case Misc:
5812333SN/A            issuing_inst = misc_head_inst;
5822333SN/A            readyMiscInsts.pop();
5832333SN/A
5842333SN/A            ++iqMiscInstsIssued;
5852333SN/A
5862333SN/A            DPRINTF(IQ, "IQ: Issuing a miscellaneous instruction PC %#x.\n",
5871060SN/A                    issuing_inst->readPC());
5882333SN/A            break;
5892064SN/A
5902292SN/A          case Squashed:
5912292SN/A            assert(0 && "Squashed insts should not issue any more!");
5922292SN/A            squashedInsts.pop();
5932292SN/A            // Set the squashed instruction as able to commit so that commit
5942292SN/A            // can just drop it from the ROB.  This is a bit faked.
5952292SN/A            ++squashed_issued;
5962292SN/A            ++freeEntries;
5972292SN/A
5982292SN/A            DPRINTF(IQ, "IQ: Issuing squashed instruction PC %#x.\n",
5992292SN/A                    squashed_head_inst->readPC());
6002292SN/A            break;
6012292SN/A        }
6022292SN/A
6032292SN/A        if (list_with_oldest != None && list_with_oldest != Squashed) {
6042292SN/A            i2e_info->insts[total_issued] = issuing_inst;
6052292SN/A            i2e_info->size++;
6062292SN/A
6072292SN/A            issuing_inst->setIssued();
6082292SN/A
6091060SN/A            ++freeEntries;
6101060SN/A            ++total_issued;
6112292SN/A        }
6122292SN/A
6132292SN/A        assert(freeEntries == (numEntries - countInsts()));
6141060SN/A    }
6152292SN/A
6162292SN/A    iqIntInstsIssued += int_issued;
6172292SN/A    iqFloatInstsIssued += float_issued;
6182292SN/A    iqBranchInstsIssued += branch_issued;
6192292SN/A    iqMemInstsIssued += memory_issued;
6202292SN/A    iqSquashedInstsIssued += squashed_issued;
6212292SN/A}
6222292SN/A
6232292SN/Atemplate <class Impl>
6242292SN/Avoid
6252292SN/AInstructionQueue<Impl>::scheduleNonSpec(const InstSeqNum &inst)
6262292SN/A{
6272292SN/A    DPRINTF(IQ, "IQ: Marking nonspeculative instruction with sequence "
6282292SN/A            "number %i as ready to execute.\n", inst);
6292292SN/A
6302292SN/A    non_spec_it_t inst_it = nonSpecInsts.find(inst);
6312292SN/A
6322292SN/A    assert(inst_it != nonSpecInsts.end());
6332292SN/A
6342292SN/A    // Mark this instruction as ready to issue.
6352292SN/A    (*inst_it).second->setCanIssue();
6361060SN/A
6371060SN/A    // Now schedule the instruction.
6382292SN/A    if (!(*inst_it).second->isMemRef()) {
6391060SN/A        addIfReady((*inst_it).second);
6401060SN/A    } else {
6412292SN/A        memDepUnit.nonSpecInstReady((*inst_it).second);
6422292SN/A    }
6432292SN/A
6442292SN/A    nonSpecInsts.erase(inst_it);
6452292SN/A}
6462292SN/A
6472307SN/Atemplate <class Impl>
6482307SN/Avoid
6492307SN/AInstructionQueue<Impl>::wakeDependents(DynInstPtr &completed_inst)
6502307SN/A{
6512292SN/A    DPRINTF(IQ, "IQ: Waking dependents of completed instruction.\n");
6522292SN/A    //Look at the physical destination register of the DynInst
6532326SN/A    //and look it up on the dependency graph.  Then mark as ready
6542326SN/A    //any instructions within the instruction queue.
6552292SN/A    DependencyEntry *curr;
6562326SN/A
6572326SN/A    // Tell the memory dependence unit to wake any dependents on this
6582326SN/A    // instruction if it is a memory instruction.
6592333SN/A
6602333SN/A    if (completed_inst->isMemRef()) {
6612292SN/A        memDepUnit.wakeDependents(completed_inst);
6622292SN/A    }
6631061SN/A
6641061SN/A    for (int dest_reg_idx = 0;
6651061SN/A         dest_reg_idx < completed_inst->numDestRegs();
6661061SN/A         dest_reg_idx++)
6671060SN/A    {
6681060SN/A        PhysRegIndex dest_reg =
6691060SN/A            completed_inst->renamedDestRegIdx(dest_reg_idx);
6702292SN/A
6712292SN/A        // Special case of uniq or control registers.  They are not
6721060SN/A        // handled by the IQ and thus have no dependency graph entry.
6731060SN/A        // @todo Figure out a cleaner way to handle this.
6741060SN/A        if (dest_reg >= numPhysRegs) {
6752292SN/A            continue;
6762292SN/A        }
6772292SN/A
6782292SN/A        DPRINTF(IQ, "IQ: Waking any dependents on register %i.\n",
6792292SN/A                (int) dest_reg);
6802292SN/A
6812292SN/A        //Maybe abstract this part into a function.
6822292SN/A        //Go through the dependency chain, marking the registers as ready
6832292SN/A        //within the waiting instructions.
6842292SN/A        while (dependGraph[dest_reg].next) {
6852292SN/A
6861060SN/A            curr = dependGraph[dest_reg].next;
6872333SN/A
6882820Sktlim@umich.edu            DPRINTF(IQ, "IQ: Waking up a dependent instruction, PC%#x.\n",
6892326SN/A                    curr->inst->readPC());
6902292SN/A
6911060SN/A            // Might want to give more information to the instruction
6922292SN/A            // so that it knows which of its source registers is ready.
6931060SN/A            // However that would mean that the dependency graph entries
6942292SN/A            // would need to hold the src_reg_idx.
6951060SN/A            curr->inst->markSrcRegReady();
6962292SN/A
6971060SN/A            addIfReady(curr->inst);
6982292SN/A
6992292SN/A            dependGraph[dest_reg].next = curr->next;
7001060SN/A
7012292SN/A            DependencyEntry::mem_alloc_counter--;
7022292SN/A
7032292SN/A            curr->inst = NULL;
7042292SN/A
7052292SN/A            delete curr;
7061060SN/A        }
7071060SN/A
7082292SN/A        // Reset the head node now that all of its dependents have been woken
7091060SN/A        // up.
7102292SN/A        dependGraph[dest_reg].next = NULL;
7112292SN/A        dependGraph[dest_reg].inst = NULL;
7122292SN/A
7131060SN/A        // Mark the scoreboard as having that register ready.
7141060SN/A        regScoreboard[dest_reg] = true;
7152326SN/A    }
7162326SN/A}
7172301SN/A
7181060SN/Atemplate <class Impl>
7192326SN/Avoid
7202326SN/AInstructionQueue<Impl>::violation(DynInstPtr &store,
7211060SN/A                                  DynInstPtr &faulting_load)
7222326SN/A{
7232326SN/A    memDepUnit.violation(store, faulting_load);
7241060SN/A}
7251060SN/A
7261060SN/Atemplate <class Impl>
7272348SN/Avoid
7282348SN/AInstructionQueue<Impl>::squash()
7292326SN/A{
7302292SN/A    DPRINTF(IQ, "IQ: Starting to squash instructions in the IQ.\n");
7312292SN/A
7322333SN/A    // Read instruction sequence number of last instruction out of the
7331060SN/A    // time buffer.
7342326SN/A    squashedSeqNum = fromCommit->commitInfo.doneSeqNum;
7352326SN/A
7362326SN/A    // Setup the squash iterator to point to the tail.
7372326SN/A    squashIt = tail;
7382292SN/A
7392292SN/A    // Call doSquash if there are insts in the IQ
7402326SN/A    if (freeEntries != numEntries) {
7412326SN/A        doSquash();
7422326SN/A    }
7431060SN/A
7442326SN/A    // Also tell the memory dependence unit to squash.
7451060SN/A    memDepUnit.squash(squashedSeqNum);
7462326SN/A}
7472292SN/A
7482348SN/Atemplate <class Impl>
7492348SN/Avoid
7502326SN/AInstructionQueue<Impl>::doSquash()
7512292SN/A{
7522292SN/A    // Make sure the squash iterator isn't pointing to nothing.
7532326SN/A    assert(squashIt != cpu->instList.end());
7542292SN/A    // Make sure the squashed sequence number is valid.
7551060SN/A    assert(squashedSeqNum != 0);
7561060SN/A
7572292SN/A    DPRINTF(IQ, "IQ: Squashing instructions in the IQ.\n");
7582292SN/A
7592301SN/A    // Squash any instructions younger than the squashed sequence number
7602292SN/A    // given.
7611060SN/A    while ((*squashIt)->seqNum > squashedSeqNum) {
7622292SN/A        DynInstPtr squashed_inst = (*squashIt);
7631061SN/A
7642292SN/A        // Only handle the instruction if it actually is in the IQ and
7652292SN/A        // hasn't already been squashed in the IQ.
7662292SN/A        if (!squashed_inst->isIssued() &&
7672292SN/A            !squashed_inst->isSquashedInIQ()) {
7682292SN/A
7691060SN/A            // Remove the instruction from the dependency list.
7701060SN/A            // Hack for now: These below don't add themselves to the
7712064SN/A            // dependency list, so don't try to remove them.
7722292SN/A            if (!squashed_inst->isNonSpeculative()/* &&
7732064SN/A                                                     !squashed_inst->isStore()*/
7742292SN/A                ) {
7752292SN/A
7762292SN/A                for (int src_reg_idx = 0;
7772292SN/A                     src_reg_idx < squashed_inst->numSrcRegs();
7782301SN/A                     src_reg_idx++)
7792731Sktlim@umich.edu                {
7802292SN/A                    PhysRegIndex src_reg =
7812301SN/A                        squashed_inst->renamedSrcRegIdx(src_reg_idx);
7822292SN/A
7832292SN/A                    // Only remove it from the dependency graph if it was
7842292SN/A                    // placed there in the first place.
7852326SN/A                    // HACK: This assumes that instructions woken up from the
7862820Sktlim@umich.edu                    // dependency chain aren't informed that a specific src
7872292SN/A                    // register has become ready.  This may not always be true
7882326SN/A                    // in the future.
7892326SN/A                    if (!squashed_inst->isReadySrcRegIdx(src_reg_idx) &&
7902292SN/A                        src_reg < numPhysRegs) {
7911060SN/A                        dependGraph[src_reg].remove(squashed_inst);
7921060SN/A                    }
7931062SN/A
7942326SN/A                    ++iqSquashedOperandsExamined;
7952326SN/A                }
7962307SN/A
7972348SN/A                // Might want to remove producers as well.
7982292SN/A            } else {
7992292SN/A                nonSpecInsts[squashed_inst->seqNum] = NULL;
8002292SN/A
8012292SN/A                nonSpecInsts.erase(squashed_inst->seqNum);
8022292SN/A
8031060SN/A                ++iqSquashedNonSpecRemoved;
8041060SN/A            }
8051061SN/A
8061060SN/A            // Might want to also clear out the head of the dependency graph.
8071061SN/A
8081060SN/A            // Mark it as squashed within the IQ.
8092292SN/A            squashed_inst->setSquashedInIQ();
8102292SN/A
8111062SN/A//            squashedInsts.push(squashed_inst);
8122292SN/A            squashed_inst->setIssued();
8131060SN/A            squashed_inst->setCanCommit();
8141061SN/A
8151060SN/A            ++freeEntries;
8162292SN/A
8172292SN/A            DPRINTF(IQ, "IQ: Instruction PC %#x squashed.\n",
8181061SN/A                    squashed_inst->readPC());
8191060SN/A        }
8201062SN/A
8211062SN/A        --squashIt;
8221062SN/A        ++iqSquashedInstsExamined;
8232292SN/A    }
8241062SN/A
8251060SN/A    assert(freeEntries <= numEntries);
8262292SN/A
8272292SN/A    if (freeEntries == numEntries) {
8281061SN/A        tail = cpu->instList.end();
8291060SN/A    }
8301060SN/A
8311061SN/A}
8321061SN/A
8332292SN/Atemplate <class Impl>
8342292SN/Avoid
8352292SN/AInstructionQueue<Impl>::stopSquash()
8362292SN/A{
8372292SN/A    // Clear up the squash variables to ensure that squashing doesn't
8382292SN/A    // get called improperly.
8392292SN/A    squashedSeqNum = 0;
8402292SN/A
8412292SN/A    squashIt = cpu->instList.end();
8422292SN/A}
8432292SN/A
8442292SN/Atemplate <class Impl>
8452292SN/Avoid
8462292SN/AInstructionQueue<Impl>::DependencyEntry::insert(DynInstPtr &new_inst)
8472292SN/A{
8482292SN/A    //Add this new, dependent instruction at the head of the dependency
8492292SN/A    //chain.
8502301SN/A
8511684SN/A    // First create the entry that will be added to the head of the
8521684SN/A    // dependency chain.
8532301SN/A    DependencyEntry *new_entry = new DependencyEntry;
8542301SN/A    new_entry->next = this->next;
8552292SN/A    new_entry->inst = new_inst;
8562292SN/A
8572292SN/A    // Then actually add it to the chain.
8581684SN/A    this->next = new_entry;
8591684SN/A
8602292SN/A    ++mem_alloc_counter;
8612326SN/A}
8622326SN/A
8632326SN/Atemplate <class Impl>
8642326SN/Avoid
8651684SN/AInstructionQueue<Impl>::DependencyEntry::remove(DynInstPtr &inst_to_remove)
8662292SN/A{
8672292SN/A    DependencyEntry *prev = this;
8682292SN/A    DependencyEntry *curr = this->next;
8692292SN/A
8702292SN/A    // Make sure curr isn't NULL.  Because this instruction is being
8711684SN/A    // removed from a dependency list, it must have been placed there at
8721684SN/A    // an earlier time.  The dependency chain should not be empty,
8731684SN/A    // unless the instruction dependent upon it is already ready.
8741684SN/A    if (curr == NULL) {
8751684SN/A        return;
8761684SN/A    }
8771684SN/A
8781684SN/A    // Find the instruction to remove within the dependency linked list.
8791684SN/A    while(curr->inst != inst_to_remove)
8801684SN/A    {
8811684SN/A        prev = curr;
8821684SN/A        curr = curr->next;
8831684SN/A
8841684SN/A        assert(curr != NULL);
8851684SN/A    }
8861684SN/A
8872292SN/A    // Now remove this instruction from the list.
8881684SN/A    prev->next = curr->next;
8891684SN/A
8902326SN/A    --mem_alloc_counter;
8912326SN/A
8922326SN/A    // Could push this off to the destructor of DependencyEntry
8931684SN/A    curr->inst = NULL;
8942326SN/A
8952292SN/A    delete curr;
8962326SN/A}
8971684SN/A
8981684SN/Atemplate <class Impl>
8992326SN/Abool
9002326SN/AInstructionQueue<Impl>::addToDependents(DynInstPtr &new_inst)
9012326SN/A{
9022326SN/A    // Loop through the instruction's source registers, adding
9031684SN/A    // them to the dependency list if they are not ready.
9042326SN/A    int8_t total_src_regs = new_inst->numSrcRegs();
9051684SN/A    bool return_val = false;
9062326SN/A
9071684SN/A    for (int src_reg_idx = 0;
9082301SN/A         src_reg_idx < total_src_regs;
9091684SN/A         src_reg_idx++)
9101684SN/A    {
9112326SN/A        // Only add it to the dependency graph if it's not ready.
9122326SN/A        if (!new_inst->isReadySrcRegIdx(src_reg_idx)) {
9132326SN/A            PhysRegIndex src_reg = new_inst->renamedSrcRegIdx(src_reg_idx);
9142326SN/A
9151684SN/A            // Check the IQ's scoreboard to make sure the register
9161684SN/A            // hasn't become ready while the instruction was in flight
9171684SN/A            // between stages.  Only if it really isn't ready should
9181684SN/A            // it be added to the dependency graph.
9192301SN/A            if (src_reg >= numPhysRegs) {
9202064SN/A                continue;
9212064SN/A            } else if (regScoreboard[src_reg] == false) {
9222064SN/A                DPRINTF(IQ, "IQ: Instruction PC %#x has src reg %i that "
9232064SN/A                        "is being added to the dependency chain.\n",
9242292SN/A                        new_inst->readPC(), src_reg);
9252064SN/A
9262292SN/A                dependGraph[src_reg].insert(new_inst);
9272292SN/A
9282292SN/A                // Change the return value to indicate that something
9292292SN/A                // was added to the dependency graph.
9302326SN/A                return_val = true;
9312326SN/A            } else {
9322326SN/A                DPRINTF(IQ, "IQ: Instruction PC %#x has src reg %i that "
9332326SN/A                        "became ready before it reached the IQ.\n",
9342326SN/A                        new_inst->readPC(), src_reg);
9352326SN/A                // Mark a register ready within the instruction.
9362326SN/A                new_inst->markSrcRegReady();
9372326SN/A            }
9382326SN/A        }
9392326SN/A    }
9402292SN/A
9412292SN/A    return return_val;
9422292SN/A}
9432064SN/A
9442064SN/Atemplate <class Impl>
9452064SN/Avoid
9462064SN/AInstructionQueue<Impl>::createDependency(DynInstPtr &new_inst)
9472292SN/A{
9482064SN/A    //Actually nothing really needs to be marked when an
9492292SN/A    //instruction becomes the producer of a register's value,
9502064SN/A    //but for convenience a ptr to the producing instruction will
9512064SN/A    //be placed in the head node of the dependency links.
9522064SN/A    int8_t total_dest_regs = new_inst->numDestRegs();
9532064SN/A
9542292SN/A    for (int dest_reg_idx = 0;
9552064SN/A         dest_reg_idx < total_dest_regs;
9562292SN/A         dest_reg_idx++)
9572292SN/A    {
9582292SN/A        PhysRegIndex dest_reg = new_inst->renamedDestRegIdx(dest_reg_idx);
9592292SN/A
9602292SN/A        // Instructions that use the misc regs will have a reg number
9612292SN/A        // higher than the normal physical registers.  In this case these
9622292SN/A        // registers are not renamed, and there is no need to track
9632292SN/A        // dependencies as these instructions must be executed at commit.
9642292SN/A        if (dest_reg >= numPhysRegs) {
9652292SN/A            continue;
9662292SN/A        }
9672292SN/A
9682292SN/A        dependGraph[dest_reg].inst = new_inst;
9692292SN/A
9702292SN/A        if (dependGraph[dest_reg].next) {
9712292SN/A            dumpDependGraph();
9722292SN/A            panic("IQ: Dependency graph not empty!");
9732292SN/A        }
9742292SN/A
9751684SN/A        // Mark the scoreboard to say it's not yet ready.
9761684SN/A        regScoreboard[dest_reg] = false;
9771684SN/A    }
9781684SN/A}
9791061SN/A
9801061SN/Atemplate <class Impl>
9811061SN/Avoid
9822292SN/AInstructionQueue<Impl>::addIfReady(DynInstPtr &inst)
9831061SN/A{
9841061SN/A    //If the instruction now has all of its source registers
9851061SN/A    // available, then add it to the list of ready instructions.
9861060SN/A    if (inst->readyToIssue()) {
9872292SN/A
9881060SN/A        //Add the instruction to the proper ready list.
9892292SN/A        if (inst->isControl()) {
9902292SN/A
9911060SN/A            DPRINTF(IQ, "IQ: Branch instruction is ready to issue, "
9921060SN/A                    "putting it onto the ready list, PC %#x.\n",
9931060SN/A                    inst->readPC());
9943093Sksewell@umich.edu            readyBranchInsts.push(inst);
9953093Sksewell@umich.edu
9963093Sksewell@umich.edu        } else if (inst->isMemRef()) {
9972292SN/A
9982935Sksewell@umich.edu            DPRINTF(IQ, "IQ: Checking if memory instruction can issue.\n");
9991060SN/A
10001681SN/A            // Message to the mem dependence unit that this instruction has
10012292SN/A            // its registers ready.
10022292SN/A
10031681SN/A            memDepUnit.regsReady(inst);
10041061SN/A
10051061SN/A#if 0
10062292SN/A            if (memDepUnit.readyToIssue(inst)) {
10071060SN/A                DPRINTF(IQ, "IQ: Memory instruction is ready to issue, "
10081060SN/A                        "putting it onto the ready list, PC %#x.\n",
10091061SN/A                        inst->readPC());
10101061SN/A                readyMemInsts.push(inst);
10112292SN/A            } else {
10121061SN/A                // Make dependent on the store.
10132326SN/A                // Will need some way to get the store instruction it should
10142326SN/A                // be dependent upon; then when the store issues it can
10152326SN/A                // put the instruction on the ready list.
10161061SN/A                // Yet another tree?
10172292SN/A                assert(0 && "Instruction has no way to actually issue");
10182292SN/A            }
10191061SN/A#endif
10201061SN/A
10211061SN/A        } else if (inst->isInteger()) {
10222326SN/A
10232326SN/A            DPRINTF(IQ, "IQ: Integer instruction is ready to issue, "
10242292SN/A                    "putting it onto the ready list, PC %#x.\n",
10252326SN/A                    inst->readPC());
10261061SN/A            readyIntInsts.push(inst);
10271061SN/A
10281061SN/A        } else if (inst->isFloating()) {
10292292SN/A
10302292SN/A            DPRINTF(IQ, "IQ: Floating instruction is ready to issue, "
10312326SN/A                    "putting it onto the ready list, PC %#x.\n",
10322292SN/A                    inst->readPC());
10332292SN/A            readyFloatInsts.push(inst);
10342292SN/A
10352292SN/A        } else {
10362292SN/A            DPRINTF(IQ, "IQ: Miscellaneous instruction is ready to issue, "
10372292SN/A                    "putting it onto the ready list, PC %#x..\n",
10381062SN/A                    inst->readPC());
10391061SN/A
10402292SN/A            readyMiscInsts.push(inst);
10412336SN/A        }
10422292SN/A    }
10432292SN/A}
10441061SN/A
10451061SN/A/*
10461681SN/A * Caution, this function must not be called prior to tail being updated at
10471061SN/A * least once, otherwise it will fail the assertion.  This is because
10481061SN/A * instList.begin() actually changes upon the insertion of an element into the
10491061SN/A * list when the list is empty.
10501061SN/A */
10511061SN/Atemplate <class Impl>
10522326SN/Aint
10532326SN/AInstructionQueue<Impl>::countInsts()
10542326SN/A{
10552326SN/A    ListIt count_it = cpu->instList.begin();
10562326SN/A    int total_insts = 0;
10572326SN/A
10582326SN/A    if (tail == cpu->instList.end())
10592326SN/A        return 0;
10602292SN/A
10611061SN/A    while (count_it != tail) {
10621061SN/A        if (!(*count_it)->isIssued()) {
10632326SN/A            ++total_insts;
10641061SN/A        }
10651062SN/A
10662292SN/A        ++count_it;
10671062SN/A
10681061SN/A        assert(count_it != cpu->instList.end());
10692064SN/A    }
10702292SN/A
10712292SN/A    // Need to count the tail iterator as well.
10722292SN/A    if (count_it != cpu->instList.end() &&
10731062SN/A        (*count_it) &&
10742292SN/A        !(*count_it)->isIssued()) {
10751681SN/A        ++total_insts;
10762292SN/A    }
10771062SN/A
10781062SN/A    return total_insts;
10791061SN/A}
10801061SN/A
10811061SN/Atemplate <class Impl>
10821061SN/Avoid
10831061SN/AInstructionQueue<Impl>::dumpDependGraph()
10841061SN/A{
10851061SN/A    DependencyEntry *curr;
10862292SN/A
10872292SN/A    for (int i = 0; i < numPhysRegs; ++i)
10881681SN/A    {
10891681SN/A        curr = &dependGraph[i];
10902731Sktlim@umich.edu
10912292SN/A        if (curr->inst) {
10922292SN/A            cprintf("dependGraph[%i]: producer: %#x consumer: ", i,
10932292SN/A                    curr->inst->readPC());
10941681SN/A        } else {
10951681SN/A            cprintf("dependGraph[%i]: No producer. consumer: ", i);
10961061SN/A        }
10972326SN/A
10982326SN/A        while (curr->next != NULL) {
10992326SN/A            curr = curr->next;
11001061SN/A
11011061SN/A            cprintf("%#x ", curr->inst->readPC());
11022326SN/A        }
11031062SN/A
11041061SN/A        cprintf("\n");
11051060SN/A    }
11061060SN/A}
11071061SN/A
11081060SN/Atemplate <class Impl>
11091061SN/Avoid
11101060SN/AInstructionQueue<Impl>::dumpLists()
11111060SN/A{
11121060SN/A    cprintf("Ready integer list size: %i\n", readyIntInsts.size());
11131060SN/A
11141060SN/A    cprintf("Ready float list size: %i\n", readyFloatInsts.size());
11151060SN/A
11161060SN/A    cprintf("Ready branch list size: %i\n", readyBranchInsts.size());
11171060SN/A
11181060SN/A    cprintf("Ready misc list size: %i\n", readyMiscInsts.size());
11191060SN/A
11201060SN/A    cprintf("Squashed list size: %i\n", squashedInsts.size());
11211060SN/A
11221060SN/A    cprintf("Non speculative list size: %i\n", nonSpecInsts.size());
11231060SN/A
11241060SN/A    non_spec_it_t non_spec_it = nonSpecInsts.begin();
11251060SN/A
11261060SN/A    cprintf("Non speculative list: ");
11271060SN/A
11281061SN/A    while (non_spec_it != nonSpecInsts.end()) {
11291061SN/A        cprintf("%#x ", (*non_spec_it).second->readPC());
11301061SN/A        ++non_spec_it;
11312292SN/A    }
11321060SN/A
11331060SN/A    cprintf("\n");
11341060SN/A
11352326SN/A}
11361060SN/A