rob_impl.hh revision 2307
12623SN/A/*
22623SN/A * Copyright (c) 2004-2005 The Regents of The University of Michigan
32623SN/A * All rights reserved.
42623SN/A *
52623SN/A * Redistribution and use in source and binary forms, with or without
62623SN/A * modification, are permitted provided that the following conditions are
72623SN/A * met: redistributions of source code must retain the above copyright
82623SN/A * notice, this list of conditions and the following disclaimer;
92623SN/A * redistributions in binary form must reproduce the above copyright
102623SN/A * notice, this list of conditions and the following disclaimer in the
112623SN/A * documentation and/or other materials provided with the distribution;
122623SN/A * neither the name of the copyright holders nor the names of its
132623SN/A * contributors may be used to endorse or promote products derived from
142623SN/A * this software without specific prior written permission.
152623SN/A *
162623SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172623SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182623SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192623SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202623SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212623SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222623SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232623SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242623SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252623SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262623SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272665Ssaidi@eecs.umich.edu */
282665Ssaidi@eecs.umich.edu
292623SN/A#include "config/full_system.hh"
302623SN/A#include "cpu/o3/rob.hh"
313170Sstever@eecs.umich.edu
322623SN/Ausing namespace std;
334040Ssaidi@eecs.umich.edu
342623SN/Atemplate <class Impl>
352623SN/AROB<Impl>::ROB(unsigned _numEntries, unsigned _squashWidth,
363348Sbinkertn@umich.edu               string _smtROBPolicy, unsigned _smtROBThreshold,
373348Sbinkertn@umich.edu               unsigned _numThreads)
382623SN/A    : numEntries(_numEntries),
392901Ssaidi@eecs.umich.edu      squashWidth(_squashWidth),
402623SN/A      numInstsInROB(0),
412623SN/A      squashedSeqNum(0),
422623SN/A      numThreads(_numThreads)
432623SN/A{
442856Srdreslin@umich.edu    for (int tid=0; tid  < numThreads; tid++) {
452856Srdreslin@umich.edu        doneSquashing[tid] = true;
462856Srdreslin@umich.edu        threadEntries[tid] = 0;
472856Srdreslin@umich.edu    }
482856Srdreslin@umich.edu
492856Srdreslin@umich.edu    string policy = _smtROBPolicy;
502856Srdreslin@umich.edu
512856Srdreslin@umich.edu    //Convert string to lowercase
522856Srdreslin@umich.edu    std::transform(policy.begin(), policy.end(), policy.begin(),
532856Srdreslin@umich.edu                   (int(*)(int)) tolower);
542623SN/A
552623SN/A    //Figure out rob policy
562623SN/A    if (policy == "dynamic") {
572623SN/A        robPolicy = Dynamic;
582623SN/A
592623SN/A        //Set Max Entries to Total ROB Capacity
602680Sktlim@umich.edu        for (int i = 0; i < numThreads; i++) {
612680Sktlim@umich.edu            maxEntries[i]=numEntries;
622623SN/A        }
632623SN/A
642680Sktlim@umich.edu    } else if (policy == "partitioned") {
652623SN/A        robPolicy = Partitioned;
662623SN/A        DPRINTF(Fetch, "ROB sharing policy set to Partitioned\n");
672623SN/A
682623SN/A        //@todo:make work if part_amt doesnt divide evenly.
692623SN/A        int part_amt = numEntries / numThreads;
703349Sbinkertn@umich.edu
712623SN/A        //Divide ROB up evenly
722623SN/A        for (int i = 0; i < numThreads; i++) {
732623SN/A            maxEntries[i]=part_amt;
742623SN/A        }
752623SN/A
762623SN/A    } else if (policy == "threshold") {
773349Sbinkertn@umich.edu        robPolicy = Threshold;
782623SN/A        DPRINTF(Fetch, "ROB sharing policy set to Threshold\n");
793184Srdreslin@umich.edu
803184Srdreslin@umich.edu        int threshold =  _smtROBThreshold;;
812623SN/A
822623SN/A        //Divide up by threshold amount
832623SN/A        for (int i = 0; i < numThreads; i++) {
842623SN/A            maxEntries[i]=threshold;
852623SN/A        }
863647Srdreslin@umich.edu    } else {
873647Srdreslin@umich.edu        assert(0 && "Invalid ROB Sharing Policy.Options Are:{Dynamic,"
883647Srdreslin@umich.edu                    "Partitioned, Threshold}");
893647Srdreslin@umich.edu    }
903647Srdreslin@umich.edu}
912631SN/A
923647Srdreslin@umich.edutemplate <class Impl>
932631SN/Astd::string
942623SN/AROB<Impl>::name() const
952623SN/A{
962623SN/A    return cpu->name() + ".rob";
972948Ssaidi@eecs.umich.edu}
982948Ssaidi@eecs.umich.edu
993349Sbinkertn@umich.edutemplate <class Impl>
1002948Ssaidi@eecs.umich.eduvoid
1012948Ssaidi@eecs.umich.eduROB<Impl>::setCPU(FullCPU *cpu_ptr)
1022948Ssaidi@eecs.umich.edu{
1032948Ssaidi@eecs.umich.edu    cpu = cpu_ptr;
1042948Ssaidi@eecs.umich.edu
1052623SN/A    // Set the per-thread iterators to the end of the instruction list.
1063170Sstever@eecs.umich.edu    for (int i=0; i < numThreads;i++) {
1073170Sstever@eecs.umich.edu        squashIt[i] = instList[i].end();
1082623SN/A    }
1092623SN/A
1103647Srdreslin@umich.edu    // Initialize the "universal" ROB head & tail point to invalid
1113647Srdreslin@umich.edu    // pointers
1123647Srdreslin@umich.edu    head = instList[0].end();
1133647Srdreslin@umich.edu    tail = instList[0].end();
1142623SN/A}
1152839Sktlim@umich.edu
1162867Sktlim@umich.edutemplate <class Impl>
1173222Sktlim@umich.eduvoid
1182901Ssaidi@eecs.umich.eduROB<Impl>::setActiveThreads(list<unsigned> *at_ptr)
1192623SN/A{
1202623SN/A    DPRINTF(ROB, "Setting active threads list pointer.\n");
1212623SN/A    activeThreads = at_ptr;
1222623SN/A}
1232623SN/A
1242623SN/Atemplate <class Impl>
1252623SN/Avoid
1262623SN/AROB<Impl>::switchOut()
1272623SN/A{
1282623SN/A    for (int tid = 0; tid < numThreads; tid++) {
1292915Sktlim@umich.edu        instList[tid].clear();
1302915Sktlim@umich.edu    }
1312623SN/A}
1322623SN/A
1332623SN/Atemplate <class Impl>
1342623SN/Avoid
1352623SN/AROB<Impl>::takeOverFrom()
1362623SN/A{
1372915Sktlim@umich.edu    for (int tid=0; tid  < numThreads; tid++) {
1382915Sktlim@umich.edu        doneSquashing[tid] = true;
1392623SN/A        threadEntries[tid] = 0;
1402798Sktlim@umich.edu        squashIt[tid] = instList[tid].end();
1412798Sktlim@umich.edu    }
1422901Ssaidi@eecs.umich.edu    numInstsInROB = 0;
1432839Sktlim@umich.edu
1442798Sktlim@umich.edu    // Initialize the "universal" ROB head & tail point to invalid
1452839Sktlim@umich.edu    // pointers
1462798Sktlim@umich.edu    head = instList[0].end();
1472798Sktlim@umich.edu    tail = instList[0].end();
1482901Ssaidi@eecs.umich.edu}
1492901Ssaidi@eecs.umich.edu
1502798Sktlim@umich.edutemplate <class Impl>
1512839Sktlim@umich.eduvoid
1522839Sktlim@umich.eduROB<Impl>::resetEntries()
1532901Ssaidi@eecs.umich.edu{
1542798Sktlim@umich.edu    if (robPolicy != Dynamic || numThreads > 1) {
1552623SN/A        int active_threads = (*activeThreads).size();
1562623SN/A
1572623SN/A        list<unsigned>::iterator threads  = (*activeThreads).begin();
1582798Sktlim@umich.edu        list<unsigned>::iterator list_end = (*activeThreads).end();
1592623SN/A
1602798Sktlim@umich.edu        while (threads != list_end) {
1613201Shsul@eecs.umich.edu            if (robPolicy == Partitioned) {
1623201Shsul@eecs.umich.edu                maxEntries[*threads++] = numEntries / active_threads;
1632867Sktlim@umich.edu            } else if (robPolicy == Threshold && active_threads == 1) {
1642867Sktlim@umich.edu                maxEntries[*threads++] = numEntries;
1652915Sktlim@umich.edu            }
1662915Sktlim@umich.edu        }
1672915Sktlim@umich.edu    }
1682867Sktlim@umich.edu}
1692867Sktlim@umich.edu
1702867Sktlim@umich.edutemplate <class Impl>
1714471Sstever@eecs.umich.eduint
1722623SN/AROB<Impl>::entryAmount(int num_threads)
1732798Sktlim@umich.edu{
1742901Ssaidi@eecs.umich.edu    if (robPolicy == Partitioned) {
1753222Sktlim@umich.edu        return numEntries / num_threads;
1762798Sktlim@umich.edu    } else {
1772798Sktlim@umich.edu        return 0;
1782798Sktlim@umich.edu    }
1792798Sktlim@umich.edu}
1802798Sktlim@umich.edu
1812798Sktlim@umich.edutemplate <class Impl>
1822798Sktlim@umich.eduint
1833222Sktlim@umich.eduROB<Impl>::countInsts()
1842867Sktlim@umich.edu{
1852867Sktlim@umich.edu    int total=0;
1862867Sktlim@umich.edu
1872867Sktlim@umich.edu    for (int i=0;i < numThreads;i++)
1882867Sktlim@umich.edu        total += countInsts(i);
1892623SN/A
1902623SN/A    return total;
1912623SN/A}
1922623SN/A
1932623SN/Atemplate <class Impl>
1942623SN/Aint
1954192Sktlim@umich.eduROB<Impl>::countInsts(unsigned tid)
1962623SN/A{
1972680Sktlim@umich.edu    return instList[tid].size();
1982623SN/A}
1992680Sktlim@umich.edu
2002680Sktlim@umich.edutemplate <class Impl>
2012680Sktlim@umich.eduvoid
2022623SN/AROB<Impl>::insertInst(DynInstPtr &inst)
2032623SN/A{
2042623SN/A    // Make sure we have the right number of instructions.
2052623SN/A    //assert(numInstsInROB == countInsts());
2063201Shsul@eecs.umich.edu
2073201Shsul@eecs.umich.edu    // Make sure the instruction is valid.
2083201Shsul@eecs.umich.edu    assert(inst);
2093201Shsul@eecs.umich.edu
2102623SN/A    DPRINTF(ROB, "Adding inst PC %#x to the ROB.\n", inst->readPC());
2112623SN/A
2122623SN/A    // If the ROB is full then exit.
2132623SN/A    assert(numInstsInROB != numEntries);
2142623SN/A
2152623SN/A    int tid = inst->threadNumber;
2162623SN/A
2172683Sktlim@umich.edu    // Place into ROB
2182623SN/A    instList[tid].push_back(inst);
2192623SN/A
2202623SN/A    //Set Up head iterator if this is the 1st instruction in the ROB
2212623SN/A    if (numInstsInROB == 0) {
2222623SN/A        head = instList[tid].begin();
2233686Sktlim@umich.edu        assert((*head) == inst);
2242623SN/A    }
2254471Sstever@eecs.umich.edu
2262623SN/A    //Must Decrement for iterator to actually be valid  since __.end()
2272623SN/A    //actually points to 1 after the last inst
2282623SN/A    tail = instList[tid].end();
2292623SN/A    tail--;
2302623SN/A
2312623SN/A    // Mark as set in ROB
2322623SN/A    inst->setInROB();
2332683Sktlim@umich.edu
2342623SN/A    // Increment ROB count
2352644Sstever@eecs.umich.edu    ++numInstsInROB;
2362623SN/A    ++threadEntries[tid];
2372644Sstever@eecs.umich.edu
2382644Sstever@eecs.umich.edu    assert((*tail) == inst);
2392623SN/A
2402623SN/A    DPRINTF(ROB, "[tid:%i] Now has %d instructions.\n", tid, threadEntries[tid]);
2412623SN/A}
2422623SN/A
2432623SN/A// Whatever calls this function needs to ensure that it properly frees up
2442623SN/A// registers prior to this function.
2452623SN/Atemplate <class Impl>
2462623SN/Avoid
2472623SN/AROB<Impl>::retireHead()
2482623SN/A{
2493169Sstever@eecs.umich.edu    //assert(numInstsInROB == countInsts());
2503169Sstever@eecs.umich.edu    assert(numInstsInROB > 0);
2513170Sstever@eecs.umich.edu
2522623SN/A    // Get the head ROB instruction's TID.
2532623SN/A    int tid = (*head)->threadNumber;
2543169Sstever@eecs.umich.edu
2552623SN/A    retireHead(tid);
2562623SN/A
2572623SN/A    if (numInstsInROB == 0) {
2583169Sstever@eecs.umich.edu        tail = instList[tid].end();
2592623SN/A    }
2602623SN/A}
2612623SN/A
2623349Sbinkertn@umich.edutemplate <class Impl>
2634878Sstever@eecs.umich.eduvoid
2644878Sstever@eecs.umich.eduROB<Impl>::retireHead(unsigned tid)
2654878Sstever@eecs.umich.edu{
2664878Sstever@eecs.umich.edu    //assert(numInstsInROB == countInsts());
2673169Sstever@eecs.umich.edu    assert(numInstsInROB > 0);
2682623SN/A
2693169Sstever@eecs.umich.edu    // Get the head ROB instruction.
2702623SN/A    InstIt head_it = instList[tid].begin();
2713169Sstever@eecs.umich.edu
2722623SN/A    DynInstPtr head_inst = (*head_it);
2732623SN/A
2743169Sstever@eecs.umich.edu    // Make certain this can retire.
2752623SN/A    assert(head_inst->readyToCommit());
2762623SN/A
2774200Ssaidi@eecs.umich.edu    DPRINTF(ROB, "[tid:%u]: Retiring head instruction, "
2784200Ssaidi@eecs.umich.edu            "instruction PC %#x,[sn:%lli]\n", tid, head_inst->readPC(),
2794200Ssaidi@eecs.umich.edu            head_inst->seqNum);
2804200Ssaidi@eecs.umich.edu
2813658Sktlim@umich.edu    // Keep track of how many instructions are in the ROB.
2823658Sktlim@umich.edu    --numInstsInROB;
2832623SN/A    --threadEntries[tid];
2842623SN/A
2852623SN/A    //Mark DynInstFlags
2862623SN/A    head_inst->removeInROB();
2872623SN/A    head_inst->setCommitted();
2882623SN/A
2892623SN/A    instList[tid].erase(head_it);
2902623SN/A
2912623SN/A    //Update "Global" Head of ROB
2924040Ssaidi@eecs.umich.edu    updateHead();
2934040Ssaidi@eecs.umich.edu
2944040Ssaidi@eecs.umich.edu    // A special case is needed if the instruction being retired is the
2954040Ssaidi@eecs.umich.edu    // only instruction in the ROB; otherwise the tail iterator will become
2964115Ssaidi@eecs.umich.edu    // invalidated.
2974115Ssaidi@eecs.umich.edu    cpu->removeFrontInst(head_inst);
2984115Ssaidi@eecs.umich.edu}
2994115Ssaidi@eecs.umich.edu
3002623SN/Atemplate <class Impl>
3012623SN/Abool
3022623SN/AROB<Impl>::isHeadReady()
3032623SN/A{
3042623SN/A    if (numInstsInROB != 0) {
3052623SN/A        return (*head)->readyToCommit();
3062623SN/A    }
3072623SN/A
3082623SN/A    return false;
3092623SN/A}
3102623SN/A
3112623SN/Atemplate <class Impl>
3122623SN/Abool
3132623SN/AROB<Impl>::isHeadReady(unsigned tid)
3142623SN/A{
3152623SN/A    if (threadEntries[tid] != 0) {
3162623SN/A        return instList[tid].front()->readyToCommit();
3172623SN/A    }
3182623SN/A
3192623SN/A    return false;
3202623SN/A}
3212623SN/A
3222623SN/Atemplate <class Impl>
3232623SN/Abool
3242623SN/AROB<Impl>::canCommit()
3252623SN/A{
3262623SN/A    //@todo: set ActiveThreads through ROB or CPU
3272623SN/A    list<unsigned>::iterator threads = (*activeThreads).begin();
3282623SN/A
3292623SN/A    while (threads != (*activeThreads).end()) {
3302623SN/A        unsigned tid = *threads++;
3312623SN/A
3322623SN/A        if (isHeadReady(tid)) {
3332623SN/A            return true;
3342623SN/A        }
3352623SN/A    }
3362623SN/A
3372623SN/A    return false;
3382623SN/A}
3392623SN/A
3402623SN/Atemplate <class Impl>
3412623SN/Aunsigned
3422623SN/AROB<Impl>::numFreeEntries()
3433169Sstever@eecs.umich.edu{
3443169Sstever@eecs.umich.edu    //assert(numInstsInROB == countInsts());
3453170Sstever@eecs.umich.edu
3462623SN/A    return numEntries - numInstsInROB;
3474040Ssaidi@eecs.umich.edu}
3484040Ssaidi@eecs.umich.edu
3494040Ssaidi@eecs.umich.edutemplate <class Impl>
3504040Ssaidi@eecs.umich.eduunsigned
3512623SN/AROB<Impl>::numFreeEntries(unsigned tid)
3523169Sstever@eecs.umich.edu{
3533169Sstever@eecs.umich.edu    return maxEntries[tid] - threadEntries[tid];
3542623SN/A}
3552623SN/A
3564878Sstever@eecs.umich.edutemplate <class Impl>
3573170Sstever@eecs.umich.eduvoid
3583170Sstever@eecs.umich.eduROB<Impl>::doSquash(unsigned tid)
3593170Sstever@eecs.umich.edu{
3604878Sstever@eecs.umich.edu    DPRINTF(ROB, "[tid:%u]: Squashing instructions until [sn:%i].\n",
3613170Sstever@eecs.umich.edu            tid, squashedSeqNum);
3624878Sstever@eecs.umich.edu
3634878Sstever@eecs.umich.edu    assert(squashIt[tid] != instList[tid].end());
3644878Sstever@eecs.umich.edu
3654878Sstever@eecs.umich.edu    if ((*squashIt[tid])->seqNum < squashedSeqNum) {
3664878Sstever@eecs.umich.edu        DPRINTF(ROB, "[tid:%u]: Done squashing instructions.\n",
3674878Sstever@eecs.umich.edu                tid);
3684040Ssaidi@eecs.umich.edu
3693170Sstever@eecs.umich.edu        squashIt[tid] = instList[tid].end();
3704881Sstever@eecs.umich.edu
3714881Sstever@eecs.umich.edu        doneSquashing[tid] = true;
3724881Sstever@eecs.umich.edu        return;
3734881Sstever@eecs.umich.edu    }
3744881Sstever@eecs.umich.edu
3754881Sstever@eecs.umich.edu    bool robTailUpdate = false;
3764881Sstever@eecs.umich.edu
3773170Sstever@eecs.umich.edu    for (int numSquashed = 0;
3783170Sstever@eecs.umich.edu         numSquashed < squashWidth &&
3793170Sstever@eecs.umich.edu         squashIt[tid] != instList[tid].end() &&
3803170Sstever@eecs.umich.edu         (*squashIt[tid])->seqNum > squashedSeqNum;
3813170Sstever@eecs.umich.edu         ++numSquashed)
3823170Sstever@eecs.umich.edu    {
3833170Sstever@eecs.umich.edu        DPRINTF(ROB, "[tid:%u]: Squashing instruction PC %#x, seq num %i.\n",
3843170Sstever@eecs.umich.edu                (*squashIt[tid])->threadNumber,
3852623SN/A                (*squashIt[tid])->readPC(),
3864200Ssaidi@eecs.umich.edu                (*squashIt[tid])->seqNum);
3874200Ssaidi@eecs.umich.edu
3884200Ssaidi@eecs.umich.edu        // Mark the instruction as squashed, and ready to commit so that
3893658Sktlim@umich.edu        // it can drain out of the pipeline.
3903658Sktlim@umich.edu        (*squashIt[tid])->setSquashed();
3912623SN/A
3922623SN/A        (*squashIt[tid])->setCanCommit();
3932623SN/A
3942623SN/A
3952623SN/A        if (squashIt[tid] == instList[tid].begin()) {
3962623SN/A            DPRINTF(ROB, "Reached head of instruction list while "
3972623SN/A                    "squashing.\n");
3982623SN/A
3992623SN/A            squashIt[tid] = instList[tid].end();
4002623SN/A
4012623SN/A            doneSquashing[tid] = true;
4022623SN/A
4034224Sgblack@eecs.umich.edu            return;
4044224Sgblack@eecs.umich.edu        }
4054224Sgblack@eecs.umich.edu
4064224Sgblack@eecs.umich.edu        InstIt tail_thread = instList[tid].end();
4074224Sgblack@eecs.umich.edu        tail_thread--;
4084224Sgblack@eecs.umich.edu
4094224Sgblack@eecs.umich.edu        if ((*squashIt[tid]) == (*tail_thread))
4104224Sgblack@eecs.umich.edu            robTailUpdate = true;
4114224Sgblack@eecs.umich.edu
4124224Sgblack@eecs.umich.edu        squashIt[tid]--;
4132623SN/A    }
4142623SN/A
4152623SN/A
4162623SN/A    // Check if ROB is done squashing.
4172623SN/A    if ((*squashIt[tid])->seqNum <= squashedSeqNum) {
4182623SN/A        DPRINTF(ROB, "[tid:%u]: Done squashing instructions.\n",
4192623SN/A                tid);
4202623SN/A
4212623SN/A        squashIt[tid] = instList[tid].end();
4222623SN/A
4232623SN/A        doneSquashing[tid] = true;
4242623SN/A    }
4252623SN/A
4262623SN/A    if (robTailUpdate) {
4272623SN/A        updateTail();
4282623SN/A    }
4292623SN/A}
4302623SN/A
4312623SN/A
4322623SN/Atemplate <class Impl>
4332623SN/Avoid
4342623SN/AROB<Impl>::updateHead()
4352623SN/A{
4362623SN/A    DynInstPtr head_inst;
4372623SN/A    InstSeqNum lowest_num = 0;
4382623SN/A    bool first_valid = true;
4392623SN/A
4402623SN/A    // @todo: set ActiveThreads through ROB or CPU
4412623SN/A    list<unsigned>::iterator threads = (*activeThreads).begin();
4422623SN/A
4432623SN/A    while (threads != (*activeThreads).end()) {
4442623SN/A        unsigned thread_num = *threads++;
4452623SN/A
4462623SN/A        if (instList[thread_num].empty())
4472623SN/A            continue;
4482623SN/A
4492623SN/A        if (first_valid) {
4502623SN/A            head = instList[thread_num].begin();
4512623SN/A            lowest_num = (*head)->seqNum;
4522623SN/A            first_valid = false;
4532623SN/A            continue;
4542623SN/A        }
4552623SN/A
4562623SN/A        InstIt head_thread = instList[thread_num].begin();
4572623SN/A
4582623SN/A        DynInstPtr head_inst = (*head_thread);
4593387Sgblack@eecs.umich.edu
4603387Sgblack@eecs.umich.edu        assert(head_inst != 0);
4612631SN/A
4622663Sstever@eecs.umich.edu        if (head_inst->seqNum < lowest_num) {
4633170Sstever@eecs.umich.edu            head = head_thread;
4642662Sstever@eecs.umich.edu            lowest_num = head_inst->seqNum;
4652623SN/A        }
4664022Sstever@eecs.umich.edu    }
4672623SN/A
4682623SN/A    if (first_valid) {
4692623SN/A        head = instList[0].end();
4702630SN/A    }
4712623SN/A
4722623SN/A}
4732623SN/A
4742623SN/Atemplate <class Impl>
4752623SN/Avoid
4762623SN/AROB<Impl>::updateTail()
4772623SN/A{
4782623SN/A    tail = instList[0].end();
4792623SN/A    bool first_valid = true;
4803658Sktlim@umich.edu
4813658Sktlim@umich.edu    list<unsigned>::iterator threads = (*activeThreads).begin();
4822644Sstever@eecs.umich.edu
4832644Sstever@eecs.umich.edu    while (threads != (*activeThreads).end()) {
4842623SN/A        unsigned tid = *threads++;
4853222Sktlim@umich.edu
4863222Sktlim@umich.edu        if (instList[tid].empty()) {
4873222Sktlim@umich.edu            continue;
4882623SN/A        }
4892623SN/A
4902623SN/A        // If this is the first valid then assign w/out
4912623SN/A        // comparison
4922644Sstever@eecs.umich.edu        if (first_valid) {
4932623SN/A            tail = instList[tid].end();
4942623SN/A            tail--;
4952623SN/A            first_valid = false;
4962631SN/A            continue;
4972631SN/A        }
4982631SN/A
4992631SN/A        // Assign new tail if this thread's tail is younger
5002631SN/A        // than our current "tail high"
5012631SN/A        InstIt tail_thread = instList[tid].end();
5022623SN/A        tail_thread--;
5032623SN/A
5042623SN/A        if ((*tail_thread)->seqNum > (*tail)->seqNum) {
5052623SN/A            tail = tail_thread;
5063349Sbinkertn@umich.edu        }
5072623SN/A    }
5082623SN/A}
5092623SN/A
5104870Sstever@eecs.umich.edu
5112623SN/Atemplate <class Impl>
5122798Sktlim@umich.eduvoid
5132623SN/AROB<Impl>::squash(InstSeqNum squash_num,unsigned tid)
5142644Sstever@eecs.umich.edu{
5153222Sktlim@umich.edu    if (isEmpty()) {
5163222Sktlim@umich.edu        DPRINTF(ROB, "Does not need to squash due to being empty "
5173222Sktlim@umich.edu                "[sn:%i]\n",
5182839Sktlim@umich.edu                squash_num);
5193658Sktlim@umich.edu
5203658Sktlim@umich.edu        return;
5213658Sktlim@umich.edu    }
5222839Sktlim@umich.edu
5232798Sktlim@umich.edu    DPRINTF(ROB, "Starting to squash within the ROB.\n");
5242798Sktlim@umich.edu
5252798Sktlim@umich.edu    robStatus[tid] = ROBSquashing;
5262623SN/A
5272644Sstever@eecs.umich.edu    doneSquashing[tid] = false;
5282623SN/A
5292623SN/A    squashedSeqNum = squash_num;
5303170Sstever@eecs.umich.edu
5313170Sstever@eecs.umich.edu    if (!instList[tid].empty()) {
5323170Sstever@eecs.umich.edu        InstIt tail_thread = instList[tid].end();
5333170Sstever@eecs.umich.edu        tail_thread--;
5342644Sstever@eecs.umich.edu
5353170Sstever@eecs.umich.edu        squashIt[tid] = tail_thread;
5363170Sstever@eecs.umich.edu
5373170Sstever@eecs.umich.edu        doSquash(tid);
5383170Sstever@eecs.umich.edu    }
5393170Sstever@eecs.umich.edu}
5403170Sstever@eecs.umich.edu
5413170Sstever@eecs.umich.edutemplate <class Impl>
5423170Sstever@eecs.umich.edutypename Impl::DynInstPtr
5433170Sstever@eecs.umich.eduROB<Impl>::readHeadInst()
5442644Sstever@eecs.umich.edu{
5452644Sstever@eecs.umich.edu    if (numInstsInROB != 0) {
5462644Sstever@eecs.umich.edu        assert((*head)->isInROB()==true);
5472623SN/A        return *head;
5482623SN/A    } else {
5492623SN/A        return dummyInst;
5502644Sstever@eecs.umich.edu    }
5512644Sstever@eecs.umich.edu}
5522623SN/A
5533658Sktlim@umich.edutemplate <class Impl>
5543658Sktlim@umich.edutypename Impl::DynInstPtr
5553658Sktlim@umich.eduROB<Impl>::readHeadInst(unsigned tid)
5562623SN/A{
5572623SN/A    if (threadEntries[tid] != 0) {
5582948Ssaidi@eecs.umich.edu        InstIt head_thread = instList[tid].begin();
5592948Ssaidi@eecs.umich.edu
5602948Ssaidi@eecs.umich.edu        assert((*head_thread)->isInROB()==true);
5612948Ssaidi@eecs.umich.edu
5622948Ssaidi@eecs.umich.edu        return *head_thread;
5632623SN/A    } else {
5642623SN/A        return dummyInst;
5653349Sbinkertn@umich.edu    }
5662623SN/A}
5673310Srdreslin@umich.edu
5683310Srdreslin@umich.edutemplate <class Impl>
5694584Ssaidi@eecs.umich.eduuint64_t
5702948Ssaidi@eecs.umich.eduROB<Impl>::readHeadPC()
5713495Sktlim@umich.edu{
5723310Srdreslin@umich.edu    //assert(numInstsInROB == countInsts());
5733310Srdreslin@umich.edu
5743495Sktlim@umich.edu    DynInstPtr head_inst = *head;
5752948Ssaidi@eecs.umich.edu
5763310Srdreslin@umich.edu    return head_inst->readPC();
5773310Srdreslin@umich.edu}
5784870Sstever@eecs.umich.edu
5794433Ssaidi@eecs.umich.edutemplate <class Impl>
5804433Ssaidi@eecs.umich.eduuint64_t
5814433Ssaidi@eecs.umich.eduROB<Impl>::readHeadPC(unsigned tid)
5824433Ssaidi@eecs.umich.edu{
5834433Ssaidi@eecs.umich.edu    //assert(numInstsInROB == countInsts());
5844433Ssaidi@eecs.umich.edu    InstIt head_thread = instList[tid].begin();
5853310Srdreslin@umich.edu
5864433Ssaidi@eecs.umich.edu    return (*head_thread)->readPC();
5874433Ssaidi@eecs.umich.edu}
5882623SN/A
5892623SN/A
5902657Ssaidi@eecs.umich.edutemplate <class Impl>
5912623SN/Auint64_t
5922623SN/AROB<Impl>::readHeadNextPC()
5932623SN/A{
5942623SN/A    //assert(numInstsInROB == countInsts());
5952623SN/A
5962623SN/A    DynInstPtr head_inst = *head;
5973349Sbinkertn@umich.edu
5982657Ssaidi@eecs.umich.edu    return head_inst->readNextPC();
5992657Ssaidi@eecs.umich.edu}
6002657Ssaidi@eecs.umich.edu
6012657Ssaidi@eecs.umich.edutemplate <class Impl>
6022623SN/Auint64_t
6032623SN/AROB<Impl>::readHeadNextPC(unsigned tid)
6042623SN/A{
6053349Sbinkertn@umich.edu    //assert(numInstsInROB == countInsts());
6062623SN/A    InstIt head_thread = instList[tid].begin();
6072623SN/A
6082623SN/A    return (*head_thread)->readNextPC();
6094870Sstever@eecs.umich.edu}
6102623SN/A
6112623SN/A
6122623SN/Atemplate <class Impl>
6133222Sktlim@umich.eduInstSeqNum
6143222Sktlim@umich.eduROB<Impl>::readHeadSeqNum()
6153184Srdreslin@umich.edu{
6162623SN/A    //assert(numInstsInROB == countInsts());
6172623SN/A    DynInstPtr head_inst = *head;
6184878Sstever@eecs.umich.edu
6193170Sstever@eecs.umich.edu    return head_inst->seqNum;
6203170Sstever@eecs.umich.edu}
6213170Sstever@eecs.umich.edu
6222644Sstever@eecs.umich.edutemplate <class Impl>
6232644Sstever@eecs.umich.eduInstSeqNum
6242644Sstever@eecs.umich.eduROB<Impl>::readHeadSeqNum(unsigned tid)
6253184Srdreslin@umich.edu{
6263227Sktlim@umich.edu    InstIt head_thread = instList[tid].begin();
6273201Shsul@eecs.umich.edu
6283201Shsul@eecs.umich.edu    return ((*head_thread)->seqNum);
6293201Shsul@eecs.umich.edu}
6303201Shsul@eecs.umich.edu
6313201Shsul@eecs.umich.edutemplate <class Impl>
6323201Shsul@eecs.umich.edutypename Impl::DynInstPtr
6333201Shsul@eecs.umich.eduROB<Impl>::readTailInst()
6342644Sstever@eecs.umich.edu{
6352623SN/A    //assert(numInstsInROB == countInsts());
6362623SN/A    //assert(tail != instList[0].end());
6372623SN/A
6382798Sktlim@umich.edu    return (*tail);
6392839Sktlim@umich.edu}
6402798Sktlim@umich.edu
6412839Sktlim@umich.edutemplate <class Impl>
6422901Ssaidi@eecs.umich.edutypename Impl::DynInstPtr
6432839Sktlim@umich.eduROB<Impl>::readTailInst(unsigned tid)
6442798Sktlim@umich.edu{
6452623SN/A    //assert(tail_thread[tid] != instList[tid].end());
6464192Sktlim@umich.edu
6474192Sktlim@umich.edu    InstIt tail_thread = instList[tid].end();
6484192Sktlim@umich.edu    tail_thread--;
6494192Sktlim@umich.edu
6504192Sktlim@umich.edu    return *tail_thread;
6514192Sktlim@umich.edu}
6524192Sktlim@umich.edu
6534192Sktlim@umich.edu
6544192Sktlim@umich.edutemplate <class Impl>
6554192Sktlim@umich.eduuint64_t
6564192Sktlim@umich.eduROB<Impl>::readTailPC()
6574192Sktlim@umich.edu{
6582623SN/A    //assert(numInstsInROB == countInsts());
6593349Sbinkertn@umich.edu
6602623SN/A    //assert(tail != instList[0].end());
6613310Srdreslin@umich.edu
6623310Srdreslin@umich.edu    return (*tail)->readPC();
6634584Ssaidi@eecs.umich.edu}
6642948Ssaidi@eecs.umich.edu
6653495Sktlim@umich.edutemplate <class Impl>
6663310Srdreslin@umich.eduuint64_t
6673310Srdreslin@umich.eduROB<Impl>::readTailPC(unsigned tid)
6683495Sktlim@umich.edu{
6692948Ssaidi@eecs.umich.edu    //assert(tail_thread[tid] != instList[tid].end());
6703310Srdreslin@umich.edu
6713310Srdreslin@umich.edu    InstIt tail_thread = instList[tid].end();
6724870Sstever@eecs.umich.edu    tail_thread--;
6734433Ssaidi@eecs.umich.edu
6744433Ssaidi@eecs.umich.edu    return (*tail_thread)->readPC();
6754433Ssaidi@eecs.umich.edu}
6764433Ssaidi@eecs.umich.edu
6774433Ssaidi@eecs.umich.edutemplate <class Impl>
6784433Ssaidi@eecs.umich.eduInstSeqNum
6793310Srdreslin@umich.eduROB<Impl>::readTailSeqNum()
6804433Ssaidi@eecs.umich.edu{
6814433Ssaidi@eecs.umich.edu    // Return the last sequence number that has not been squashed.  Other
6822948Ssaidi@eecs.umich.edu    // stages can use it to squash any instructions younger than the current
6832948Ssaidi@eecs.umich.edu    // tail.
6842948Ssaidi@eecs.umich.edu    return (*tail)->seqNum;
6852948Ssaidi@eecs.umich.edu}
6862948Ssaidi@eecs.umich.edu
6872630SN/Atemplate <class Impl>
6882623SN/AInstSeqNum
6892623SN/AROB<Impl>::readTailSeqNum(unsigned tid)
6902657Ssaidi@eecs.umich.edu{
6912623SN/A    // Return the last sequence number that has not been squashed.  Other
6922623SN/A    // stages can use it to squash any instructions younger than the current
6932623SN/A    // tail.
6942623SN/A    //    assert(tail_thread[tid] != instList[tid].end());
6952623SN/A
6962623SN/A    InstIt tail_thread = instList[tid].end();
6973349Sbinkertn@umich.edu    tail_thread--;
6982657Ssaidi@eecs.umich.edu
6992657Ssaidi@eecs.umich.edu    return (*tail_thread)->seqNum;
7003170Sstever@eecs.umich.edu}
7012657Ssaidi@eecs.umich.edu
7022657Ssaidi@eecs.umich.edu