inst_queue_impl.hh revision 1717
111308Santhony.gutierrez@amd.com/*
211308Santhony.gutierrez@amd.com * Copyright (c) 2004-2005 The Regents of The University of Michigan
311308Santhony.gutierrez@amd.com * All rights reserved.
411308Santhony.gutierrez@amd.com *
511308Santhony.gutierrez@amd.com * Redistribution and use in source and binary forms, with or without
611308Santhony.gutierrez@amd.com * modification, are permitted provided that the following conditions are
711308Santhony.gutierrez@amd.com * met: redistributions of source code must retain the above copyright
811308Santhony.gutierrez@amd.com * notice, this list of conditions and the following disclaimer;
911308Santhony.gutierrez@amd.com * redistributions in binary form must reproduce the above copyright
1011308Santhony.gutierrez@amd.com * notice, this list of conditions and the following disclaimer in the
1111308Santhony.gutierrez@amd.com * documentation and/or other materials provided with the distribution;
1211308Santhony.gutierrez@amd.com * neither the name of the copyright holders nor the names of its
1311308Santhony.gutierrez@amd.com * contributors may be used to endorse or promote products derived from
1411308Santhony.gutierrez@amd.com * this software without specific prior written permission.
1511308Santhony.gutierrez@amd.com *
1611308Santhony.gutierrez@amd.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1711308Santhony.gutierrez@amd.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1811308Santhony.gutierrez@amd.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1911308Santhony.gutierrez@amd.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2011308Santhony.gutierrez@amd.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2111308Santhony.gutierrez@amd.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2211308Santhony.gutierrez@amd.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2311308Santhony.gutierrez@amd.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2411308Santhony.gutierrez@amd.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2511308Santhony.gutierrez@amd.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2611308Santhony.gutierrez@amd.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2711308Santhony.gutierrez@amd.com */
2811308Santhony.gutierrez@amd.com
2911308Santhony.gutierrez@amd.com// Todo:
3011308Santhony.gutierrez@amd.com// Current ordering allows for 0 cycle added-to-scheduled.  Could maybe fake
3111308Santhony.gutierrez@amd.com// it; either do in reverse order, or have added instructions put into a
3211308Santhony.gutierrez@amd.com// different ready queue that, in scheduleRreadyInsts(), gets put onto the
3311308Santhony.gutierrez@amd.com// normal ready queue.  This would however give only a one cycle delay,
3411308Santhony.gutierrez@amd.com// but probably is more flexible to actually add in a delay parameter than
3511308Santhony.gutierrez@amd.com// just running it backwards.
3611308Santhony.gutierrez@amd.com
3711308Santhony.gutierrez@amd.com#include <vector>
3811308Santhony.gutierrez@amd.com
3911308Santhony.gutierrez@amd.com#include "sim/root.hh"
4011308Santhony.gutierrez@amd.com
4111308Santhony.gutierrez@amd.com#include "cpu/o3/inst_queue.hh"
4211308Santhony.gutierrez@amd.com
4311670Sandreas.hansson@arm.com// Either compile error or max int due to sign extension.
4411670Sandreas.hansson@arm.com// Hack to avoid compile warnings.
4511308Santhony.gutierrez@amd.comconst InstSeqNum MaxInstSeqNum = 0 - 1;
4611308Santhony.gutierrez@amd.com
4711308Santhony.gutierrez@amd.comtemplate <class Impl>
4811308Santhony.gutierrez@amd.comInstructionQueue<Impl>::InstructionQueue(Params &params)
4911308Santhony.gutierrez@amd.com    : memDepUnit(params),
5011308Santhony.gutierrez@amd.com      numEntries(params.numIQEntries),
5111308Santhony.gutierrez@amd.com      intWidth(params.executeIntWidth),
5211308Santhony.gutierrez@amd.com      floatWidth(params.executeFloatWidth),
5311308Santhony.gutierrez@amd.com      branchWidth(params.executeBranchWidth),
5411308Santhony.gutierrez@amd.com      memoryWidth(params.executeMemoryWidth),
5511308Santhony.gutierrez@amd.com      totalWidth(params.issueWidth),
5611308Santhony.gutierrez@amd.com      numPhysIntRegs(params.numPhysIntRegs),
5711308Santhony.gutierrez@amd.com      numPhysFloatRegs(params.numPhysFloatRegs),
5811308Santhony.gutierrez@amd.com      commitToIEWDelay(params.commitToIEWDelay)
5911308Santhony.gutierrez@amd.com{
6011308Santhony.gutierrez@amd.com    // Initialize the number of free IQ entries.
6111308Santhony.gutierrez@amd.com    freeEntries = numEntries;
6211308Santhony.gutierrez@amd.com
6311308Santhony.gutierrez@amd.com    // Set the number of physical registers as the number of int + float
6411308Santhony.gutierrez@amd.com    numPhysRegs = numPhysIntRegs + numPhysFloatRegs;
6511308Santhony.gutierrez@amd.com
6611308Santhony.gutierrez@amd.com    DPRINTF(IQ, "IQ: There are %i physical registers.\n", numPhysRegs);
6711308Santhony.gutierrez@amd.com
6811308Santhony.gutierrez@amd.com    //Create an entry for each physical register within the
6911308Santhony.gutierrez@amd.com    //dependency graph.
7011308Santhony.gutierrez@amd.com    dependGraph = new DependencyEntry[numPhysRegs];
7111308Santhony.gutierrez@amd.com
7211308Santhony.gutierrez@amd.com    // Resize the register scoreboard.
7311308Santhony.gutierrez@amd.com    regScoreboard.resize(numPhysRegs);
7411308Santhony.gutierrez@amd.com
7511308Santhony.gutierrez@amd.com    // Initialize all the head pointers to point to NULL, and all the
7611308Santhony.gutierrez@amd.com    // entries as unready.
7711308Santhony.gutierrez@amd.com    // Note that in actuality, the registers corresponding to the logical
7811308Santhony.gutierrez@amd.com    // registers start off as ready.  However this doesn't matter for the
7911308Santhony.gutierrez@amd.com    // IQ as the instruction should have been correctly told if those
8011308Santhony.gutierrez@amd.com    // registers are ready in rename.  Thus it can all be initialized as
8111308Santhony.gutierrez@amd.com    // unready.
8211308Santhony.gutierrez@amd.com    for (int i = 0; i < numPhysRegs; ++i)
8311308Santhony.gutierrez@amd.com    {
8411308Santhony.gutierrez@amd.com        dependGraph[i].next = NULL;
8511308Santhony.gutierrez@amd.com        dependGraph[i].inst = NULL;
8611308Santhony.gutierrez@amd.com        regScoreboard[i] = false;
8711308Santhony.gutierrez@amd.com    }
8811308Santhony.gutierrez@amd.com
8911308Santhony.gutierrez@amd.com}
9011308Santhony.gutierrez@amd.com
9111308Santhony.gutierrez@amd.comtemplate <class Impl>
9211308Santhony.gutierrez@amd.comvoid
9311308Santhony.gutierrez@amd.comInstructionQueue<Impl>::regStats()
9411308Santhony.gutierrez@amd.com{
9511308Santhony.gutierrez@amd.com    iqInstsAdded
9611308Santhony.gutierrez@amd.com        .name(name() + ".iqInstsAdded")
9711308Santhony.gutierrez@amd.com        .desc("Number of instructions added to the IQ (excludes non-spec)")
9811308Santhony.gutierrez@amd.com        .prereq(iqInstsAdded);
9911308Santhony.gutierrez@amd.com
10011308Santhony.gutierrez@amd.com    iqNonSpecInstsAdded
10111308Santhony.gutierrez@amd.com        .name(name() + ".iqNonSpecInstsAdded")
10211308Santhony.gutierrez@amd.com        .desc("Number of non-speculative instructions added to the IQ")
10311308Santhony.gutierrez@amd.com        .prereq(iqNonSpecInstsAdded);
10411308Santhony.gutierrez@amd.com
10511308Santhony.gutierrez@amd.com//    iqIntInstsAdded;
10611308Santhony.gutierrez@amd.com
10711308Santhony.gutierrez@amd.com    iqIntInstsIssued
10811308Santhony.gutierrez@amd.com        .name(name() + ".iqIntInstsIssued")
10911308Santhony.gutierrez@amd.com        .desc("Number of integer instructions issued")
11011308Santhony.gutierrez@amd.com        .prereq(iqIntInstsIssued);
11111308Santhony.gutierrez@amd.com
11211308Santhony.gutierrez@amd.com//    iqFloatInstsAdded;
11311308Santhony.gutierrez@amd.com
11411308Santhony.gutierrez@amd.com    iqFloatInstsIssued
11511308Santhony.gutierrez@amd.com        .name(name() + ".iqFloatInstsIssued")
11611308Santhony.gutierrez@amd.com        .desc("Number of float instructions issued")
11711308Santhony.gutierrez@amd.com        .prereq(iqFloatInstsIssued);
11811308Santhony.gutierrez@amd.com
11911308Santhony.gutierrez@amd.com//    iqBranchInstsAdded;
12011308Santhony.gutierrez@amd.com
12111308Santhony.gutierrez@amd.com    iqBranchInstsIssued
12211308Santhony.gutierrez@amd.com        .name(name() + ".iqBranchInstsIssued")
12311308Santhony.gutierrez@amd.com        .desc("Number of branch instructions issued")
12411308Santhony.gutierrez@amd.com        .prereq(iqBranchInstsIssued);
12511308Santhony.gutierrez@amd.com
12611308Santhony.gutierrez@amd.com//    iqMemInstsAdded;
12711308Santhony.gutierrez@amd.com
12811308Santhony.gutierrez@amd.com    iqMemInstsIssued
12911308Santhony.gutierrez@amd.com        .name(name() + ".iqMemInstsIssued")
13011308Santhony.gutierrez@amd.com        .desc("Number of memory instructions issued")
13111308Santhony.gutierrez@amd.com        .prereq(iqMemInstsIssued);
13211308Santhony.gutierrez@amd.com
13311308Santhony.gutierrez@amd.com//    iqMiscInstsAdded;
13411308Santhony.gutierrez@amd.com
13511308Santhony.gutierrez@amd.com    iqMiscInstsIssued
13611308Santhony.gutierrez@amd.com        .name(name() + ".iqMiscInstsIssued")
13711308Santhony.gutierrez@amd.com        .desc("Number of miscellaneous instructions issued")
13811308Santhony.gutierrez@amd.com        .prereq(iqMiscInstsIssued);
13911308Santhony.gutierrez@amd.com
14011308Santhony.gutierrez@amd.com    iqSquashedInstsIssued
14111308Santhony.gutierrez@amd.com        .name(name() + ".iqSquashedInstsIssued")
14211308Santhony.gutierrez@amd.com        .desc("Number of squashed instructions issued")
14311308Santhony.gutierrez@amd.com        .prereq(iqSquashedInstsIssued);
14411308Santhony.gutierrez@amd.com
14511308Santhony.gutierrez@amd.com    iqLoopSquashStalls
14611308Santhony.gutierrez@amd.com        .name(name() + ".iqLoopSquashStalls")
14711308Santhony.gutierrez@amd.com        .desc("Number of times issue loop had to restart due to squashed "
14811308Santhony.gutierrez@amd.com              "inst; mainly for profiling")
14911308Santhony.gutierrez@amd.com        .prereq(iqLoopSquashStalls);
15011308Santhony.gutierrez@amd.com
15111308Santhony.gutierrez@amd.com    iqSquashedInstsExamined
15211308Santhony.gutierrez@amd.com        .name(name() + ".iqSquashedInstsExamined")
15311308Santhony.gutierrez@amd.com        .desc("Number of squashed instructions iterated over during squash;"
15411308Santhony.gutierrez@amd.com              " mainly for profiling")
15511308Santhony.gutierrez@amd.com        .prereq(iqSquashedInstsExamined);
15611308Santhony.gutierrez@amd.com
15711308Santhony.gutierrez@amd.com    iqSquashedOperandsExamined
15811308Santhony.gutierrez@amd.com        .name(name() + ".iqSquashedOperandsExamined")
15911308Santhony.gutierrez@amd.com        .desc("Number of squashed operands that are examined and possibly "
16011308Santhony.gutierrez@amd.com              "removed from graph")
16111308Santhony.gutierrez@amd.com        .prereq(iqSquashedOperandsExamined);
16211308Santhony.gutierrez@amd.com
16311308Santhony.gutierrez@amd.com    iqSquashedNonSpecRemoved
16411308Santhony.gutierrez@amd.com        .name(name() + ".iqSquashedNonSpecRemoved")
16511308Santhony.gutierrez@amd.com        .desc("Number of squashed non-spec instructions that were removed")
16611308Santhony.gutierrez@amd.com        .prereq(iqSquashedNonSpecRemoved);
16711308Santhony.gutierrez@amd.com
16811308Santhony.gutierrez@amd.com    // Tell mem dependence unit to reg stats as well.
16911308Santhony.gutierrez@amd.com    memDepUnit.regStats();
17012065Snikos.nikoleris@arm.com}
17111308Santhony.gutierrez@amd.com
17211308Santhony.gutierrez@amd.comtemplate <class Impl>
17311308Santhony.gutierrez@amd.comvoid
17411308Santhony.gutierrez@amd.comInstructionQueue<Impl>::setCPU(FullCPU *cpu_ptr)
17512065Snikos.nikoleris@arm.com{
17612065Snikos.nikoleris@arm.com    cpu = cpu_ptr;
17711308Santhony.gutierrez@amd.com
17811308Santhony.gutierrez@amd.com    tail = cpu->instList.begin();
17911308Santhony.gutierrez@amd.com}
18011308Santhony.gutierrez@amd.com
18111308Santhony.gutierrez@amd.comtemplate <class Impl>
18211308Santhony.gutierrez@amd.comvoid
18311308Santhony.gutierrez@amd.comInstructionQueue<Impl>::setIssueToExecuteQueue(
18411308Santhony.gutierrez@amd.com                        TimeBuffer<IssueStruct> *i2e_ptr)
18511308Santhony.gutierrez@amd.com{
18611308Santhony.gutierrez@amd.com    DPRINTF(IQ, "IQ: Set the issue to execute queue.\n");
18711308Santhony.gutierrez@amd.com    issueToExecuteQueue = i2e_ptr;
18811308Santhony.gutierrez@amd.com}
18911308Santhony.gutierrez@amd.com
19011308Santhony.gutierrez@amd.comtemplate <class Impl>
19111308Santhony.gutierrez@amd.comvoid
19211308Santhony.gutierrez@amd.comInstructionQueue<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
19311308Santhony.gutierrez@amd.com{
19411308Santhony.gutierrez@amd.com    DPRINTF(IQ, "IQ: Set the time buffer.\n");
19511308Santhony.gutierrez@amd.com    timeBuffer = tb_ptr;
19611308Santhony.gutierrez@amd.com
19711308Santhony.gutierrez@amd.com    fromCommit = timeBuffer->getWire(-commitToIEWDelay);
19811308Santhony.gutierrez@amd.com}
19911308Santhony.gutierrez@amd.com
20011308Santhony.gutierrez@amd.comtemplate <class Impl>
20111308Santhony.gutierrez@amd.comunsigned
20211308Santhony.gutierrez@amd.comInstructionQueue<Impl>::numFreeEntries()
20311308Santhony.gutierrez@amd.com{
20411308Santhony.gutierrez@amd.com    return freeEntries;
20511308Santhony.gutierrez@amd.com}
20611308Santhony.gutierrez@amd.com
20711308Santhony.gutierrez@amd.com// Might want to do something more complex if it knows how many instructions
20811308Santhony.gutierrez@amd.com// will be issued this cycle.
20911308Santhony.gutierrez@amd.comtemplate <class Impl>
21011308Santhony.gutierrez@amd.combool
21111308Santhony.gutierrez@amd.comInstructionQueue<Impl>::isFull()
21211308Santhony.gutierrez@amd.com{
21311308Santhony.gutierrez@amd.com    if (freeEntries == 0) {
21411308Santhony.gutierrez@amd.com        return(true);
21511308Santhony.gutierrez@amd.com    } else {
21611308Santhony.gutierrez@amd.com        return(false);
21711308Santhony.gutierrez@amd.com    }
21811308Santhony.gutierrez@amd.com}
21911308Santhony.gutierrez@amd.com
22011308Santhony.gutierrez@amd.comtemplate <class Impl>
22111308Santhony.gutierrez@amd.comvoid
22211308Santhony.gutierrez@amd.comInstructionQueue<Impl>::insert(DynInstPtr &new_inst)
22311308Santhony.gutierrez@amd.com{
22411308Santhony.gutierrez@amd.com    // Make sure the instruction is valid
22511308Santhony.gutierrez@amd.com    assert(new_inst);
22611308Santhony.gutierrez@amd.com
22711308Santhony.gutierrez@amd.com    DPRINTF(IQ, "IQ: Adding instruction PC %#x to the IQ.\n",
22811308Santhony.gutierrez@amd.com            new_inst->readPC());
22911308Santhony.gutierrez@amd.com
23011308Santhony.gutierrez@amd.com    // Check if there are any free entries.  Panic if there are none.
23111308Santhony.gutierrez@amd.com    // Might want to have this return a fault in the future instead of
23211308Santhony.gutierrez@amd.com    // panicing.
23311308Santhony.gutierrez@amd.com    assert(freeEntries != 0);
23411308Santhony.gutierrez@amd.com
23511308Santhony.gutierrez@amd.com    // If the IQ currently has nothing in it, then there's a possibility
23611308Santhony.gutierrez@amd.com    // that the tail iterator is invalid (might have been pointing at an
23711308Santhony.gutierrez@amd.com    // instruction that was retired).  Reset the tail iterator.
23812065Snikos.nikoleris@arm.com    if (freeEntries == numEntries) {
23912065Snikos.nikoleris@arm.com        tail = cpu->instList.begin();
24012065Snikos.nikoleris@arm.com    }
24112065Snikos.nikoleris@arm.com
24212065Snikos.nikoleris@arm.com    // Move the tail iterator.  Instructions may not have been issued
24312065Snikos.nikoleris@arm.com    // to the IQ, so we may have to increment the iterator more than once.
24412065Snikos.nikoleris@arm.com    while ((*tail) != new_inst) {
24512065Snikos.nikoleris@arm.com        tail++;
24612065Snikos.nikoleris@arm.com
24712065Snikos.nikoleris@arm.com        // Make sure the tail iterator points at something legal.
24812065Snikos.nikoleris@arm.com        assert(tail != cpu->instList.end());
24911308Santhony.gutierrez@amd.com    }
25012065Snikos.nikoleris@arm.com
25112065Snikos.nikoleris@arm.com
25212065Snikos.nikoleris@arm.com    // Decrease the number of free entries.
25312065Snikos.nikoleris@arm.com    --freeEntries;
25412065Snikos.nikoleris@arm.com
25512065Snikos.nikoleris@arm.com    // Look through its source registers (physical regs), and mark any
25612065Snikos.nikoleris@arm.com    // dependencies.
25712065Snikos.nikoleris@arm.com    addToDependents(new_inst);
25811308Santhony.gutierrez@amd.com
25911308Santhony.gutierrez@amd.com    // Have this instruction set itself as the producer of its destination
26012065Snikos.nikoleris@arm.com    // register(s).
26111308Santhony.gutierrez@amd.com    createDependency(new_inst);
26211308Santhony.gutierrez@amd.com
26311308Santhony.gutierrez@amd.com    // If it's a memory instruction, add it to the memory dependency
26411308Santhony.gutierrez@amd.com    // unit.
26511308Santhony.gutierrez@amd.com    if (new_inst->isMemRef()) {
26611308Santhony.gutierrez@amd.com        memDepUnit.insert(new_inst);
26711308Santhony.gutierrez@amd.com        // Uh..forgot to look it up and put it on the proper dependency list
26811308Santhony.gutierrez@amd.com        // if the instruction should not go yet.
26911308Santhony.gutierrez@amd.com    } else {
27011308Santhony.gutierrez@amd.com        // If the instruction is ready then add it to the ready list.
27111308Santhony.gutierrez@amd.com        addIfReady(new_inst);
27211308Santhony.gutierrez@amd.com    }
27311308Santhony.gutierrez@amd.com
27411308Santhony.gutierrez@amd.com    ++iqInstsAdded;
27511308Santhony.gutierrez@amd.com
27611308Santhony.gutierrez@amd.com    assert(freeEntries == (numEntries - countInsts()));
27711308Santhony.gutierrez@amd.com}
27811308Santhony.gutierrez@amd.com
27911308Santhony.gutierrez@amd.comtemplate <class Impl>
28011308Santhony.gutierrez@amd.comvoid
28111308Santhony.gutierrez@amd.comInstructionQueue<Impl>::insertNonSpec(DynInstPtr &inst)
28211308Santhony.gutierrez@amd.com{
28311308Santhony.gutierrez@amd.com    nonSpecInsts[inst->seqNum] = inst;
28411308Santhony.gutierrez@amd.com
28511308Santhony.gutierrez@amd.com    // @todo: Clean up this code; can do it by setting inst as unable
28611308Santhony.gutierrez@amd.com    // to issue, then calling normal insert on the inst.
28711308Santhony.gutierrez@amd.com
28811308Santhony.gutierrez@amd.com    // Make sure the instruction is valid
28911308Santhony.gutierrez@amd.com    assert(inst);
29011308Santhony.gutierrez@amd.com
29111308Santhony.gutierrez@amd.com    DPRINTF(IQ, "IQ: Adding instruction PC %#x to the IQ.\n",
29211308Santhony.gutierrez@amd.com            inst->readPC());
29311308Santhony.gutierrez@amd.com
29411308Santhony.gutierrez@amd.com    // Check if there are any free entries.  Panic if there are none.
29511308Santhony.gutierrez@amd.com    // Might want to have this return a fault in the future instead of
29611308Santhony.gutierrez@amd.com    // panicing.
29711308Santhony.gutierrez@amd.com    assert(freeEntries != 0);
29811308Santhony.gutierrez@amd.com
29911308Santhony.gutierrez@amd.com    // If the IQ currently has nothing in it, then there's a possibility
30011308Santhony.gutierrez@amd.com    // that the tail iterator is invalid (might have been pointing at an
30111308Santhony.gutierrez@amd.com    // instruction that was retired).  Reset the tail iterator.
30211308Santhony.gutierrez@amd.com    if (freeEntries == numEntries) {
30311308Santhony.gutierrez@amd.com        tail = cpu->instList.begin();
30411308Santhony.gutierrez@amd.com    }
30511308Santhony.gutierrez@amd.com
30611308Santhony.gutierrez@amd.com    // Move the tail iterator.  Instructions may not have been issued
30711308Santhony.gutierrez@amd.com    // to the IQ, so we may have to increment the iterator more than once.
30811308Santhony.gutierrez@amd.com    while ((*tail) != inst) {
30911308Santhony.gutierrez@amd.com        tail++;
31011308Santhony.gutierrez@amd.com
31111308Santhony.gutierrez@amd.com        // Make sure the tail iterator points at something legal.
31211308Santhony.gutierrez@amd.com        assert(tail != cpu->instList.end());
31311308Santhony.gutierrez@amd.com    }
31411308Santhony.gutierrez@amd.com
31511308Santhony.gutierrez@amd.com    // Decrease the number of free entries.
31611308Santhony.gutierrez@amd.com    --freeEntries;
31711308Santhony.gutierrez@amd.com
31811308Santhony.gutierrez@amd.com    // Have this instruction set itself as the producer of its destination
31911308Santhony.gutierrez@amd.com    // register(s).
32011308Santhony.gutierrez@amd.com    createDependency(inst);
32111308Santhony.gutierrez@amd.com
32211308Santhony.gutierrez@amd.com    // If it's a memory instruction, add it to the memory dependency
32311308Santhony.gutierrez@amd.com    // unit.
32411308Santhony.gutierrez@amd.com    if (inst->isMemRef()) {
32511308Santhony.gutierrez@amd.com        memDepUnit.insertNonSpec(inst);
32611308Santhony.gutierrez@amd.com    }
32711308Santhony.gutierrez@amd.com
32811308Santhony.gutierrez@amd.com    ++iqNonSpecInstsAdded;
32911308Santhony.gutierrez@amd.com}
33011308Santhony.gutierrez@amd.com
33111308Santhony.gutierrez@amd.com// Slightly hack function to advance the tail iterator in the case that
33211308Santhony.gutierrez@amd.com// the IEW stage issues an instruction that is not added to the IQ.  This
33311308Santhony.gutierrez@amd.com// is needed in case a long chain of such instructions occurs.
33411308Santhony.gutierrez@amd.com// I don't think this is used anymore.
33511308Santhony.gutierrez@amd.comtemplate <class Impl>
336void
337InstructionQueue<Impl>::advanceTail(DynInstPtr &inst)
338{
339    // Make sure the instruction is valid
340    assert(inst);
341
342    DPRINTF(IQ, "IQ: Adding instruction PC %#x to the IQ.\n",
343            inst->readPC());
344
345    // Check if there are any free entries.  Panic if there are none.
346    // Might want to have this return a fault in the future instead of
347    // panicing.
348    assert(freeEntries != 0);
349
350    // If the IQ currently has nothing in it, then there's a possibility
351    // that the tail iterator is invalid (might have been pointing at an
352    // instruction that was retired).  Reset the tail iterator.
353    if (freeEntries == numEntries) {
354        tail = cpu->instList.begin();
355    }
356
357    // Move the tail iterator.  Instructions may not have been issued
358    // to the IQ, so we may have to increment the iterator more than once.
359    while ((*tail) != inst) {
360        tail++;
361
362        // Make sure the tail iterator points at something legal.
363        assert(tail != cpu->instList.end());
364    }
365
366    assert(freeEntries <= numEntries);
367
368    // Have this instruction set itself as the producer of its destination
369    // register(s).
370    createDependency(inst);
371}
372
373// Need to make sure the number of float and integer instructions
374// issued does not exceed the total issue bandwidth.
375// @todo: Figure out a better way to remove the squashed items from the
376// lists.  Checking the top item of each list to see if it's squashed
377// wastes time and forces jumps.
378template <class Impl>
379void
380InstructionQueue<Impl>::scheduleReadyInsts()
381{
382    DPRINTF(IQ, "IQ: Attempting to schedule ready instructions from "
383                "the IQ.\n");
384
385    int int_issued = 0;
386    int float_issued = 0;
387    int branch_issued = 0;
388    int memory_issued = 0;
389    int squashed_issued = 0;
390    int total_issued = 0;
391
392    IssueStruct *i2e_info = issueToExecuteQueue->access(0);
393
394    bool insts_available = !readyBranchInsts.empty() ||
395        !readyIntInsts.empty() ||
396        !readyFloatInsts.empty() ||
397        !memDepUnit.empty() ||
398        !readyMiscInsts.empty() ||
399        !squashedInsts.empty();
400
401    // Note: Requires a globally defined constant.
402    InstSeqNum oldest_inst = MaxInstSeqNum;
403    InstList list_with_oldest = None;
404
405    // Temporary values.
406    DynInstPtr int_head_inst;
407    DynInstPtr float_head_inst;
408    DynInstPtr branch_head_inst;
409    DynInstPtr mem_head_inst;
410    DynInstPtr misc_head_inst;
411    DynInstPtr squashed_head_inst;
412
413    // Somewhat nasty code to look at all of the lists where issuable
414    // instructions are located, and choose the oldest instruction among
415    // those lists.  Consider a rewrite in the future.
416    while (insts_available && total_issued < totalWidth)
417    {
418        // Set this to false.  Each if-block is required to set it to true
419        // if there were instructions available this check.  This will cause
420        // this loop to run once more than necessary, but avoids extra calls.
421        insts_available = false;
422
423        oldest_inst = MaxInstSeqNum;
424
425        list_with_oldest = None;
426
427        if (!readyIntInsts.empty() &&
428            int_issued < intWidth) {
429
430            insts_available = true;
431
432            int_head_inst = readyIntInsts.top();
433
434            if (int_head_inst->isSquashed()) {
435                readyIntInsts.pop();
436
437                ++iqLoopSquashStalls;
438
439                continue;
440            }
441
442            oldest_inst = int_head_inst->seqNum;
443
444            list_with_oldest = Int;
445        }
446
447        if (!readyFloatInsts.empty() &&
448            float_issued < floatWidth) {
449
450            insts_available = true;
451
452            float_head_inst = readyFloatInsts.top();
453
454            if (float_head_inst->isSquashed()) {
455                readyFloatInsts.pop();
456
457                ++iqLoopSquashStalls;
458
459                continue;
460            } else if (float_head_inst->seqNum < oldest_inst) {
461                oldest_inst = float_head_inst->seqNum;
462
463                list_with_oldest = Float;
464            }
465        }
466
467        if (!readyBranchInsts.empty() &&
468            branch_issued < branchWidth) {
469
470            insts_available = true;
471
472            branch_head_inst = readyBranchInsts.top();
473
474            if (branch_head_inst->isSquashed()) {
475                readyBranchInsts.pop();
476
477                ++iqLoopSquashStalls;
478
479                continue;
480            } else if (branch_head_inst->seqNum < oldest_inst) {
481                oldest_inst = branch_head_inst->seqNum;
482
483                list_with_oldest = Branch;
484            }
485
486        }
487
488        if (!memDepUnit.empty() &&
489            memory_issued < memoryWidth) {
490
491            insts_available = true;
492
493            mem_head_inst = memDepUnit.top();
494
495            if (mem_head_inst->isSquashed()) {
496                memDepUnit.pop();
497
498                ++iqLoopSquashStalls;
499
500                continue;
501            } else if (mem_head_inst->seqNum < oldest_inst) {
502                oldest_inst = mem_head_inst->seqNum;
503
504                list_with_oldest = Memory;
505            }
506        }
507
508        if (!readyMiscInsts.empty()) {
509
510            insts_available = true;
511
512            misc_head_inst = readyMiscInsts.top();
513
514            if (misc_head_inst->isSquashed()) {
515                readyMiscInsts.pop();
516
517                ++iqLoopSquashStalls;
518
519                continue;
520            } else if (misc_head_inst->seqNum < oldest_inst) {
521                oldest_inst = misc_head_inst->seqNum;
522
523                list_with_oldest = Misc;
524            }
525        }
526
527        if (!squashedInsts.empty()) {
528
529            insts_available = true;
530
531            squashed_head_inst = squashedInsts.top();
532
533            if (squashed_head_inst->seqNum < oldest_inst) {
534                list_with_oldest = Squashed;
535            }
536
537        }
538
539        DynInstPtr issuing_inst = NULL;
540
541        switch (list_with_oldest) {
542          case None:
543            DPRINTF(IQ, "IQ: Not able to schedule any instructions. Issuing "
544                    "inst is %#x.\n", issuing_inst);
545            break;
546
547          case Int:
548            issuing_inst = int_head_inst;
549            readyIntInsts.pop();
550            ++int_issued;
551            DPRINTF(IQ, "IQ: Issuing integer instruction PC %#x.\n",
552                    issuing_inst->readPC());
553            break;
554
555          case Float:
556            issuing_inst = float_head_inst;
557            readyFloatInsts.pop();
558            ++float_issued;
559            DPRINTF(IQ, "IQ: Issuing float instruction PC %#x.\n",
560                    issuing_inst->readPC());
561            break;
562
563          case Branch:
564            issuing_inst = branch_head_inst;
565            readyBranchInsts.pop();
566            ++branch_issued;
567            DPRINTF(IQ, "IQ: Issuing branch instruction PC %#x.\n",
568                    issuing_inst->readPC());
569            break;
570
571          case Memory:
572            issuing_inst = mem_head_inst;
573
574            memDepUnit.pop();
575            ++memory_issued;
576            DPRINTF(IQ, "IQ: Issuing memory instruction PC %#x.\n",
577                    issuing_inst->readPC());
578            break;
579
580          case Misc:
581            issuing_inst = misc_head_inst;
582            readyMiscInsts.pop();
583
584            ++iqMiscInstsIssued;
585
586            DPRINTF(IQ, "IQ: Issuing a miscellaneous instruction PC %#x.\n",
587                    issuing_inst->readPC());
588            break;
589
590          case Squashed:
591            assert(0 && "Squashed insts should not issue any more!");
592            squashedInsts.pop();
593            // Set the squashed instruction as able to commit so that commit
594            // can just drop it from the ROB.  This is a bit faked.
595            ++squashed_issued;
596            ++freeEntries;
597
598            DPRINTF(IQ, "IQ: Issuing squashed instruction PC %#x.\n",
599                    squashed_head_inst->readPC());
600            break;
601        }
602
603        if (list_with_oldest != None && list_with_oldest != Squashed) {
604            i2e_info->insts[total_issued] = issuing_inst;
605            i2e_info->size++;
606
607            issuing_inst->setIssued();
608
609            ++freeEntries;
610            ++total_issued;
611        }
612
613        assert(freeEntries == (numEntries - countInsts()));
614    }
615
616    iqIntInstsIssued += int_issued;
617    iqFloatInstsIssued += float_issued;
618    iqBranchInstsIssued += branch_issued;
619    iqMemInstsIssued += memory_issued;
620    iqSquashedInstsIssued += squashed_issued;
621}
622
623template <class Impl>
624void
625InstructionQueue<Impl>::scheduleNonSpec(const InstSeqNum &inst)
626{
627    DPRINTF(IQ, "IQ: Marking nonspeculative instruction with sequence "
628            "number %i as ready to execute.\n", inst);
629
630    non_spec_it_t inst_it = nonSpecInsts.find(inst);
631
632    assert(inst_it != nonSpecInsts.end());
633
634    // Mark this instruction as ready to issue.
635    (*inst_it).second->setCanIssue();
636
637    // Now schedule the instruction.
638    if (!(*inst_it).second->isMemRef()) {
639        addIfReady((*inst_it).second);
640    } else {
641        memDepUnit.nonSpecInstReady((*inst_it).second);
642    }
643
644    nonSpecInsts.erase(inst_it);
645}
646
647template <class Impl>
648void
649InstructionQueue<Impl>::wakeDependents(DynInstPtr &completed_inst)
650{
651    DPRINTF(IQ, "IQ: Waking dependents of completed instruction.\n");
652    //Look at the physical destination register of the DynInst
653    //and look it up on the dependency graph.  Then mark as ready
654    //any instructions within the instruction queue.
655    DependencyEntry *curr;
656
657    // Tell the memory dependence unit to wake any dependents on this
658    // instruction if it is a memory instruction.
659
660    if (completed_inst->isMemRef()) {
661        memDepUnit.wakeDependents(completed_inst);
662    }
663
664    for (int dest_reg_idx = 0;
665         dest_reg_idx < completed_inst->numDestRegs();
666         dest_reg_idx++)
667    {
668        PhysRegIndex dest_reg =
669            completed_inst->renamedDestRegIdx(dest_reg_idx);
670
671        // Special case of uniq or control registers.  They are not
672        // handled by the IQ and thus have no dependency graph entry.
673        // @todo Figure out a cleaner way to handle this.
674        if (dest_reg >= numPhysRegs) {
675            continue;
676        }
677
678        DPRINTF(IQ, "IQ: Waking any dependents on register %i.\n",
679                (int) dest_reg);
680
681        //Maybe abstract this part into a function.
682        //Go through the dependency chain, marking the registers as ready
683        //within the waiting instructions.
684        while (dependGraph[dest_reg].next) {
685
686            curr = dependGraph[dest_reg].next;
687
688            DPRINTF(IQ, "IQ: Waking up a dependent instruction, PC%#x.\n",
689                    curr->inst->readPC());
690
691            // Might want to give more information to the instruction
692            // so that it knows which of its source registers is ready.
693            // However that would mean that the dependency graph entries
694            // would need to hold the src_reg_idx.
695            curr->inst->markSrcRegReady();
696
697            addIfReady(curr->inst);
698
699            dependGraph[dest_reg].next = curr->next;
700
701            DependencyEntry::mem_alloc_counter--;
702
703            curr->inst = NULL;
704
705            delete curr;
706        }
707
708        // Reset the head node now that all of its dependents have been woken
709        // up.
710        dependGraph[dest_reg].next = NULL;
711        dependGraph[dest_reg].inst = NULL;
712
713        // Mark the scoreboard as having that register ready.
714        regScoreboard[dest_reg] = true;
715    }
716}
717
718template <class Impl>
719void
720InstructionQueue<Impl>::violation(DynInstPtr &store,
721                                  DynInstPtr &faulting_load)
722{
723    memDepUnit.violation(store, faulting_load);
724}
725
726template <class Impl>
727void
728InstructionQueue<Impl>::squash()
729{
730    DPRINTF(IQ, "IQ: Starting to squash instructions in the IQ.\n");
731
732    // Read instruction sequence number of last instruction out of the
733    // time buffer.
734    squashedSeqNum = fromCommit->commitInfo.doneSeqNum;
735
736    // Setup the squash iterator to point to the tail.
737    squashIt = tail;
738
739    // Call doSquash if there are insts in the IQ
740    if (freeEntries != numEntries) {
741        doSquash();
742    }
743
744    // Also tell the memory dependence unit to squash.
745    memDepUnit.squash(squashedSeqNum);
746}
747
748template <class Impl>
749void
750InstructionQueue<Impl>::doSquash()
751{
752    // Make sure the squash iterator isn't pointing to nothing.
753    assert(squashIt != cpu->instList.end());
754    // Make sure the squashed sequence number is valid.
755    assert(squashedSeqNum != 0);
756
757    DPRINTF(IQ, "IQ: Squashing instructions in the IQ.\n");
758
759    // Squash any instructions younger than the squashed sequence number
760    // given.
761    while ((*squashIt)->seqNum > squashedSeqNum) {
762        DynInstPtr squashed_inst = (*squashIt);
763
764        // Only handle the instruction if it actually is in the IQ and
765        // hasn't already been squashed in the IQ.
766        if (!squashed_inst->isIssued() &&
767            !squashed_inst->isSquashedInIQ()) {
768
769            // Remove the instruction from the dependency list.
770            // Hack for now: These below don't add themselves to the
771            // dependency list, so don't try to remove them.
772            if (!squashed_inst->isNonSpeculative()/* &&
773                                                     !squashed_inst->isStore()*/
774                ) {
775
776                for (int src_reg_idx = 0;
777                     src_reg_idx < squashed_inst->numSrcRegs();
778                     src_reg_idx++)
779                {
780                    PhysRegIndex src_reg =
781                        squashed_inst->renamedSrcRegIdx(src_reg_idx);
782
783                    // Only remove it from the dependency graph if it was
784                    // placed there in the first place.
785                    // HACK: This assumes that instructions woken up from the
786                    // dependency chain aren't informed that a specific src
787                    // register has become ready.  This may not always be true
788                    // in the future.
789                    if (!squashed_inst->isReadySrcRegIdx(src_reg_idx) &&
790                        src_reg < numPhysRegs) {
791                        dependGraph[src_reg].remove(squashed_inst);
792                    }
793
794                    ++iqSquashedOperandsExamined;
795                }
796
797                // Might want to remove producers as well.
798            } else {
799                nonSpecInsts[squashed_inst->seqNum] = NULL;
800
801                nonSpecInsts.erase(squashed_inst->seqNum);
802
803                ++iqSquashedNonSpecRemoved;
804            }
805
806            // Might want to also clear out the head of the dependency graph.
807
808            // Mark it as squashed within the IQ.
809            squashed_inst->setSquashedInIQ();
810
811//            squashedInsts.push(squashed_inst);
812            squashed_inst->setIssued();
813            squashed_inst->setCanCommit();
814
815            ++freeEntries;
816
817            DPRINTF(IQ, "IQ: Instruction PC %#x squashed.\n",
818                    squashed_inst->readPC());
819        }
820
821        --squashIt;
822        ++iqSquashedInstsExamined;
823    }
824
825    assert(freeEntries <= numEntries);
826
827    if (freeEntries == numEntries) {
828        tail = cpu->instList.end();
829    }
830
831}
832
833template <class Impl>
834void
835InstructionQueue<Impl>::stopSquash()
836{
837    // Clear up the squash variables to ensure that squashing doesn't
838    // get called improperly.
839    squashedSeqNum = 0;
840
841    squashIt = cpu->instList.end();
842}
843
844template <class Impl>
845void
846InstructionQueue<Impl>::DependencyEntry::insert(DynInstPtr &new_inst)
847{
848    //Add this new, dependent instruction at the head of the dependency
849    //chain.
850
851    // First create the entry that will be added to the head of the
852    // dependency chain.
853    DependencyEntry *new_entry = new DependencyEntry;
854    new_entry->next = this->next;
855    new_entry->inst = new_inst;
856
857    // Then actually add it to the chain.
858    this->next = new_entry;
859
860    ++mem_alloc_counter;
861}
862
863template <class Impl>
864void
865InstructionQueue<Impl>::DependencyEntry::remove(DynInstPtr &inst_to_remove)
866{
867    DependencyEntry *prev = this;
868    DependencyEntry *curr = this->next;
869
870    // Make sure curr isn't NULL.  Because this instruction is being
871    // removed from a dependency list, it must have been placed there at
872    // an earlier time.  The dependency chain should not be empty,
873    // unless the instruction dependent upon it is already ready.
874    if (curr == NULL) {
875        return;
876    }
877
878    // Find the instruction to remove within the dependency linked list.
879    while(curr->inst != inst_to_remove)
880    {
881        prev = curr;
882        curr = curr->next;
883
884        assert(curr != NULL);
885    }
886
887    // Now remove this instruction from the list.
888    prev->next = curr->next;
889
890    --mem_alloc_counter;
891
892    // Could push this off to the destructor of DependencyEntry
893    curr->inst = NULL;
894
895    delete curr;
896}
897
898template <class Impl>
899bool
900InstructionQueue<Impl>::addToDependents(DynInstPtr &new_inst)
901{
902    // Loop through the instruction's source registers, adding
903    // them to the dependency list if they are not ready.
904    int8_t total_src_regs = new_inst->numSrcRegs();
905    bool return_val = false;
906
907    for (int src_reg_idx = 0;
908         src_reg_idx < total_src_regs;
909         src_reg_idx++)
910    {
911        // Only add it to the dependency graph if it's not ready.
912        if (!new_inst->isReadySrcRegIdx(src_reg_idx)) {
913            PhysRegIndex src_reg = new_inst->renamedSrcRegIdx(src_reg_idx);
914
915            // Check the IQ's scoreboard to make sure the register
916            // hasn't become ready while the instruction was in flight
917            // between stages.  Only if it really isn't ready should
918            // it be added to the dependency graph.
919            if (src_reg >= numPhysRegs) {
920                continue;
921            } else if (regScoreboard[src_reg] == false) {
922                DPRINTF(IQ, "IQ: Instruction PC %#x has src reg %i that "
923                        "is being added to the dependency chain.\n",
924                        new_inst->readPC(), src_reg);
925
926                dependGraph[src_reg].insert(new_inst);
927
928                // Change the return value to indicate that something
929                // was added to the dependency graph.
930                return_val = true;
931            } else {
932                DPRINTF(IQ, "IQ: Instruction PC %#x has src reg %i that "
933                        "became ready before it reached the IQ.\n",
934                        new_inst->readPC(), src_reg);
935                // Mark a register ready within the instruction.
936                new_inst->markSrcRegReady();
937            }
938        }
939    }
940
941    return return_val;
942}
943
944template <class Impl>
945void
946InstructionQueue<Impl>::createDependency(DynInstPtr &new_inst)
947{
948    //Actually nothing really needs to be marked when an
949    //instruction becomes the producer of a register's value,
950    //but for convenience a ptr to the producing instruction will
951    //be placed in the head node of the dependency links.
952    int8_t total_dest_regs = new_inst->numDestRegs();
953
954    for (int dest_reg_idx = 0;
955         dest_reg_idx < total_dest_regs;
956         dest_reg_idx++)
957    {
958        PhysRegIndex dest_reg = new_inst->renamedDestRegIdx(dest_reg_idx);
959
960        // Instructions that use the misc regs will have a reg number
961        // higher than the normal physical registers.  In this case these
962        // registers are not renamed, and there is no need to track
963        // dependencies as these instructions must be executed at commit.
964        if (dest_reg >= numPhysRegs) {
965            continue;
966        }
967
968        dependGraph[dest_reg].inst = new_inst;
969
970        if (dependGraph[dest_reg].next) {
971            dumpDependGraph();
972            panic("IQ: Dependency graph not empty!");
973        }
974
975        // Mark the scoreboard to say it's not yet ready.
976        regScoreboard[dest_reg] = false;
977    }
978}
979
980template <class Impl>
981void
982InstructionQueue<Impl>::addIfReady(DynInstPtr &inst)
983{
984    //If the instruction now has all of its source registers
985    // available, then add it to the list of ready instructions.
986    if (inst->readyToIssue()) {
987
988        //Add the instruction to the proper ready list.
989        if (inst->isControl()) {
990
991            DPRINTF(IQ, "IQ: Branch instruction is ready to issue, "
992                    "putting it onto the ready list, PC %#x.\n",
993                    inst->readPC());
994            readyBranchInsts.push(inst);
995
996        } else if (inst->isMemRef()) {
997
998            DPRINTF(IQ, "IQ: Checking if memory instruction can issue.\n");
999
1000            // Message to the mem dependence unit that this instruction has
1001            // its registers ready.
1002
1003            memDepUnit.regsReady(inst);
1004
1005#if 0
1006            if (memDepUnit.readyToIssue(inst)) {
1007                DPRINTF(IQ, "IQ: Memory instruction is ready to issue, "
1008                        "putting it onto the ready list, PC %#x.\n",
1009                        inst->readPC());
1010                readyMemInsts.push(inst);
1011            } else {
1012                // Make dependent on the store.
1013                // Will need some way to get the store instruction it should
1014                // be dependent upon; then when the store issues it can
1015                // put the instruction on the ready list.
1016                // Yet another tree?
1017                assert(0 && "Instruction has no way to actually issue");
1018            }
1019#endif
1020
1021        } else if (inst->isInteger()) {
1022
1023            DPRINTF(IQ, "IQ: Integer instruction is ready to issue, "
1024                    "putting it onto the ready list, PC %#x.\n",
1025                    inst->readPC());
1026            readyIntInsts.push(inst);
1027
1028        } else if (inst->isFloating()) {
1029
1030            DPRINTF(IQ, "IQ: Floating instruction is ready to issue, "
1031                    "putting it onto the ready list, PC %#x.\n",
1032                    inst->readPC());
1033            readyFloatInsts.push(inst);
1034
1035        } else {
1036            DPRINTF(IQ, "IQ: Miscellaneous instruction is ready to issue, "
1037                    "putting it onto the ready list, PC %#x..\n",
1038                    inst->readPC());
1039
1040            readyMiscInsts.push(inst);
1041        }
1042    }
1043}
1044
1045/*
1046 * Caution, this function must not be called prior to tail being updated at
1047 * least once, otherwise it will fail the assertion.  This is because
1048 * instList.begin() actually changes upon the insertion of an element into the
1049 * list when the list is empty.
1050 */
1051template <class Impl>
1052int
1053InstructionQueue<Impl>::countInsts()
1054{
1055    ListIt count_it = cpu->instList.begin();
1056    int total_insts = 0;
1057
1058    if (tail == cpu->instList.end())
1059        return 0;
1060
1061    while (count_it != tail) {
1062        if (!(*count_it)->isIssued()) {
1063            ++total_insts;
1064        }
1065
1066        ++count_it;
1067
1068        assert(count_it != cpu->instList.end());
1069    }
1070
1071    // Need to count the tail iterator as well.
1072    if (count_it != cpu->instList.end() &&
1073        (*count_it) &&
1074        !(*count_it)->isIssued()) {
1075        ++total_insts;
1076    }
1077
1078    return total_insts;
1079}
1080
1081template <class Impl>
1082void
1083InstructionQueue<Impl>::dumpDependGraph()
1084{
1085    DependencyEntry *curr;
1086
1087    for (int i = 0; i < numPhysRegs; ++i)
1088    {
1089        curr = &dependGraph[i];
1090
1091        if (curr->inst) {
1092            cprintf("dependGraph[%i]: producer: %#x consumer: ", i,
1093                    curr->inst->readPC());
1094        } else {
1095            cprintf("dependGraph[%i]: No producer. consumer: ", i);
1096        }
1097
1098        while (curr->next != NULL) {
1099            curr = curr->next;
1100
1101            cprintf("%#x ", curr->inst->readPC());
1102        }
1103
1104        cprintf("\n");
1105    }
1106}
1107
1108template <class Impl>
1109void
1110InstructionQueue<Impl>::dumpLists()
1111{
1112    cprintf("Ready integer list size: %i\n", readyIntInsts.size());
1113
1114    cprintf("Ready float list size: %i\n", readyFloatInsts.size());
1115
1116    cprintf("Ready branch list size: %i\n", readyBranchInsts.size());
1117
1118    cprintf("Ready misc list size: %i\n", readyMiscInsts.size());
1119
1120    cprintf("Squashed list size: %i\n", squashedInsts.size());
1121
1122    cprintf("Non speculative list size: %i\n", nonSpecInsts.size());
1123
1124    non_spec_it_t non_spec_it = nonSpecInsts.begin();
1125
1126    cprintf("Non speculative list: ");
1127
1128    while (non_spec_it != nonSpecInsts.end()) {
1129        cprintf("%#x ", (*non_spec_it).second->readPC());
1130        ++non_spec_it;
1131    }
1132
1133    cprintf("\n");
1134
1135}
1136