inst_queue_impl.hh revision 2698:d5f35d41e017
16657Snate@binkert.org/*
26657Snate@binkert.org * Copyright (c) 2004-2006 The Regents of The University of Michigan
36657Snate@binkert.org * All rights reserved.
46657Snate@binkert.org *
56657Snate@binkert.org * Redistribution and use in source and binary forms, with or without
66657Snate@binkert.org * modification, are permitted provided that the following conditions are
76657Snate@binkert.org * met: redistributions of source code must retain the above copyright
86657Snate@binkert.org * notice, this list of conditions and the following disclaimer;
96657Snate@binkert.org * redistributions in binary form must reproduce the above copyright
106657Snate@binkert.org * notice, this list of conditions and the following disclaimer in the
116657Snate@binkert.org * documentation and/or other materials provided with the distribution;
126657Snate@binkert.org * neither the name of the copyright holders nor the names of its
136657Snate@binkert.org * contributors may be used to endorse or promote products derived from
146657Snate@binkert.org * this software without specific prior written permission.
156657Snate@binkert.org *
166657Snate@binkert.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
176657Snate@binkert.org * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
186657Snate@binkert.org * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
196657Snate@binkert.org * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
206657Snate@binkert.org * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
216657Snate@binkert.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
226657Snate@binkert.org * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
236657Snate@binkert.org * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
246657Snate@binkert.org * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
256657Snate@binkert.org * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
266657Snate@binkert.org * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
276657Snate@binkert.org *
286999Snate@binkert.org * Authors: Kevin Lim
296657Snate@binkert.org */
306657Snate@binkert.org
316657Snate@binkert.org#include <limits>
326657Snate@binkert.org#include <vector>
336657Snate@binkert.org
346882SBrad.Beckmann@amd.com#include "sim/root.hh"
356882SBrad.Beckmann@amd.com
366882SBrad.Beckmann@amd.com#include "cpu/o3/fu_pool.hh"
376882SBrad.Beckmann@amd.com#include "cpu/o3/inst_queue.hh"
386882SBrad.Beckmann@amd.com
396882SBrad.Beckmann@amd.comusing namespace std;
406882SBrad.Beckmann@amd.com
416888SBrad.Beckmann@amd.comtemplate <class Impl>
426882SBrad.Beckmann@amd.comInstructionQueue<Impl>::FUCompletion::FUCompletion(DynInstPtr &_inst,
436882SBrad.Beckmann@amd.com                                                   int fu_idx,
446657Snate@binkert.org                                                   InstructionQueue<Impl> *iq_ptr)
456657Snate@binkert.org    : Event(&mainEventQueue, Stat_Event_Pri),
466657Snate@binkert.org      inst(_inst), fuIdx(fu_idx), iqPtr(iq_ptr), freeFU(false)
476657Snate@binkert.org{
486657Snate@binkert.org    this->setFlags(Event::AutoDelete);
496657Snate@binkert.org}
506882SBrad.Beckmann@amd.com
516882SBrad.Beckmann@amd.comtemplate <class Impl>
526882SBrad.Beckmann@amd.comvoid
536882SBrad.Beckmann@amd.comInstructionQueue<Impl>::FUCompletion::process()
546882SBrad.Beckmann@amd.com{
556882SBrad.Beckmann@amd.com    iqPtr->processFUCompletion(inst, freeFU ? fuIdx : -1);
566657Snate@binkert.org    inst = NULL;
576657Snate@binkert.org}
586657Snate@binkert.org
596657Snate@binkert.org
606657Snate@binkert.orgtemplate <class Impl>
616657Snate@binkert.orgconst char *
626657Snate@binkert.orgInstructionQueue<Impl>::FUCompletion::description()
636657Snate@binkert.org{
646657Snate@binkert.org    return "Functional unit completion event";
656657Snate@binkert.org}
666657Snate@binkert.org
676657Snate@binkert.orgtemplate <class Impl>
686657Snate@binkert.orgInstructionQueue<Impl>::InstructionQueue(Params *params)
696657Snate@binkert.org    : fuPool(params->fuPool),
706657Snate@binkert.org      numEntries(params->numIQEntries),
716657Snate@binkert.org      totalWidth(params->issueWidth),
726657Snate@binkert.org      numPhysIntRegs(params->numPhysIntRegs),
736657Snate@binkert.org      numPhysFloatRegs(params->numPhysFloatRegs),
746657Snate@binkert.org      commitToIEWDelay(params->commitToIEWDelay)
756657Snate@binkert.org{
766657Snate@binkert.org    assert(fuPool);
776657Snate@binkert.org
786657Snate@binkert.org    switchedOut = false;
796657Snate@binkert.org
806657Snate@binkert.org    numThreads = params->numberOfThreads;
816657Snate@binkert.org
826657Snate@binkert.org    // Set the number of physical registers as the number of int + float
836657Snate@binkert.org    numPhysRegs = numPhysIntRegs + numPhysFloatRegs;
846657Snate@binkert.org
856779SBrad.Beckmann@amd.com    DPRINTF(IQ, "There are %i physical registers.\n", numPhysRegs);
866657Snate@binkert.org
876657Snate@binkert.org    //Create an entry for each physical register within the
886657Snate@binkert.org    //dependency graph.
896657Snate@binkert.org    dependGraph.resize(numPhysRegs);
906657Snate@binkert.org
916657Snate@binkert.org    // Resize the register scoreboard.
926657Snate@binkert.org    regScoreboard.resize(numPhysRegs);
936657Snate@binkert.org
946657Snate@binkert.org    //Initialize Mem Dependence Units
956657Snate@binkert.org    for (int i = 0; i < numThreads; i++) {
966657Snate@binkert.org        memDepUnit[i].init(params,i);
976657Snate@binkert.org        memDepUnit[i].setIQ(this);
986657Snate@binkert.org    }
996657Snate@binkert.org
1006657Snate@binkert.org    resetState();
1016657Snate@binkert.org
1026657Snate@binkert.org    string policy = params->smtIQPolicy;
1036657Snate@binkert.org
1046657Snate@binkert.org    //Convert string to lowercase
1056657Snate@binkert.org    std::transform(policy.begin(), policy.end(), policy.begin(),
1066657Snate@binkert.org                   (int(*)(int)) tolower);
1076657Snate@binkert.org
1086657Snate@binkert.org    //Figure out resource sharing policy
1096657Snate@binkert.org    if (policy == "dynamic") {
1106657Snate@binkert.org        iqPolicy = Dynamic;
1116657Snate@binkert.org
1126657Snate@binkert.org        //Set Max Entries to Total ROB Capacity
1136657Snate@binkert.org        for (int i = 0; i < numThreads; i++) {
1146657Snate@binkert.org            maxEntries[i] = numEntries;
1156657Snate@binkert.org        }
1166657Snate@binkert.org
1176657Snate@binkert.org    } else if (policy == "partitioned") {
1186657Snate@binkert.org        iqPolicy = Partitioned;
1196657Snate@binkert.org
1206657Snate@binkert.org        //@todo:make work if part_amt doesnt divide evenly.
1216657Snate@binkert.org        int part_amt = numEntries / numThreads;
1226657Snate@binkert.org
1236657Snate@binkert.org        //Divide ROB up evenly
1246657Snate@binkert.org        for (int i = 0; i < numThreads; i++) {
1256657Snate@binkert.org            maxEntries[i] = part_amt;
1266657Snate@binkert.org        }
1276657Snate@binkert.org
1286657Snate@binkert.org        DPRINTF(Fetch, "IQ sharing policy set to Partitioned:"
1296657Snate@binkert.org                "%i entries per thread.\n",part_amt);
1306657Snate@binkert.org
1316657Snate@binkert.org    } else if (policy == "threshold") {
1326657Snate@binkert.org        iqPolicy = Threshold;
1336657Snate@binkert.org
1346657Snate@binkert.org        double threshold =  (double)params->smtIQThreshold / 100;
1356657Snate@binkert.org
1366657Snate@binkert.org        int thresholdIQ = (int)((double)threshold * numEntries);
1376657Snate@binkert.org
1386657Snate@binkert.org        //Divide up by threshold amount
1396657Snate@binkert.org        for (int i = 0; i < numThreads; i++) {
1406657Snate@binkert.org            maxEntries[i] = thresholdIQ;
1416877Ssteve.reinhardt@amd.com        }
1426657Snate@binkert.org
1436657Snate@binkert.org        DPRINTF(Fetch, "IQ sharing policy set to Threshold:"
1446657Snate@binkert.org                "%i entries per thread.\n",thresholdIQ);
1456657Snate@binkert.org   } else {
1466657Snate@binkert.org       assert(0 && "Invalid IQ Sharing Policy.Options Are:{Dynamic,"
1476657Snate@binkert.org              "Partitioned, Threshold}");
1486657Snate@binkert.org   }
1496657Snate@binkert.org}
1506657Snate@binkert.org
1516657Snate@binkert.orgtemplate <class Impl>
1526877Ssteve.reinhardt@amd.comInstructionQueue<Impl>::~InstructionQueue()
1536999Snate@binkert.org{
1546877Ssteve.reinhardt@amd.com    dependGraph.reset();
1556877Ssteve.reinhardt@amd.com#ifdef DEBUG
1566877Ssteve.reinhardt@amd.com    cprintf("Nodes traversed: %i, removed: %i\n",
1576877Ssteve.reinhardt@amd.com            dependGraph.nodesTraversed, dependGraph.nodesRemoved);
1586877Ssteve.reinhardt@amd.com#endif
1596877Ssteve.reinhardt@amd.com}
1606877Ssteve.reinhardt@amd.com
1616877Ssteve.reinhardt@amd.comtemplate <class Impl>
1626877Ssteve.reinhardt@amd.comstd::string
1636877Ssteve.reinhardt@amd.comInstructionQueue<Impl>::name() const
1646877Ssteve.reinhardt@amd.com{
1656877Ssteve.reinhardt@amd.com    return cpu->name() + ".iq";
1666877Ssteve.reinhardt@amd.com}
1676877Ssteve.reinhardt@amd.com
1686877Ssteve.reinhardt@amd.comtemplate <class Impl>
1696877Ssteve.reinhardt@amd.comvoid
1706882SBrad.Beckmann@amd.comInstructionQueue<Impl>::regStats()
1716882SBrad.Beckmann@amd.com{
1726882SBrad.Beckmann@amd.com    using namespace Stats;
1736882SBrad.Beckmann@amd.com    iqInstsAdded
1746882SBrad.Beckmann@amd.com        .name(name() + ".iqInstsAdded")
1756882SBrad.Beckmann@amd.com        .desc("Number of instructions added to the IQ (excludes non-spec)")
1766882SBrad.Beckmann@amd.com        .prereq(iqInstsAdded);
1776877Ssteve.reinhardt@amd.com
1786877Ssteve.reinhardt@amd.com    iqNonSpecInstsAdded
1796877Ssteve.reinhardt@amd.com        .name(name() + ".iqNonSpecInstsAdded")
1806877Ssteve.reinhardt@amd.com        .desc("Number of non-speculative instructions added to the IQ")
1816657Snate@binkert.org        .prereq(iqNonSpecInstsAdded);
1826657Snate@binkert.org
1836999Snate@binkert.org    iqInstsIssued
1846657Snate@binkert.org        .name(name() + ".iqInstsIssued")
1856657Snate@binkert.org        .desc("Number of instructions issued")
1866657Snate@binkert.org        .prereq(iqInstsIssued);
1876657Snate@binkert.org
1886657Snate@binkert.org    iqIntInstsIssued
1896657Snate@binkert.org        .name(name() + ".iqIntInstsIssued")
1907007Snate@binkert.org        .desc("Number of integer instructions issued")
1916657Snate@binkert.org        .prereq(iqIntInstsIssued);
1926657Snate@binkert.org
1936657Snate@binkert.org    iqFloatInstsIssued
1946657Snate@binkert.org        .name(name() + ".iqFloatInstsIssued")
1956657Snate@binkert.org        .desc("Number of float instructions issued")
1967007Snate@binkert.org        .prereq(iqFloatInstsIssued);
1977007Snate@binkert.org
1986657Snate@binkert.org    iqBranchInstsIssued
1997002Snate@binkert.org        .name(name() + ".iqBranchInstsIssued")
2007002Snate@binkert.org        .desc("Number of branch instructions issued")
2017002Snate@binkert.org        .prereq(iqBranchInstsIssued);
2027002Snate@binkert.org
2036877Ssteve.reinhardt@amd.com    iqMemInstsIssued
2046877Ssteve.reinhardt@amd.com        .name(name() + ".iqMemInstsIssued")
2056657Snate@binkert.org        .desc("Number of memory instructions issued")
2066657Snate@binkert.org        .prereq(iqMemInstsIssued);
2076657Snate@binkert.org
2086657Snate@binkert.org    iqMiscInstsIssued
2096657Snate@binkert.org        .name(name() + ".iqMiscInstsIssued")
2106657Snate@binkert.org        .desc("Number of miscellaneous instructions issued")
2116657Snate@binkert.org        .prereq(iqMiscInstsIssued);
2126657Snate@binkert.org
2136657Snate@binkert.org    iqSquashedInstsIssued
2146657Snate@binkert.org        .name(name() + ".iqSquashedInstsIssued")
2156793SBrad.Beckmann@amd.com        .desc("Number of squashed instructions issued")
2166657Snate@binkert.org        .prereq(iqSquashedInstsIssued);
2176657Snate@binkert.org
2186657Snate@binkert.org    iqSquashedInstsExamined
2196657Snate@binkert.org        .name(name() + ".iqSquashedInstsExamined")
2206657Snate@binkert.org        .desc("Number of squashed instructions iterated over during squash;"
2217002Snate@binkert.org              " mainly for profiling")
2226657Snate@binkert.org        .prereq(iqSquashedInstsExamined);
2237007Snate@binkert.org
2247007Snate@binkert.org    iqSquashedOperandsExamined
2257007Snate@binkert.org        .name(name() + ".iqSquashedOperandsExamined")
2267007Snate@binkert.org        .desc("Number of squashed operands that are examined and possibly "
2277007Snate@binkert.org              "removed from graph")
2286657Snate@binkert.org        .prereq(iqSquashedOperandsExamined);
2296877Ssteve.reinhardt@amd.com
2306877Ssteve.reinhardt@amd.com    iqSquashedNonSpecRemoved
2316657Snate@binkert.org        .name(name() + ".iqSquashedNonSpecRemoved")
2326877Ssteve.reinhardt@amd.com        .desc("Number of squashed non-spec instructions that were removed")
2336657Snate@binkert.org        .prereq(iqSquashedNonSpecRemoved);
2346657Snate@binkert.org
2357002Snate@binkert.org    queueResDist
2367002Snate@binkert.org        .init(Num_OpClasses, 0, 99, 2)
2376657Snate@binkert.org        .name(name() + ".IQ:residence:")
2386881SBrad.Beckmann@amd.com        .desc("cycles from dispatch to issue")
2397002Snate@binkert.org        .flags(total | pdf | cdf )
2407002Snate@binkert.org        ;
2416657Snate@binkert.org    for (int i = 0; i < Num_OpClasses; ++i) {
2427002Snate@binkert.org        queueResDist.subname(i, opClassStrings[i]);
2436902SBrad.Beckmann@amd.com    }
2446863Sdrh5@cs.wisc.edu    numIssuedDist
2456863Sdrh5@cs.wisc.edu        .init(0,totalWidth,1)
2467007Snate@binkert.org        .name(name() + ".ISSUE:issued_per_cycle")
2476657Snate@binkert.org        .desc("Number of insts issued each cycle")
2486657Snate@binkert.org        .flags(pdf)
2496657Snate@binkert.org        ;
2506657Snate@binkert.org/*
2516657Snate@binkert.org    dist_unissued
2526657Snate@binkert.org        .init(Num_OpClasses+2)
2536882SBrad.Beckmann@amd.com        .name(name() + ".ISSUE:unissued_cause")
2546882SBrad.Beckmann@amd.com        .desc("Reason ready instruction not issued")
2556882SBrad.Beckmann@amd.com        .flags(pdf | dist)
2566882SBrad.Beckmann@amd.com        ;
2576657Snate@binkert.org    for (int i=0; i < (Num_OpClasses + 2); ++i) {
2586657Snate@binkert.org        dist_unissued.subname(i, unissued_names[i]);
2596657Snate@binkert.org    }
2606657Snate@binkert.org*/
2617007Snate@binkert.org    statIssuedInstType
2627007Snate@binkert.org        .init(numThreads,Num_OpClasses)
2637007Snate@binkert.org        .name(name() + ".ISSUE:FU_type")
2647007Snate@binkert.org        .desc("Type of FU issued")
2657007Snate@binkert.org        .flags(total | pdf | dist)
2667007Snate@binkert.org        ;
2677007Snate@binkert.org    statIssuedInstType.ysubnames(opClassStrings);
2687007Snate@binkert.org
2697007Snate@binkert.org    //
2707002Snate@binkert.org    //  How long did instructions for a particular FU type wait prior to issue
2716657Snate@binkert.org    //
2726657Snate@binkert.org
2736657Snate@binkert.org    issueDelayDist
2747002Snate@binkert.org        .init(Num_OpClasses,0,99,2)
2756657Snate@binkert.org        .name(name() + ".ISSUE:")
2766657Snate@binkert.org        .desc("cycles from operands ready to issue")
2776657Snate@binkert.org        .flags(pdf | cdf)
2786863Sdrh5@cs.wisc.edu        ;
2796863Sdrh5@cs.wisc.edu
2806657Snate@binkert.org    for (int i=0; i<Num_OpClasses; ++i) {
2816657Snate@binkert.org        stringstream subname;
2827007Snate@binkert.org        subname << opClassStrings[i] << "_delay";
2836657Snate@binkert.org        issueDelayDist.subname(i, subname.str());
2846657Snate@binkert.org    }
2856657Snate@binkert.org
2866657Snate@binkert.org    issueRate
2876657Snate@binkert.org        .name(name() + ".ISSUE:rate")
2886657Snate@binkert.org        .desc("Inst issue rate")
2896657Snate@binkert.org        .flags(total)
2906657Snate@binkert.org        ;
2916657Snate@binkert.org    issueRate = iqInstsIssued / cpu->numCycles;
2926657Snate@binkert.org/*
2936657Snate@binkert.org    issue_stores
2946657Snate@binkert.org        .name(name() + ".ISSUE:stores")
2956657Snate@binkert.org        .desc("Number of stores issued")
2966657Snate@binkert.org        .flags(total)
2976657Snate@binkert.org        ;
2986657Snate@binkert.org    issue_stores = exe_refs - exe_loads;
2996657Snate@binkert.org*/
3006657Snate@binkert.org/*
3016657Snate@binkert.org    issue_op_rate
3027007Snate@binkert.org        .name(name() + ".ISSUE:op_rate")
3036657Snate@binkert.org        .desc("Operation issue rate")
3046657Snate@binkert.org        .flags(total)
3056657Snate@binkert.org        ;
3066657Snate@binkert.org    issue_op_rate = issued_ops / numCycles;
3076657Snate@binkert.org*/
3086657Snate@binkert.org    statFuBusy
3096657Snate@binkert.org        .init(Num_OpClasses)
3106657Snate@binkert.org        .name(name() + ".ISSUE:fu_full")
3116657Snate@binkert.org        .desc("attempts to use FU when none available")
3126657Snate@binkert.org        .flags(pdf | dist)
3137007Snate@binkert.org        ;
3146657Snate@binkert.org    for (int i=0; i < Num_OpClasses; ++i) {
3156657Snate@binkert.org        statFuBusy.subname(i, opClassStrings[i]);
3166657Snate@binkert.org    }
3176657Snate@binkert.org
3186657Snate@binkert.org    fuBusy
3196999Snate@binkert.org        .init(numThreads)
3206657Snate@binkert.org        .name(name() + ".ISSUE:fu_busy_cnt")
3216657Snate@binkert.org        .desc("FU busy when requested")
3226657Snate@binkert.org        .flags(total)
3236657Snate@binkert.org        ;
3247007Snate@binkert.org
3256657Snate@binkert.org    fuBusyRate
3266657Snate@binkert.org        .name(name() + ".ISSUE:fu_busy_rate")
3276657Snate@binkert.org        .desc("FU busy rate (busy events/executed inst)")
3286657Snate@binkert.org        .flags(total)
3296657Snate@binkert.org        ;
3307002Snate@binkert.org    fuBusyRate = fuBusy / iqInstsIssued;
3317002Snate@binkert.org
3327002Snate@binkert.org    for ( int i=0; i < numThreads; i++) {
3336657Snate@binkert.org        // Tell mem dependence unit to reg stats as well.
3346657Snate@binkert.org        memDepUnit[i].regStats();
3356657Snate@binkert.org    }
3366657Snate@binkert.org}
3376657Snate@binkert.org
3386657Snate@binkert.orgtemplate <class Impl>
3396657Snate@binkert.orgvoid
3407002Snate@binkert.orgInstructionQueue<Impl>::resetState()
3417002Snate@binkert.org{
3426657Snate@binkert.org    //Initialize thread IQ counts
3436657Snate@binkert.org    for (int i = 0; i <numThreads; i++) {
3446657Snate@binkert.org        count[i] = 0;
3456657Snate@binkert.org        instList[i].clear();
3466657Snate@binkert.org    }
3476793SBrad.Beckmann@amd.com
3486657Snate@binkert.org    // Initialize the number of free IQ entries.
3496657Snate@binkert.org    freeEntries = numEntries;
3506657Snate@binkert.org
3516657Snate@binkert.org    // Note that in actuality, the registers corresponding to the logical
3526877Ssteve.reinhardt@amd.com    // registers start off as ready.  However this doesn't matter for the
3536877Ssteve.reinhardt@amd.com    // IQ as the instruction should have been correctly told if those
3546877Ssteve.reinhardt@amd.com    // registers are ready in rename.  Thus it can all be initialized as
3556877Ssteve.reinhardt@amd.com    // unready.
3566877Ssteve.reinhardt@amd.com    for (int i = 0; i < numPhysRegs; ++i) {
3576877Ssteve.reinhardt@amd.com        regScoreboard[i] = false;
3586657Snate@binkert.org    }
3596657Snate@binkert.org
3607007Snate@binkert.org    for (int i = 0; i < numThreads; ++i) {
3616657Snate@binkert.org        squashedSeqNum[i] = 0;
3626657Snate@binkert.org    }
3637007Snate@binkert.org
3646657Snate@binkert.org    for (int i = 0; i < Num_OpClasses; ++i) {
3656877Ssteve.reinhardt@amd.com        while (!readyInsts[i].empty())
3666877Ssteve.reinhardt@amd.com            readyInsts[i].pop();
3676657Snate@binkert.org        queueOnList[i] = false;
3686877Ssteve.reinhardt@amd.com        readyIt[i] = listOrder.end();
3696877Ssteve.reinhardt@amd.com    }
3706877Ssteve.reinhardt@amd.com    nonSpecInsts.clear();
3716877Ssteve.reinhardt@amd.com    listOrder.clear();
3726877Ssteve.reinhardt@amd.com}
3736969SBrad.Beckmann@amd.com
3746657Snate@binkert.orgtemplate <class Impl>
3756657Snate@binkert.orgvoid
3766882SBrad.Beckmann@amd.comInstructionQueue<Impl>::setActiveThreads(list<unsigned> *at_ptr)
3776882SBrad.Beckmann@amd.com{
3786882SBrad.Beckmann@amd.com    DPRINTF(IQ, "Setting active threads list pointer.\n");
3796882SBrad.Beckmann@amd.com    activeThreads = at_ptr;
3806882SBrad.Beckmann@amd.com}
3816882SBrad.Beckmann@amd.com
3826882SBrad.Beckmann@amd.comtemplate <class Impl>
3836882SBrad.Beckmann@amd.comvoid
3846877Ssteve.reinhardt@amd.comInstructionQueue<Impl>::setIssueToExecuteQueue(TimeBuffer<IssueStruct> *i2e_ptr)
3856888SBrad.Beckmann@amd.com{
3866882SBrad.Beckmann@amd.com    DPRINTF(IQ, "Set the issue to execute queue.\n");
3876882SBrad.Beckmann@amd.com    issueToExecuteQueue = i2e_ptr;
3886882SBrad.Beckmann@amd.com}
3896882SBrad.Beckmann@amd.com
3906882SBrad.Beckmann@amd.comtemplate <class Impl>
3916882SBrad.Beckmann@amd.comvoid
3926882SBrad.Beckmann@amd.comInstructionQueue<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
3936882SBrad.Beckmann@amd.com{
3946882SBrad.Beckmann@amd.com    DPRINTF(IQ, "Set the time buffer.\n");
3956882SBrad.Beckmann@amd.com    timeBuffer = tb_ptr;
3966882SBrad.Beckmann@amd.com
3976882SBrad.Beckmann@amd.com    fromCommit = timeBuffer->getWire(-commitToIEWDelay);
3986882SBrad.Beckmann@amd.com}
3996882SBrad.Beckmann@amd.com
4006882SBrad.Beckmann@amd.comtemplate <class Impl>
4016882SBrad.Beckmann@amd.comvoid
4026882SBrad.Beckmann@amd.comInstructionQueue<Impl>::switchOut()
4036882SBrad.Beckmann@amd.com{
4046888SBrad.Beckmann@amd.com    resetState();
4056888SBrad.Beckmann@amd.com    dependGraph.reset();
4066888SBrad.Beckmann@amd.com    switchedOut = true;
4076888SBrad.Beckmann@amd.com    for (int i = 0; i < numThreads; ++i) {
4086888SBrad.Beckmann@amd.com        memDepUnit[i].switchOut();
4096888SBrad.Beckmann@amd.com    }
4106888SBrad.Beckmann@amd.com}
4116888SBrad.Beckmann@amd.com
4126657Snate@binkert.orgtemplate <class Impl>
4136888SBrad.Beckmann@amd.comvoid
4146888SBrad.Beckmann@amd.comInstructionQueue<Impl>::takeOverFrom()
4156888SBrad.Beckmann@amd.com{
4166888SBrad.Beckmann@amd.com    switchedOut = false;
4176657Snate@binkert.org}
4186657Snate@binkert.org
4196657Snate@binkert.orgtemplate <class Impl>
4206657Snate@binkert.orgint
4216657Snate@binkert.orgInstructionQueue<Impl>::entryAmount(int num_threads)
4226657Snate@binkert.org{
4236657Snate@binkert.org    if (iqPolicy == Partitioned) {
4246657Snate@binkert.org        return numEntries / num_threads;
4256657Snate@binkert.org    } else {
4267007Snate@binkert.org        return 0;
4277007Snate@binkert.org    }
4286657Snate@binkert.org}
4297007Snate@binkert.org
4307007Snate@binkert.org
4317007Snate@binkert.orgtemplate <class Impl>
4326657Snate@binkert.orgvoid
4336657Snate@binkert.orgInstructionQueue<Impl>::resetEntries()
4346657Snate@binkert.org{
4357007Snate@binkert.org    if (iqPolicy != Dynamic || numThreads > 1) {
4366657Snate@binkert.org        int active_threads = (*activeThreads).size();
4377007Snate@binkert.org
4386657Snate@binkert.org        list<unsigned>::iterator threads  = (*activeThreads).begin();
4396657Snate@binkert.org        list<unsigned>::iterator list_end = (*activeThreads).end();
4406657Snate@binkert.org
4416657Snate@binkert.org        while (threads != list_end) {
4426657Snate@binkert.org            if (iqPolicy == Partitioned) {
4436657Snate@binkert.org                maxEntries[*threads++] = numEntries / active_threads;
4446657Snate@binkert.org            } else if(iqPolicy == Threshold && active_threads == 1) {
4456657Snate@binkert.org                maxEntries[*threads++] = numEntries;
4466657Snate@binkert.org            }
4476657Snate@binkert.org        }
4486657Snate@binkert.org    }
4496657Snate@binkert.org}
4506657Snate@binkert.org
4516657Snate@binkert.orgtemplate <class Impl>
4526657Snate@binkert.orgunsigned
4536657Snate@binkert.orgInstructionQueue<Impl>::numFreeEntries()
4546657Snate@binkert.org{
4556657Snate@binkert.org    return freeEntries;
4566657Snate@binkert.org}
4576657Snate@binkert.org
4586657Snate@binkert.orgtemplate <class Impl>
4596657Snate@binkert.orgunsigned
4606657Snate@binkert.orgInstructionQueue<Impl>::numFreeEntries(unsigned tid)
4616657Snate@binkert.org{
4626657Snate@binkert.org    return maxEntries[tid] - count[tid];
4636657Snate@binkert.org}
4646657Snate@binkert.org
4656657Snate@binkert.org// Might want to do something more complex if it knows how many instructions
4667007Snate@binkert.org// will be issued this cycle.
4676657Snate@binkert.orgtemplate <class Impl>
4686657Snate@binkert.orgbool
4696657Snate@binkert.orgInstructionQueue<Impl>::isFull()
4706657Snate@binkert.org{
4717007Snate@binkert.org    if (freeEntries == 0) {
4726657Snate@binkert.org        return(true);
4737007Snate@binkert.org    } else {
4747007Snate@binkert.org        return(false);
4756657Snate@binkert.org    }
4766657Snate@binkert.org}
4776657Snate@binkert.org
4786657Snate@binkert.orgtemplate <class Impl>
4796657Snate@binkert.orgbool
4806657Snate@binkert.orgInstructionQueue<Impl>::isFull(unsigned tid)
4816657Snate@binkert.org{
4826657Snate@binkert.org    if (numFreeEntries(tid) == 0) {
4836657Snate@binkert.org        return(true);
4846657Snate@binkert.org    } else {
4856657Snate@binkert.org        return(false);
4866657Snate@binkert.org    }
4876657Snate@binkert.org}
4886657Snate@binkert.org
4896657Snate@binkert.orgtemplate <class Impl>
4906657Snate@binkert.orgbool
4916657Snate@binkert.orgInstructionQueue<Impl>::hasReadyInsts()
4926657Snate@binkert.org{
4936657Snate@binkert.org    if (!listOrder.empty()) {
4946657Snate@binkert.org        return true;
4956657Snate@binkert.org    }
4966657Snate@binkert.org
4976657Snate@binkert.org    for (int i = 0; i < Num_OpClasses; ++i) {
4987007Snate@binkert.org        if (!readyInsts[i].empty()) {
4997007Snate@binkert.org            return true;
5007007Snate@binkert.org        }
5016657Snate@binkert.org    }
5026657Snate@binkert.org
5036657Snate@binkert.org    return false;
5046657Snate@binkert.org}
5056657Snate@binkert.org
5066657Snate@binkert.orgtemplate <class Impl>
5076657Snate@binkert.orgvoid
5086657Snate@binkert.orgInstructionQueue<Impl>::insert(DynInstPtr &new_inst)
5096657Snate@binkert.org{
5106657Snate@binkert.org    // Make sure the instruction is valid
5116657Snate@binkert.org    assert(new_inst);
5126657Snate@binkert.org
5136657Snate@binkert.org    DPRINTF(IQ, "Adding instruction [sn:%lli] PC %#x to the IQ.\n",
5146657Snate@binkert.org            new_inst->seqNum, new_inst->readPC());
5156657Snate@binkert.org
5166657Snate@binkert.org    assert(freeEntries != 0);
5176657Snate@binkert.org
5186657Snate@binkert.org    instList[new_inst->threadNumber].push_back(new_inst);
5196657Snate@binkert.org
5206657Snate@binkert.org    --freeEntries;
5216657Snate@binkert.org
5226657Snate@binkert.org    new_inst->setInIQ();
5236657Snate@binkert.org
5246657Snate@binkert.org    // Look through its source registers (physical regs), and mark any
5256657Snate@binkert.org    // dependencies.
5266657Snate@binkert.org    addToDependents(new_inst);
5276657Snate@binkert.org
5287007Snate@binkert.org    // Have this instruction set itself as the producer of its destination
5297007Snate@binkert.org    // register(s).
5307007Snate@binkert.org    addToProducers(new_inst);
5317007Snate@binkert.org
5326657Snate@binkert.org    if (new_inst->isMemRef()) {
5336657Snate@binkert.org        memDepUnit[new_inst->threadNumber].insert(new_inst);
5346657Snate@binkert.org    } else {
5356657Snate@binkert.org        addIfReady(new_inst);
5366657Snate@binkert.org    }
5376657Snate@binkert.org
5386657Snate@binkert.org    ++iqInstsAdded;
5396657Snate@binkert.org
5406657Snate@binkert.org    count[new_inst->threadNumber]++;
5416657Snate@binkert.org
5426657Snate@binkert.org    assert(freeEntries == (numEntries - countInsts()));
5436657Snate@binkert.org}
5446657Snate@binkert.org
5456657Snate@binkert.orgtemplate <class Impl>
5466657Snate@binkert.orgvoid
5476657Snate@binkert.orgInstructionQueue<Impl>::insertNonSpec(DynInstPtr &new_inst)
5486657Snate@binkert.org{
5496657Snate@binkert.org    // @todo: Clean up this code; can do it by setting inst as unable
5506657Snate@binkert.org    // to issue, then calling normal insert on the inst.
5516657Snate@binkert.org
5526657Snate@binkert.org    assert(new_inst);
5536657Snate@binkert.org
5546657Snate@binkert.org    nonSpecInsts[new_inst->seqNum] = new_inst;
5556657Snate@binkert.org
5566657Snate@binkert.org    DPRINTF(IQ, "Adding non-speculative instruction [sn:%lli] PC %#x "
5576657Snate@binkert.org            "to the IQ.\n",
5586657Snate@binkert.org            new_inst->seqNum, new_inst->readPC());
5596657Snate@binkert.org
5606657Snate@binkert.org    assert(freeEntries != 0);
5616657Snate@binkert.org
5626657Snate@binkert.org    instList[new_inst->threadNumber].push_back(new_inst);
5636657Snate@binkert.org
5646657Snate@binkert.org    --freeEntries;
5656657Snate@binkert.org
5666657Snate@binkert.org    new_inst->setInIQ();
5676657Snate@binkert.org
5686657Snate@binkert.org    // Have this instruction set itself as the producer of its destination
5696657Snate@binkert.org    // register(s).
5706657Snate@binkert.org    addToProducers(new_inst);
5716657Snate@binkert.org
5726657Snate@binkert.org    // If it's a memory instruction, add it to the memory dependency
5736657Snate@binkert.org    // unit.
5746657Snate@binkert.org    if (new_inst->isMemRef()) {
5756657Snate@binkert.org        memDepUnit[new_inst->threadNumber].insertNonSpec(new_inst);
5767007Snate@binkert.org    }
5777007Snate@binkert.org
5787007Snate@binkert.org    ++iqNonSpecInstsAdded;
5796657Snate@binkert.org
5806657Snate@binkert.org    count[new_inst->threadNumber]++;
5816657Snate@binkert.org
5827007Snate@binkert.org    assert(freeEntries == (numEntries - countInsts()));
5837007Snate@binkert.org}
5847007Snate@binkert.org
5856657Snate@binkert.orgtemplate <class Impl>
5866657Snate@binkert.orgvoid
5876657Snate@binkert.orgInstructionQueue<Impl>::insertBarrier(DynInstPtr &barr_inst)
5887007Snate@binkert.org{
5897007Snate@binkert.org    memDepUnit[barr_inst->threadNumber].insertBarrier(barr_inst);
5907007Snate@binkert.org
5916657Snate@binkert.org    insertNonSpec(barr_inst);
5926657Snate@binkert.org}
5936657Snate@binkert.org
5947007Snate@binkert.orgtemplate <class Impl>
5957007Snate@binkert.orgtypename Impl::DynInstPtr
5967007Snate@binkert.orgInstructionQueue<Impl>::getInstToExecute()
5976657Snate@binkert.org{
5986657Snate@binkert.org    assert(!instsToExecute.empty());
5996657Snate@binkert.org    DynInstPtr inst = instsToExecute.front();
6007007Snate@binkert.org    instsToExecute.pop_front();
6017007Snate@binkert.org    return inst;
6027007Snate@binkert.org}
6036657Snate@binkert.org
6046657Snate@binkert.orgtemplate <class Impl>
6057007Snate@binkert.orgvoid
6067007Snate@binkert.orgInstructionQueue<Impl>::addToOrderList(OpClass op_class)
6077007Snate@binkert.org{
6087007Snate@binkert.org    assert(!readyInsts[op_class].empty());
6096657Snate@binkert.org
6106657Snate@binkert.org    ListOrderEntry queue_entry;
6116657Snate@binkert.org
6127007Snate@binkert.org    queue_entry.queueType = op_class;
6137007Snate@binkert.org
6147007Snate@binkert.org    queue_entry.oldestInst = readyInsts[op_class].top()->seqNum;
6156863Sdrh5@cs.wisc.edu
6166863Sdrh5@cs.wisc.edu    ListOrderIt list_it = listOrder.begin();
6176863Sdrh5@cs.wisc.edu    ListOrderIt list_end_it = listOrder.end();
6187007Snate@binkert.org
6197007Snate@binkert.org    while (list_it != list_end_it) {
6207007Snate@binkert.org        if ((*list_it).oldestInst > queue_entry.oldestInst) {
6217007Snate@binkert.org            break;
6226863Sdrh5@cs.wisc.edu        }
6236863Sdrh5@cs.wisc.edu
6246863Sdrh5@cs.wisc.edu        list_it++;
6256863Sdrh5@cs.wisc.edu    }
6266863Sdrh5@cs.wisc.edu
6276863Sdrh5@cs.wisc.edu    readyIt[op_class] = listOrder.insert(list_it, queue_entry);
6287007Snate@binkert.org    queueOnList[op_class] = true;
6297007Snate@binkert.org}
6307007Snate@binkert.org
6317007Snate@binkert.orgtemplate <class Impl>
6327007Snate@binkert.orgvoid
6336657Snate@binkert.orgInstructionQueue<Impl>::moveToYoungerInst(ListOrderIt list_order_it)
6347007Snate@binkert.org{
6357007Snate@binkert.org    // Get iterator of next item on the list
6367007Snate@binkert.org    // Delete the original iterator
6376657Snate@binkert.org    // Determine if the next item is either the end of the list or younger
6386657Snate@binkert.org    // than the new instruction.  If so, then add in a new iterator right here.
6397007Snate@binkert.org    // If not, then move along.
6407007Snate@binkert.org    ListOrderEntry queue_entry;
6417007Snate@binkert.org    OpClass op_class = (*list_order_it).queueType;
6426657Snate@binkert.org    ListOrderIt next_it = list_order_it;
6436657Snate@binkert.org
6447007Snate@binkert.org    ++next_it;
6457007Snate@binkert.org
6467007Snate@binkert.org    queue_entry.queueType = op_class;
6476902SBrad.Beckmann@amd.com    queue_entry.oldestInst = readyInsts[op_class].top()->seqNum;
6486902SBrad.Beckmann@amd.com
6496902SBrad.Beckmann@amd.com    while (next_it != listOrder.end() &&
6506902SBrad.Beckmann@amd.com           (*next_it).oldestInst < queue_entry.oldestInst) {
6516902SBrad.Beckmann@amd.com        ++next_it;
6526902SBrad.Beckmann@amd.com    }
6536902SBrad.Beckmann@amd.com
6546902SBrad.Beckmann@amd.com    readyIt[op_class] = listOrder.insert(next_it, queue_entry);
6556902SBrad.Beckmann@amd.com}
6566902SBrad.Beckmann@amd.com
6576902SBrad.Beckmann@amd.comtemplate <class Impl>
6586902SBrad.Beckmann@amd.comvoid
6596902SBrad.Beckmann@amd.comInstructionQueue<Impl>::processFUCompletion(DynInstPtr &inst, int fu_idx)
6606902SBrad.Beckmann@amd.com{
6616902SBrad.Beckmann@amd.com    // The CPU could have been sleeping until this op completed (*extremely*
6626902SBrad.Beckmann@amd.com    // long latency op).  Wake it if it was.  This may be overkill.
6636902SBrad.Beckmann@amd.com    if (isSwitchedOut()) {
6646902SBrad.Beckmann@amd.com        return;
6656902SBrad.Beckmann@amd.com    }
6666902SBrad.Beckmann@amd.com
6676902SBrad.Beckmann@amd.com    iewStage->wakeCPU();
6686902SBrad.Beckmann@amd.com
6696902SBrad.Beckmann@amd.com    if (fu_idx > -1)
6706902SBrad.Beckmann@amd.com        fuPool->freeUnitNextCycle(fu_idx);
6716902SBrad.Beckmann@amd.com
6726902SBrad.Beckmann@amd.com    // @todo: Ensure that these FU Completions happen at the beginning
6736902SBrad.Beckmann@amd.com    // of a cycle, otherwise they could add too many instructions to
6746902SBrad.Beckmann@amd.com    // the queue.
6756902SBrad.Beckmann@amd.com    issueToExecuteQueue->access(0)->size++;
6766902SBrad.Beckmann@amd.com    instsToExecute.push_back(inst);
6776902SBrad.Beckmann@amd.com}
6786657Snate@binkert.org
6796657Snate@binkert.org// @todo: Figure out a better way to remove the squashed items from the
6806657Snate@binkert.org// lists.  Checking the top item of each list to see if it's squashed
6816657Snate@binkert.org// wastes time and forces jumps.
6826657Snate@binkert.orgtemplate <class Impl>
6836657Snate@binkert.orgvoid
6846657Snate@binkert.orgInstructionQueue<Impl>::scheduleReadyInsts()
6856657Snate@binkert.org{
6866657Snate@binkert.org    DPRINTF(IQ, "Attempting to schedule ready instructions from "
6877007Snate@binkert.org            "the IQ.\n");
6887007Snate@binkert.org
6896657Snate@binkert.org    IssueStruct *i2e_info = issueToExecuteQueue->access(0);
6906657Snate@binkert.org
6916657Snate@binkert.org    // Have iterator to head of the list
6926657Snate@binkert.org    // While I haven't exceeded bandwidth or reached the end of the list,
6936657Snate@binkert.org    // Try to get a FU that can do what this op needs.
6946657Snate@binkert.org    // If successful, change the oldestInst to the new top of the list, put
6956657Snate@binkert.org    // the queue in the proper place in the list.
6966657Snate@binkert.org    // Increment the iterator.
6976657Snate@binkert.org    // This will avoid trying to schedule a certain op class if there are no
6986657Snate@binkert.org    // FUs that handle it.
6996657Snate@binkert.org    ListOrderIt order_it = listOrder.begin();
7006999Snate@binkert.org    ListOrderIt order_end_it = listOrder.end();
7016657Snate@binkert.org    int total_issued = 0;
7026657Snate@binkert.org
7036657Snate@binkert.org    while (total_issued < totalWidth &&
7046657Snate@binkert.org           order_it != order_end_it) {
7056657Snate@binkert.org        OpClass op_class = (*order_it).queueType;
7066657Snate@binkert.org
7077007Snate@binkert.org        assert(!readyInsts[op_class].empty());
7086657Snate@binkert.org
7096657Snate@binkert.org        DynInstPtr issuing_inst = readyInsts[op_class].top();
7106657Snate@binkert.org
7116657Snate@binkert.org        assert(issuing_inst->seqNum == (*order_it).oldestInst);
7126657Snate@binkert.org
7136657Snate@binkert.org        if (issuing_inst->isSquashed()) {
7146657Snate@binkert.org            readyInsts[op_class].pop();
7156657Snate@binkert.org
7167007Snate@binkert.org            if (!readyInsts[op_class].empty()) {
7177007Snate@binkert.org                moveToYoungerInst(order_it);
7186657Snate@binkert.org            } else {
7197007Snate@binkert.org                readyIt[op_class] = listOrder.end();
7207007Snate@binkert.org                queueOnList[op_class] = false;
7216657Snate@binkert.org            }
7226657Snate@binkert.org
7236657Snate@binkert.org            listOrder.erase(order_it++);
7246657Snate@binkert.org
7256657Snate@binkert.org            ++iqSquashedInstsIssued;
7266657Snate@binkert.org
7277007Snate@binkert.org            continue;
7287007Snate@binkert.org        }
7297007Snate@binkert.org
7307007Snate@binkert.org        int idx = -2;
7317007Snate@binkert.org        int op_latency = 1;
7326657Snate@binkert.org        int tid = issuing_inst->threadNumber;
7336657Snate@binkert.org
7346657Snate@binkert.org        if (op_class != No_OpClass) {
7356657Snate@binkert.org            idx = fuPool->getUnit(op_class);
7366657Snate@binkert.org
7376657Snate@binkert.org            if (idx > -1) {
7386657Snate@binkert.org                op_latency = fuPool->getOpLatency(op_class);
7396657Snate@binkert.org            }
7406657Snate@binkert.org        }
7416657Snate@binkert.org
7426657Snate@binkert.org        // If we have an instruction that doesn't require a FU, or a
7436657Snate@binkert.org        // valid FU, then schedule for execution.
7446657Snate@binkert.org        if (idx == -2 || idx != -1) {
7456657Snate@binkert.org            if (op_latency == 1) {
7466657Snate@binkert.org                i2e_info->size++;
7476657Snate@binkert.org                instsToExecute.push_back(issuing_inst);
7486657Snate@binkert.org
7496657Snate@binkert.org                // Add the FU onto the list of FU's to be freed next
7506657Snate@binkert.org                // cycle if we used one.
7516657Snate@binkert.org                if (idx >= 0)
7526657Snate@binkert.org                    fuPool->freeUnitNextCycle(idx);
7536657Snate@binkert.org            } else {
7547007Snate@binkert.org                int issue_latency = fuPool->getIssueLatency(op_class);
7557007Snate@binkert.org                // Generate completion event for the FU
7566657Snate@binkert.org                FUCompletion *execution = new FUCompletion(issuing_inst,
7576657Snate@binkert.org                                                           idx, this);
7586657Snate@binkert.org
7596657Snate@binkert.org                execution->schedule(curTick + cpu->cycles(issue_latency - 1));
7606657Snate@binkert.org
7616657Snate@binkert.org                // @todo: Enforce that issue_latency == 1 or op_latency
7626657Snate@binkert.org                if (issue_latency > 1) {
7636657Snate@binkert.org                    // If FU isn't pipelined, then it must be freed
7646999Snate@binkert.org                    // upon the execution completing.
7656657Snate@binkert.org                    execution->setFreeFU();
7666657Snate@binkert.org                } else {
7676657Snate@binkert.org                    // Add the FU onto the list of FU's to be freed next cycle.
7686657Snate@binkert.org                    fuPool->freeUnitNextCycle(idx);
7696657Snate@binkert.org                }
7706657Snate@binkert.org            }
7716657Snate@binkert.org
7726657Snate@binkert.org            DPRINTF(IQ, "Thread %i: Issuing instruction PC %#x "
7736657Snate@binkert.org                    "[sn:%lli]\n",
7746657Snate@binkert.org                    tid, issuing_inst->readPC(),
7756657Snate@binkert.org                    issuing_inst->seqNum);
7766657Snate@binkert.org
7776657Snate@binkert.org            readyInsts[op_class].pop();
7786657Snate@binkert.org
7796657Snate@binkert.org            if (!readyInsts[op_class].empty()) {
7806657Snate@binkert.org                moveToYoungerInst(order_it);
7816657Snate@binkert.org            } else {
7826657Snate@binkert.org                readyIt[op_class] = listOrder.end();
7837007Snate@binkert.org                queueOnList[op_class] = false;
7847007Snate@binkert.org            }
7857007Snate@binkert.org
7867007Snate@binkert.org            issuing_inst->setIssued();
7876657Snate@binkert.org            ++total_issued;
7886657Snate@binkert.org
7896657Snate@binkert.org            if (!issuing_inst->isMemRef()) {
7906657Snate@binkert.org                // Memory instructions can not be freed from the IQ until they
7916657Snate@binkert.org                // complete.
7926657Snate@binkert.org                ++freeEntries;
7936657Snate@binkert.org                count[tid]--;
7946657Snate@binkert.org                issuing_inst->removeInIQ();
7956657Snate@binkert.org            } else {
7966657Snate@binkert.org                memDepUnit[tid].issue(issuing_inst);
7977007Snate@binkert.org            }
7987007Snate@binkert.org
7996657Snate@binkert.org            listOrder.erase(order_it++);
8006657Snate@binkert.org            statIssuedInstType[tid][op_class]++;
8016657Snate@binkert.org        } else {
8026657Snate@binkert.org            statFuBusy[op_class]++;
8036657Snate@binkert.org            fuBusy[tid]++;
8046657Snate@binkert.org            ++order_it;
8057007Snate@binkert.org        }
8067007Snate@binkert.org    }
8076657Snate@binkert.org
8086657Snate@binkert.org    numIssuedDist.sample(total_issued);
8097007Snate@binkert.org    iqInstsIssued+= total_issued;
8107007Snate@binkert.org
8116657Snate@binkert.org    // If we issued any instructions, tell the CPU we had activity.
8126657Snate@binkert.org    if (total_issued) {
8136657Snate@binkert.org        cpu->activityThisCycle();
8146657Snate@binkert.org    } else {
8156657Snate@binkert.org        DPRINTF(IQ, "Not able to schedule any instructions.\n");
8166657Snate@binkert.org    }
8177007Snate@binkert.org}
8187007Snate@binkert.org
8196657Snate@binkert.orgtemplate <class Impl>
8206657Snate@binkert.orgvoid
8216657Snate@binkert.orgInstructionQueue<Impl>::scheduleNonSpec(const InstSeqNum &inst)
8226657Snate@binkert.org{
8236657Snate@binkert.org    DPRINTF(IQ, "Marking nonspeculative instruction [sn:%lli] as ready "
8246657Snate@binkert.org            "to execute.\n", inst);
8256657Snate@binkert.org
8266657Snate@binkert.org    NonSpecMapIt inst_it = nonSpecInsts.find(inst);
8276657Snate@binkert.org
8287007Snate@binkert.org    assert(inst_it != nonSpecInsts.end());
8297007Snate@binkert.org
8306657Snate@binkert.org    unsigned tid = (*inst_it).second->threadNumber;
8316657Snate@binkert.org
8326657Snate@binkert.org    (*inst_it).second->setCanIssue();
8336657Snate@binkert.org
8346657Snate@binkert.org    if (!(*inst_it).second->isMemRef()) {
8356657Snate@binkert.org        addIfReady((*inst_it).second);
8366657Snate@binkert.org    } else {
8376657Snate@binkert.org        memDepUnit[tid].nonSpecInstReady((*inst_it).second);
8386657Snate@binkert.org    }
8396657Snate@binkert.org
8407007Snate@binkert.org    (*inst_it).second = NULL;
8417007Snate@binkert.org
8427007Snate@binkert.org    nonSpecInsts.erase(inst_it);
8437007Snate@binkert.org}
8447007Snate@binkert.org
8456657Snate@binkert.orgtemplate <class Impl>
8466657Snate@binkert.orgvoid
8476657Snate@binkert.orgInstructionQueue<Impl>::commit(const InstSeqNum &inst, unsigned tid)
8486657Snate@binkert.org{
8496657Snate@binkert.org    DPRINTF(IQ, "[tid:%i]: Committing instructions older than [sn:%i]\n",
8506657Snate@binkert.org            tid,inst);
8516657Snate@binkert.org
8526657Snate@binkert.org    ListIt iq_it = instList[tid].begin();
8536657Snate@binkert.org
8546657Snate@binkert.org    while (iq_it != instList[tid].end() &&
8556657Snate@binkert.org           (*iq_it)->seqNum <= inst) {
8566999Snate@binkert.org        ++iq_it;
8576657Snate@binkert.org        instList[tid].pop_front();
8586657Snate@binkert.org    }
8596657Snate@binkert.org
8606657Snate@binkert.org    assert(freeEntries == (numEntries - countInsts()));
8616657Snate@binkert.org}
8626657Snate@binkert.org
8636657Snate@binkert.orgtemplate <class Impl>
8646657Snate@binkert.orgint
8656657Snate@binkert.orgInstructionQueue<Impl>::wakeDependents(DynInstPtr &completed_inst)
8666657Snate@binkert.org{
8676657Snate@binkert.org    int dependents = 0;
8686657Snate@binkert.org
8696657Snate@binkert.org    DPRINTF(IQ, "Waking dependents of completed instruction.\n");
8707007Snate@binkert.org
8716657Snate@binkert.org    assert(!completed_inst->isSquashed());
8726657Snate@binkert.org
8736657Snate@binkert.org    // Tell the memory dependence unit to wake any dependents on this
8746657Snate@binkert.org    // instruction if it is a memory instruction.  Also complete the memory
8756657Snate@binkert.org    // instruction at this point since we know it executed without issues.
8766657Snate@binkert.org    // @todo: Might want to rename "completeMemInst" to something that
8776657Snate@binkert.org    // indicates that it won't need to be replayed, and call this
8786657Snate@binkert.org    // earlier.  Might not be a big deal.
8796657Snate@binkert.org    if (completed_inst->isMemRef()) {
8806657Snate@binkert.org        memDepUnit[completed_inst->threadNumber].wakeDependents(completed_inst);
8816657Snate@binkert.org        completeMemInst(completed_inst);
8826657Snate@binkert.org    } else if (completed_inst->isMemBarrier() ||
8836657Snate@binkert.org               completed_inst->isWriteBarrier()) {
8846657Snate@binkert.org        memDepUnit[completed_inst->threadNumber].completeBarrier(completed_inst);
8856657Snate@binkert.org    }
8866657Snate@binkert.org
8876657Snate@binkert.org    for (int dest_reg_idx = 0;
8886657Snate@binkert.org         dest_reg_idx < completed_inst->numDestRegs();
8896657Snate@binkert.org         dest_reg_idx++)
8906657Snate@binkert.org    {
8916657Snate@binkert.org        PhysRegIndex dest_reg =
8926657Snate@binkert.org            completed_inst->renamedDestRegIdx(dest_reg_idx);
8936657Snate@binkert.org
8946657Snate@binkert.org        // Special case of uniq or control registers.  They are not
8956657Snate@binkert.org        // handled by the IQ and thus have no dependency graph entry.
8966657Snate@binkert.org        // @todo Figure out a cleaner way to handle this.
8976657Snate@binkert.org        if (dest_reg >= numPhysRegs) {
8986657Snate@binkert.org            continue;
8996657Snate@binkert.org        }
9006657Snate@binkert.org
9016657Snate@binkert.org        DPRINTF(IQ, "Waking any dependents on register %i.\n",
9026657Snate@binkert.org                (int) dest_reg);
9036657Snate@binkert.org
9046657Snate@binkert.org        //Go through the dependency chain, marking the registers as
9056657Snate@binkert.org        //ready within the waiting instructions.
9066657Snate@binkert.org        DynInstPtr dep_inst = dependGraph.pop(dest_reg);
9076657Snate@binkert.org
9086657Snate@binkert.org        while (dep_inst) {
9096657Snate@binkert.org            DPRINTF(IQ, "Waking up a dependent instruction, PC%#x.\n",
9106657Snate@binkert.org                    dep_inst->readPC());
9116657Snate@binkert.org
9126657Snate@binkert.org            // Might want to give more information to the instruction
9136657Snate@binkert.org            // so that it knows which of its source registers is
9146657Snate@binkert.org            // ready.  However that would mean that the dependency
9156657Snate@binkert.org            // graph entries would need to hold the src_reg_idx.
9166657Snate@binkert.org            dep_inst->markSrcRegReady();
9176657Snate@binkert.org
9186657Snate@binkert.org            addIfReady(dep_inst);
9196657Snate@binkert.org
9206657Snate@binkert.org            dep_inst = dependGraph.pop(dest_reg);
9216657Snate@binkert.org
9226657Snate@binkert.org            ++dependents;
9236657Snate@binkert.org        }
9246657Snate@binkert.org
9256657Snate@binkert.org        // Reset the head node now that all of its dependents have
9266657Snate@binkert.org        // been woken up.
9276657Snate@binkert.org        assert(dependGraph.empty(dest_reg));
9286999Snate@binkert.org        dependGraph.clearInst(dest_reg);
9296657Snate@binkert.org
9306657Snate@binkert.org        // Mark the scoreboard as having that register ready.
9316657Snate@binkert.org        regScoreboard[dest_reg] = true;
9326657Snate@binkert.org    }
9336657Snate@binkert.org    return dependents;
9346657Snate@binkert.org}
9357007Snate@binkert.org
9367007Snate@binkert.orgtemplate <class Impl>
9376657Snate@binkert.orgvoid
9387002Snate@binkert.orgInstructionQueue<Impl>::addReadyMemInst(DynInstPtr &ready_inst)
9397002Snate@binkert.org{
9406657Snate@binkert.org    OpClass op_class = ready_inst->opClass();
9416657Snate@binkert.org
9426657Snate@binkert.org    readyInsts[op_class].push(ready_inst);
9436657Snate@binkert.org
9447007Snate@binkert.org    // Will need to reorder the list if either a queue is not on the list,
9457007Snate@binkert.org    // or it has an older instruction than last time.
9466657Snate@binkert.org    if (!queueOnList[op_class]) {
9476657Snate@binkert.org        addToOrderList(op_class);
9486657Snate@binkert.org    } else if (readyInsts[op_class].top()->seqNum  <
9496657Snate@binkert.org               (*readyIt[op_class]).oldestInst) {
9506657Snate@binkert.org        listOrder.erase(readyIt[op_class]);
9517002Snate@binkert.org        addToOrderList(op_class);
9526657Snate@binkert.org    }
9536657Snate@binkert.org
9546657Snate@binkert.org    DPRINTF(IQ, "Instruction is ready to issue, putting it onto "
9556657Snate@binkert.org            "the ready list, PC %#x opclass:%i [sn:%lli].\n",
9566657Snate@binkert.org            ready_inst->readPC(), op_class, ready_inst->seqNum);
9576657Snate@binkert.org}
9586657Snate@binkert.org
9596657Snate@binkert.orgtemplate <class Impl>
9606657Snate@binkert.orgvoid
9617007Snate@binkert.orgInstructionQueue<Impl>::rescheduleMemInst(DynInstPtr &resched_inst)
9626657Snate@binkert.org{
9636657Snate@binkert.org    memDepUnit[resched_inst->threadNumber].reschedule(resched_inst);
9646657Snate@binkert.org}
9656657Snate@binkert.org
9666999Snate@binkert.orgtemplate <class Impl>
9676657Snate@binkert.orgvoid
9686657Snate@binkert.orgInstructionQueue<Impl>::replayMemInst(DynInstPtr &replay_inst)
9696657Snate@binkert.org{
9706657Snate@binkert.org    memDepUnit[replay_inst->threadNumber].replay(replay_inst);
9716657Snate@binkert.org}
9726657Snate@binkert.org
9736657Snate@binkert.orgtemplate <class Impl>
9746657Snate@binkert.orgvoid
9756657Snate@binkert.orgInstructionQueue<Impl>::completeMemInst(DynInstPtr &completed_inst)
9766657Snate@binkert.org{
9776657Snate@binkert.org    int tid = completed_inst->threadNumber;
9786657Snate@binkert.org
9796657Snate@binkert.org    DPRINTF(IQ, "Completing mem instruction PC:%#x [sn:%lli]\n",
9806657Snate@binkert.org            completed_inst->readPC(), completed_inst->seqNum);
9816657Snate@binkert.org
9826657Snate@binkert.org    ++freeEntries;
9836657Snate@binkert.org
9846657Snate@binkert.org    completed_inst->memOpDone = true;
9856657Snate@binkert.org
9866657Snate@binkert.org    memDepUnit[tid].completed(completed_inst);
9877007Snate@binkert.org
9887007Snate@binkert.org    count[tid]--;
9897007Snate@binkert.org}
9906657Snate@binkert.org
9916657Snate@binkert.orgtemplate <class Impl>
9926657Snate@binkert.orgvoid
9937007Snate@binkert.orgInstructionQueue<Impl>::violation(DynInstPtr &store,
9947007Snate@binkert.org                                  DynInstPtr &faulting_load)
9957007Snate@binkert.org{
9966657Snate@binkert.org    memDepUnit[store->threadNumber].violation(store, faulting_load);
9976657Snate@binkert.org}
9986657Snate@binkert.org
9996657Snate@binkert.orgtemplate <class Impl>
10006657Snate@binkert.orgvoid
10016657Snate@binkert.orgInstructionQueue<Impl>::squash(unsigned tid)
10026657Snate@binkert.org{
10036657Snate@binkert.org    DPRINTF(IQ, "[tid:%i]: Starting to squash instructions in "
10046657Snate@binkert.org            "the IQ.\n", tid);
10056657Snate@binkert.org
10066657Snate@binkert.org    // Read instruction sequence number of last instruction out of the
10077007Snate@binkert.org    // time buffer.
10087007Snate@binkert.org    squashedSeqNum[tid] = fromCommit->commitInfo[tid].doneSeqNum;
10096657Snate@binkert.org
10106657Snate@binkert.org    // Call doSquash if there are insts in the IQ
10116657Snate@binkert.org    if (count[tid] > 0) {
10126657Snate@binkert.org        doSquash(tid);
10136657Snate@binkert.org    }
10147007Snate@binkert.org
10157007Snate@binkert.org    // Also tell the memory dependence unit to squash.
10167007Snate@binkert.org    memDepUnit[tid].squash(squashedSeqNum[tid], tid);
10176657Snate@binkert.org}
10186657Snate@binkert.org
10196657Snate@binkert.orgtemplate <class Impl>
10207007Snate@binkert.orgvoid
10217007Snate@binkert.orgInstructionQueue<Impl>::doSquash(unsigned tid)
10227007Snate@binkert.org{
10236657Snate@binkert.org    // Start at the tail.
10247002Snate@binkert.org    ListIt squash_it = instList[tid].end();
10257002Snate@binkert.org    --squash_it;
10266657Snate@binkert.org
10276657Snate@binkert.org    DPRINTF(IQ, "[tid:%i]: Squashing until sequence number %i!\n",
10286657Snate@binkert.org            tid, squashedSeqNum[tid]);
10296657Snate@binkert.org
10306657Snate@binkert.org    // Squash any instructions younger than the squashed sequence number
10316657Snate@binkert.org    // given.
10326657Snate@binkert.org    while (squash_it != instList[tid].end() &&
10336657Snate@binkert.org           (*squash_it)->seqNum > squashedSeqNum[tid]) {
10346657Snate@binkert.org
10356657Snate@binkert.org        DynInstPtr squashed_inst = (*squash_it);
10366657Snate@binkert.org
10376657Snate@binkert.org        // Only handle the instruction if it actually is in the IQ and
10387007Snate@binkert.org        // hasn't already been squashed in the IQ.
10397007Snate@binkert.org        if (squashed_inst->threadNumber != tid ||
10406657Snate@binkert.org            squashed_inst->isSquashedInIQ()) {
10416657Snate@binkert.org            --squash_it;
10426657Snate@binkert.org            continue;
10436657Snate@binkert.org        }
10446657Snate@binkert.org
10456657Snate@binkert.org        if (!squashed_inst->isIssued() ||
10466657Snate@binkert.org            (squashed_inst->isMemRef() &&
10476657Snate@binkert.org             !squashed_inst->memOpDone)) {
10486657Snate@binkert.org
10496657Snate@binkert.org            // Remove the instruction from the dependency list.
10506657Snate@binkert.org            if (!squashed_inst->isNonSpeculative() &&
10516657Snate@binkert.org                !squashed_inst->isStoreConditional() &&
10526657Snate@binkert.org                !squashed_inst->isMemBarrier() &&
10536657Snate@binkert.org                !squashed_inst->isWriteBarrier()) {
10546657Snate@binkert.org
10557007Snate@binkert.org                for (int src_reg_idx = 0;
10566999Snate@binkert.org                     src_reg_idx < squashed_inst->numSrcRegs();
10577007Snate@binkert.org                     src_reg_idx++)
10587007Snate@binkert.org                {
10597007Snate@binkert.org                    PhysRegIndex src_reg =
10607007Snate@binkert.org                        squashed_inst->renamedSrcRegIdx(src_reg_idx);
10617007Snate@binkert.org
10627007Snate@binkert.org                    // Only remove it from the dependency graph if it
10636657Snate@binkert.org                    // was placed there in the first place.
10646657Snate@binkert.org
10656657Snate@binkert.org                    // Instead of doing a linked list traversal, we
10666657Snate@binkert.org                    // can just remove these squashed instructions
10676657Snate@binkert.org                    // either at issue time, or when the register is
10686657Snate@binkert.org                    // overwritten.  The only downside to this is it
10696657Snate@binkert.org                    // leaves more room for error.
10706657Snate@binkert.org
10716657Snate@binkert.org                    if (!squashed_inst->isReadySrcRegIdx(src_reg_idx) &&
10726657Snate@binkert.org                        src_reg < numPhysRegs) {
10736657Snate@binkert.org                        dependGraph.remove(src_reg, squashed_inst);
10746657Snate@binkert.org                    }
10756657Snate@binkert.org
10766657Snate@binkert.org
10776657Snate@binkert.org                    ++iqSquashedOperandsExamined;
10786657Snate@binkert.org                }
10796657Snate@binkert.org            } else {
10806657Snate@binkert.org                NonSpecMapIt ns_inst_it =
10816657Snate@binkert.org                    nonSpecInsts.find(squashed_inst->seqNum);
10826657Snate@binkert.org                assert(ns_inst_it != nonSpecInsts.end());
10836657Snate@binkert.org
10846657Snate@binkert.org                (*ns_inst_it).second = NULL;
10856657Snate@binkert.org
10866657Snate@binkert.org                nonSpecInsts.erase(ns_inst_it);
10876657Snate@binkert.org
10886657Snate@binkert.org                ++iqSquashedNonSpecRemoved;
10896657Snate@binkert.org            }
10906657Snate@binkert.org
10916657Snate@binkert.org            // Might want to also clear out the head of the dependency graph.
10926999Snate@binkert.org
10936657Snate@binkert.org            // Mark it as squashed within the IQ.
10946657Snate@binkert.org            squashed_inst->setSquashedInIQ();
10957007Snate@binkert.org
10967007Snate@binkert.org            // @todo: Remove this hack where several statuses are set so the
10976657Snate@binkert.org            // inst will flow through the rest of the pipeline.
10986657Snate@binkert.org            squashed_inst->setIssued();
10996657Snate@binkert.org            squashed_inst->setCanCommit();
11006657Snate@binkert.org            squashed_inst->removeInIQ();
11016657Snate@binkert.org
11026657Snate@binkert.org            //Update Thread IQ Count
11036657Snate@binkert.org            count[squashed_inst->threadNumber]--;
11046657Snate@binkert.org
11056657Snate@binkert.org            ++freeEntries;
11066657Snate@binkert.org
11076657Snate@binkert.org            DPRINTF(IQ, "[tid:%i]: Instruction [sn:%lli] PC %#x "
11086657Snate@binkert.org                    "squashed.\n",
11096657Snate@binkert.org                    tid, squashed_inst->seqNum, squashed_inst->readPC());
11106657Snate@binkert.org        }
11116657Snate@binkert.org
11126657Snate@binkert.org        instList[tid].erase(squash_it--);
11136657Snate@binkert.org        ++iqSquashedInstsExamined;
11146657Snate@binkert.org    }
11156657Snate@binkert.org}
11166657Snate@binkert.org
11176657Snate@binkert.orgtemplate <class Impl>
11186657Snate@binkert.orgbool
11196657Snate@binkert.orgInstructionQueue<Impl>::addToDependents(DynInstPtr &new_inst)
11206657Snate@binkert.org{
11216657Snate@binkert.org    // Loop through the instruction's source registers, adding
11226657Snate@binkert.org    // them to the dependency list if they are not ready.
11236657Snate@binkert.org    int8_t total_src_regs = new_inst->numSrcRegs();
11246657Snate@binkert.org    bool return_val = false;
11256657Snate@binkert.org
11266657Snate@binkert.org    for (int src_reg_idx = 0;
11276657Snate@binkert.org         src_reg_idx < total_src_regs;
11286657Snate@binkert.org         src_reg_idx++)
11296657Snate@binkert.org    {
11306657Snate@binkert.org        // Only add it to the dependency graph if it's not ready.
11316657Snate@binkert.org        if (!new_inst->isReadySrcRegIdx(src_reg_idx)) {
11326657Snate@binkert.org            PhysRegIndex src_reg = new_inst->renamedSrcRegIdx(src_reg_idx);
11336657Snate@binkert.org
11346657Snate@binkert.org            // Check the IQ's scoreboard to make sure the register
11356657Snate@binkert.org            // hasn't become ready while the instruction was in flight
11366657Snate@binkert.org            // between stages.  Only if it really isn't ready should
11376657Snate@binkert.org            // it be added to the dependency graph.
11386657Snate@binkert.org            if (src_reg >= numPhysRegs) {
11396657Snate@binkert.org                continue;
11406657Snate@binkert.org            } else if (regScoreboard[src_reg] == false) {
11416657Snate@binkert.org                DPRINTF(IQ, "Instruction PC %#x has src reg %i that "
11426657Snate@binkert.org                        "is being added to the dependency chain.\n",
11436657Snate@binkert.org                        new_inst->readPC(), src_reg);
11446657Snate@binkert.org
11456657Snate@binkert.org                dependGraph.insert(src_reg, new_inst);
11466657Snate@binkert.org
11476657Snate@binkert.org                // Change the return value to indicate that something
11486657Snate@binkert.org                // was added to the dependency graph.
11496657Snate@binkert.org                return_val = true;
11506657Snate@binkert.org            } else {
11516657Snate@binkert.org                DPRINTF(IQ, "Instruction PC %#x has src reg %i that "
11526657Snate@binkert.org                        "became ready before it reached the IQ.\n",
11536657Snate@binkert.org                        new_inst->readPC(), src_reg);
11546657Snate@binkert.org                // Mark a register ready within the instruction.
11556657Snate@binkert.org                new_inst->markSrcRegReady(src_reg_idx);
11566657Snate@binkert.org            }
11576657Snate@binkert.org        }
11586657Snate@binkert.org    }
11596657Snate@binkert.org
11606657Snate@binkert.org    return return_val;
11616657Snate@binkert.org}
11626657Snate@binkert.org
11636657Snate@binkert.orgtemplate <class Impl>
11646657Snate@binkert.orgvoid
11656657Snate@binkert.orgInstructionQueue<Impl>::addToProducers(DynInstPtr &new_inst)
11666657Snate@binkert.org{
11676657Snate@binkert.org    // Nothing really needs to be marked when an instruction becomes
11686657Snate@binkert.org    // the producer of a register's value, but for convenience a ptr
11696657Snate@binkert.org    // to the producing instruction will be placed in the head node of
11706657Snate@binkert.org    // the dependency links.
11716657Snate@binkert.org    int8_t total_dest_regs = new_inst->numDestRegs();
11726657Snate@binkert.org
11736657Snate@binkert.org    for (int dest_reg_idx = 0;
11746657Snate@binkert.org         dest_reg_idx < total_dest_regs;
11756657Snate@binkert.org         dest_reg_idx++)
11766657Snate@binkert.org    {
11776657Snate@binkert.org        PhysRegIndex dest_reg = new_inst->renamedDestRegIdx(dest_reg_idx);
11786657Snate@binkert.org
11796657Snate@binkert.org        // Instructions that use the misc regs will have a reg number
11806657Snate@binkert.org        // higher than the normal physical registers.  In this case these
11816657Snate@binkert.org        // registers are not renamed, and there is no need to track
11826657Snate@binkert.org        // dependencies as these instructions must be executed at commit.
11836657Snate@binkert.org        if (dest_reg >= numPhysRegs) {
11846657Snate@binkert.org            continue;
11857007Snate@binkert.org        }
11866657Snate@binkert.org
11876657Snate@binkert.org        if (!dependGraph.empty(dest_reg)) {
11886657Snate@binkert.org            dependGraph.dump();
11896657Snate@binkert.org            panic("Dependency graph %i not empty!", dest_reg);
11906657Snate@binkert.org        }
11916657Snate@binkert.org
11926657Snate@binkert.org        dependGraph.setInst(dest_reg, new_inst);
11937007Snate@binkert.org
11946657Snate@binkert.org        // Mark the scoreboard to say it's not yet ready.
11956657Snate@binkert.org        regScoreboard[dest_reg] = false;
11966657Snate@binkert.org    }
11976657Snate@binkert.org}
11986657Snate@binkert.org
11996657Snate@binkert.orgtemplate <class Impl>
12006657Snate@binkert.orgvoid
12016657Snate@binkert.orgInstructionQueue<Impl>::addIfReady(DynInstPtr &inst)
12026657Snate@binkert.org{
12036657Snate@binkert.org    // If the instruction now has all of its source registers
12046657Snate@binkert.org    // available, then add it to the list of ready instructions.
12056657Snate@binkert.org    if (inst->readyToIssue()) {
12066657Snate@binkert.org
12076657Snate@binkert.org        //Add the instruction to the proper ready list.
12086657Snate@binkert.org        if (inst->isMemRef()) {
12097007Snate@binkert.org
12106657Snate@binkert.org            DPRINTF(IQ, "Checking if memory instruction can issue.\n");
12116657Snate@binkert.org
12126657Snate@binkert.org            // Message to the mem dependence unit that this instruction has
12136657Snate@binkert.org            // its registers ready.
12146657Snate@binkert.org            memDepUnit[inst->threadNumber].regsReady(inst);
12156657Snate@binkert.org
12166657Snate@binkert.org            return;
12176657Snate@binkert.org        }
12186657Snate@binkert.org
12196657Snate@binkert.org        OpClass op_class = inst->opClass();
12206657Snate@binkert.org
12216657Snate@binkert.org        DPRINTF(IQ, "Instruction is ready to issue, putting it onto "
12226657Snate@binkert.org                "the ready list, PC %#x opclass:%i [sn:%lli].\n",
12236657Snate@binkert.org                inst->readPC(), op_class, inst->seqNum);
12246657Snate@binkert.org
12256657Snate@binkert.org        readyInsts[op_class].push(inst);
12266657Snate@binkert.org
12276657Snate@binkert.org        // Will need to reorder the list if either a queue is not on the list,
12286657Snate@binkert.org        // or it has an older instruction than last time.
12296657Snate@binkert.org        if (!queueOnList[op_class]) {
12306657Snate@binkert.org            addToOrderList(op_class);
12316657Snate@binkert.org        } else if (readyInsts[op_class].top()->seqNum  <
1232                   (*readyIt[op_class]).oldestInst) {
1233            listOrder.erase(readyIt[op_class]);
1234            addToOrderList(op_class);
1235        }
1236    }
1237}
1238
1239template <class Impl>
1240int
1241InstructionQueue<Impl>::countInsts()
1242{
1243#if 0
1244    //ksewell:This works but definitely could use a cleaner write
1245    //with a more intuitive way of counting. Right now it's
1246    //just brute force ....
1247    // Change the #if if you want to use this method.
1248    int total_insts = 0;
1249
1250    for (int i = 0; i < numThreads; ++i) {
1251        ListIt count_it = instList[i].begin();
1252
1253        while (count_it != instList[i].end()) {
1254            if (!(*count_it)->isSquashed() && !(*count_it)->isSquashedInIQ()) {
1255                if (!(*count_it)->isIssued()) {
1256                    ++total_insts;
1257                } else if ((*count_it)->isMemRef() &&
1258                           !(*count_it)->memOpDone) {
1259                    // Loads that have not been marked as executed still count
1260                    // towards the total instructions.
1261                    ++total_insts;
1262                }
1263            }
1264
1265            ++count_it;
1266        }
1267    }
1268
1269    return total_insts;
1270#else
1271    return numEntries - freeEntries;
1272#endif
1273}
1274
1275template <class Impl>
1276void
1277InstructionQueue<Impl>::dumpLists()
1278{
1279    for (int i = 0; i < Num_OpClasses; ++i) {
1280        cprintf("Ready list %i size: %i\n", i, readyInsts[i].size());
1281
1282        cprintf("\n");
1283    }
1284
1285    cprintf("Non speculative list size: %i\n", nonSpecInsts.size());
1286
1287    NonSpecMapIt non_spec_it = nonSpecInsts.begin();
1288    NonSpecMapIt non_spec_end_it = nonSpecInsts.end();
1289
1290    cprintf("Non speculative list: ");
1291
1292    while (non_spec_it != non_spec_end_it) {
1293        cprintf("%#x [sn:%lli]", (*non_spec_it).second->readPC(),
1294                (*non_spec_it).second->seqNum);
1295        ++non_spec_it;
1296    }
1297
1298    cprintf("\n");
1299
1300    ListOrderIt list_order_it = listOrder.begin();
1301    ListOrderIt list_order_end_it = listOrder.end();
1302    int i = 1;
1303
1304    cprintf("List order: ");
1305
1306    while (list_order_it != list_order_end_it) {
1307        cprintf("%i OpClass:%i [sn:%lli] ", i, (*list_order_it).queueType,
1308                (*list_order_it).oldestInst);
1309
1310        ++list_order_it;
1311        ++i;
1312    }
1313
1314    cprintf("\n");
1315}
1316
1317
1318template <class Impl>
1319void
1320InstructionQueue<Impl>::dumpInsts()
1321{
1322    for (int i = 0; i < numThreads; ++i) {
1323        int num = 0;
1324        int valid_num = 0;
1325        ListIt inst_list_it = instList[i].begin();
1326
1327        while (inst_list_it != instList[i].end())
1328        {
1329            cprintf("Instruction:%i\n",
1330                    num);
1331            if (!(*inst_list_it)->isSquashed()) {
1332                if (!(*inst_list_it)->isIssued()) {
1333                    ++valid_num;
1334                    cprintf("Count:%i\n", valid_num);
1335                } else if ((*inst_list_it)->isMemRef() &&
1336                           !(*inst_list_it)->memOpDone) {
1337                    // Loads that have not been marked as executed
1338                    // still count towards the total instructions.
1339                    ++valid_num;
1340                    cprintf("Count:%i\n", valid_num);
1341                }
1342            }
1343
1344            cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n"
1345                    "Issued:%i\nSquashed:%i\n",
1346                    (*inst_list_it)->readPC(),
1347                    (*inst_list_it)->seqNum,
1348                    (*inst_list_it)->threadNumber,
1349                    (*inst_list_it)->isIssued(),
1350                    (*inst_list_it)->isSquashed());
1351
1352            if ((*inst_list_it)->isMemRef()) {
1353                cprintf("MemOpDone:%i\n", (*inst_list_it)->memOpDone);
1354            }
1355
1356            cprintf("\n");
1357
1358            inst_list_it++;
1359            ++num;
1360        }
1361    }
1362
1363    cprintf("Insts to Execute list:\n");
1364
1365    int num = 0;
1366    int valid_num = 0;
1367    ListIt inst_list_it = instsToExecute.begin();
1368
1369    while (inst_list_it != instsToExecute.end())
1370    {
1371        cprintf("Instruction:%i\n",
1372                num);
1373        if (!(*inst_list_it)->isSquashed()) {
1374            if (!(*inst_list_it)->isIssued()) {
1375                ++valid_num;
1376                cprintf("Count:%i\n", valid_num);
1377            } else if ((*inst_list_it)->isMemRef() &&
1378                       !(*inst_list_it)->memOpDone) {
1379                // Loads that have not been marked as executed
1380                // still count towards the total instructions.
1381                ++valid_num;
1382                cprintf("Count:%i\n", valid_num);
1383            }
1384        }
1385
1386        cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n"
1387                "Issued:%i\nSquashed:%i\n",
1388                (*inst_list_it)->readPC(),
1389                (*inst_list_it)->seqNum,
1390                (*inst_list_it)->threadNumber,
1391                (*inst_list_it)->isIssued(),
1392                (*inst_list_it)->isSquashed());
1393
1394        if ((*inst_list_it)->isMemRef()) {
1395            cprintf("MemOpDone:%i\n", (*inst_list_it)->memOpDone);
1396        }
1397
1398        cprintf("\n");
1399
1400        inst_list_it++;
1401        ++num;
1402    }
1403}
1404