inst_queue_impl.hh revision 2301
16167SN/A/*
26167SN/A * Copyright (c) 2004-2005 The Regents of The University of Michigan
36167SN/A * All rights reserved.
410036SAli.Saidi@ARM.com *
58835SAli.Saidi@ARM.com * Redistribution and use in source and binary forms, with or without
610036SAli.Saidi@ARM.com * modification, are permitted provided that the following conditions are
77935SN/A * met: redistributions of source code must retain the above copyright
87935SN/A * notice, this list of conditions and the following disclaimer;
97935SN/A * redistributions in binary form must reproduce the above copyright
106167SN/A * notice, this list of conditions and the following disclaimer in the
116167SN/A * documentation and/or other materials provided with the distribution;
126167SN/A * neither the name of the copyright holders nor the names of its
1310315Snilay@cs.wisc.edu * contributors may be used to endorse or promote products derived from
148835SAli.Saidi@ARM.com * this software without specific prior written permission.
159864Snilay@cs.wisc.edu *
169864Snilay@cs.wisc.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1710036SAli.Saidi@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
188835SAli.Saidi@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
198835SAli.Saidi@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2010315Snilay@cs.wisc.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
218835SAli.Saidi@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2210093Snilay@cs.wisc.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
237935SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
249864Snilay@cs.wisc.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
258540SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
268721SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
278835SAli.Saidi@ARM.com */
288835SAli.Saidi@ARM.com
297935SN/A// Todo:
307935SN/A// Current ordering allows for 0 cycle added-to-scheduled.  Could maybe fake
317935SN/A// it; either do in reverse order, or have added instructions put into a
327935SN/A// different ready queue that, in scheduleRreadyInsts(), gets put onto the
337935SN/A// normal ready queue.  This would however give only a one cycle delay,
347935SN/A// but probably is more flexible to actually add in a delay parameter than
357935SN/A// just running it backwards.
368983Snate@binkert.org
376167SN/A#include <limits>
389864Snilay@cs.wisc.edu#include <vector>
399864Snilay@cs.wisc.edu
409864Snilay@cs.wisc.edu#include "sim/root.hh"
4110315Snilay@cs.wisc.edu
4210036SAli.Saidi@ARM.com#include "cpu/o3/fu_pool.hh"
4310315Snilay@cs.wisc.edu#include "cpu/o3/inst_queue.hh"
449864Snilay@cs.wisc.edu
459864Snilay@cs.wisc.eduusing namespace std;
466167SN/A
476167SN/Atemplate <class Impl>
489864Snilay@cs.wisc.eduInstructionQueue<Impl>::FUCompletion::FUCompletion(DynInstPtr &_inst,
4910093Snilay@cs.wisc.edu                                                   int fu_idx,
506167SN/A                                                   InstructionQueue<Impl> *iq_ptr)
519864Snilay@cs.wisc.edu    : Event(&mainEventQueue, Stat_Event_Pri),
526167SN/A      inst(_inst), fuIdx(fu_idx), iqPtr(iq_ptr)
536167SN/A{
548835SAli.Saidi@ARM.com    this->setFlags(Event::AutoDelete);
556167SN/A}
566167SN/A
5710036SAli.Saidi@ARM.comtemplate <class Impl>
586167SN/Avoid
596167SN/AInstructionQueue<Impl>::FUCompletion::process()
608835SAli.Saidi@ARM.com{
619469Snilay@cs.wisc.edu    iqPtr->processFUCompletion(inst, fuIdx);
626167SN/A    inst = NULL;
636167SN/A}
646167SN/A
656167SN/A
666167SN/Atemplate <class Impl>
676167SN/Aconst char *
688835SAli.Saidi@ARM.comInstructionQueue<Impl>::FUCompletion::description()
696167SN/A{
709864Snilay@cs.wisc.edu    return "Functional unit completion event";
7110229Snilay@cs.wisc.edu}
729469Snilay@cs.wisc.edu
736167SN/Atemplate <class Impl>
746167SN/AInstructionQueue<Impl>::InstructionQueue(Params *params)
756167SN/A    : dcacheInterface(params->dcacheInterface),
769469Snilay@cs.wisc.edu      fuPool(params->fuPool),
779469Snilay@cs.wisc.edu      numEntries(params->numIQEntries),
786167SN/A      totalWidth(params->issueWidth),
799864Snilay@cs.wisc.edu      numPhysIntRegs(params->numPhysIntRegs),
809864Snilay@cs.wisc.edu      numPhysFloatRegs(params->numPhysFloatRegs),
819864Snilay@cs.wisc.edu      commitToIEWDelay(params->commitToIEWDelay)
8210315Snilay@cs.wisc.edu{
8310036SAli.Saidi@ARM.com    assert(fuPool);
8410315Snilay@cs.wisc.edu
859864Snilay@cs.wisc.edu    numThreads = params->numberOfThreads;
869864Snilay@cs.wisc.edu
876167SN/A    //Initialize thread IQ counts
886167SN/A    for (int i = 0; i <numThreads; i++) {
8910036SAli.Saidi@ARM.com        count[i] = 0;
906167SN/A    }
916167SN/A
928835SAli.Saidi@ARM.com    // Initialize the number of free IQ entries.
938835SAli.Saidi@ARM.com    freeEntries = numEntries;
9410036SAli.Saidi@ARM.com
958835SAli.Saidi@ARM.com    // Set the number of physical registers as the number of int + float
969469Snilay@cs.wisc.edu    numPhysRegs = numPhysIntRegs + numPhysFloatRegs;
979469Snilay@cs.wisc.edu
9810036SAli.Saidi@ARM.com    DPRINTF(IQ, "There are %i physical registers.\n", numPhysRegs);
999469Snilay@cs.wisc.edu
1009469Snilay@cs.wisc.edu    //Create an entry for each physical register within the
10110036SAli.Saidi@ARM.com    //dependency graph.
1029469Snilay@cs.wisc.edu    dependGraph = new DependencyEntry[numPhysRegs];
1036167SN/A
1046167SN/A    // Resize the register scoreboard.
10510036SAli.Saidi@ARM.com    regScoreboard.resize(numPhysRegs);
1066167SN/A
1076167SN/A    //Initialize Mem Dependence Units
1086167SN/A    for (int i = 0; i < numThreads; i++) {
1096167SN/A        memDepUnit[i].init(params,i);
11010036SAli.Saidi@ARM.com        memDepUnit[i].setIQ(this);
1116167SN/A    }
1126167SN/A
1136167SN/A    // Initialize all the head pointers to point to NULL, and all the
1146167SN/A    // entries as unready.
1156167SN/A    // Note that in actuality, the registers corresponding to the logical
1166167SN/A    // registers start off as ready.  However this doesn't matter for the
1176167SN/A    // IQ as the instruction should have been correctly told if those
1186167SN/A    // registers are ready in rename.  Thus it can all be initialized as
1196167SN/A    // unready.
12010036SAli.Saidi@ARM.com    for (int i = 0; i < numPhysRegs; ++i) {
12110229Snilay@cs.wisc.edu        dependGraph[i].next = NULL;
1226167SN/A        dependGraph[i].inst = NULL;
1236167SN/A        regScoreboard[i] = false;
1246167SN/A    }
1256167SN/A
1266167SN/A    for (int i = 0; i < numThreads; ++i) {
1276167SN/A        squashedSeqNum[i] = 0;
1286167SN/A    }
1296167SN/A
1306167SN/A    for (int i = 0; i < Num_OpClasses; ++i) {
13110451Snilay@cs.wisc.edu        queueOnList[i] = false;
1326167SN/A        readyIt[i] = listOrder.end();
13310315Snilay@cs.wisc.edu    }
13410315Snilay@cs.wisc.edu
13510315Snilay@cs.wisc.edu    string policy = params->smtIQPolicy;
13610315Snilay@cs.wisc.edu
13710315Snilay@cs.wisc.edu    //Convert string to lowercase
13810315Snilay@cs.wisc.edu    std::transform(policy.begin(), policy.end(), policy.begin(),
13910315Snilay@cs.wisc.edu                   (int(*)(int)) tolower);
14010315Snilay@cs.wisc.edu
1419469Snilay@cs.wisc.edu    //Figure out resource sharing policy
1429469Snilay@cs.wisc.edu    if (policy == "dynamic") {
1439469Snilay@cs.wisc.edu        iqPolicy = Dynamic;
1449864Snilay@cs.wisc.edu
1459864Snilay@cs.wisc.edu        //Set Max Entries to Total ROB Capacity
14610036SAli.Saidi@ARM.com        for (int i = 0; i < numThreads; i++) {
1479469Snilay@cs.wisc.edu            maxEntries[i] = numEntries;
1489469Snilay@cs.wisc.edu        }
1499469Snilay@cs.wisc.edu
1509578Snilay@cs.wisc.edu    } else if (policy == "partitioned") {
1519469Snilay@cs.wisc.edu        iqPolicy = Partitioned;
1529469Snilay@cs.wisc.edu
1539469Snilay@cs.wisc.edu        //@todo:make work if part_amt doesnt divide evenly.
1549469Snilay@cs.wisc.edu        int part_amt = numEntries / numThreads;
15510036SAli.Saidi@ARM.com
15610036SAli.Saidi@ARM.com        //Divide ROB up evenly
1579469Snilay@cs.wisc.edu        for (int i = 0; i < numThreads; i++) {
1589864Snilay@cs.wisc.edu            maxEntries[i] = part_amt;
15910036SAli.Saidi@ARM.com        }
16010036SAli.Saidi@ARM.com
1619864Snilay@cs.wisc.edu        DPRINTF(Fetch, "IQ sharing policy set to Partitioned:"
1629469Snilay@cs.wisc.edu                "%i entries per thread.\n",part_amt);
16310036SAli.Saidi@ARM.com
1649469Snilay@cs.wisc.edu    } else if (policy == "threshold") {
1659469Snilay@cs.wisc.edu        iqPolicy = Threshold;
1669469Snilay@cs.wisc.edu
1679864Snilay@cs.wisc.edu        double threshold =  (double)params->smtIQThreshold / 100;
1689864Snilay@cs.wisc.edu
1699864Snilay@cs.wisc.edu        int thresholdIQ = (int)((double)threshold * numEntries);
17010315Snilay@cs.wisc.edu
17110036SAli.Saidi@ARM.com        //Divide up by threshold amount
17210315Snilay@cs.wisc.edu        for (int i = 0; i < numThreads; i++) {
1739864Snilay@cs.wisc.edu            maxEntries[i] = thresholdIQ;
1749864Snilay@cs.wisc.edu        }
1759469Snilay@cs.wisc.edu
1766928SN/A        DPRINTF(Fetch, "IQ sharing policy set to Threshold:"
1776928SN/A                "%i entries per thread.\n",thresholdIQ);
1786928SN/A   } else {
1799864Snilay@cs.wisc.edu       assert(0 && "Invalid IQ Sharing Policy.Options Are:{Dynamic,"
18010036SAli.Saidi@ARM.com              "Partitioned, Threshold}");
1819469Snilay@cs.wisc.edu   }
1826928SN/A}
18310036SAli.Saidi@ARM.com
1849469Snilay@cs.wisc.edutemplate <class Impl>
1856928SN/AInstructionQueue<Impl>::~InstructionQueue()
1869605Snilay@cs.wisc.edu{
1876928SN/A    // Clear the dependency graph
1888540SN/A    DependencyEntry *curr;
1899864Snilay@cs.wisc.edu    DependencyEntry *prev;
1906928SN/A
19110315Snilay@cs.wisc.edu    for (int i = 0; i < numPhysRegs; ++i) {
19210315Snilay@cs.wisc.edu        curr = dependGraph[i].next;
19310315Snilay@cs.wisc.edu
19410315Snilay@cs.wisc.edu        while (curr) {
19510315Snilay@cs.wisc.edu            DependencyEntry::mem_alloc_counter--;
1966928SN/A
1979469Snilay@cs.wisc.edu            prev = curr;
1986928SN/A            curr = prev->next;
19910036SAli.Saidi@ARM.com            prev->inst = NULL;
2007935SN/A
2019469Snilay@cs.wisc.edu            delete prev;
2029864Snilay@cs.wisc.edu        }
2037935SN/A
2046928SN/A        if (dependGraph[i].inst) {
2056928SN/A            dependGraph[i].inst = NULL;
2069469Snilay@cs.wisc.edu        }
2076928SN/A
2086928SN/A        dependGraph[i].next = NULL;
2096928SN/A    }
2106928SN/A
2116928SN/A    assert(DependencyEntry::mem_alloc_counter == 0);
2126928SN/A
2139864Snilay@cs.wisc.edu    delete [] dependGraph;
2146928SN/A}
2156928SN/A
21610036SAli.Saidi@ARM.comtemplate <class Impl>
2176928SN/Astd::string
2186928SN/AInstructionQueue<Impl>::name() const
2196928SN/A{
2206928SN/A    return cpu->name() + ".iq";
2216928SN/A}
2226928SN/A
2236928SN/Atemplate <class Impl>
2246928SN/Avoid
2259207Snilay@cs.wisc.eduInstructionQueue<Impl>::regStats()
2266928SN/A{
2276928SN/A    using namespace Stats;
2286928SN/A    iqInstsAdded
2299469Snilay@cs.wisc.edu        .name(name() + ".iqInstsAdded")
2307935SN/A        .desc("Number of instructions added to the IQ (excludes non-spec)")
2318540SN/A        .prereq(iqInstsAdded);
2327935SN/A
2339469Snilay@cs.wisc.edu    iqNonSpecInstsAdded
2347935SN/A        .name(name() + ".iqNonSpecInstsAdded")
23510315Snilay@cs.wisc.edu        .desc("Number of non-speculative instructions added to the IQ")
23610036SAli.Saidi@ARM.com        .prereq(iqNonSpecInstsAdded);
23710036SAli.Saidi@ARM.com
2387935SN/A//    iqIntInstsAdded;
2397935SN/A
2409605Snilay@cs.wisc.edu    iqInstsIssued
2417935SN/A        .name(name() + ".iqInstsIssued")
2428540SN/A        .desc("Number of instructions issued")
2438835SAli.Saidi@ARM.com        .prereq(iqInstsIssued);
2449469Snilay@cs.wisc.edu
2459864Snilay@cs.wisc.edu    iqIntInstsIssued
2467935SN/A        .name(name() + ".iqIntInstsIssued")
24710315Snilay@cs.wisc.edu        .desc("Number of integer instructions issued")
24810315Snilay@cs.wisc.edu        .prereq(iqIntInstsIssued);
24910315Snilay@cs.wisc.edu
25010315Snilay@cs.wisc.edu//    iqFloatInstsAdded;
2517935SN/A
2529469Snilay@cs.wisc.edu    iqFloatInstsIssued
2538540SN/A        .name(name() + ".iqFloatInstsIssued")
2548540SN/A        .desc("Number of float instructions issued")
2559113SBrad.Beckmann@amd.com        .prereq(iqFloatInstsIssued);
2569113SBrad.Beckmann@amd.com
25710036SAli.Saidi@ARM.com//    iqBranchInstsAdded;
2588721SN/A
2598540SN/A    iqBranchInstsIssued
2608540SN/A        .name(name() + ".iqBranchInstsIssued")
2619113SBrad.Beckmann@amd.com        .desc("Number of branch instructions issued")
2628540SN/A        .prereq(iqBranchInstsIssued);
2638540SN/A
2649113SBrad.Beckmann@amd.com//    iqMemInstsAdded;
2659113SBrad.Beckmann@amd.com
2668540SN/A    iqMemInstsIssued
2679469Snilay@cs.wisc.edu        .name(name() + ".iqMemInstsIssued")
2688540SN/A        .desc("Number of memory instructions issued")
2699578Snilay@cs.wisc.edu        .prereq(iqMemInstsIssued);
27010315Snilay@cs.wisc.edu
2719469Snilay@cs.wisc.edu//    iqMiscInstsAdded;
2728540SN/A
27310036SAli.Saidi@ARM.com    iqMiscInstsIssued
2749469Snilay@cs.wisc.edu        .name(name() + ".iqMiscInstsIssued")
2758540SN/A        .desc("Number of miscellaneous instructions issued")
2768540SN/A        .prereq(iqMiscInstsIssued);
2778983Snate@binkert.org
2788983Snate@binkert.org    iqSquashedInstsIssued
2798983Snate@binkert.org        .name(name() + ".iqSquashedInstsIssued")
2808540SN/A        .desc("Number of squashed instructions issued")
2818540SN/A        .prereq(iqSquashedInstsIssued);
2828540SN/A
2838983Snate@binkert.org    iqSquashedInstsExamined
2848540SN/A        .name(name() + ".iqSquashedInstsExamined")
2859864Snilay@cs.wisc.edu        .desc("Number of squashed instructions iterated over during squash;"
2869864Snilay@cs.wisc.edu              " mainly for profiling")
2879864Snilay@cs.wisc.edu        .prereq(iqSquashedInstsExamined);
2889864Snilay@cs.wisc.edu
28910036SAli.Saidi@ARM.com    iqSquashedOperandsExamined
2909864Snilay@cs.wisc.edu        .name(name() + ".iqSquashedOperandsExamined")
2917935SN/A        .desc("Number of squashed operands that are examined and possibly "
2927935SN/A              "removed from graph")
2939864Snilay@cs.wisc.edu        .prereq(iqSquashedOperandsExamined);
2947935SN/A
2957935SN/A    iqSquashedNonSpecRemoved
2969864Snilay@cs.wisc.edu        .name(name() + ".iqSquashedNonSpecRemoved")
2977935SN/A        .desc("Number of squashed non-spec instructions that were removed")
2988540SN/A        .prereq(iqSquashedNonSpecRemoved);
29910036SAli.Saidi@ARM.com
3009605Snilay@cs.wisc.edu    queue_res_dist
3019605Snilay@cs.wisc.edu        .init(Num_OpClasses, 0, 99, 2)
30210229Snilay@cs.wisc.edu        .name(name() + ".IQ:residence:")
3037935SN/A        .desc("cycles from dispatch to issue")
3049864Snilay@cs.wisc.edu        .flags(total | pdf | cdf )
3058540SN/A        ;
3069605Snilay@cs.wisc.edu    for (int i = 0; i < Num_OpClasses; ++i) {
30710315Snilay@cs.wisc.edu        queue_res_dist.subname(i, opClassStrings[i]);
30810315Snilay@cs.wisc.edu    }
3097935SN/A    n_issued_dist
3109605Snilay@cs.wisc.edu        .init(totalWidth + 1)
3118540SN/A        .name(name() + ".ISSUE:issued_per_cycle")
3128540SN/A        .desc("Number of insts issued each cycle")
31310036SAli.Saidi@ARM.com        .flags(total | pdf | dist)
3149469Snilay@cs.wisc.edu        ;
3159864Snilay@cs.wisc.edu/*
3167935SN/A    dist_unissued
3178540SN/A        .init(Num_OpClasses+2)
3187935SN/A        .name(name() + ".ISSUE:unissued_cause")
3197935SN/A        .desc("Reason ready instruction not issued")
3209605Snilay@cs.wisc.edu        .flags(pdf | dist)
3218540SN/A        ;
3228540SN/A    for (int i=0; i < (Num_OpClasses + 2); ++i) {
32310036SAli.Saidi@ARM.com        dist_unissued.subname(i, unissued_names[i]);
3249469Snilay@cs.wisc.edu    }
3259864Snilay@cs.wisc.edu*/
3267935SN/A    stat_issued_inst_type
3278540SN/A        .init(numThreads,Num_OpClasses)
3287935SN/A        .name(name() + ".ISSUE:FU_type")
3297935SN/A        .desc("Type of FU issued")
3309605Snilay@cs.wisc.edu        .flags(total | pdf | dist)
3318540SN/A        ;
3328540SN/A    stat_issued_inst_type.ysubnames(opClassStrings);
33310036SAli.Saidi@ARM.com
3346928SN/A    //
3358540SN/A    //  How long did instructions for a particular FU type wait prior to issue
3369864Snilay@cs.wisc.edu    //
3379864Snilay@cs.wisc.edu
3386928SN/A    issue_delay_dist
3396928SN/A        .init(Num_OpClasses,0,99,2)
3409605Snilay@cs.wisc.edu        .name(name() + ".ISSUE:")
3418540SN/A        .desc("cycles from operands ready to issue")
3428540SN/A        .flags(pdf | cdf)
34310036SAli.Saidi@ARM.com        ;
3446928SN/A
3458540SN/A    for (int i=0; i<Num_OpClasses; ++i) {
3469864Snilay@cs.wisc.edu        stringstream subname;
3479864Snilay@cs.wisc.edu        subname << opClassStrings[i] << "_delay";
3486928SN/A        issue_delay_dist.subname(i, subname.str());
3496928SN/A    }
3509864Snilay@cs.wisc.edu
3519864Snilay@cs.wisc.edu    issue_rate
3529864Snilay@cs.wisc.edu        .name(name() + ".ISSUE:rate")
35310036SAli.Saidi@ARM.com        .desc("Inst issue rate")
3549864Snilay@cs.wisc.edu        .flags(total)
3559864Snilay@cs.wisc.edu        ;
3569864Snilay@cs.wisc.edu    issue_rate = iqInstsIssued / cpu->numCycles;
3579864Snilay@cs.wisc.edu/*
3589864Snilay@cs.wisc.edu    issue_stores
3599864Snilay@cs.wisc.edu        .name(name() + ".ISSUE:stores")
36010036SAli.Saidi@ARM.com        .desc("Number of stores issued")
3619864Snilay@cs.wisc.edu        .flags(total)
3629864Snilay@cs.wisc.edu        ;
3639864Snilay@cs.wisc.edu    issue_stores = exe_refs - exe_loads;
3649864Snilay@cs.wisc.edu*/
3659864Snilay@cs.wisc.edu/*
3669864Snilay@cs.wisc.edu    issue_op_rate
36710036SAli.Saidi@ARM.com        .name(name() + ".ISSUE:op_rate")
3689864Snilay@cs.wisc.edu        .desc("Operation issue rate")
3699864Snilay@cs.wisc.edu        .flags(total)
3709864Snilay@cs.wisc.edu        ;
3718721SN/A    issue_op_rate = issued_ops / numCycles;
3728721SN/A*/
3738721SN/A    stat_fu_busy
3749864Snilay@cs.wisc.edu        .init(Num_OpClasses)
37510036SAli.Saidi@ARM.com        .name(name() + ".ISSUE:fu_full")
3768540SN/A        .desc("attempts to use FU when none available")
3778983Snate@binkert.org        .flags(pdf | dist)
3788983Snate@binkert.org        ;
3798983Snate@binkert.org    for (int i=0; i < Num_OpClasses; ++i) {
3808721SN/A        stat_fu_busy.subname(i, opClassStrings[i]);
3818721SN/A    }
3828983Snate@binkert.org
3836928SN/A    fu_busy
3849864Snilay@cs.wisc.edu        .init(numThreads)
3859864Snilay@cs.wisc.edu        .name(name() + ".ISSUE:fu_busy_cnt")
38610036SAli.Saidi@ARM.com        .desc("FU busy when requested")
3879864Snilay@cs.wisc.edu        .flags(total)
3889864Snilay@cs.wisc.edu        ;
389
390    fu_busy_rate
391        .name(name() + ".ISSUE:fu_busy_rate")
392        .desc("FU busy rate (busy events/executed inst)")
393        .flags(total)
394        ;
395    fu_busy_rate = fu_busy / iqInstsIssued;
396
397    for ( int i=0; i < numThreads; i++) {
398        // Tell mem dependence unit to reg stats as well.
399        memDepUnit[i].regStats();
400    }
401}
402
403template <class Impl>
404void
405InstructionQueue<Impl>::setActiveThreads(list<unsigned> *at_ptr)
406{
407    DPRINTF(IQ, "Setting active threads list pointer.\n");
408    activeThreads = at_ptr;
409}
410
411template <class Impl>
412void
413InstructionQueue<Impl>::setIssueToExecuteQueue(TimeBuffer<IssueStruct> *i2e_ptr)
414{
415    DPRINTF(IQ, "Set the issue to execute queue.\n");
416    issueToExecuteQueue = i2e_ptr;
417}
418
419template <class Impl>
420void
421InstructionQueue<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
422{
423    DPRINTF(IQ, "Set the time buffer.\n");
424    timeBuffer = tb_ptr;
425
426    fromCommit = timeBuffer->getWire(-commitToIEWDelay);
427}
428
429template <class Impl>
430int
431InstructionQueue<Impl>::entryAmount(int num_threads)
432{
433    if (iqPolicy == Partitioned) {
434        return numEntries / num_threads;
435    } else {
436        return 0;
437    }
438}
439
440
441template <class Impl>
442void
443InstructionQueue<Impl>::resetEntries()
444{
445    if (iqPolicy != Dynamic || numThreads > 1) {
446        int active_threads = (*activeThreads).size();
447
448        list<unsigned>::iterator threads  = (*activeThreads).begin();
449        list<unsigned>::iterator list_end = (*activeThreads).end();
450
451        while (threads != list_end) {
452            if (iqPolicy == Partitioned) {
453                maxEntries[*threads++] = numEntries / active_threads;
454            } else if(iqPolicy == Threshold && active_threads == 1) {
455                maxEntries[*threads++] = numEntries;
456            }
457        }
458    }
459}
460
461template <class Impl>
462unsigned
463InstructionQueue<Impl>::numFreeEntries()
464{
465    return freeEntries;
466}
467
468template <class Impl>
469unsigned
470InstructionQueue<Impl>::numFreeEntries(unsigned tid)
471{
472    return maxEntries[tid] - count[tid];
473}
474
475// Might want to do something more complex if it knows how many instructions
476// will be issued this cycle.
477template <class Impl>
478bool
479InstructionQueue<Impl>::isFull()
480{
481    if (freeEntries == 0) {
482        return(true);
483    } else {
484        return(false);
485    }
486}
487
488template <class Impl>
489bool
490InstructionQueue<Impl>::isFull(unsigned tid)
491{
492    if (numFreeEntries(tid) == 0) {
493        return(true);
494    } else {
495        return(false);
496    }
497}
498
499template <class Impl>
500bool
501InstructionQueue<Impl>::hasReadyInsts()
502{
503    if (!listOrder.empty()) {
504        return true;
505    }
506
507    for (int i = 0; i < Num_OpClasses; ++i) {
508        if (!readyInsts[i].empty()) {
509            return true;
510        }
511    }
512
513    return false;
514}
515
516template <class Impl>
517void
518InstructionQueue<Impl>::insert(DynInstPtr &new_inst)
519{
520    // Make sure the instruction is valid
521    assert(new_inst);
522
523    DPRINTF(IQ, "Adding instruction PC %#x to the IQ.\n",
524            new_inst->readPC());
525
526    // Check if there are any free entries.  Panic if there are none.
527    // Might want to have this return a fault in the future instead of
528    // panicing.
529    assert(freeEntries != 0);
530
531    instList[new_inst->threadNumber].push_back(new_inst);
532
533    // Decrease the number of free entries.
534    --freeEntries;
535
536    //Mark Instruction as in IQ
537    new_inst->setInIQ();
538
539    // Look through its source registers (physical regs), and mark any
540    // dependencies.
541    addToDependents(new_inst);
542
543    // Have this instruction set itself as the producer of its destination
544    // register(s).
545    createDependency(new_inst);
546
547    // If it's a memory instruction, add it to the memory dependency
548    // unit.
549    if (new_inst->isMemRef()) {
550        memDepUnit[new_inst->threadNumber].insert(new_inst);
551    } else {
552        // If the instruction is ready then add it to the ready list.
553        addIfReady(new_inst);
554    }
555
556    ++iqInstsAdded;
557
558
559    //Update Thread IQ Count
560    count[new_inst->threadNumber]++;
561
562    assert(freeEntries == (numEntries - countInsts()));
563}
564
565template <class Impl>
566void
567InstructionQueue<Impl>::insertNonSpec(DynInstPtr &new_inst)
568{
569    // @todo: Clean up this code; can do it by setting inst as unable
570    // to issue, then calling normal insert on the inst.
571
572    // Make sure the instruction is valid
573    assert(new_inst);
574
575    nonSpecInsts[new_inst->seqNum] = new_inst;
576
577    DPRINTF(IQ, "Adding instruction PC %#x to the IQ.\n",
578            new_inst->readPC());
579
580    // Check if there are any free entries.  Panic if there are none.
581    // Might want to have this return a fault in the future instead of
582    // panicing.
583    assert(freeEntries != 0);
584
585    instList[new_inst->threadNumber].push_back(new_inst);
586
587    // Decrease the number of free entries.
588    --freeEntries;
589
590    //Mark Instruction as in IQ
591    new_inst->setInIQ();
592
593    // Have this instruction set itself as the producer of its destination
594    // register(s).
595    createDependency(new_inst);
596
597    // If it's a memory instruction, add it to the memory dependency
598    // unit.
599    if (new_inst->isMemRef()) {
600        memDepUnit[new_inst->threadNumber].insertNonSpec(new_inst);
601    }
602
603    ++iqNonSpecInstsAdded;
604
605    //Update Thread IQ Count
606    count[new_inst->threadNumber]++;
607
608    assert(freeEntries == (numEntries - countInsts()));
609}
610
611template <class Impl>
612void
613InstructionQueue<Impl>::insertBarrier(DynInstPtr &barr_inst)
614{
615    memDepUnit[barr_inst->threadNumber].insertBarrier(barr_inst);
616
617    insertNonSpec(barr_inst);
618}
619
620template <class Impl>
621void
622InstructionQueue<Impl>::advanceTail(DynInstPtr &inst)
623{
624    // Have this instruction set itself as the producer of its destination
625    // register(s).
626    createDependency(inst);
627}
628
629template <class Impl>
630void
631InstructionQueue<Impl>::addToOrderList(OpClass op_class)
632{
633    assert(!readyInsts[op_class].empty());
634
635    ListOrderEntry queue_entry;
636
637    queue_entry.queueType = op_class;
638
639    queue_entry.oldestInst = readyInsts[op_class].top()->seqNum;
640
641    ListOrderIt list_it = listOrder.begin();
642    ListOrderIt list_end_it = listOrder.end();
643
644    while (list_it != list_end_it) {
645        if ((*list_it).oldestInst > queue_entry.oldestInst) {
646            break;
647        }
648
649        list_it++;
650    }
651
652    readyIt[op_class] = listOrder.insert(list_it, queue_entry);
653    queueOnList[op_class] = true;
654}
655
656template <class Impl>
657void
658InstructionQueue<Impl>::moveToYoungerInst(ListOrderIt list_order_it)
659{
660    // Get iterator of next item on the list
661    // Delete the original iterator
662    // Determine if the next item is either the end of the list or younger
663    // than the new instruction.  If so, then add in a new iterator right here.
664    // If not, then move along.
665    ListOrderEntry queue_entry;
666    OpClass op_class = (*list_order_it).queueType;
667    ListOrderIt next_it = list_order_it;
668
669    ++next_it;
670
671    queue_entry.queueType = op_class;
672    queue_entry.oldestInst = readyInsts[op_class].top()->seqNum;
673
674    while (next_it != listOrder.end() &&
675           (*next_it).oldestInst < queue_entry.oldestInst) {
676        ++next_it;
677    }
678
679    readyIt[op_class] = listOrder.insert(next_it, queue_entry);
680}
681
682template <class Impl>
683void
684InstructionQueue<Impl>::processFUCompletion(DynInstPtr &inst, int fu_idx)
685{
686    // The CPU could have been sleeping until this op completed (*extremely*
687    // long latency op).  Wake it if it was.  This may be overkill.
688    iewStage->wakeCPU();
689
690    fuPool->freeUnit(fu_idx);
691
692    int &size = issueToExecuteQueue->access(0)->size;
693
694    issueToExecuteQueue->access(0)->insts[size++] = inst;
695}
696
697// @todo: Figure out a better way to remove the squashed items from the
698// lists.  Checking the top item of each list to see if it's squashed
699// wastes time and forces jumps.
700template <class Impl>
701void
702InstructionQueue<Impl>::scheduleReadyInsts()
703{
704    DPRINTF(IQ, "Attempting to schedule ready instructions from "
705            "the IQ.\n");
706
707    IssueStruct *i2e_info = issueToExecuteQueue->access(0);
708
709    // Will need to reorder the list if either a queue is not on the list,
710    // or it has an older instruction than last time.
711    for (int i = 0; i < Num_OpClasses; ++i) {
712        if (!readyInsts[i].empty()) {
713            if (!queueOnList[i]) {
714                addToOrderList(OpClass(i));
715            } else if (readyInsts[i].top()->seqNum  <
716                       (*readyIt[i]).oldestInst) {
717                listOrder.erase(readyIt[i]);
718                addToOrderList(OpClass(i));
719            }
720        }
721    }
722
723    // Have iterator to head of the list
724    // While I haven't exceeded bandwidth or reached the end of the list,
725    // Try to get a FU that can do what this op needs.
726    // If successful, change the oldestInst to the new top of the list, put
727    // the queue in the proper place in the list.
728    // Increment the iterator.
729    // This will avoid trying to schedule a certain op class if there are no
730    // FUs that handle it.
731    ListOrderIt order_it = listOrder.begin();
732    ListOrderIt order_end_it = listOrder.end();
733    int total_issued = 0;
734    int exec_queue_slot = i2e_info->size;
735
736    while (exec_queue_slot < totalWidth && order_it != order_end_it) {
737        OpClass op_class = (*order_it).queueType;
738
739        assert(!readyInsts[op_class].empty());
740
741        DynInstPtr issuing_inst = readyInsts[op_class].top();
742
743        assert(issuing_inst->seqNum == (*order_it).oldestInst);
744
745        if (issuing_inst->isSquashed()) {
746            readyInsts[op_class].pop();
747
748            if (!readyInsts[op_class].empty()) {
749                moveToYoungerInst(order_it);
750            } else {
751                readyIt[op_class] = listOrder.end();
752                queueOnList[op_class] = false;
753            }
754
755            listOrder.erase(order_it++);
756
757            ++iqSquashedInstsIssued;
758
759            continue;
760        }
761
762        int idx = fuPool->getUnit(op_class);
763
764        int tid = issuing_inst->threadNumber;
765
766        if (idx == -2) {
767            assert(op_class == No_OpClass);
768
769            i2e_info->insts[exec_queue_slot++] = issuing_inst;
770            i2e_info->size++;
771
772            DPRINTF(IQ, "Thread %i: Issuing instruction PC that needs no FU"
773                    " %#x [sn:%lli]\n",
774                    tid, issuing_inst->readPC(),
775                    issuing_inst->seqNum);
776
777            readyInsts[op_class].pop();
778
779            if (!readyInsts[op_class].empty()) {
780                moveToYoungerInst(order_it);
781            } else {
782                readyIt[op_class] = listOrder.end();
783                queueOnList[op_class] = false;
784            }
785
786            issuing_inst->setIssued();
787            ++total_issued;
788
789            if (!issuing_inst->isMemRef()) {
790                // Memory instructions can not be freed from the IQ until they
791                // complete.
792                ++freeEntries;
793                count[tid]--;
794                issuing_inst->removeInIQ();
795            } else {
796                memDepUnit[tid].issue(issuing_inst);
797            }
798
799            listOrder.erase(order_it++);
800
801            stat_issued_inst_type[tid][op_class]++;
802        } else if (idx != -1) {
803            int op_latency = fuPool->getOpLatency(op_class);
804
805            if (op_latency == 1) {
806                i2e_info->insts[exec_queue_slot++] = issuing_inst;
807                i2e_info->size++;
808
809                // Add the FU onto the list of FU's to be freed next cycle.
810                fuPool->freeUnit(idx);
811            } else {
812                int issue_latency = fuPool->getIssueLatency(op_class);
813
814                if (issue_latency > 1) {
815                    // Generate completion event for the FU
816                    FUCompletion *execution = new FUCompletion(issuing_inst,
817                                                               idx, this);
818
819                    execution->schedule(curTick + issue_latency - 1);
820                } else {
821                    i2e_info->insts[exec_queue_slot++] = issuing_inst;
822                    i2e_info->size++;
823
824                    // Add the FU onto the list of FU's to be freed next cycle.
825                    fuPool->freeUnit(idx);
826                }
827            }
828
829            DPRINTF(IQ, "Thread %i: Issuing instruction PC %#x "
830                    "[sn:%lli]\n",
831                    tid, issuing_inst->readPC(),
832                    issuing_inst->seqNum);
833
834            readyInsts[op_class].pop();
835
836            if (!readyInsts[op_class].empty()) {
837                moveToYoungerInst(order_it);
838            } else {
839                readyIt[op_class] = listOrder.end();
840                queueOnList[op_class] = false;
841            }
842
843            issuing_inst->setIssued();
844            ++total_issued;
845
846            if (!issuing_inst->isMemRef()) {
847                // Memory instructions can not be freed from the IQ until they
848                // complete.
849                ++freeEntries;
850                count[tid]--;
851                issuing_inst->removeInIQ();
852            } else {
853                memDepUnit[tid].issue(issuing_inst);
854            }
855
856            listOrder.erase(order_it++);
857            stat_issued_inst_type[tid][op_class]++;
858        } else {
859            stat_fu_busy[op_class]++;
860            fu_busy[tid]++;
861            ++order_it;
862        }
863    }
864
865    if (total_issued) {
866        cpu->activityThisCycle();
867    } else {
868        DPRINTF(IQ, "Not able to schedule any instructions.\n");
869    }
870}
871
872template <class Impl>
873void
874InstructionQueue<Impl>::scheduleNonSpec(const InstSeqNum &inst)
875{
876    DPRINTF(IQ, "Marking nonspeculative instruction [sn:%lli] as ready "
877            "to execute.\n", inst);
878
879    NonSpecMapIt inst_it = nonSpecInsts.find(inst);
880
881    assert(inst_it != nonSpecInsts.end());
882
883    unsigned tid = (*inst_it).second->threadNumber;
884
885    // Mark this instruction as ready to issue.
886    (*inst_it).second->setCanIssue();
887
888    // Now schedule the instruction.
889    if (!(*inst_it).second->isMemRef()) {
890        addIfReady((*inst_it).second);
891    } else {
892        memDepUnit[tid].nonSpecInstReady((*inst_it).second);
893    }
894
895    (*inst_it).second = NULL;
896
897    nonSpecInsts.erase(inst_it);
898}
899
900template <class Impl>
901void
902InstructionQueue<Impl>::commit(const InstSeqNum &inst, unsigned tid)
903{
904    /*Need to go through each thread??*/
905    DPRINTF(IQ, "[tid:%i]: Committing instructions older than [sn:%i]\n",
906            tid,inst);
907
908    ListIt iq_it = instList[tid].begin();
909
910    while (iq_it != instList[tid].end() &&
911           (*iq_it)->seqNum <= inst) {
912        ++iq_it;
913        instList[tid].pop_front();
914    }
915
916    assert(freeEntries == (numEntries - countInsts()));
917}
918
919template <class Impl>
920int
921InstructionQueue<Impl>::wakeDependents(DynInstPtr &completed_inst)
922{
923    int dependents = 0;
924
925    DPRINTF(IQ, "Waking dependents of completed instruction.\n");
926
927    assert(!completed_inst->isSquashed());
928    // Look at the physical destination register of the DynInst
929    // and look it up on the dependency graph.  Then mark as ready
930    // any instructions within the instruction queue.
931    DependencyEntry *curr;
932    DependencyEntry *prev;
933
934    // Tell the memory dependence unit to wake any dependents on this
935    // instruction if it is a memory instruction.  Also complete the memory
936    // instruction at this point since we know it executed fine.
937    // @todo: Might want to rename "completeMemInst" to
938    // something that indicates that it won't need to be replayed, and call
939    // this earlier.  Might not be a big deal.
940    if (completed_inst->isMemRef()) {
941        memDepUnit[completed_inst->threadNumber].wakeDependents(completed_inst);
942        completeMemInst(completed_inst);
943    } else if (completed_inst->isMemBarrier() ||
944               completed_inst->isWriteBarrier()) {
945        memDepUnit[completed_inst->threadNumber].completeBarrier(completed_inst);
946    }
947
948    for (int dest_reg_idx = 0;
949         dest_reg_idx < completed_inst->numDestRegs();
950         dest_reg_idx++)
951    {
952        PhysRegIndex dest_reg =
953            completed_inst->renamedDestRegIdx(dest_reg_idx);
954
955        // Special case of uniq or control registers.  They are not
956        // handled by the IQ and thus have no dependency graph entry.
957        // @todo Figure out a cleaner way to handle this.
958        if (dest_reg >= numPhysRegs) {
959            continue;
960        }
961
962        DPRINTF(IQ, "Waking any dependents on register %i.\n",
963                (int) dest_reg);
964
965        //Maybe abstract this part into a function.
966        //Go through the dependency chain, marking the registers as ready
967        //within the waiting instructions.
968
969        curr = dependGraph[dest_reg].next;
970
971        while (curr) {
972            DPRINTF(IQ, "Waking up a dependent instruction, PC%#x.\n",
973                    curr->inst->readPC());
974
975            // Might want to give more information to the instruction
976            // so that it knows which of its source registers is ready.
977            // However that would mean that the dependency graph entries
978            // would need to hold the src_reg_idx.
979            curr->inst->markSrcRegReady();
980
981            addIfReady(curr->inst);
982
983            DependencyEntry::mem_alloc_counter--;
984
985            prev = curr;
986            curr = prev->next;
987            prev->inst = NULL;
988
989            ++dependents;
990
991            delete prev;
992        }
993
994        // Reset the head node now that all of its dependents have been woken
995        // up.
996        dependGraph[dest_reg].next = NULL;
997        dependGraph[dest_reg].inst = NULL;
998
999        // Mark the scoreboard as having that register ready.
1000        regScoreboard[dest_reg] = true;
1001    }
1002    return dependents;
1003}
1004
1005template <class Impl>
1006void
1007InstructionQueue<Impl>::addReadyMemInst(DynInstPtr &ready_inst)
1008{
1009    OpClass op_class = ready_inst->opClass();
1010
1011    readyInsts[op_class].push(ready_inst);
1012
1013    DPRINTF(IQ, "Instruction is ready to issue, putting it onto "
1014            "the ready list, PC %#x opclass:%i [sn:%lli].\n",
1015            ready_inst->readPC(), op_class, ready_inst->seqNum);
1016}
1017
1018template <class Impl>
1019void
1020InstructionQueue<Impl>::rescheduleMemInst(DynInstPtr &resched_inst)
1021{
1022    memDepUnit[resched_inst->threadNumber].reschedule(resched_inst);
1023}
1024
1025template <class Impl>
1026void
1027InstructionQueue<Impl>::replayMemInst(DynInstPtr &replay_inst)
1028{
1029    memDepUnit[replay_inst->threadNumber].replay(replay_inst);
1030}
1031
1032template <class Impl>
1033void
1034InstructionQueue<Impl>::completeMemInst(DynInstPtr &completed_inst)
1035{
1036    int tid = completed_inst->threadNumber;
1037
1038    DPRINTF(IQ, "Completing mem instruction PC:%#x [sn:%lli]\n",
1039            completed_inst->readPC(), completed_inst->seqNum);
1040
1041    ++freeEntries;
1042
1043    completed_inst->memOpDone = true;
1044
1045    memDepUnit[tid].completed(completed_inst);
1046
1047    count[tid]--;
1048}
1049
1050template <class Impl>
1051void
1052InstructionQueue<Impl>::violation(DynInstPtr &store,
1053                                  DynInstPtr &faulting_load)
1054{
1055    memDepUnit[store->threadNumber].violation(store, faulting_load);
1056}
1057
1058template <class Impl>
1059void
1060InstructionQueue<Impl>::squash(unsigned tid)
1061{
1062    DPRINTF(IQ, "[tid:%i]: Starting to squash instructions in "
1063            "the IQ.\n", tid);
1064
1065    // Read instruction sequence number of last instruction out of the
1066    // time buffer.
1067    squashedSeqNum[tid] = fromCommit->commitInfo[tid].doneSeqNum;
1068
1069    // Setup the squash iterator to point to the tail.
1070    squashIt[tid] = instList[tid].end();
1071    --squashIt[tid];
1072
1073    // Call doSquash if there are insts in the IQ
1074    if (count[tid] > 0) {
1075        doSquash(tid);
1076    }
1077
1078    // Also tell the memory dependence unit to squash.
1079    memDepUnit[tid].squash(squashedSeqNum[tid], tid);
1080}
1081
1082template <class Impl>
1083void
1084InstructionQueue<Impl>::doSquash(unsigned tid)
1085{
1086    // Make sure the squashed sequence number is valid.
1087//    assert(squashedSeqNum[tid] != 0);
1088
1089    DPRINTF(IQ, "[tid:%i]: Squashing until sequence number %i!\n",
1090            tid, squashedSeqNum[tid]);
1091
1092    // Squash any instructions younger than the squashed sequence number
1093    // given.
1094    while (squashIt[tid] != instList[tid].end() &&
1095           (*squashIt[tid])->seqNum > squashedSeqNum[tid]) {
1096
1097        DynInstPtr squashed_inst = (*squashIt[tid]);
1098
1099        // Only handle the instruction if it actually is in the IQ and
1100        // hasn't already been squashed in the IQ.
1101        if (squashed_inst->threadNumber != tid ||
1102            squashed_inst->isSquashedInIQ()) {
1103            --squashIt[tid];
1104            continue;
1105        }
1106
1107        if (!squashed_inst->isIssued() ||
1108            (squashed_inst->isMemRef() &&
1109             !squashed_inst->memOpDone)) {
1110
1111            // Remove the instruction from the dependency list.
1112            if (!squashed_inst->isNonSpeculative() &&
1113                !squashed_inst->isMemBarrier() &&
1114                !squashed_inst->isWriteBarrier()) {
1115
1116                for (int src_reg_idx = 0;
1117                     src_reg_idx < squashed_inst->numSrcRegs();
1118                     src_reg_idx++)
1119                {
1120                    PhysRegIndex src_reg =
1121                        squashed_inst->renamedSrcRegIdx(src_reg_idx);
1122
1123                    // Only remove it from the dependency graph if it was
1124                    // placed there in the first place.
1125                    // HACK: This assumes that instructions woken up from the
1126                    // dependency chain aren't informed that a specific src
1127                    // register has become ready.  This may not always be true
1128                    // in the future.
1129                    // Instead of doing a linked list traversal, we can just
1130                    // remove these squashed instructions either at issue time,
1131                    // or when the register is overwritten.  The only downside
1132                    // to this is it leaves more room for error.
1133
1134                    if (!squashed_inst->isReadySrcRegIdx(src_reg_idx) &&
1135                        src_reg < numPhysRegs) {
1136                        dependGraph[src_reg].remove(squashed_inst);
1137                    }
1138
1139
1140                    ++iqSquashedOperandsExamined;
1141                }
1142
1143                // Might want to remove producers as well.
1144            } else {
1145                NonSpecMapIt ns_inst_it =
1146                    nonSpecInsts.find(squashed_inst->seqNum);
1147                assert(ns_inst_it != nonSpecInsts.end());
1148
1149                (*ns_inst_it).second = NULL;
1150
1151                nonSpecInsts.erase(ns_inst_it);
1152
1153                ++iqSquashedNonSpecRemoved;
1154            }
1155
1156            // Might want to also clear out the head of the dependency graph.
1157
1158            // Mark it as squashed within the IQ.
1159            squashed_inst->setSquashedInIQ();
1160
1161            // @todo: Remove this hack where several statuses are set so the
1162            // inst will flow through the rest of the pipeline.
1163            squashed_inst->setIssued();
1164            squashed_inst->setCanCommit();
1165            squashed_inst->removeInIQ();
1166
1167            //Update Thread IQ Count
1168            count[squashed_inst->threadNumber]--;
1169
1170            ++freeEntries;
1171
1172            if (numThreads > 1) {
1173                DPRINTF(IQ, "[tid:%i]: Instruction [sn:%lli] PC %#x "
1174                        "squashed.\n",
1175                        tid, squashed_inst->seqNum, squashed_inst->readPC());
1176            } else {
1177                DPRINTF(IQ, "Instruction [sn:%lli] PC %#x squashed.\n",
1178                        squashed_inst->seqNum, squashed_inst->readPC());
1179            }
1180        }
1181
1182        instList[tid].erase(squashIt[tid]--);
1183        ++iqSquashedInstsExamined;
1184    }
1185}
1186
1187template <class Impl>
1188void
1189InstructionQueue<Impl>::DependencyEntry::insert(DynInstPtr &new_inst)
1190{
1191    //Add this new, dependent instruction at the head of the dependency
1192    //chain.
1193
1194    // First create the entry that will be added to the head of the
1195    // dependency chain.
1196    DependencyEntry *new_entry = new DependencyEntry;
1197    new_entry->next = this->next;
1198    new_entry->inst = new_inst;
1199
1200    // Then actually add it to the chain.
1201    this->next = new_entry;
1202
1203    ++mem_alloc_counter;
1204}
1205
1206template <class Impl>
1207void
1208InstructionQueue<Impl>::DependencyEntry::remove(DynInstPtr &inst_to_remove)
1209{
1210    DependencyEntry *prev = this;
1211    DependencyEntry *curr = this->next;
1212
1213    // Make sure curr isn't NULL.  Because this instruction is being
1214    // removed from a dependency list, it must have been placed there at
1215    // an earlier time.  The dependency chain should not be empty,
1216    // unless the instruction dependent upon it is already ready.
1217    if (curr == NULL) {
1218        return;
1219    }
1220
1221    // Find the instruction to remove within the dependency linked list.
1222    while (curr->inst != inst_to_remove) {
1223        prev = curr;
1224        curr = curr->next;
1225
1226        assert(curr != NULL);
1227    }
1228
1229    // Now remove this instruction from the list.
1230    prev->next = curr->next;
1231
1232    --mem_alloc_counter;
1233
1234    // Could push this off to the destructor of DependencyEntry
1235    curr->inst = NULL;
1236
1237    delete curr;
1238}
1239
1240template <class Impl>
1241bool
1242InstructionQueue<Impl>::addToDependents(DynInstPtr &new_inst)
1243{
1244    // Loop through the instruction's source registers, adding
1245    // them to the dependency list if they are not ready.
1246    int8_t total_src_regs = new_inst->numSrcRegs();
1247    bool return_val = false;
1248
1249    for (int src_reg_idx = 0;
1250         src_reg_idx < total_src_regs;
1251         src_reg_idx++)
1252    {
1253        // Only add it to the dependency graph if it's not ready.
1254        if (!new_inst->isReadySrcRegIdx(src_reg_idx)) {
1255            PhysRegIndex src_reg = new_inst->renamedSrcRegIdx(src_reg_idx);
1256
1257            // Check the IQ's scoreboard to make sure the register
1258            // hasn't become ready while the instruction was in flight
1259            // between stages.  Only if it really isn't ready should
1260            // it be added to the dependency graph.
1261            if (src_reg >= numPhysRegs) {
1262                continue;
1263            } else if (regScoreboard[src_reg] == false) {
1264                DPRINTF(IQ, "Instruction PC %#x has src reg %i that "
1265                        "is being added to the dependency chain.\n",
1266                        new_inst->readPC(), src_reg);
1267
1268                dependGraph[src_reg].insert(new_inst);
1269
1270                // Change the return value to indicate that something
1271                // was added to the dependency graph.
1272                return_val = true;
1273            } else {
1274                DPRINTF(IQ, "Instruction PC %#x has src reg %i that "
1275                        "became ready before it reached the IQ.\n",
1276                        new_inst->readPC(), src_reg);
1277                // Mark a register ready within the instruction.
1278                new_inst->markSrcRegReady();
1279            }
1280        }
1281    }
1282
1283    return return_val;
1284}
1285
1286template <class Impl>
1287void
1288InstructionQueue<Impl>::createDependency(DynInstPtr &new_inst)
1289{
1290    //Actually nothing really needs to be marked when an
1291    //instruction becomes the producer of a register's value,
1292    //but for convenience a ptr to the producing instruction will
1293    //be placed in the head node of the dependency links.
1294    int8_t total_dest_regs = new_inst->numDestRegs();
1295
1296    for (int dest_reg_idx = 0;
1297         dest_reg_idx < total_dest_regs;
1298         dest_reg_idx++)
1299    {
1300        PhysRegIndex dest_reg = new_inst->renamedDestRegIdx(dest_reg_idx);
1301
1302        // Instructions that use the misc regs will have a reg number
1303        // higher than the normal physical registers.  In this case these
1304        // registers are not renamed, and there is no need to track
1305        // dependencies as these instructions must be executed at commit.
1306        if (dest_reg >= numPhysRegs) {
1307            continue;
1308        }
1309
1310        if (dependGraph[dest_reg].next) {
1311            dumpDependGraph();
1312            panic("Dependency graph %i not empty!", dest_reg);
1313        }
1314
1315        dependGraph[dest_reg].inst = new_inst;
1316
1317        // Mark the scoreboard to say it's not yet ready.
1318        regScoreboard[dest_reg] = false;
1319    }
1320}
1321
1322template <class Impl>
1323void
1324InstructionQueue<Impl>::addIfReady(DynInstPtr &inst)
1325{
1326    //If the instruction now has all of its source registers
1327    // available, then add it to the list of ready instructions.
1328    if (inst->readyToIssue()) {
1329
1330        //Add the instruction to the proper ready list.
1331        if (inst->isMemRef()) {
1332
1333            DPRINTF(IQ, "Checking if memory instruction can issue.\n");
1334
1335            // Message to the mem dependence unit that this instruction has
1336            // its registers ready.
1337
1338            memDepUnit[inst->threadNumber].regsReady(inst);
1339
1340            return;
1341        }
1342
1343        OpClass op_class = inst->opClass();
1344
1345        DPRINTF(IQ, "Instruction is ready to issue, putting it onto "
1346                "the ready list, PC %#x opclass:%i [sn:%lli].\n",
1347                inst->readPC(), op_class, inst->seqNum);
1348
1349        readyInsts[op_class].push(inst);
1350    }
1351}
1352
1353template <class Impl>
1354int
1355InstructionQueue<Impl>::countInsts()
1356{
1357    //ksewell:This works but definitely could use a cleaner write
1358    //with a more intuitive way of counting. Right now it's
1359    //just brute force ....
1360
1361#if 0
1362    int total_insts = 0;
1363
1364    for (int i = 0; i < numThreads; ++i) {
1365        ListIt count_it = instList[i].begin();
1366
1367        while (count_it != instList[i].end()) {
1368            if (!(*count_it)->isSquashed() && !(*count_it)->isSquashedInIQ()) {
1369                if (!(*count_it)->isIssued()) {
1370                    ++total_insts;
1371                } else if ((*count_it)->isMemRef() &&
1372                           !(*count_it)->memOpDone) {
1373                    // Loads that have not been marked as executed still count
1374                    // towards the total instructions.
1375                    ++total_insts;
1376                }
1377            }
1378
1379            ++count_it;
1380        }
1381    }
1382
1383    return total_insts;
1384#else
1385    return numEntries - freeEntries;
1386#endif
1387}
1388
1389template <class Impl>
1390void
1391InstructionQueue<Impl>::dumpDependGraph()
1392{
1393    DependencyEntry *curr;
1394
1395    for (int i = 0; i < numPhysRegs; ++i)
1396    {
1397        curr = &dependGraph[i];
1398
1399        if (curr->inst) {
1400            cprintf("dependGraph[%i]: producer: %#x [sn:%lli] consumer: ",
1401                    i, curr->inst->readPC(), curr->inst->seqNum);
1402        } else {
1403            cprintf("dependGraph[%i]: No producer. consumer: ", i);
1404        }
1405
1406        while (curr->next != NULL) {
1407            curr = curr->next;
1408
1409            cprintf("%#x [sn:%lli] ",
1410                    curr->inst->readPC(), curr->inst->seqNum);
1411        }
1412
1413        cprintf("\n");
1414    }
1415}
1416
1417template <class Impl>
1418void
1419InstructionQueue<Impl>::dumpLists()
1420{
1421    for (int i = 0; i < Num_OpClasses; ++i) {
1422        cprintf("Ready list %i size: %i\n", i, readyInsts[i].size());
1423
1424        cprintf("\n");
1425    }
1426
1427    cprintf("Non speculative list size: %i\n", nonSpecInsts.size());
1428
1429    NonSpecMapIt non_spec_it = nonSpecInsts.begin();
1430    NonSpecMapIt non_spec_end_it = nonSpecInsts.end();
1431
1432    cprintf("Non speculative list: ");
1433
1434    while (non_spec_it != non_spec_end_it) {
1435        cprintf("%#x [sn:%lli]", (*non_spec_it).second->readPC(),
1436                (*non_spec_it).second->seqNum);
1437        ++non_spec_it;
1438    }
1439
1440    cprintf("\n");
1441
1442    ListOrderIt list_order_it = listOrder.begin();
1443    ListOrderIt list_order_end_it = listOrder.end();
1444    int i = 1;
1445
1446    cprintf("List order: ");
1447
1448    while (list_order_it != list_order_end_it) {
1449        cprintf("%i OpClass:%i [sn:%lli] ", i, (*list_order_it).queueType,
1450                (*list_order_it).oldestInst);
1451
1452        ++list_order_it;
1453        ++i;
1454    }
1455
1456    cprintf("\n");
1457}
1458
1459
1460template <class Impl>
1461void
1462InstructionQueue<Impl>::dumpInsts()
1463{
1464    for (int i = 0; i < numThreads; ++i) {
1465        int num = 0;
1466        int valid_num = 0;
1467        ListIt inst_list_it = instList[i].begin();
1468
1469        while (inst_list_it != instList[i].end())
1470        {
1471            cprintf("Instruction:%i\n",
1472                    num);
1473            if (!(*inst_list_it)->isSquashed()) {
1474                if (!(*inst_list_it)->isIssued()) {
1475                    ++valid_num;
1476                    cprintf("Count:%i\n", valid_num);
1477                } else if ((*inst_list_it)->isMemRef() &&
1478                           !(*inst_list_it)->memOpDone) {
1479                    // Loads that have not been marked as executed still count
1480                    // towards the total instructions.
1481                    ++valid_num;
1482                    cprintf("Count:%i\n", valid_num);
1483                }
1484            }
1485
1486            cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n"
1487                    "Issued:%i\nSquashed:%i\n",
1488                    (*inst_list_it)->readPC(),
1489                    (*inst_list_it)->seqNum,
1490                    (*inst_list_it)->threadNumber,
1491                    (*inst_list_it)->isIssued(),
1492                    (*inst_list_it)->isSquashed());
1493
1494            if ((*inst_list_it)->isMemRef()) {
1495                cprintf("MemOpDone:%i\n", (*inst_list_it)->memOpDone);
1496            }
1497
1498            cprintf("\n");
1499
1500            inst_list_it++;
1501            ++num;
1502        }
1503    }
1504}
1505