inst_queue_impl.hh revision 1062
11689SN/A#ifndef __INST_QUEUE_IMPL_HH__
29444SAndreas.Sandberg@ARM.com#define __INST_QUEUE_IMPL_HH__
39444SAndreas.Sandberg@ARM.com
49444SAndreas.Sandberg@ARM.com// Todo:
59444SAndreas.Sandberg@ARM.com// Current ordering allows for 0 cycle added-to-scheduled.  Could maybe fake
69444SAndreas.Sandberg@ARM.com// it; either do in reverse order, or have added instructions put into a
79444SAndreas.Sandberg@ARM.com// different ready queue that, in scheduleRreadyInsts(), gets put onto the
89444SAndreas.Sandberg@ARM.com// normal ready queue.  This would however give only a one cycle delay,
99444SAndreas.Sandberg@ARM.com// but probably is more flexible to actually add in a delay parameter than
109444SAndreas.Sandberg@ARM.com// just running it backwards.
119444SAndreas.Sandberg@ARM.com
129444SAndreas.Sandberg@ARM.com#include <vector>
139444SAndreas.Sandberg@ARM.com
142329SN/A#include "sim/universe.hh"
151689SN/A#include "cpu/beta_cpu/inst_queue.hh"
161689SN/A
171689SN/A// Either compile error or max int due to sign extension.
181689SN/A// Blatant hack to avoid compile warnings.
191689SN/Aconst InstSeqNum MaxInstSeqNum = 0 - 1;
201689SN/A
211689SN/Atemplate <class Impl>
221689SN/AInstructionQueue<Impl>::InstructionQueue(Params &params)
231689SN/A    : memDepUnit(params),
241689SN/A      numEntries(params.numIQEntries),
251689SN/A      intWidth(params.executeIntWidth),
261689SN/A      floatWidth(params.executeFloatWidth),
271689SN/A      branchWidth(params.executeBranchWidth),
281689SN/A      memoryWidth(params.executeMemoryWidth),
291689SN/A      totalWidth(params.issueWidth),
301689SN/A      numPhysIntRegs(params.numPhysIntRegs),
311689SN/A      numPhysFloatRegs(params.numPhysFloatRegs),
321689SN/A      commitToIEWDelay(params.commitToIEWDelay)
331689SN/A{
341689SN/A    DPRINTF(IQ, "IQ: Int width is %i.\n", params.executeIntWidth);
351689SN/A
361689SN/A    // Initialize the number of free IQ entries.
371689SN/A    freeEntries = numEntries;
381689SN/A
392665Ssaidi@eecs.umich.edu    // Set the number of physical registers as the number of int + float
402665Ssaidi@eecs.umich.edu    numPhysRegs = numPhysIntRegs + numPhysFloatRegs;
412831Sksewell@umich.edu
421689SN/A    DPRINTF(IQ, "IQ: There are %i physical registers.\n", numPhysRegs);
431689SN/A
449944Smatt.horsnell@ARM.com    //Create an entry for each physical register within the
459944Smatt.horsnell@ARM.com    //dependency graph.
469944Smatt.horsnell@ARM.com    dependGraph = new DependencyEntry[numPhysRegs];
476221Snate@binkert.org
486221Snate@binkert.org    // Resize the register scoreboard.
491717SN/A    regScoreboard.resize(numPhysRegs);
508232Snate@binkert.org
518232Snate@binkert.org    // Initialize all the head pointers to point to NULL, and all the
521060SN/A    // entries as unready.
536221Snate@binkert.org    // Note that in actuality, the registers corresponding to the logical
542292SN/A    // registers start off as ready.  However this doesn't matter for the
551061SN/A    // IQ as the instruction should have been correctly told if those
564329Sktlim@umich.edu    // registers are ready in rename.  Thus it can all be initialized as
572980Sgblack@eecs.umich.edu    // unready.
586221Snate@binkert.org    for (int i = 0; i < numPhysRegs; ++i)
594329Sktlim@umich.edu    {
604329Sktlim@umich.edu        dependGraph[i].next = NULL;
611060SN/A        dependGraph[i].inst = NULL;
621060SN/A        regScoreboard[i] = false;
632292SN/A    }
641060SN/A
652980Sgblack@eecs.umich.edu}
662292SN/A
672292SN/Atemplate <class Impl>
682292SN/Avoid
692292SN/AInstructionQueue<Impl>::regStats()
702292SN/A{
712292SN/A    iqInstsAdded
722292SN/A        .name(name() + ".iqInstsAdded")
732292SN/A        .desc("Number of instructions added to the IQ (excludes non-spec)")
742292SN/A        .prereq(iqInstsAdded);
752292SN/A
766221Snate@binkert.org    iqNonSpecInstsAdded
776221Snate@binkert.org        .name(name() + ".iqNonSpecInstsAdded")
782292SN/A        .desc("Number of non-speculative instructions added to the IQ")
792292SN/A        .prereq(iqNonSpecInstsAdded);
802292SN/A
812292SN/A//    iqIntInstsAdded;
824329Sktlim@umich.edu
832292SN/A    iqIntInstsIssued
842292SN/A        .name(name() + ".iqIntInstsIssued")
852292SN/A        .desc("Number of integer instructions issued")
862292SN/A        .prereq(iqIntInstsIssued);
872292SN/A
886221Snate@binkert.org//    iqFloatInstsAdded;
896221Snate@binkert.org
902292SN/A    iqFloatInstsIssued
912292SN/A        .name(name() + ".iqFloatInstsIssued")
922292SN/A        .desc("Number of float instructions issued")
932292SN/A        .prereq(iqFloatInstsIssued);
944329Sktlim@umich.edu
952292SN/A//    iqBranchInstsAdded;
962292SN/A
972292SN/A    iqBranchInstsIssued
982292SN/A        .name(name() + ".iqBranchInstsIssued")
996221Snate@binkert.org        .desc("Number of branch instructions issued")
1006221Snate@binkert.org        .prereq(iqBranchInstsIssued);
1012292SN/A
1022292SN/A//    iqMemInstsAdded;
1032292SN/A
1042292SN/A    iqMemInstsIssued
1052292SN/A        .name(name() + ".iqMemInstsIssued")
1061060SN/A        .desc("Number of memory instructions issued")
1079444SAndreas.Sandberg@ARM.com        .prereq(iqMemInstsIssued);
1089444SAndreas.Sandberg@ARM.com
1099444SAndreas.Sandberg@ARM.com//    iqMiscInstsAdded;
1109444SAndreas.Sandberg@ARM.com
1119444SAndreas.Sandberg@ARM.com    iqMiscInstsIssued
1129444SAndreas.Sandberg@ARM.com        .name(name() + ".iqMiscInstsIssued")
1139444SAndreas.Sandberg@ARM.com        .desc("Number of miscellaneous instructions issued")
1149444SAndreas.Sandberg@ARM.com        .prereq(iqMiscInstsIssued);
1159444SAndreas.Sandberg@ARM.com
1169444SAndreas.Sandberg@ARM.com    iqSquashedInstsIssued
1176221Snate@binkert.org        .name(name() + ".iqSquashedInstsIssued")
1189444SAndreas.Sandberg@ARM.com        .desc("Number of squashed instructions issued")
1192292SN/A        .prereq(iqSquashedInstsIssued);
1209444SAndreas.Sandberg@ARM.com
1211060SN/A    iqLoopSquashStalls
1222292SN/A        .name(name() + ".iqLoopSquashStalls")
1232292SN/A        .desc("Number of times issue loop had to restart due to squashed "
1242292SN/A              "inst; mainly for profiling")
1252292SN/A        .prereq(iqLoopSquashStalls);
1262292SN/A
1272292SN/A    iqSquashedInstsExamined
1282292SN/A        .name(name() + ".iqSquashedInstsExamined")
1294329Sktlim@umich.edu        .desc("Number of squashed instructions iterated over during squash;"
1304329Sktlim@umich.edu              " mainly for profiling")
1314329Sktlim@umich.edu        .prereq(iqSquashedInstsExamined);
1324329Sktlim@umich.edu
1334329Sktlim@umich.edu    iqSquashedOperandsExamined
1344329Sktlim@umich.edu        .name(name() + ".iqSquashedOperandsExamined")
1354329Sktlim@umich.edu        .desc("Number of squashed operands that are examined and possibly "
1362292SN/A              "removed from graph")
1376221Snate@binkert.org        .prereq(iqSquashedOperandsExamined);
1382292SN/A
1392292SN/A    iqSquashedNonSpecRemoved
1402292SN/A        .name(name() + ".iqSquashedNonSpecRemoved")
1412292SN/A        .desc("Number of squashed non-spec instructions that were removed")
1422292SN/A        .prereq(iqSquashedNonSpecRemoved);
1432307SN/A
1442307SN/A    // Tell mem dependence unit to reg stats as well.
1459444SAndreas.Sandberg@ARM.com    memDepUnit.regStats();
1462307SN/A}
1479444SAndreas.Sandberg@ARM.com
1489444SAndreas.Sandberg@ARM.comtemplate <class Impl>
1499444SAndreas.Sandberg@ARM.comvoid
1502307SN/AInstructionQueue<Impl>::setCPU(FullCPU *cpu_ptr)
1512307SN/A{
1522307SN/A    cpu = cpu_ptr;
1532307SN/A
1542307SN/A    tail = cpu->instList.begin();
1552307SN/A}
1569444SAndreas.Sandberg@ARM.com
1572307SN/Atemplate <class Impl>
1582292SN/Avoid
1592292SN/AInstructionQueue<Impl>::setIssueToExecuteQueue(
1602292SN/A                        TimeBuffer<IssueStruct> *i2e_ptr)
1612292SN/A{
1622292SN/A    DPRINTF(IQ, "IQ: Set the issue to execute queue.\n");
1632292SN/A    issueToExecuteQueue = i2e_ptr;
1643867Sbinkertn@umich.edu}
1652292SN/A
1666221Snate@binkert.orgtemplate <class Impl>
1676221Snate@binkert.orgvoid
1682292SN/AInstructionQueue<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
1693867Sbinkertn@umich.edu{
1706221Snate@binkert.org    DPRINTF(IQ, "IQ: Set the time buffer.\n");
1713867Sbinkertn@umich.edu    timeBuffer = tb_ptr;
1722292SN/A
1733867Sbinkertn@umich.edu    fromCommit = timeBuffer->getWire(-commitToIEWDelay);
1742292SN/A}
1753867Sbinkertn@umich.edu
1762292SN/A// Might want to do something more complex if it knows how many instructions
1772292SN/A// will be issued this cycle.
1782292SN/Atemplate <class Impl>
1792292SN/Abool
1802292SN/AInstructionQueue<Impl>::isFull()
1812292SN/A{
1822292SN/A    if (freeEntries == 0) {
1836221Snate@binkert.org        return(true);
1842292SN/A    } else {
1852292SN/A        return(false);
1862292SN/A    }
1872292SN/A}
1882292SN/A
1892292SN/Atemplate <class Impl>
1901060SN/Aunsigned
1911060SN/AInstructionQueue<Impl>::numFreeEntries()
1921061SN/A{
1931060SN/A    return freeEntries;
1941060SN/A}
1951060SN/A
1966221Snate@binkert.orgtemplate <class Impl>
1971061SN/Avoid
1986221Snate@binkert.orgInstructionQueue<Impl>::insert(DynInstPtr &new_inst)
1996221Snate@binkert.org{
2001060SN/A    // Make sure the instruction is valid
2012292SN/A    assert(new_inst);
2022292SN/A
2031060SN/A    DPRINTF(IQ, "IQ: Adding instruction PC %#x to the IQ.\n",
2042292SN/A            new_inst->readPC());
2052292SN/A
2066221Snate@binkert.org    // Check if there are any free entries.  Panic if there are none.
2072292SN/A    // Might want to have this return a fault in the future instead of
2082292SN/A    // panicing.
2091060SN/A    assert(freeEntries != 0);
2101060SN/A
2111061SN/A    // If the IQ currently has nothing in it, then there's a possibility
2121060SN/A    // that the tail iterator is invalid (might have been pointing at an
2131061SN/A    // instruction that was retired).  Reset the tail iterator.
2141060SN/A    if (freeEntries == numEntries) {
2151060SN/A        tail = cpu->instList.begin();
2161060SN/A    }
2177897Shestness@cs.utexas.edu
2187897Shestness@cs.utexas.edu    // Move the tail iterator.  Instructions may not have been issued
2197720Sgblack@eecs.umich.edu    // to the IQ, so we may have to increment the iterator more than once.
2201060SN/A    while ((*tail) != new_inst) {
2211060SN/A        tail++;
2221060SN/A
2236221Snate@binkert.org        // Make sure the tail iterator points at something legal.
2241060SN/A        assert(tail != cpu->instList.end());
2252292SN/A    }
2262292SN/A
2272292SN/A
2282292SN/A    // Decrease the number of free entries.
2292292SN/A    --freeEntries;
2302292SN/A
2311060SN/A    // Look through its source registers (physical regs), and mark any
2321060SN/A    // dependencies.
2332292SN/A    addToDependents(new_inst);
2342292SN/A
2352292SN/A    // Have this instruction set itself as the producer of its destination
2362292SN/A    // register(s).
2372292SN/A    createDependency(new_inst);
2382292SN/A
2392292SN/A    // If it's a memory instruction, add it to the memory dependency
2402292SN/A    // unit.
2412292SN/A    if (new_inst->isMemRef()) {
2422292SN/A        memDepUnit.insert(new_inst);
2431060SN/A        // Uh..forgot to look it up and put it on the proper dependency list
2441060SN/A        // if the instruction should not go yet.
2452292SN/A    } else {
2461060SN/A        // If the instruction is ready then add it to the ready list.
2471060SN/A        addIfReady(new_inst);
2482292SN/A    }
2492292SN/A
2506221Snate@binkert.org    ++iqInstsAdded;
2512292SN/A
2527897Shestness@cs.utexas.edu    assert(freeEntries == (numEntries - countInsts()));
2537897Shestness@cs.utexas.edu}
2541061SN/A
2551060SN/Atemplate <class Impl>
2561060SN/Avoid
2572292SN/AInstructionQueue<Impl>::insertNonSpec(DynInstPtr &inst)
2581060SN/A{
2592292SN/A    nonSpecInsts[inst->seqNum] = inst;
2601858SN/A
2611060SN/A    // @todo: Clean up this code; can do it by setting inst as unable
2621060SN/A    // to issue, then calling normal insert on the inst.
2632292SN/A
2647720Sgblack@eecs.umich.edu    // Make sure the instruction is valid
2651060SN/A    assert(inst);
2661060SN/A
2671060SN/A    DPRINTF(IQ, "IQ: Adding instruction PC %#x to the IQ.\n",
2682292SN/A            inst->readPC());
2691060SN/A
2702731Sktlim@umich.edu    // Check if there are any free entries.  Panic if there are none.
2712292SN/A    // Might want to have this return a fault in the future instead of
2722292SN/A    // panicing.
2732292SN/A    assert(freeEntries != 0);
2742292SN/A
2752292SN/A    // If the IQ currently has nothing in it, then there's a possibility
2762292SN/A    // that the tail iterator is invalid (might have been pointing at an
2772292SN/A    // instruction that was retired).  Reset the tail iterator.
2782329SN/A    if (freeEntries == numEntries) {
2792329SN/A        tail = cpu->instList.begin();
2802329SN/A    }
2811681SN/A
2821060SN/A    // Move the tail iterator.  Instructions may not have been issued
2832292SN/A    // to the IQ, so we may have to increment the iterator more than once.
2842292SN/A    while ((*tail) != inst) {
2852292SN/A        tail++;
2866221Snate@binkert.org
2872292SN/A        // Make sure the tail iterator points at something legal.
2887897Shestness@cs.utexas.edu        assert(tail != cpu->instList.end());
2892292SN/A    }
2902292SN/A
2912292SN/A    // Decrease the number of free entries.
2922292SN/A    --freeEntries;
2932292SN/A
2942292SN/A    // Look through its source registers (physical regs), and mark any
2952292SN/A    // dependencies.
2962292SN/A//    addToDependents(inst);
2972292SN/A
2982292SN/A    // Have this instruction set itself as the producer of its destination
2992292SN/A    // register(s).
3002292SN/A    createDependency(inst);
3016221Snate@binkert.org
3026221Snate@binkert.org    // If it's a memory instruction, add it to the memory dependency
3032292SN/A    // unit.
3043867Sbinkertn@umich.edu    if (inst->isMemRef()) {
3056221Snate@binkert.org        memDepUnit.insertNonSpec(inst);
3062292SN/A    }
3072292SN/A
3082292SN/A    ++iqNonSpecInstsAdded;
3092292SN/A}
3101060SN/A
3111060SN/A// Slightly hack function to advance the tail iterator in the case that
3121060SN/A// the IEW stage issues an instruction that is not added to the IQ.  This
3131060SN/A// is needed in case a long chain of such instructions occurs.
3141060SN/A// I don't think this is used anymore.
3151061SN/Atemplate <class Impl>
3161060SN/Avoid
3171060SN/AInstructionQueue<Impl>::advanceTail(DynInstPtr &inst)
3181060SN/A{
3191060SN/A    // Make sure the instruction is valid
3201060SN/A    assert(inst);
3211060SN/A
3221061SN/A    DPRINTF(IQ, "IQ: Adding instruction PC %#x to the IQ.\n",
3232292SN/A            inst->readPC());
3246221Snate@binkert.org
3251060SN/A    // Check if there are any free entries.  Panic if there are none.
3262292SN/A    // Might want to have this return a fault in the future instead of
3271060SN/A    // panicing.
3281060SN/A    assert(freeEntries != 0);
3291061SN/A
3301060SN/A    // If the IQ currently has nothing in it, then there's a possibility
3316221Snate@binkert.org    // that the tail iterator is invalid (might have been pointing at an
3321060SN/A    // instruction that was retired).  Reset the tail iterator.
3337897Shestness@cs.utexas.edu    if (freeEntries == numEntries) {
3342292SN/A        tail = cpu->instList.begin();
3352877Sksewell@umich.edu    }
3361858SN/A
3372292SN/A    // Move the tail iterator.  Instructions may not have been issued
3382292SN/A    // to the IQ, so we may have to increment the iterator more than once.
3392877Sksewell@umich.edu    while ((*tail) != inst) {
3402292SN/A        tail++;
3412292SN/A
3422292SN/A        // Make sure the tail iterator points at something legal.
3432292SN/A        assert(tail != cpu->instList.end());
3442292SN/A    }
3452292SN/A
3462292SN/A    assert(freeEntries <= numEntries);
3472292SN/A
3482292SN/A    // Have this instruction set itself as the producer of its destination
3492292SN/A    // register(s).
3501858SN/A    createDependency(inst);
3511858SN/A}
3522292SN/A
3532292SN/A// Need to make sure the number of float and integer instructions
3542877Sksewell@umich.edu// issued does not exceed the total issue bandwidth.
3551858SN/A// @todo: Figure out a better way to remove the squashed items from the
3561858SN/A// lists.  Checking the top item of each list to see if it's squashed
3577720Sgblack@eecs.umich.edu// wastes time and forces jumps.
3582292SN/Atemplate <class Impl>
3597720Sgblack@eecs.umich.eduvoid
3602292SN/AInstructionQueue<Impl>::scheduleReadyInsts()
3611858SN/A{
3621858SN/A    DPRINTF(IQ, "IQ: Attempting to schedule ready instructions from "
3631858SN/A                "the IQ.\n");
3642292SN/A
3651858SN/A    int int_issued = 0;
3662292SN/A    int float_issued = 0;
3671858SN/A    int branch_issued = 0;
3682292SN/A    int memory_issued = 0;
3692292SN/A    int squashed_issued = 0;
3702292SN/A    int total_issued = 0;
3711858SN/A
3721858SN/A    IssueStruct *i2e_info = issueToExecuteQueue->access(0);
3732292SN/A
3741858SN/A    bool insts_available = !readyBranchInsts.empty() ||
3752292SN/A        !readyIntInsts.empty() ||
3761858SN/A        !readyFloatInsts.empty() ||
3771858SN/A        !memDepUnit.empty() ||
3781858SN/A        !readyMiscInsts.empty() ||
3791858SN/A        !squashedInsts.empty();
3802292SN/A
3812292SN/A    // Note: Requires a globally defined constant.
3822292SN/A    InstSeqNum oldest_inst = MaxInstSeqNum;
3832292SN/A    InstList list_with_oldest = None;
3842292SN/A
3852292SN/A    // Temporary values.
3862292SN/A    DynInstPtr int_head_inst;
3871858SN/A    DynInstPtr float_head_inst;
3881858SN/A    DynInstPtr branch_head_inst;
3891858SN/A    DynInstPtr mem_head_inst;
3901858SN/A    DynInstPtr misc_head_inst;
3912877Sksewell@umich.edu    DynInstPtr squashed_head_inst;
3922292SN/A
3932292SN/A    // Somewhat nasty code to look at all of the lists where issuable
3941858SN/A    // instructions are located, and choose the oldest instruction among
3952292SN/A    // those lists.  Consider a rewrite in the future.
3961858SN/A    while (insts_available && total_issued < totalWidth)
3972292SN/A    {
3982292SN/A        // Set this to false.  Each if-block is required to set it to true
3992292SN/A        // if there were instructions available this check.  This will cause
4002292SN/A        // this loop to run once more than necessary, but avoids extra calls.
4012292SN/A        insts_available = false;
4022292SN/A
4032292SN/A        oldest_inst = MaxInstSeqNum;
4042292SN/A
4052292SN/A        list_with_oldest = None;
4062292SN/A
4072292SN/A        if (!readyIntInsts.empty() &&
4082292SN/A            int_issued < intWidth) {
4092292SN/A
4102292SN/A            insts_available = true;
4112292SN/A
4122292SN/A            int_head_inst = readyIntInsts.top();
4132292SN/A
4146221Snate@binkert.org            if (int_head_inst->isSquashed()) {
4156221Snate@binkert.org                readyIntInsts.pop();
4162292SN/A
4173867Sbinkertn@umich.edu                ++iqLoopSquashStalls;
4186221Snate@binkert.org
4192292SN/A                continue;
4203867Sbinkertn@umich.edu            }
4212292SN/A
4222292SN/A            oldest_inst = int_head_inst->seqNum;
4232292SN/A
4243867Sbinkertn@umich.edu            list_with_oldest = Int;
4252292SN/A        }
4262292SN/A
4272292SN/A        if (!readyFloatInsts.empty() &&
4282292SN/A            float_issued < floatWidth) {
4292292SN/A
4303867Sbinkertn@umich.edu            insts_available = true;
4312292SN/A
4322292SN/A            float_head_inst = readyFloatInsts.top();
4332292SN/A
4342292SN/A            if (float_head_inst->isSquashed()) {
4352292SN/A                readyFloatInsts.pop();
4362292SN/A
4372292SN/A                ++iqLoopSquashStalls;
4382292SN/A
4392292SN/A                continue;
4402292SN/A            } else if (float_head_inst->seqNum < oldest_inst) {
4412292SN/A                oldest_inst = float_head_inst->seqNum;
4422292SN/A
4432292SN/A                list_with_oldest = Float;
4442292SN/A            }
4452292SN/A        }
4462292SN/A
4472292SN/A        if (!readyBranchInsts.empty() &&
4482292SN/A            branch_issued < branchWidth) {
4492292SN/A
4502292SN/A            insts_available = true;
4512292SN/A
4522292SN/A            branch_head_inst = readyBranchInsts.top();
4532292SN/A
4542292SN/A            if (branch_head_inst->isSquashed()) {
4556221Snate@binkert.org                readyBranchInsts.pop();
4566221Snate@binkert.org
4572292SN/A                ++iqLoopSquashStalls;
4583867Sbinkertn@umich.edu
4596221Snate@binkert.org                continue;
4602292SN/A            } else if (branch_head_inst->seqNum < oldest_inst) {
4612292SN/A                oldest_inst = branch_head_inst->seqNum;
4622292SN/A
4632292SN/A                list_with_oldest = Branch;
4642292SN/A            }
4652292SN/A
4662292SN/A        }
4672292SN/A
4682292SN/A        if (!memDepUnit.empty() &&
4692292SN/A            memory_issued < memoryWidth) {
4702292SN/A
4712292SN/A            insts_available = true;
4722292SN/A
4732292SN/A            mem_head_inst = memDepUnit.top();
4742292SN/A
4752292SN/A            if (mem_head_inst->isSquashed()) {
4762292SN/A                memDepUnit.pop();
4772292SN/A
4782292SN/A                ++iqLoopSquashStalls;
4792292SN/A
4802292SN/A                continue;
4812292SN/A            } else if (mem_head_inst->seqNum < oldest_inst) {
4822292SN/A                oldest_inst = mem_head_inst->seqNum;
4832292SN/A
4842292SN/A                list_with_oldest = Memory;
4852292SN/A            }
4862292SN/A        }
4872292SN/A
4886221Snate@binkert.org        if (!readyMiscInsts.empty()) {
4892292SN/A
4902292SN/A            insts_available = true;
4912292SN/A
4922292SN/A            misc_head_inst = readyMiscInsts.top();
4932292SN/A
4942292SN/A            if (misc_head_inst->isSquashed()) {
4952292SN/A                readyMiscInsts.pop();
4962292SN/A
4972292SN/A                ++iqLoopSquashStalls;
4982292SN/A
4992292SN/A                continue;
5002292SN/A            } else if (misc_head_inst->seqNum < oldest_inst) {
5012292SN/A                oldest_inst = misc_head_inst->seqNum;
5022292SN/A
5031060SN/A                list_with_oldest = Misc;
5042877Sksewell@umich.edu            }
5051060SN/A        }
5062292SN/A
5072292SN/A        if (!squashedInsts.empty()) {
5082292SN/A
5091060SN/A            insts_available = true;
5102292SN/A
5111060SN/A            squashed_head_inst = squashedInsts.top();
5122292SN/A
5131858SN/A            if (squashed_head_inst->seqNum < oldest_inst) {
5141060SN/A                list_with_oldest = Squashed;
5152877Sksewell@umich.edu            }
5162292SN/A
5172292SN/A        }
5186221Snate@binkert.org
5192292SN/A        DynInstPtr issuing_inst = NULL;
5202292SN/A
5212292SN/A        switch (list_with_oldest) {
5221060SN/A          case None:
5232292SN/A            DPRINTF(IQ, "IQ: Not able to schedule any instructions. Issuing "
5241858SN/A                    "inst is %#x.\n", issuing_inst);
5252292SN/A            break;
5262292SN/A
5272292SN/A          case Int:
5282292SN/A            issuing_inst = int_head_inst;
5291858SN/A            readyIntInsts.pop();
5302877Sksewell@umich.edu            ++int_issued;
5312292SN/A            DPRINTF(IQ, "IQ: Issuing integer instruction PC %#x.\n",
5322292SN/A                    issuing_inst->readPC());
5336221Snate@binkert.org            break;
5342292SN/A
5352292SN/A          case Float:
5362292SN/A            issuing_inst = float_head_inst;
5372292SN/A            readyFloatInsts.pop();
5382292SN/A            ++float_issued;
5392292SN/A            DPRINTF(IQ, "IQ: Issuing float instruction PC %#x.\n",
5402292SN/A                    issuing_inst->readPC());
5417897Shestness@cs.utexas.edu            break;
5427897Shestness@cs.utexas.edu
5437897Shestness@cs.utexas.edu          case Branch:
5447897Shestness@cs.utexas.edu            issuing_inst = branch_head_inst;
5457897Shestness@cs.utexas.edu            readyBranchInsts.pop();
5467897Shestness@cs.utexas.edu            ++branch_issued;
5477897Shestness@cs.utexas.edu            DPRINTF(IQ, "IQ: Issuing branch instruction PC %#x.\n",
5487897Shestness@cs.utexas.edu                    issuing_inst->readPC());
5497897Shestness@cs.utexas.edu            break;
5507897Shestness@cs.utexas.edu
5517897Shestness@cs.utexas.edu          case Memory:
5527897Shestness@cs.utexas.edu            issuing_inst = mem_head_inst;
5537897Shestness@cs.utexas.edu
5547897Shestness@cs.utexas.edu            memDepUnit.pop();
5558822Snilay@cs.wisc.edu            ++memory_issued;
5568822Snilay@cs.wisc.edu            DPRINTF(IQ, "IQ: Issuing memory instruction PC %#x.\n",
5578822Snilay@cs.wisc.edu                    issuing_inst->readPC());
5588822Snilay@cs.wisc.edu            break;
5598822Snilay@cs.wisc.edu
5608822Snilay@cs.wisc.edu          case Misc:
5618822Snilay@cs.wisc.edu            issuing_inst = misc_head_inst;
5628822Snilay@cs.wisc.edu            readyMiscInsts.pop();
5638822Snilay@cs.wisc.edu
5648822Snilay@cs.wisc.edu            ++iqMiscInstsIssued;
5658822Snilay@cs.wisc.edu
5669944Smatt.horsnell@ARM.com            DPRINTF(IQ, "IQ: Issuing a miscellaneous instruction PC %#x.\n",
5679944Smatt.horsnell@ARM.com                    issuing_inst->readPC());
568            break;
569
570          case Squashed:
571            issuing_inst = squashed_head_inst;
572            squashedInsts.pop();
573            ++squashed_issued;
574            DPRINTF(IQ, "IQ: Issuing squashed instruction PC %#x.\n",
575                    issuing_inst->readPC());
576            break;
577        }
578
579        if (list_with_oldest != None) {
580            i2e_info->insts[total_issued] = issuing_inst;
581            i2e_info->size++;
582
583            issuing_inst->setIssued();
584
585            ++freeEntries;
586            ++total_issued;
587        }
588
589        assert(freeEntries == (numEntries - countInsts()));
590    }
591
592    iqIntInstsIssued += int_issued;
593    iqFloatInstsIssued += float_issued;
594    iqBranchInstsIssued += branch_issued;
595    iqMemInstsIssued += memory_issued;
596    iqSquashedInstsIssued += squashed_issued;
597}
598
599template <class Impl>
600void
601InstructionQueue<Impl>::scheduleNonSpec(const InstSeqNum &inst)
602{
603    DPRINTF(IQ, "IQ: Marking nonspeculative instruction with sequence "
604            "number %i as ready to execute.\n", inst);
605
606    non_spec_it_t inst_it = nonSpecInsts.find(inst);
607
608    assert(inst_it != nonSpecInsts.end());
609
610    // Mark this instruction as ready to issue.
611    (*inst_it).second->setCanIssue();
612
613    // Now schedule the instruction.
614    if (!(*inst_it).second->isMemRef()) {
615        addIfReady((*inst_it).second);
616    } else {
617        memDepUnit.nonSpecInstReady((*inst_it).second);
618    }
619
620    nonSpecInsts.erase(inst_it);
621}
622
623template <class Impl>
624void
625InstructionQueue<Impl>::violation(DynInstPtr &store,
626                                  DynInstPtr &faulting_load)
627{
628    memDepUnit.violation(store, faulting_load);
629}
630
631template <class Impl>
632void
633InstructionQueue<Impl>::squash()
634{
635    DPRINTF(IQ, "IQ: Starting to squash instructions in the IQ.\n");
636
637    // Read instruction sequence number of last instruction out of the
638    // time buffer.
639    squashedSeqNum = fromCommit->commitInfo.doneSeqNum;
640
641    // Setup the squash iterator to point to the tail.
642    squashIt = tail;
643
644    // Call doSquash.
645    doSquash();
646
647    // Also tell the memory dependence unit to squash.
648    memDepUnit.squash(squashedSeqNum);
649}
650
651template <class Impl>
652void
653InstructionQueue<Impl>::doSquash()
654{
655    // Make sure the squash iterator isn't pointing to nothing.
656    assert(squashIt != cpu->instList.end());
657    // Make sure the squashed sequence number is valid.
658    assert(squashedSeqNum != 0);
659
660    DPRINTF(IQ, "IQ: Squashing instructions in the IQ.\n");
661
662    // Squash any instructions younger than the squashed sequence number
663    // given.
664    while ((*squashIt)->seqNum > squashedSeqNum) {
665        DynInstPtr squashed_inst = (*squashIt);
666
667        // Only handle the instruction if it actually is in the IQ and
668        // hasn't already been squashed in the IQ.
669        if (!squashed_inst->isIssued() &&
670            !squashed_inst->isSquashedInIQ()) {
671
672            // Remove the instruction from the dependency list.
673            // Hack for now: These below don't add themselves to the
674            // dependency list, so don't try to remove them.
675            if (!squashed_inst->isNonSpeculative() &&
676                !squashed_inst->isStore()) {
677                int8_t total_src_regs = squashed_inst->numSrcRegs();
678
679                for (int src_reg_idx = 0;
680                     src_reg_idx < total_src_regs;
681                     src_reg_idx++)
682                {
683                    PhysRegIndex src_reg =
684                        squashed_inst->renamedSrcRegIdx(src_reg_idx);
685
686                    // Only remove it from the dependency graph if it was
687                    // placed there in the first place.
688                    // HACK: This assumes that instructions woken up from the
689                    // dependency chain aren't informed that a specific src
690                    // register has become ready.  This may not always be true
691                    // in the future.
692                    if (!squashed_inst->isReadySrcRegIdx(src_reg_idx) &&
693                        src_reg < numPhysRegs) {
694                        dependGraph[src_reg].remove(squashed_inst);
695                    }
696
697                    ++iqSquashedOperandsExamined;
698                }
699
700                // Might want to remove producers as well.
701            } else {
702                nonSpecInsts.erase(squashed_inst->seqNum);
703
704                ++iqSquashedNonSpecRemoved;
705            }
706
707            // Might want to also clear out the head of the dependency graph.
708
709            // Mark it as squashed within the IQ.
710            squashed_inst->setSquashedInIQ();
711
712            squashedInsts.push(squashed_inst);
713
714            DPRINTF(IQ, "IQ: Instruction PC %#x squashed.\n",
715                    squashed_inst->readPC());
716        }
717
718        --squashIt;
719        ++iqSquashedInstsExamined;
720    }
721}
722
723template <class Impl>
724void
725InstructionQueue<Impl>::stopSquash()
726{
727    // Clear up the squash variables to ensure that squashing doesn't
728    // get called improperly.
729    squashedSeqNum = 0;
730
731    squashIt = cpu->instList.end();
732}
733
734template <class Impl>
735void
736InstructionQueue<Impl>::wakeDependents(DynInstPtr &completed_inst)
737{
738    DPRINTF(IQ, "IQ: Waking dependents of completed instruction.\n");
739    //Look at the physical destination register of the DynInst
740    //and look it up on the dependency graph.  Then mark as ready
741    //any instructions within the instruction queue.
742    int8_t total_dest_regs = completed_inst->numDestRegs();
743
744    DependencyEntry *curr;
745
746    // Tell the memory dependence unit to wake any dependents on this
747    // instruction if it is a memory instruction.
748
749    if (completed_inst->isMemRef()) {
750        memDepUnit.wakeDependents(completed_inst);
751    }
752
753    for (int dest_reg_idx = 0;
754         dest_reg_idx < total_dest_regs;
755         dest_reg_idx++)
756    {
757        PhysRegIndex dest_reg =
758            completed_inst->renamedDestRegIdx(dest_reg_idx);
759
760        // Special case of uniq or control registers.  They are not
761        // handled by the IQ and thus have no dependency graph entry.
762        // @todo Figure out a cleaner way to handle thie.
763        if (dest_reg >= numPhysRegs) {
764            continue;
765        }
766
767        DPRINTF(IQ, "IQ: Waking any dependents on register %i.\n",
768                (int) dest_reg);
769
770        //Maybe abstract this part into a function.
771        //Go through the dependency chain, marking the registers as ready
772        //within the waiting instructions.
773        while (dependGraph[dest_reg].next) {
774
775            curr = dependGraph[dest_reg].next;
776
777            DPRINTF(IQ, "IQ: Waking up a dependent instruction, PC%#x.\n",
778                    curr->inst->readPC());
779
780            // Might want to give more information to the instruction
781            // so that it knows which of its source registers is ready.
782            // However that would mean that the dependency graph entries
783            // would need to hold the src_reg_idx.
784            curr->inst->markSrcRegReady();
785
786            addIfReady(curr->inst);
787
788            dependGraph[dest_reg].next = curr->next;
789
790            DependencyEntry::mem_alloc_counter--;
791
792            delete curr;
793        }
794
795        // Reset the head node now that all of its dependents have been woken
796        // up.
797        dependGraph[dest_reg].next = NULL;
798        dependGraph[dest_reg].inst = NULL;
799
800        // Mark the scoreboard as having that register ready.
801        regScoreboard[dest_reg] = true;
802    }
803}
804
805template <class Impl>
806bool
807InstructionQueue<Impl>::addToDependents(DynInstPtr &new_inst)
808{
809    // Loop through the instruction's source registers, adding
810    // them to the dependency list if they are not ready.
811    int8_t total_src_regs = new_inst->numSrcRegs();
812    bool return_val = false;
813
814    for (int src_reg_idx = 0;
815         src_reg_idx < total_src_regs;
816         src_reg_idx++)
817    {
818        // Only add it to the dependency graph if it's not ready.
819        if (!new_inst->isReadySrcRegIdx(src_reg_idx)) {
820            PhysRegIndex src_reg = new_inst->renamedSrcRegIdx(src_reg_idx);
821
822            // Check the IQ's scoreboard to make sure the register
823            // hasn't become ready while the instruction was in flight
824            // between stages.  Only if it really isn't ready should
825            // it be added to the dependency graph.
826            if (src_reg >= numPhysRegs) {
827                continue;
828            } else if (regScoreboard[src_reg] == false) {
829                DPRINTF(IQ, "IQ: Instruction PC %#x has src reg %i that "
830                        "is being added to the dependency chain.\n",
831                        new_inst->readPC(), src_reg);
832
833                dependGraph[src_reg].insert(new_inst);
834
835                // Change the return value to indicate that something
836                // was added to the dependency graph.
837                return_val = true;
838            } else {
839                DPRINTF(IQ, "IQ: Instruction PC %#x has src reg %i that "
840                        "became ready before it reached the IQ.\n",
841                        new_inst->readPC(), src_reg);
842                // Mark a register ready within the instruction.
843                new_inst->markSrcRegReady();
844            }
845        }
846    }
847
848    return return_val;
849}
850
851template <class Impl>
852void
853InstructionQueue<Impl>::createDependency(DynInstPtr &new_inst)
854{
855    //Actually nothing really needs to be marked when an
856    //instruction becomes the producer of a register's value,
857    //but for convenience a ptr to the producing instruction will
858    //be placed in the head node of the dependency links.
859    int8_t total_dest_regs = new_inst->numDestRegs();
860
861    for (int dest_reg_idx = 0;
862         dest_reg_idx < total_dest_regs;
863         dest_reg_idx++)
864    {
865        PhysRegIndex dest_reg = new_inst->renamedDestRegIdx(dest_reg_idx);
866
867        // Instructions that use the misc regs will have a reg number
868        // higher than the normal physical registers.  In this case these
869        // registers are not renamed, and there is no need to track
870        // dependencies as these instructions must be executed at commit.
871        if (dest_reg >= numPhysRegs) {
872            continue;
873        }
874
875        dependGraph[dest_reg].inst = new_inst;
876
877        assert(!dependGraph[dest_reg].next);
878
879        // Mark the scoreboard to say it's not yet ready.
880        regScoreboard[dest_reg] = false;
881    }
882}
883
884template <class Impl>
885void
886InstructionQueue<Impl>::DependencyEntry::insert(DynInstPtr &new_inst)
887{
888    //Add this new, dependent instruction at the head of the dependency
889    //chain.
890
891    // First create the entry that will be added to the head of the
892    // dependency chain.
893    DependencyEntry *new_entry = new DependencyEntry;
894    new_entry->next = this->next;
895    new_entry->inst = new_inst;
896
897    // Then actually add it to the chain.
898    this->next = new_entry;
899
900    ++mem_alloc_counter;
901}
902
903template <class Impl>
904void
905InstructionQueue<Impl>::DependencyEntry::remove(DynInstPtr &inst_to_remove)
906{
907    DependencyEntry *prev = this;
908    DependencyEntry *curr = this->next;
909
910    // Make sure curr isn't NULL.  Because this instruction is being
911    // removed from a dependency list, it must have been placed there at
912    // an earlier time.  The dependency chain should not be empty,
913    // unless the instruction dependent upon it is already ready.
914    if (curr == NULL) {
915        return;
916    }
917
918    // Find the instruction to remove within the dependency linked list.
919    while(curr->inst != inst_to_remove)
920    {
921        prev = curr;
922        curr = curr->next;
923
924        assert(curr != NULL);
925    }
926
927    // Now remove this instruction from the list.
928    prev->next = curr->next;
929
930    --mem_alloc_counter;
931
932    delete curr;
933}
934
935template <class Impl>
936void
937InstructionQueue<Impl>::dumpDependGraph()
938{
939    DependencyEntry *curr;
940
941    for (int i = 0; i < numPhysRegs; ++i)
942    {
943        curr = &dependGraph[i];
944
945        if (curr->inst) {
946            cprintf("dependGraph[%i]: producer: %#x consumer: ", i,
947                    curr->inst->readPC());
948        } else {
949            cprintf("dependGraph[%i]: No producer. consumer: ", i);
950        }
951
952        while (curr->next != NULL) {
953            curr = curr->next;
954
955            cprintf("%#x ", curr->inst->readPC());
956        }
957
958        cprintf("\n");
959    }
960}
961
962template <class Impl>
963void
964InstructionQueue<Impl>::addIfReady(DynInstPtr &inst)
965{
966    //If the instruction now has all of its source registers
967    // available, then add it to the list of ready instructions.
968    if (inst->readyToIssue()) {
969
970        //Add the instruction to the proper ready list.
971        if (inst->isControl()) {
972
973            DPRINTF(IQ, "IQ: Branch instruction is ready to issue, "
974                    "putting it onto the ready list, PC %#x.\n",
975                    inst->readPC());
976            readyBranchInsts.push(inst);
977
978        } else if (inst->isMemRef()) {
979
980            DPRINTF(IQ, "IQ: Checking if memory instruction can issue.\n");
981
982            // Message to the mem dependence unit that this instruction has
983            // its registers ready.
984
985            memDepUnit.regsReady(inst);
986
987#if 0
988            if (memDepUnit.readyToIssue(inst)) {
989                DPRINTF(IQ, "IQ: Memory instruction is ready to issue, "
990                        "putting it onto the ready list, PC %#x.\n",
991                        inst->readPC());
992                readyMemInsts.push(inst);
993            } else {
994                // Make dependent on the store.
995                // Will need some way to get the store instruction it should
996                // be dependent upon; then when the store issues it can
997                // put the instruction on the ready list.
998                // Yet another tree?
999                assert(0 && "Instruction has no way to actually issue");
1000            }
1001#endif
1002
1003        } else if (inst->isInteger()) {
1004
1005            DPRINTF(IQ, "IQ: Integer instruction is ready to issue, "
1006                    "putting it onto the ready list, PC %#x.\n",
1007                    inst->readPC());
1008            readyIntInsts.push(inst);
1009
1010        } else if (inst->isFloating()) {
1011
1012            DPRINTF(IQ, "IQ: Floating instruction is ready to issue, "
1013                    "putting it onto the ready list, PC %#x.\n",
1014                    inst->readPC());
1015            readyFloatInsts.push(inst);
1016
1017        } else {
1018            DPRINTF(IQ, "IQ: Miscellaneous instruction is ready to issue, "
1019                    "putting it onto the ready list, PC %#x..\n",
1020                    inst->readPC());
1021
1022            readyMiscInsts.push(inst);
1023        }
1024    }
1025}
1026
1027template <class Impl>
1028int
1029InstructionQueue<Impl>::countInsts()
1030{
1031    ListIt count_it = cpu->instList.begin();
1032    int total_insts = 0;
1033
1034    while (count_it != tail) {
1035        if (!(*count_it)->isIssued()) {
1036            ++total_insts;
1037        }
1038
1039        ++count_it;
1040
1041        assert(count_it != cpu->instList.end());
1042    }
1043
1044    // Need to count the tail iterator as well.
1045    if (count_it != cpu->instList.end() &&
1046        (*count_it) &&
1047        !(*count_it)->isIssued()) {
1048        ++total_insts;
1049    }
1050
1051    return total_insts;
1052}
1053
1054template <class Impl>
1055void
1056InstructionQueue<Impl>::dumpLists()
1057{
1058    cprintf("Ready integer list size: %i\n", readyIntInsts.size());
1059
1060    cprintf("Ready float list size: %i\n", readyFloatInsts.size());
1061
1062    cprintf("Ready branch list size: %i\n", readyBranchInsts.size());
1063
1064//    cprintf("Ready memory list size: %i\n", readyMemInsts.size());
1065
1066    cprintf("Ready misc list size: %i\n", readyMiscInsts.size());
1067
1068    cprintf("Squashed list size: %i\n", squashedInsts.size());
1069
1070    cprintf("Non speculative list size: %i\n", nonSpecInsts.size());
1071
1072    non_spec_it_t non_spec_it = nonSpecInsts.begin();
1073
1074    cprintf("Non speculative list: ");
1075
1076    while (non_spec_it != nonSpecInsts.end()) {
1077        cprintf("%#x ", (*non_spec_it).second->readPC());
1078        ++non_spec_it;
1079    }
1080
1081    cprintf("\n");
1082
1083}
1084
1085#endif // __INST_QUEUE_IMPL_HH__
1086