rob_impl.hh revision 6221:58a3c04e6344
16019Shines@cs.fsu.edu/*
26019Shines@cs.fsu.edu * Copyright (c) 2004-2006 The Regents of The University of Michigan
37178Sgblack@eecs.umich.edu * All rights reserved.
47178Sgblack@eecs.umich.edu *
57178Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
67178Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are
77178Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright
87178Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer;
97178Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
107178Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the
117178Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution;
127178Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its
137178Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from
147178Sgblack@eecs.umich.edu * this software without specific prior written permission.
156019Shines@cs.fsu.edu *
166019Shines@cs.fsu.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
176019Shines@cs.fsu.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
186019Shines@cs.fsu.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
196019Shines@cs.fsu.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
206019Shines@cs.fsu.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
216019Shines@cs.fsu.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
226019Shines@cs.fsu.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
236019Shines@cs.fsu.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
246019Shines@cs.fsu.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
256019Shines@cs.fsu.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
266019Shines@cs.fsu.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
276019Shines@cs.fsu.edu *
286019Shines@cs.fsu.edu * Authors: Kevin Lim
296019Shines@cs.fsu.edu *          Korey Sewell
306019Shines@cs.fsu.edu */
316019Shines@cs.fsu.edu
326019Shines@cs.fsu.edu#include <list>
336019Shines@cs.fsu.edu
346019Shines@cs.fsu.edu#include "config/full_system.hh"
356019Shines@cs.fsu.edu#include "cpu/o3/rob.hh"
366019Shines@cs.fsu.edu
376019Shines@cs.fsu.eduusing namespace std;
386019Shines@cs.fsu.edu
396019Shines@cs.fsu.edutemplate <class Impl>
406019Shines@cs.fsu.eduROB<Impl>::ROB(O3CPU *_cpu, unsigned _numEntries, unsigned _squashWidth,
416019Shines@cs.fsu.edu               std::string _smtROBPolicy, unsigned _smtROBThreshold,
426019Shines@cs.fsu.edu               ThreadID _numThreads)
436019Shines@cs.fsu.edu    : cpu(_cpu),
446019Shines@cs.fsu.edu      numEntries(_numEntries),
456019Shines@cs.fsu.edu      squashWidth(_squashWidth),
466019Shines@cs.fsu.edu      numInstsInROB(0),
476019Shines@cs.fsu.edu      numThreads(_numThreads)
486019Shines@cs.fsu.edu{
496019Shines@cs.fsu.edu    for (ThreadID tid = 0; tid  < numThreads; tid++) {
506019Shines@cs.fsu.edu        squashedSeqNum[tid] = 0;
516019Shines@cs.fsu.edu        doneSquashing[tid] = true;
526019Shines@cs.fsu.edu        threadEntries[tid] = 0;
536019Shines@cs.fsu.edu    }
546019Shines@cs.fsu.edu
556019Shines@cs.fsu.edu    std::string policy = _smtROBPolicy;
566019Shines@cs.fsu.edu
576019Shines@cs.fsu.edu    //Convert string to lowercase
586243Sgblack@eecs.umich.edu    std::transform(policy.begin(), policy.end(), policy.begin(),
596243Sgblack@eecs.umich.edu                   (int(*)(int)) tolower);
606243Sgblack@eecs.umich.edu
616243Sgblack@eecs.umich.edu    //Figure out rob policy
626243Sgblack@eecs.umich.edu    if (policy == "dynamic") {
636019Shines@cs.fsu.edu        robPolicy = Dynamic;
646019Shines@cs.fsu.edu
656019Shines@cs.fsu.edu        //Set Max Entries to Total ROB Capacity
666019Shines@cs.fsu.edu        for (ThreadID tid = 0; tid < numThreads; tid++) {
676019Shines@cs.fsu.edu            maxEntries[tid] = numEntries;
686019Shines@cs.fsu.edu        }
696019Shines@cs.fsu.edu
706019Shines@cs.fsu.edu    } else if (policy == "partitioned") {
716019Shines@cs.fsu.edu        robPolicy = Partitioned;
726019Shines@cs.fsu.edu        DPRINTF(Fetch, "ROB sharing policy set to Partitioned\n");
736019Shines@cs.fsu.edu
746019Shines@cs.fsu.edu        //@todo:make work if part_amt doesnt divide evenly.
756019Shines@cs.fsu.edu        int part_amt = numEntries / numThreads;
766019Shines@cs.fsu.edu
776019Shines@cs.fsu.edu        //Divide ROB up evenly
786019Shines@cs.fsu.edu        for (ThreadID tid = 0; tid < numThreads; tid++) {
796019Shines@cs.fsu.edu            maxEntries[tid] = part_amt;
806019Shines@cs.fsu.edu        }
816019Shines@cs.fsu.edu
826019Shines@cs.fsu.edu    } else if (policy == "threshold") {
836019Shines@cs.fsu.edu        robPolicy = Threshold;
846019Shines@cs.fsu.edu        DPRINTF(Fetch, "ROB sharing policy set to Threshold\n");
856019Shines@cs.fsu.edu
866019Shines@cs.fsu.edu        int threshold =  _smtROBThreshold;;
876019Shines@cs.fsu.edu
886019Shines@cs.fsu.edu        //Divide up by threshold amount
896019Shines@cs.fsu.edu        for (ThreadID tid = 0; tid < numThreads; tid++) {
906019Shines@cs.fsu.edu            maxEntries[tid] = threshold;
916019Shines@cs.fsu.edu        }
926019Shines@cs.fsu.edu    } else {
936019Shines@cs.fsu.edu        assert(0 && "Invalid ROB Sharing Policy.Options Are:{Dynamic,"
946252Sgblack@eecs.umich.edu                    "Partitioned, Threshold}");
956243Sgblack@eecs.umich.edu    }
966243Sgblack@eecs.umich.edu
976243Sgblack@eecs.umich.edu    // Set the per-thread iterators to the end of the instruction list.
986019Shines@cs.fsu.edu    for (ThreadID tid = 0; tid < numThreads; tid++) {
996019Shines@cs.fsu.edu        squashIt[tid] = instList[tid].end();
1006019Shines@cs.fsu.edu    }
1016019Shines@cs.fsu.edu
1026019Shines@cs.fsu.edu    // Initialize the "universal" ROB head & tail point to invalid
1036252Sgblack@eecs.umich.edu    // pointers
1046243Sgblack@eecs.umich.edu    head = instList[0].end();
1056243Sgblack@eecs.umich.edu    tail = instList[0].end();
1066243Sgblack@eecs.umich.edu}
1076019Shines@cs.fsu.edu
1086019Shines@cs.fsu.edutemplate <class Impl>
1096019Shines@cs.fsu.edustd::string
1106019Shines@cs.fsu.eduROB<Impl>::name() const
1116019Shines@cs.fsu.edu{
1126019Shines@cs.fsu.edu    return cpu->name() + ".rob";
1136019Shines@cs.fsu.edu}
1146252Sgblack@eecs.umich.edu
1156243Sgblack@eecs.umich.edutemplate <class Impl>
1166243Sgblack@eecs.umich.eduvoid
1176243Sgblack@eecs.umich.eduROB<Impl>::setActiveThreads(list<ThreadID> *at_ptr)
1186019Shines@cs.fsu.edu{
1196019Shines@cs.fsu.edu    DPRINTF(ROB, "Setting active threads list pointer.\n");
1206019Shines@cs.fsu.edu    activeThreads = at_ptr;
1216019Shines@cs.fsu.edu}
1226019Shines@cs.fsu.edu
1236019Shines@cs.fsu.edutemplate <class Impl>
1246019Shines@cs.fsu.eduvoid
1256019Shines@cs.fsu.eduROB<Impl>::switchOut()
1266019Shines@cs.fsu.edu{
1276019Shines@cs.fsu.edu    for (ThreadID tid = 0; tid < numThreads; tid++) {
1286019Shines@cs.fsu.edu        instList[tid].clear();
1296019Shines@cs.fsu.edu    }
1306019Shines@cs.fsu.edu}
1316019Shines@cs.fsu.edu
1326019Shines@cs.fsu.edutemplate <class Impl>
1336019Shines@cs.fsu.eduvoid
1346724Sgblack@eecs.umich.eduROB<Impl>::takeOverFrom()
1356724Sgblack@eecs.umich.edu{
1366019Shines@cs.fsu.edu    for (ThreadID tid = 0; tid  < numThreads; tid++) {
1376019Shines@cs.fsu.edu        doneSquashing[tid] = true;
1386019Shines@cs.fsu.edu        threadEntries[tid] = 0;
1396019Shines@cs.fsu.edu        squashIt[tid] = instList[tid].end();
1406019Shines@cs.fsu.edu    }
1416252Sgblack@eecs.umich.edu    numInstsInROB = 0;
1426243Sgblack@eecs.umich.edu
1436243Sgblack@eecs.umich.edu    // Initialize the "universal" ROB head & tail point to invalid
1446243Sgblack@eecs.umich.edu    // pointers
1456019Shines@cs.fsu.edu    head = instList[0].end();
1466019Shines@cs.fsu.edu    tail = instList[0].end();
1476019Shines@cs.fsu.edu}
1486019Shines@cs.fsu.edu
1496019Shines@cs.fsu.edutemplate <class Impl>
1506019Shines@cs.fsu.eduvoid
1517356Sgblack@eecs.umich.eduROB<Impl>::resetEntries()
1527356Sgblack@eecs.umich.edu{
1537356Sgblack@eecs.umich.edu    if (robPolicy != Dynamic || numThreads > 1) {
1547356Sgblack@eecs.umich.edu        int active_threads = activeThreads->size();
1557356Sgblack@eecs.umich.edu
1567356Sgblack@eecs.umich.edu        list<ThreadID>::iterator threads = activeThreads->begin();
1577356Sgblack@eecs.umich.edu        list<ThreadID>::iterator end = activeThreads->end();
1587356Sgblack@eecs.umich.edu
1597178Sgblack@eecs.umich.edu        while (threads != end) {
1607178Sgblack@eecs.umich.edu            ThreadID tid = *threads++;
1617178Sgblack@eecs.umich.edu
1627337Sgblack@eecs.umich.edu            if (robPolicy == Partitioned) {
1637178Sgblack@eecs.umich.edu                maxEntries[tid] = numEntries / active_threads;
1647178Sgblack@eecs.umich.edu            } else if (robPolicy == Threshold && active_threads == 1) {
1657178Sgblack@eecs.umich.edu                maxEntries[tid] = numEntries;
1667178Sgblack@eecs.umich.edu            }
1677178Sgblack@eecs.umich.edu        }
1687178Sgblack@eecs.umich.edu    }
1697178Sgblack@eecs.umich.edu}
1707178Sgblack@eecs.umich.edu
1717178Sgblack@eecs.umich.edutemplate <class Impl>
1727178Sgblack@eecs.umich.eduint
1737178Sgblack@eecs.umich.eduROB<Impl>::entryAmount(ThreadID num_threads)
1747335Sgblack@eecs.umich.edu{
1757335Sgblack@eecs.umich.edu    if (robPolicy == Partitioned) {
1767335Sgblack@eecs.umich.edu        return numEntries / num_threads;
1777335Sgblack@eecs.umich.edu    } else {
1787335Sgblack@eecs.umich.edu        return 0;
1797335Sgblack@eecs.umich.edu    }
1807335Sgblack@eecs.umich.edu}
1817335Sgblack@eecs.umich.edu
1827335Sgblack@eecs.umich.edutemplate <class Impl>
1837335Sgblack@eecs.umich.eduint
1847335Sgblack@eecs.umich.eduROB<Impl>::countInsts()
1857335Sgblack@eecs.umich.edu{
1867337Sgblack@eecs.umich.edu    int total = 0;
1877335Sgblack@eecs.umich.edu
1887335Sgblack@eecs.umich.edu    for (ThreadID tid = 0; tid < numThreads; tid++)
1897335Sgblack@eecs.umich.edu        total += countInsts(tid);
1907335Sgblack@eecs.umich.edu
1917335Sgblack@eecs.umich.edu    return total;
1927335Sgblack@eecs.umich.edu}
1937335Sgblack@eecs.umich.edu
1947335Sgblack@eecs.umich.edutemplate <class Impl>
1957335Sgblack@eecs.umich.eduint
1967335Sgblack@eecs.umich.eduROB<Impl>::countInsts(ThreadID tid)
1977335Sgblack@eecs.umich.edu{
1987335Sgblack@eecs.umich.edu    return instList[tid].size();
1997178Sgblack@eecs.umich.edu}
2007178Sgblack@eecs.umich.edu
2017178Sgblack@eecs.umich.edutemplate <class Impl>
2027178Sgblack@eecs.umich.eduvoid
2037178Sgblack@eecs.umich.eduROB<Impl>::insertInst(DynInstPtr &inst)
2047178Sgblack@eecs.umich.edu{
2057178Sgblack@eecs.umich.edu    //assert(numInstsInROB == countInsts());
2067178Sgblack@eecs.umich.edu    assert(inst);
2077178Sgblack@eecs.umich.edu
2087178Sgblack@eecs.umich.edu    DPRINTF(ROB, "Adding inst PC %#x to the ROB.\n", inst->readPC());
2097178Sgblack@eecs.umich.edu
2107178Sgblack@eecs.umich.edu    assert(numInstsInROB != numEntries);
2117178Sgblack@eecs.umich.edu
2127178Sgblack@eecs.umich.edu    ThreadID tid = inst->threadNumber;
2137178Sgblack@eecs.umich.edu
2147178Sgblack@eecs.umich.edu    instList[tid].push_back(inst);
2157178Sgblack@eecs.umich.edu
2167178Sgblack@eecs.umich.edu    //Set Up head iterator if this is the 1st instruction in the ROB
2177178Sgblack@eecs.umich.edu    if (numInstsInROB == 0) {
2187178Sgblack@eecs.umich.edu        head = instList[tid].begin();
2197178Sgblack@eecs.umich.edu        assert((*head) == inst);
2207178Sgblack@eecs.umich.edu    }
2217178Sgblack@eecs.umich.edu
2227178Sgblack@eecs.umich.edu    //Must Decrement for iterator to actually be valid  since __.end()
2237178Sgblack@eecs.umich.edu    //actually points to 1 after the last inst
2247178Sgblack@eecs.umich.edu    tail = instList[tid].end();
2257178Sgblack@eecs.umich.edu    tail--;
2267178Sgblack@eecs.umich.edu
2277178Sgblack@eecs.umich.edu    inst->setInROB();
2287346Sgblack@eecs.umich.edu
2297346Sgblack@eecs.umich.edu    ++numInstsInROB;
2307346Sgblack@eecs.umich.edu    ++threadEntries[tid];
2317346Sgblack@eecs.umich.edu
2327346Sgblack@eecs.umich.edu    assert((*tail) == inst);
2337346Sgblack@eecs.umich.edu
2347346Sgblack@eecs.umich.edu    DPRINTF(ROB, "[tid:%i] Now has %d instructions.\n", tid, threadEntries[tid]);
2357346Sgblack@eecs.umich.edu}
2367346Sgblack@eecs.umich.edu
2377346Sgblack@eecs.umich.edu// Whatever calls this function needs to ensure that it properly frees up
2387178Sgblack@eecs.umich.edu// registers prior to this function.
2397346Sgblack@eecs.umich.edu/*
2407346Sgblack@eecs.umich.edutemplate <class Impl>
2417346Sgblack@eecs.umich.eduvoid
2427346Sgblack@eecs.umich.eduROB<Impl>::retireHead()
2437346Sgblack@eecs.umich.edu{
2447346Sgblack@eecs.umich.edu    //assert(numInstsInROB == countInsts());
2457346Sgblack@eecs.umich.edu    assert(numInstsInROB > 0);
2467346Sgblack@eecs.umich.edu
2477346Sgblack@eecs.umich.edu    ThreadID tid = (*head)->threadNumber;
2487346Sgblack@eecs.umich.edu
2497346Sgblack@eecs.umich.edu    retireHead(tid);
2507346Sgblack@eecs.umich.edu
2517346Sgblack@eecs.umich.edu    if (numInstsInROB == 0) {
2527346Sgblack@eecs.umich.edu        tail = instList[tid].end();
2537346Sgblack@eecs.umich.edu    }
2547178Sgblack@eecs.umich.edu}
2557337Sgblack@eecs.umich.edu*/
2567337Sgblack@eecs.umich.edu
2577337Sgblack@eecs.umich.edutemplate <class Impl>
2587337Sgblack@eecs.umich.eduvoid
2597337Sgblack@eecs.umich.eduROB<Impl>::retireHead(ThreadID tid)
2607337Sgblack@eecs.umich.edu{
2617337Sgblack@eecs.umich.edu    //assert(numInstsInROB == countInsts());
2627337Sgblack@eecs.umich.edu    assert(numInstsInROB > 0);
2637337Sgblack@eecs.umich.edu
2647337Sgblack@eecs.umich.edu    // Get the head ROB instruction.
2657337Sgblack@eecs.umich.edu    InstIt head_it = instList[tid].begin();
2667337Sgblack@eecs.umich.edu
2677337Sgblack@eecs.umich.edu    DynInstPtr head_inst = (*head_it);
2687337Sgblack@eecs.umich.edu
2697337Sgblack@eecs.umich.edu    assert(head_inst->readyToCommit());
2707178Sgblack@eecs.umich.edu
2717178Sgblack@eecs.umich.edu    DPRINTF(ROB, "[tid:%u]: Retiring head instruction, "
2727178Sgblack@eecs.umich.edu            "instruction PC %#x,[sn:%lli]\n", tid, head_inst->readPC(),
2737178Sgblack@eecs.umich.edu            head_inst->seqNum);
2747337Sgblack@eecs.umich.edu
2757337Sgblack@eecs.umich.edu    --numInstsInROB;
2767337Sgblack@eecs.umich.edu    --threadEntries[tid];
2777337Sgblack@eecs.umich.edu
2787346Sgblack@eecs.umich.edu    head_inst->clearInROB();
2797346Sgblack@eecs.umich.edu    head_inst->setCommitted();
2807346Sgblack@eecs.umich.edu
2817346Sgblack@eecs.umich.edu    instList[tid].erase(head_it);
2827346Sgblack@eecs.umich.edu
2837337Sgblack@eecs.umich.edu    //Update "Global" Head of ROB
2847178Sgblack@eecs.umich.edu    updateHead();
2857321Sgblack@eecs.umich.edu
2867356Sgblack@eecs.umich.edu    // @todo: A special case is needed if the instruction being
2877321Sgblack@eecs.umich.edu    // retired is the only instruction in the ROB; otherwise the tail
2887356Sgblack@eecs.umich.edu    // iterator will become invalidated.
2897356Sgblack@eecs.umich.edu    cpu->removeFrontInst(head_inst);
2907356Sgblack@eecs.umich.edu}
2917356Sgblack@eecs.umich.edu/*
2927356Sgblack@eecs.umich.edutemplate <class Impl>
2937356Sgblack@eecs.umich.edubool
2947356Sgblack@eecs.umich.eduROB<Impl>::isHeadReady()
2957356Sgblack@eecs.umich.edu{
2967356Sgblack@eecs.umich.edu    if (numInstsInROB != 0) {
2977356Sgblack@eecs.umich.edu        return (*head)->readyToCommit();
2987356Sgblack@eecs.umich.edu    }
2997356Sgblack@eecs.umich.edu
3007321Sgblack@eecs.umich.edu    return false;
3017321Sgblack@eecs.umich.edu}
3027321Sgblack@eecs.umich.edu*/
3037321Sgblack@eecs.umich.edutemplate <class Impl>
3047321Sgblack@eecs.umich.edubool
3057321Sgblack@eecs.umich.eduROB<Impl>::isHeadReady(ThreadID tid)
3067321Sgblack@eecs.umich.edu{
3077321Sgblack@eecs.umich.edu    if (threadEntries[tid] != 0) {
3087321Sgblack@eecs.umich.edu        return instList[tid].front()->readyToCommit();
3097321Sgblack@eecs.umich.edu    }
3107321Sgblack@eecs.umich.edu
3117335Sgblack@eecs.umich.edu    return false;
3127335Sgblack@eecs.umich.edu}
3137335Sgblack@eecs.umich.edu
3147335Sgblack@eecs.umich.edutemplate <class Impl>
3157335Sgblack@eecs.umich.edubool
3167335Sgblack@eecs.umich.eduROB<Impl>::canCommit()
3177335Sgblack@eecs.umich.edu{
3187335Sgblack@eecs.umich.edu    //@todo: set ActiveThreads through ROB or CPU
3197335Sgblack@eecs.umich.edu    list<ThreadID>::iterator threads = activeThreads->begin();
3207321Sgblack@eecs.umich.edu    list<ThreadID>::iterator end = activeThreads->end();
3217323Sgblack@eecs.umich.edu
3227323Sgblack@eecs.umich.edu    while (threads != end) {
3237323Sgblack@eecs.umich.edu        ThreadID tid = *threads++;
3247323Sgblack@eecs.umich.edu
3257323Sgblack@eecs.umich.edu        if (isHeadReady(tid)) {
3267323Sgblack@eecs.umich.edu            return true;
3277323Sgblack@eecs.umich.edu        }
3287323Sgblack@eecs.umich.edu    }
3297323Sgblack@eecs.umich.edu
3307323Sgblack@eecs.umich.edu    return false;
3317323Sgblack@eecs.umich.edu}
3327323Sgblack@eecs.umich.edu
3337323Sgblack@eecs.umich.edutemplate <class Impl>
3347323Sgblack@eecs.umich.eduunsigned
3357323Sgblack@eecs.umich.eduROB<Impl>::numFreeEntries()
3367323Sgblack@eecs.umich.edu{
3377323Sgblack@eecs.umich.edu    //assert(numInstsInROB == countInsts());
3387321Sgblack@eecs.umich.edu
3397321Sgblack@eecs.umich.edu    return numEntries - numInstsInROB;
3407321Sgblack@eecs.umich.edu}
3417335Sgblack@eecs.umich.edu
3427335Sgblack@eecs.umich.edutemplate <class Impl>
3437335Sgblack@eecs.umich.eduunsigned
3447335Sgblack@eecs.umich.eduROB<Impl>::numFreeEntries(ThreadID tid)
3457335Sgblack@eecs.umich.edu{
3467335Sgblack@eecs.umich.edu    return maxEntries[tid] - threadEntries[tid];
3477335Sgblack@eecs.umich.edu}
3487335Sgblack@eecs.umich.edu
3497335Sgblack@eecs.umich.edutemplate <class Impl>
3507335Sgblack@eecs.umich.eduvoid
3517335Sgblack@eecs.umich.eduROB<Impl>::doSquash(ThreadID tid)
3527335Sgblack@eecs.umich.edu{
3537335Sgblack@eecs.umich.edu    DPRINTF(ROB, "[tid:%u]: Squashing instructions until [sn:%i].\n",
3547335Sgblack@eecs.umich.edu            tid, squashedSeqNum[tid]);
3557335Sgblack@eecs.umich.edu
3567335Sgblack@eecs.umich.edu    assert(squashIt[tid] != instList[tid].end());
3577335Sgblack@eecs.umich.edu
3587335Sgblack@eecs.umich.edu    if ((*squashIt[tid])->seqNum < squashedSeqNum[tid]) {
3597335Sgblack@eecs.umich.edu        DPRINTF(ROB, "[tid:%u]: Done squashing instructions.\n",
3607335Sgblack@eecs.umich.edu                tid);
3617335Sgblack@eecs.umich.edu
3627335Sgblack@eecs.umich.edu        squashIt[tid] = instList[tid].end();
3637335Sgblack@eecs.umich.edu
3647335Sgblack@eecs.umich.edu        doneSquashing[tid] = true;
3657335Sgblack@eecs.umich.edu        return;
3667335Sgblack@eecs.umich.edu    }
3677335Sgblack@eecs.umich.edu
3687335Sgblack@eecs.umich.edu    bool robTailUpdate = false;
3697335Sgblack@eecs.umich.edu
3707335Sgblack@eecs.umich.edu    for (int numSquashed = 0;
3717335Sgblack@eecs.umich.edu         numSquashed < squashWidth &&
3727335Sgblack@eecs.umich.edu         squashIt[tid] != instList[tid].end() &&
3737335Sgblack@eecs.umich.edu         (*squashIt[tid])->seqNum > squashedSeqNum[tid];
3747321Sgblack@eecs.umich.edu         ++numSquashed)
3757321Sgblack@eecs.umich.edu    {
3767321Sgblack@eecs.umich.edu        DPRINTF(ROB, "[tid:%u]: Squashing instruction PC %#x, seq num %i.\n",
3777321Sgblack@eecs.umich.edu                (*squashIt[tid])->threadNumber,
3787321Sgblack@eecs.umich.edu                (*squashIt[tid])->readPC(),
3797321Sgblack@eecs.umich.edu                (*squashIt[tid])->seqNum);
3807335Sgblack@eecs.umich.edu
3817335Sgblack@eecs.umich.edu        // Mark the instruction as squashed, and ready to commit so that
3827335Sgblack@eecs.umich.edu        // it can drain out of the pipeline.
3837335Sgblack@eecs.umich.edu        (*squashIt[tid])->setSquashed();
3847335Sgblack@eecs.umich.edu
3857335Sgblack@eecs.umich.edu        (*squashIt[tid])->setCanCommit();
3867335Sgblack@eecs.umich.edu
3877335Sgblack@eecs.umich.edu
3887335Sgblack@eecs.umich.edu        if (squashIt[tid] == instList[tid].begin()) {
3897321Sgblack@eecs.umich.edu            DPRINTF(ROB, "Reached head of instruction list while "
3907326Sgblack@eecs.umich.edu                    "squashing.\n");
3917326Sgblack@eecs.umich.edu
3927326Sgblack@eecs.umich.edu            squashIt[tid] = instList[tid].end();
3937326Sgblack@eecs.umich.edu
3947326Sgblack@eecs.umich.edu            doneSquashing[tid] = true;
3957326Sgblack@eecs.umich.edu
3967326Sgblack@eecs.umich.edu            return;
3977326Sgblack@eecs.umich.edu        }
3987326Sgblack@eecs.umich.edu
3997326Sgblack@eecs.umich.edu        InstIt tail_thread = instList[tid].end();
4007326Sgblack@eecs.umich.edu        tail_thread--;
4017326Sgblack@eecs.umich.edu
4027326Sgblack@eecs.umich.edu        if ((*squashIt[tid]) == (*tail_thread))
4037326Sgblack@eecs.umich.edu            robTailUpdate = true;
4047326Sgblack@eecs.umich.edu
4057326Sgblack@eecs.umich.edu        squashIt[tid]--;
4067326Sgblack@eecs.umich.edu    }
4077326Sgblack@eecs.umich.edu
4087326Sgblack@eecs.umich.edu
4097326Sgblack@eecs.umich.edu    // Check if ROB is done squashing.
4107326Sgblack@eecs.umich.edu    if ((*squashIt[tid])->seqNum <= squashedSeqNum[tid]) {
4117326Sgblack@eecs.umich.edu        DPRINTF(ROB, "[tid:%u]: Done squashing instructions.\n",
4127326Sgblack@eecs.umich.edu                tid);
4137321Sgblack@eecs.umich.edu
4147321Sgblack@eecs.umich.edu        squashIt[tid] = instList[tid].end();
4157335Sgblack@eecs.umich.edu
4167335Sgblack@eecs.umich.edu        doneSquashing[tid] = true;
4177335Sgblack@eecs.umich.edu    }
4187335Sgblack@eecs.umich.edu
4197335Sgblack@eecs.umich.edu    if (robTailUpdate) {
4207335Sgblack@eecs.umich.edu        updateTail();
4217335Sgblack@eecs.umich.edu    }
4227335Sgblack@eecs.umich.edu}
4237335Sgblack@eecs.umich.edu
4247335Sgblack@eecs.umich.edu
4257335Sgblack@eecs.umich.edutemplate <class Impl>
4267335Sgblack@eecs.umich.eduvoid
4277335Sgblack@eecs.umich.eduROB<Impl>::updateHead()
4287335Sgblack@eecs.umich.edu{
4297335Sgblack@eecs.umich.edu    DynInstPtr head_inst;
4307335Sgblack@eecs.umich.edu    InstSeqNum lowest_num = 0;
4317335Sgblack@eecs.umich.edu    bool first_valid = true;
4327335Sgblack@eecs.umich.edu
4337335Sgblack@eecs.umich.edu    // @todo: set ActiveThreads through ROB or CPU
4347335Sgblack@eecs.umich.edu    list<ThreadID>::iterator threads = activeThreads->begin();
4357335Sgblack@eecs.umich.edu    list<ThreadID>::iterator end = activeThreads->end();
4367335Sgblack@eecs.umich.edu
4377335Sgblack@eecs.umich.edu    while (threads != end) {
4387335Sgblack@eecs.umich.edu        ThreadID tid = *threads++;
4397335Sgblack@eecs.umich.edu
4407335Sgblack@eecs.umich.edu        if (instList[tid].empty())
4417335Sgblack@eecs.umich.edu            continue;
4427335Sgblack@eecs.umich.edu
4437335Sgblack@eecs.umich.edu        if (first_valid) {
4447335Sgblack@eecs.umich.edu            head = instList[tid].begin();
4457335Sgblack@eecs.umich.edu            lowest_num = (*head)->seqNum;
4467335Sgblack@eecs.umich.edu            first_valid = false;
4477335Sgblack@eecs.umich.edu            continue;
4487335Sgblack@eecs.umich.edu        }
4497335Sgblack@eecs.umich.edu
4507335Sgblack@eecs.umich.edu        InstIt head_thread = instList[tid].begin();
4517335Sgblack@eecs.umich.edu
4527335Sgblack@eecs.umich.edu        DynInstPtr head_inst = (*head_thread);
4537335Sgblack@eecs.umich.edu
4547335Sgblack@eecs.umich.edu        assert(head_inst != 0);
4557335Sgblack@eecs.umich.edu
4567335Sgblack@eecs.umich.edu        if (head_inst->seqNum < lowest_num) {
4577335Sgblack@eecs.umich.edu            head = head_thread;
4587335Sgblack@eecs.umich.edu            lowest_num = head_inst->seqNum;
4597321Sgblack@eecs.umich.edu        }
4607321Sgblack@eecs.umich.edu    }
4617321Sgblack@eecs.umich.edu
4627321Sgblack@eecs.umich.edu    if (first_valid) {
4637321Sgblack@eecs.umich.edu        head = instList[0].end();
4647356Sgblack@eecs.umich.edu    }
4657356Sgblack@eecs.umich.edu
4667356Sgblack@eecs.umich.edu}
4677356Sgblack@eecs.umich.edu
4687356Sgblack@eecs.umich.edutemplate <class Impl>
4697356Sgblack@eecs.umich.eduvoid
4707363Sgblack@eecs.umich.eduROB<Impl>::updateTail()
4717363Sgblack@eecs.umich.edu{
4727363Sgblack@eecs.umich.edu    tail = instList[0].end();
4737363Sgblack@eecs.umich.edu    bool first_valid = true;
4747363Sgblack@eecs.umich.edu
4757363Sgblack@eecs.umich.edu    list<ThreadID>::iterator threads = activeThreads->begin();
4767363Sgblack@eecs.umich.edu    list<ThreadID>::iterator end = activeThreads->end();
4777363Sgblack@eecs.umich.edu
4787363Sgblack@eecs.umich.edu    while (threads != end) {
4797363Sgblack@eecs.umich.edu        ThreadID tid = *threads++;
4807363Sgblack@eecs.umich.edu
4817363Sgblack@eecs.umich.edu        if (instList[tid].empty()) {
4827363Sgblack@eecs.umich.edu            continue;
4837363Sgblack@eecs.umich.edu        }
4847372Sgblack@eecs.umich.edu
4857372Sgblack@eecs.umich.edu        // If this is the first valid then assign w/out
4867372Sgblack@eecs.umich.edu        // comparison
4877372Sgblack@eecs.umich.edu        if (first_valid) {
4887372Sgblack@eecs.umich.edu            tail = instList[tid].end();
4897372Sgblack@eecs.umich.edu            tail--;
4907372Sgblack@eecs.umich.edu            first_valid = false;
4917372Sgblack@eecs.umich.edu            continue;
4927372Sgblack@eecs.umich.edu        }
4937372Sgblack@eecs.umich.edu
4947372Sgblack@eecs.umich.edu        // Assign new tail if this thread's tail is younger
4957372Sgblack@eecs.umich.edu        // than our current "tail high"
4967372Sgblack@eecs.umich.edu        InstIt tail_thread = instList[tid].end();
4977372Sgblack@eecs.umich.edu        tail_thread--;
4987372Sgblack@eecs.umich.edu
4997372Sgblack@eecs.umich.edu        if ((*tail_thread)->seqNum > (*tail)->seqNum) {
5007372Sgblack@eecs.umich.edu            tail = tail_thread;
5017372Sgblack@eecs.umich.edu        }
5027372Sgblack@eecs.umich.edu    }
5037363Sgblack@eecs.umich.edu}
5047363Sgblack@eecs.umich.edu
5057370Sgblack@eecs.umich.edu
5067372Sgblack@eecs.umich.edutemplate <class Impl>
5077376Sgblack@eecs.umich.eduvoid
5087376Sgblack@eecs.umich.eduROB<Impl>::squash(InstSeqNum squash_num, ThreadID tid)
5097370Sgblack@eecs.umich.edu{
5107376Sgblack@eecs.umich.edu    if (isEmpty()) {
5117376Sgblack@eecs.umich.edu        DPRINTF(ROB, "Does not need to squash due to being empty "
5127370Sgblack@eecs.umich.edu                "[sn:%i]\n",
5137370Sgblack@eecs.umich.edu                squash_num);
5147372Sgblack@eecs.umich.edu
5157376Sgblack@eecs.umich.edu        return;
5167376Sgblack@eecs.umich.edu    }
5177370Sgblack@eecs.umich.edu
5187376Sgblack@eecs.umich.edu    DPRINTF(ROB, "Starting to squash within the ROB.\n");
5197376Sgblack@eecs.umich.edu
5207370Sgblack@eecs.umich.edu    robStatus[tid] = ROBSquashing;
5217370Sgblack@eecs.umich.edu
5227371Sgblack@eecs.umich.edu    doneSquashing[tid] = false;
5237371Sgblack@eecs.umich.edu
5247372Sgblack@eecs.umich.edu    squashedSeqNum[tid] = squash_num;
5257376Sgblack@eecs.umich.edu
5267376Sgblack@eecs.umich.edu    if (!instList[tid].empty()) {
5277371Sgblack@eecs.umich.edu        InstIt tail_thread = instList[tid].end();
5287376Sgblack@eecs.umich.edu        tail_thread--;
5297376Sgblack@eecs.umich.edu
5307371Sgblack@eecs.umich.edu        squashIt[tid] = tail_thread;
5317371Sgblack@eecs.umich.edu
5327372Sgblack@eecs.umich.edu        doSquash(tid);
5337376Sgblack@eecs.umich.edu    }
5347376Sgblack@eecs.umich.edu}
5357371Sgblack@eecs.umich.edu/*
5367376Sgblack@eecs.umich.edutemplate <class Impl>
5377376Sgblack@eecs.umich.edutypename Impl::DynInstPtr
5387371Sgblack@eecs.umich.eduROB<Impl>::readHeadInst()
5397371Sgblack@eecs.umich.edu{
5407363Sgblack@eecs.umich.edu    if (numInstsInROB != 0) {
5417363Sgblack@eecs.umich.edu        assert((*head)->isInROB()==true);
5427372Sgblack@eecs.umich.edu        return *head;
5437376Sgblack@eecs.umich.edu    } else {
5447376Sgblack@eecs.umich.edu        return dummyInst;
5457364Sgblack@eecs.umich.edu    }
5467376Sgblack@eecs.umich.edu}
5477376Sgblack@eecs.umich.edu*/
5487364Sgblack@eecs.umich.edu
5497371Sgblack@eecs.umich.edutemplate <class Impl>
5507372Sgblack@eecs.umich.edutypename Impl::DynInstPtr
5517376Sgblack@eecs.umich.eduROB<Impl>::readHeadInst(ThreadID tid)
5527376Sgblack@eecs.umich.edu{
5537371Sgblack@eecs.umich.edu    if (threadEntries[tid] != 0) {
5547376Sgblack@eecs.umich.edu        InstIt head_thread = instList[tid].begin();
5557376Sgblack@eecs.umich.edu
5567371Sgblack@eecs.umich.edu        assert((*head_thread)->isInROB()==true);
5577363Sgblack@eecs.umich.edu
5587363Sgblack@eecs.umich.edu        return *head_thread;
5597363Sgblack@eecs.umich.edu    } else {
5607372Sgblack@eecs.umich.edu        return dummyInst;
5617376Sgblack@eecs.umich.edu    }
5627376Sgblack@eecs.umich.edu}
5637367Sgblack@eecs.umich.edu
5647376Sgblack@eecs.umich.edu/*
5657376Sgblack@eecs.umich.edutemplate <class Impl>
5667367Sgblack@eecs.umich.eduuint64_t
5677363Sgblack@eecs.umich.eduROB<Impl>::readHeadPC()
5687372Sgblack@eecs.umich.edu{
5697376Sgblack@eecs.umich.edu    //assert(numInstsInROB == countInsts());
5707376Sgblack@eecs.umich.edu
5717368Sgblack@eecs.umich.edu    DynInstPtr head_inst = *head;
5727376Sgblack@eecs.umich.edu
5737376Sgblack@eecs.umich.edu    return head_inst->readPC();
5747368Sgblack@eecs.umich.edu}
5757363Sgblack@eecs.umich.edu
5767363Sgblack@eecs.umich.edutemplate <class Impl>
5777363Sgblack@eecs.umich.eduuint64_t
5787372Sgblack@eecs.umich.eduROB<Impl>::readHeadPC(ThreadID tid)
5797376Sgblack@eecs.umich.edu{
5807376Sgblack@eecs.umich.edu    //assert(numInstsInROB == countInsts());
5817369Sgblack@eecs.umich.edu    InstIt head_thread = instList[tid].begin();
5827376Sgblack@eecs.umich.edu
5837376Sgblack@eecs.umich.edu    return (*head_thread)->readPC();
5847369Sgblack@eecs.umich.edu}
5857363Sgblack@eecs.umich.edu
5867363Sgblack@eecs.umich.edu
5877363Sgblack@eecs.umich.edutemplate <class Impl>
5887363Sgblack@eecs.umich.eduuint64_t
5897363Sgblack@eecs.umich.eduROB<Impl>::readHeadNextPC()
5907363Sgblack@eecs.umich.edu{
5917372Sgblack@eecs.umich.edu    //assert(numInstsInROB == countInsts());
5927363Sgblack@eecs.umich.edu
5937376Sgblack@eecs.umich.edu    DynInstPtr head_inst = *head;
5947376Sgblack@eecs.umich.edu
5957363Sgblack@eecs.umich.edu    return head_inst->readNextPC();
5967363Sgblack@eecs.umich.edu}
5977376Sgblack@eecs.umich.edu
5987376Sgblack@eecs.umich.edutemplate <class Impl>
5997363Sgblack@eecs.umich.eduuint64_t
6007363Sgblack@eecs.umich.eduROB<Impl>::readHeadNextPC(ThreadID tid)
6017363Sgblack@eecs.umich.edu{
6027363Sgblack@eecs.umich.edu    //assert(numInstsInROB == countInsts());
6037363Sgblack@eecs.umich.edu    InstIt head_thread = instList[tid].begin();
6047372Sgblack@eecs.umich.edu
6057376Sgblack@eecs.umich.edu    return (*head_thread)->readNextPC();
6067376Sgblack@eecs.umich.edu}
6077363Sgblack@eecs.umich.edu
6087376Sgblack@eecs.umich.edutemplate <class Impl>
6097376Sgblack@eecs.umich.eduInstSeqNum
6107363Sgblack@eecs.umich.eduROB<Impl>::readHeadSeqNum()
6117363Sgblack@eecs.umich.edu{
6127372Sgblack@eecs.umich.edu    //assert(numInstsInROB == countInsts());
6137376Sgblack@eecs.umich.edu    DynInstPtr head_inst = *head;
6147376Sgblack@eecs.umich.edu
6157366Sgblack@eecs.umich.edu    return head_inst->seqNum;
6167376Sgblack@eecs.umich.edu}
6177376Sgblack@eecs.umich.edu
6187366Sgblack@eecs.umich.edutemplate <class Impl>
6197363Sgblack@eecs.umich.eduInstSeqNum
6207363Sgblack@eecs.umich.eduROB<Impl>::readHeadSeqNum(ThreadID tid)
6217363Sgblack@eecs.umich.edu{
6227372Sgblack@eecs.umich.edu    InstIt head_thread = instList[tid].begin();
6237376Sgblack@eecs.umich.edu
6247376Sgblack@eecs.umich.edu    return ((*head_thread)->seqNum);
6257365Sgblack@eecs.umich.edu}
6267376Sgblack@eecs.umich.edu
6277376Sgblack@eecs.umich.edutemplate <class Impl>
6287365Sgblack@eecs.umich.edutypename Impl::DynInstPtr
6297363Sgblack@eecs.umich.eduROB<Impl>::readTailInst()
6307372Sgblack@eecs.umich.edu{
6317376Sgblack@eecs.umich.edu    //assert(numInstsInROB == countInsts());
6327376Sgblack@eecs.umich.edu    //assert(tail != instList[0].end());
6337369Sgblack@eecs.umich.edu
6347376Sgblack@eecs.umich.edu    return (*tail);
6357376Sgblack@eecs.umich.edu}
6367369Sgblack@eecs.umich.edu*/
6377363Sgblack@eecs.umich.edutemplate <class Impl>
6387363Sgblack@eecs.umich.edutypename Impl::DynInstPtr
6397363Sgblack@eecs.umich.eduROB<Impl>::readTailInst(ThreadID tid)
6407363Sgblack@eecs.umich.edu{
6417363Sgblack@eecs.umich.edu    //assert(tail_thread[tid] != instList[tid].end());
6427363Sgblack@eecs.umich.edu
6437363Sgblack@eecs.umich.edu    InstIt tail_thread = instList[tid].end();
6447363Sgblack@eecs.umich.edu    tail_thread--;
6457363Sgblack@eecs.umich.edu
6467363Sgblack@eecs.umich.edu    return *tail_thread;
6477374Sgblack@eecs.umich.edu}
6487374Sgblack@eecs.umich.edu
6497374Sgblack@eecs.umich.edu/*
6507374Sgblack@eecs.umich.edutemplate <class Impl>
6517374Sgblack@eecs.umich.eduuint64_t
6527374Sgblack@eecs.umich.eduROB<Impl>::readTailPC()
6537374Sgblack@eecs.umich.edu{
6547374Sgblack@eecs.umich.edu    //assert(numInstsInROB == countInsts());
6557374Sgblack@eecs.umich.edu
6567363Sgblack@eecs.umich.edu    //assert(tail != instList[0].end());
6577363Sgblack@eecs.umich.edu
6587363Sgblack@eecs.umich.edu    return (*tail)->readPC();
6597373Sgblack@eecs.umich.edu}
6607373Sgblack@eecs.umich.edu
6617373Sgblack@eecs.umich.edutemplate <class Impl>
6627373Sgblack@eecs.umich.eduuint64_t
6637373Sgblack@eecs.umich.eduROB<Impl>::readTailPC(ThreadID tid)
6647373Sgblack@eecs.umich.edu{
6657373Sgblack@eecs.umich.edu    //assert(tail_thread[tid] != instList[tid].end());
6667373Sgblack@eecs.umich.edu
6677373Sgblack@eecs.umich.edu    InstIt tail_thread = instList[tid].end();
6687373Sgblack@eecs.umich.edu    tail_thread--;
6697373Sgblack@eecs.umich.edu
6707373Sgblack@eecs.umich.edu    return (*tail_thread)->readPC();
6717373Sgblack@eecs.umich.edu}
6727373Sgblack@eecs.umich.edu
6737373Sgblack@eecs.umich.edutemplate <class Impl>
6747373Sgblack@eecs.umich.eduInstSeqNum
6757373Sgblack@eecs.umich.eduROB<Impl>::readTailSeqNum()
6767363Sgblack@eecs.umich.edu{
6777363Sgblack@eecs.umich.edu    // Return the last sequence number that has not been squashed.  Other
6787363Sgblack@eecs.umich.edu    // stages can use it to squash any instructions younger than the current
6797363Sgblack@eecs.umich.edu    // tail.
6807363Sgblack@eecs.umich.edu    return (*tail)->seqNum;
6817373Sgblack@eecs.umich.edu}
6827373Sgblack@eecs.umich.edu
6837373Sgblack@eecs.umich.edutemplate <class Impl>
6847373Sgblack@eecs.umich.eduInstSeqNum
6857373Sgblack@eecs.umich.eduROB<Impl>::readTailSeqNum(ThreadID tid)
6867373Sgblack@eecs.umich.edu{
6877373Sgblack@eecs.umich.edu    // Return the last sequence number that has not been squashed.  Other
6887363Sgblack@eecs.umich.edu    // stages can use it to squash any instructions younger than the current
6897373Sgblack@eecs.umich.edu    // tail.
6907373Sgblack@eecs.umich.edu    //    assert(tail_thread[tid] != instList[tid].end());
6917373Sgblack@eecs.umich.edu
6927373Sgblack@eecs.umich.edu    InstIt tail_thread = instList[tid].end();
6937373Sgblack@eecs.umich.edu    tail_thread--;
6947373Sgblack@eecs.umich.edu
6957373Sgblack@eecs.umich.edu    return (*tail_thread)->seqNum;
6967363Sgblack@eecs.umich.edu}
6977363Sgblack@eecs.umich.edu*/
6987363Sgblack@eecs.umich.edu