rob_impl.hh revision 2980
17259Sgblack@eecs.umich.edu/*
211574SCurtis.Dunham@arm.com * Copyright (c) 2004-2006 The Regents of The University of Michigan
37259Sgblack@eecs.umich.edu * All rights reserved.
47259Sgblack@eecs.umich.edu *
57259Sgblack@eecs.umich.edu * Redistribution and use in source and binary forms, with or without
67259Sgblack@eecs.umich.edu * modification, are permitted provided that the following conditions are
77259Sgblack@eecs.umich.edu * met: redistributions of source code must retain the above copyright
87259Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer;
97259Sgblack@eecs.umich.edu * redistributions in binary form must reproduce the above copyright
107259Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the
117259Sgblack@eecs.umich.edu * documentation and/or other materials provided with the distribution;
127259Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its
137259Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from
147259Sgblack@eecs.umich.edu * this software without specific prior written permission.
157259Sgblack@eecs.umich.edu *
167259Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
177259Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
187259Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
197259Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
207259Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
217259Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
227259Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
237259Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
247259Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
257259Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
267259Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
277259Sgblack@eecs.umich.edu *
287259Sgblack@eecs.umich.edu * Authors: Kevin Lim
297259Sgblack@eecs.umich.edu *          Korey Sewell
307259Sgblack@eecs.umich.edu */
317259Sgblack@eecs.umich.edu
327259Sgblack@eecs.umich.edu#include "config/full_system.hh"
337259Sgblack@eecs.umich.edu#include "cpu/o3/rob.hh"
347259Sgblack@eecs.umich.edu
357259Sgblack@eecs.umich.edu#include <list>
367259Sgblack@eecs.umich.edu
377259Sgblack@eecs.umich.edutemplate <class Impl>
387405SAli.Saidi@ARM.comROB<Impl>::ROB(unsigned _numEntries, unsigned _squashWidth,
3910037SARM gem5 Developers               std::string _smtROBPolicy, unsigned _smtROBThreshold,
407259Sgblack@eecs.umich.edu               unsigned _numThreads)
417259Sgblack@eecs.umich.edu    : numEntries(_numEntries),
427405SAli.Saidi@ARM.com      squashWidth(_squashWidth),
437259Sgblack@eecs.umich.edu      numInstsInROB(0),
447404SAli.Saidi@ARM.com      numThreads(_numThreads)
4510037SARM gem5 Developers{
4610828SGiacomo.Gabrielli@arm.com    for (int tid=0; tid  < numThreads; tid++) {
477259Sgblack@eecs.umich.edu        squashedSeqNum[tid] = 0;
487259Sgblack@eecs.umich.edu        doneSquashing[tid] = true;
497259Sgblack@eecs.umich.edu        threadEntries[tid] = 0;
507259Sgblack@eecs.umich.edu    }
517259Sgblack@eecs.umich.edu
528868SMatt.Horsnell@arm.com    std::string policy = _smtROBPolicy;
538868SMatt.Horsnell@arm.com
548868SMatt.Horsnell@arm.com    //Convert string to lowercase
558868SMatt.Horsnell@arm.com    std::transform(policy.begin(), policy.end(), policy.begin(),
5610037SARM gem5 Developers                   (int(*)(int)) tolower);
578868SMatt.Horsnell@arm.com
5810037SARM gem5 Developers    //Figure out rob policy
598868SMatt.Horsnell@arm.com    if (policy == "dynamic") {
6010037SARM gem5 Developers        robPolicy = Dynamic;
6110037SARM gem5 Developers
6210037SARM gem5 Developers        //Set Max Entries to Total ROB Capacity
6310037SARM gem5 Developers        for (int i = 0; i < numThreads; i++) {
6410037SARM gem5 Developers            maxEntries[i]=numEntries;
6510037SARM gem5 Developers        }
6610037SARM gem5 Developers
678868SMatt.Horsnell@arm.com    } else if (policy == "partitioned") {
6810037SARM gem5 Developers        robPolicy = Partitioned;
6910037SARM gem5 Developers        DPRINTF(Fetch, "ROB sharing policy set to Partitioned\n");
7010037SARM gem5 Developers
7110037SARM gem5 Developers        //@todo:make work if part_amt doesnt divide evenly.
7210037SARM gem5 Developers        int part_amt = numEntries / numThreads;
7310037SARM gem5 Developers
7410037SARM gem5 Developers        //Divide ROB up evenly
7510037SARM gem5 Developers        for (int i = 0; i < numThreads; i++) {
7610037SARM gem5 Developers            maxEntries[i]=part_amt;
7710037SARM gem5 Developers        }
7810037SARM gem5 Developers
799959Schander.sudanthi@arm.com    } else if (policy == "threshold") {
8010037SARM gem5 Developers        robPolicy = Threshold;
819959Schander.sudanthi@arm.com        DPRINTF(Fetch, "ROB sharing policy set to Threshold\n");
829959Schander.sudanthi@arm.com
839959Schander.sudanthi@arm.com        int threshold =  _smtROBThreshold;;
849959Schander.sudanthi@arm.com
859959Schander.sudanthi@arm.com        //Divide up by threshold amount
869959Schander.sudanthi@arm.com        for (int i = 0; i < numThreads; i++) {
879959Schander.sudanthi@arm.com            maxEntries[i]=threshold;
889959Schander.sudanthi@arm.com        }
899959Schander.sudanthi@arm.com    } else {
9010037SARM gem5 Developers        assert(0 && "Invalid ROB Sharing Policy.Options Are:{Dynamic,"
919959Schander.sudanthi@arm.com                    "Partitioned, Threshold}");
9210037SARM gem5 Developers    }
9310037SARM gem5 Developers}
9410037SARM gem5 Developers
9510037SARM gem5 Developerstemplate <class Impl>
9610037SARM gem5 Developersstd::string
9710037SARM gem5 DevelopersROB<Impl>::name() const
9810037SARM gem5 Developers{
9910037SARM gem5 Developers    return cpu->name() + ".rob";
10010037SARM gem5 Developers}
10110037SARM gem5 Developers
10210037SARM gem5 Developerstemplate <class Impl>
1038868SMatt.Horsnell@arm.comvoid
10410037SARM gem5 DevelopersROB<Impl>::setCPU(O3CPU *cpu_ptr)
10510037SARM gem5 Developers{
10610037SARM gem5 Developers    cpu = cpu_ptr;
10710037SARM gem5 Developers
10810037SARM gem5 Developers    // Set the per-thread iterators to the end of the instruction list.
10910037SARM gem5 Developers    for (int i=0; i < numThreads;i++) {
11010037SARM gem5 Developers        squashIt[i] = instList[i].end();
11110037SARM gem5 Developers    }
11210037SARM gem5 Developers
11310037SARM gem5 Developers    // Initialize the "universal" ROB head & tail point to invalid
11410037SARM gem5 Developers    // pointers
11510037SARM gem5 Developers    head = instList[0].end();
11610037SARM gem5 Developers    tail = instList[0].end();
11710037SARM gem5 Developers}
11810037SARM gem5 Developers
1198868SMatt.Horsnell@arm.comtemplate <class Impl>
12010037SARM gem5 Developersvoid
12110037SARM gem5 DevelopersROB<Impl>::setActiveThreads(std::list<unsigned> *at_ptr)
12210037SARM gem5 Developers{
12310037SARM gem5 Developers    DPRINTF(ROB, "Setting active threads list pointer.\n");
12410037SARM gem5 Developers    activeThreads = at_ptr;
1258868SMatt.Horsnell@arm.com}
12610037SARM gem5 Developers
12710037SARM gem5 Developerstemplate <class Impl>
12810037SARM gem5 Developersvoid
12910037SARM gem5 DevelopersROB<Impl>::switchOut()
13010506SAli.Saidi@ARM.com{
13110037SARM gem5 Developers    for (int tid = 0; tid < numThreads; tid++) {
13210506SAli.Saidi@ARM.com        instList[tid].clear();
13310037SARM gem5 Developers    }
13410506SAli.Saidi@ARM.com}
13510037SARM gem5 Developers
13610506SAli.Saidi@ARM.comtemplate <class Impl>
13710037SARM gem5 Developersvoid
13810506SAli.Saidi@ARM.comROB<Impl>::takeOverFrom()
13910037SARM gem5 Developers{
14010506SAli.Saidi@ARM.com    for (int tid=0; tid  < numThreads; tid++) {
14110037SARM gem5 Developers        doneSquashing[tid] = true;
14210506SAli.Saidi@ARM.com        threadEntries[tid] = 0;
14310037SARM gem5 Developers        squashIt[tid] = instList[tid].end();
14410506SAli.Saidi@ARM.com    }
14510037SARM gem5 Developers    numInstsInROB = 0;
14610506SAli.Saidi@ARM.com
14710037SARM gem5 Developers    // Initialize the "universal" ROB head & tail point to invalid
14810506SAli.Saidi@ARM.com    // pointers
14910037SARM gem5 Developers    head = instList[0].end();
15010506SAli.Saidi@ARM.com    tail = instList[0].end();
15110037SARM gem5 Developers}
15210506SAli.Saidi@ARM.com
15310037SARM gem5 Developerstemplate <class Impl>
15410506SAli.Saidi@ARM.comvoid
15510037SARM gem5 DevelopersROB<Impl>::resetEntries()
15610506SAli.Saidi@ARM.com{
15710037SARM gem5 Developers    if (robPolicy != Dynamic || numThreads > 1) {
15810506SAli.Saidi@ARM.com        int active_threads = (*activeThreads).size();
15910037SARM gem5 Developers
16010037SARM gem5 Developers        std::list<unsigned>::iterator threads  = (*activeThreads).begin();
16110037SARM gem5 Developers        std::list<unsigned>::iterator list_end = (*activeThreads).end();
16210506SAli.Saidi@ARM.com
16310037SARM gem5 Developers        while (threads != list_end) {
16410506SAli.Saidi@ARM.com            if (robPolicy == Partitioned) {
16510037SARM gem5 Developers                maxEntries[*threads++] = numEntries / active_threads;
16610506SAli.Saidi@ARM.com            } else if (robPolicy == Threshold && active_threads == 1) {
16710037SARM gem5 Developers                maxEntries[*threads++] = numEntries;
16810506SAli.Saidi@ARM.com            }
16910037SARM gem5 Developers        }
17010506SAli.Saidi@ARM.com    }
17110037SARM gem5 Developers}
17210506SAli.Saidi@ARM.com
17310037SARM gem5 Developerstemplate <class Impl>
17410506SAli.Saidi@ARM.comint
17510037SARM gem5 DevelopersROB<Impl>::entryAmount(int num_threads)
17610506SAli.Saidi@ARM.com{
17710037SARM gem5 Developers    if (robPolicy == Partitioned) {
17810506SAli.Saidi@ARM.com        return numEntries / num_threads;
17910037SARM gem5 Developers    } else {
18010506SAli.Saidi@ARM.com        return 0;
18110037SARM gem5 Developers    }
18210506SAli.Saidi@ARM.com}
18310037SARM gem5 Developers
18410506SAli.Saidi@ARM.comtemplate <class Impl>
18510037SARM gem5 Developersint
18610506SAli.Saidi@ARM.comROB<Impl>::countInsts()
18710037SARM gem5 Developers{
18810506SAli.Saidi@ARM.com    int total=0;
18910037SARM gem5 Developers
19010506SAli.Saidi@ARM.com    for (int i=0;i < numThreads;i++)
19110037SARM gem5 Developers        total += countInsts(i);
19210037SARM gem5 Developers
19310037SARM gem5 Developers    return total;
19410506SAli.Saidi@ARM.com}
19510037SARM gem5 Developers
19610506SAli.Saidi@ARM.comtemplate <class Impl>
19710037SARM gem5 Developersint
19810506SAli.Saidi@ARM.comROB<Impl>::countInsts(unsigned tid)
19910037SARM gem5 Developers{
20010506SAli.Saidi@ARM.com    return instList[tid].size();
20110037SARM gem5 Developers}
20210506SAli.Saidi@ARM.com
20310037SARM gem5 Developerstemplate <class Impl>
20410506SAli.Saidi@ARM.comvoid
20510037SARM gem5 DevelopersROB<Impl>::insertInst(DynInstPtr &inst)
20610506SAli.Saidi@ARM.com{
20710037SARM gem5 Developers    //assert(numInstsInROB == countInsts());
20810506SAli.Saidi@ARM.com    assert(inst);
20910037SARM gem5 Developers
21010506SAli.Saidi@ARM.com    DPRINTF(ROB, "Adding inst PC %#x to the ROB.\n", inst->readPC());
21110037SARM gem5 Developers
21210506SAli.Saidi@ARM.com    assert(numInstsInROB != numEntries);
21310037SARM gem5 Developers
21410506SAli.Saidi@ARM.com    int tid = inst->threadNumber;
21510037SARM gem5 Developers
21610506SAli.Saidi@ARM.com    instList[tid].push_back(inst);
21710037SARM gem5 Developers
21810506SAli.Saidi@ARM.com    //Set Up head iterator if this is the 1st instruction in the ROB
21910037SARM gem5 Developers    if (numInstsInROB == 0) {
22010506SAli.Saidi@ARM.com        head = instList[tid].begin();
22110037SARM gem5 Developers        assert((*head) == inst);
22210506SAli.Saidi@ARM.com    }
22310037SARM gem5 Developers
22410506SAli.Saidi@ARM.com    //Must Decrement for iterator to actually be valid  since __.end()
22510037SARM gem5 Developers    //actually points to 1 after the last inst
22610506SAli.Saidi@ARM.com    tail = instList[tid].end();
22710037SARM gem5 Developers    tail--;
22810506SAli.Saidi@ARM.com
22910037SARM gem5 Developers    inst->setInROB();
23010506SAli.Saidi@ARM.com
23110037SARM gem5 Developers    ++numInstsInROB;
23210506SAli.Saidi@ARM.com    ++threadEntries[tid];
23310037SARM gem5 Developers
23410506SAli.Saidi@ARM.com    assert((*tail) == inst);
23510037SARM gem5 Developers
23610506SAli.Saidi@ARM.com    DPRINTF(ROB, "[tid:%i] Now has %d instructions.\n", tid, threadEntries[tid]);
23710037SARM gem5 Developers}
23810506SAli.Saidi@ARM.com
23910037SARM gem5 Developers// Whatever calls this function needs to ensure that it properly frees up
24010506SAli.Saidi@ARM.com// registers prior to this function.
24110037SARM gem5 Developers/*
24210506SAli.Saidi@ARM.comtemplate <class Impl>
24310037SARM gem5 Developersvoid
24410506SAli.Saidi@ARM.comROB<Impl>::retireHead()
24510037SARM gem5 Developers{
24610506SAli.Saidi@ARM.com    //assert(numInstsInROB == countInsts());
24710037SARM gem5 Developers    assert(numInstsInROB > 0);
24810506SAli.Saidi@ARM.com
24910037SARM gem5 Developers    int tid = (*head)->threadNumber;
25010506SAli.Saidi@ARM.com
25110037SARM gem5 Developers    retireHead(tid);
25210506SAli.Saidi@ARM.com
25310037SARM gem5 Developers    if (numInstsInROB == 0) {
25410506SAli.Saidi@ARM.com        tail = instList[tid].end();
25510037SARM gem5 Developers    }
25610506SAli.Saidi@ARM.com}
25710037SARM gem5 Developers*/
25810506SAli.Saidi@ARM.com
25910037SARM gem5 Developerstemplate <class Impl>
26010506SAli.Saidi@ARM.comvoid
26110037SARM gem5 DevelopersROB<Impl>::retireHead(unsigned tid)
26210506SAli.Saidi@ARM.com{
26310037SARM gem5 Developers    //assert(numInstsInROB == countInsts());
26410506SAli.Saidi@ARM.com    assert(numInstsInROB > 0);
26510037SARM gem5 Developers
26610506SAli.Saidi@ARM.com    // Get the head ROB instruction.
26710037SARM gem5 Developers    InstIt head_it = instList[tid].begin();
26810506SAli.Saidi@ARM.com
26910037SARM gem5 Developers    DynInstPtr head_inst = (*head_it);
27010506SAli.Saidi@ARM.com
27110037SARM gem5 Developers    assert(head_inst->readyToCommit());
27210506SAli.Saidi@ARM.com
27310037SARM gem5 Developers    DPRINTF(ROB, "[tid:%u]: Retiring head instruction, "
27410506SAli.Saidi@ARM.com            "instruction PC %#x,[sn:%lli]\n", tid, head_inst->readPC(),
27510037SARM gem5 Developers            head_inst->seqNum);
27610506SAli.Saidi@ARM.com
27710037SARM gem5 Developers    --numInstsInROB;
27810506SAli.Saidi@ARM.com    --threadEntries[tid];
27910037SARM gem5 Developers
28010506SAli.Saidi@ARM.com    head_inst->clearInROB();
28110037SARM gem5 Developers    head_inst->setCommitted();
28210506SAli.Saidi@ARM.com
28310037SARM gem5 Developers    instList[tid].erase(head_it);
28410506SAli.Saidi@ARM.com
28510037SARM gem5 Developers    //Update "Global" Head of ROB
28610506SAli.Saidi@ARM.com    updateHead();
28710037SARM gem5 Developers
28810506SAli.Saidi@ARM.com    // @todo: A special case is needed if the instruction being
28910037SARM gem5 Developers    // retired is the only instruction in the ROB; otherwise the tail
29010506SAli.Saidi@ARM.com    // iterator will become invalidated.
29110037SARM gem5 Developers    cpu->removeFrontInst(head_inst);
29210506SAli.Saidi@ARM.com}
29310037SARM gem5 Developers/*
29410037SARM gem5 Developerstemplate <class Impl>
29510037SARM gem5 Developersbool
29610506SAli.Saidi@ARM.comROB<Impl>::isHeadReady()
29710037SARM gem5 Developers{
29810506SAli.Saidi@ARM.com    if (numInstsInROB != 0) {
29910037SARM gem5 Developers        return (*head)->readyToCommit();
30010506SAli.Saidi@ARM.com    }
30110037SARM gem5 Developers
30210506SAli.Saidi@ARM.com    return false;
30310037SARM gem5 Developers}
30410506SAli.Saidi@ARM.com*/
30510037SARM gem5 Developerstemplate <class Impl>
30610506SAli.Saidi@ARM.combool
30710037SARM gem5 DevelopersROB<Impl>::isHeadReady(unsigned tid)
30810506SAli.Saidi@ARM.com{
30910037SARM gem5 Developers    if (threadEntries[tid] != 0) {
31010506SAli.Saidi@ARM.com        return instList[tid].front()->readyToCommit();
31110037SARM gem5 Developers    }
31210506SAli.Saidi@ARM.com
31310037SARM gem5 Developers    return false;
31410506SAli.Saidi@ARM.com}
31510037SARM gem5 Developers
31610506SAli.Saidi@ARM.comtemplate <class Impl>
31710037SARM gem5 Developersbool
31810506SAli.Saidi@ARM.comROB<Impl>::canCommit()
31910037SARM gem5 Developers{
32010506SAli.Saidi@ARM.com    //@todo: set ActiveThreads through ROB or CPU
32110037SARM gem5 Developers    std::list<unsigned>::iterator threads = (*activeThreads).begin();
32210506SAli.Saidi@ARM.com
32310037SARM gem5 Developers    while (threads != (*activeThreads).end()) {
32410506SAli.Saidi@ARM.com        unsigned tid = *threads++;
32510037SARM gem5 Developers
32610506SAli.Saidi@ARM.com        if (isHeadReady(tid)) {
32710037SARM gem5 Developers            return true;
32810506SAli.Saidi@ARM.com        }
32910037SARM gem5 Developers    }
33010506SAli.Saidi@ARM.com
33110037SARM gem5 Developers    return false;
33210506SAli.Saidi@ARM.com}
33310037SARM gem5 Developers
33410506SAli.Saidi@ARM.comtemplate <class Impl>
33510037SARM gem5 Developersunsigned
33610506SAli.Saidi@ARM.comROB<Impl>::numFreeEntries()
33710037SARM gem5 Developers{
33810506SAli.Saidi@ARM.com    //assert(numInstsInROB == countInsts());
33910037SARM gem5 Developers
34010506SAli.Saidi@ARM.com    return numEntries - numInstsInROB;
34110037SARM gem5 Developers}
34210506SAli.Saidi@ARM.com
34310037SARM gem5 Developerstemplate <class Impl>
34410506SAli.Saidi@ARM.comunsigned
34510037SARM gem5 DevelopersROB<Impl>::numFreeEntries(unsigned tid)
34610506SAli.Saidi@ARM.com{
34710037SARM gem5 Developers    return maxEntries[tid] - threadEntries[tid];
34810506SAli.Saidi@ARM.com}
34910037SARM gem5 Developers
35010506SAli.Saidi@ARM.comtemplate <class Impl>
35110037SARM gem5 Developersvoid
35210506SAli.Saidi@ARM.comROB<Impl>::doSquash(unsigned tid)
35310037SARM gem5 Developers{
35410506SAli.Saidi@ARM.com    DPRINTF(ROB, "[tid:%u]: Squashing instructions until [sn:%i].\n",
35510037SARM gem5 Developers            tid, squashedSeqNum[tid]);
35610506SAli.Saidi@ARM.com
35710037SARM gem5 Developers    assert(squashIt[tid] != instList[tid].end());
35810506SAli.Saidi@ARM.com
35910037SARM gem5 Developers    if ((*squashIt[tid])->seqNum < squashedSeqNum[tid]) {
36010506SAli.Saidi@ARM.com        DPRINTF(ROB, "[tid:%u]: Done squashing instructions.\n",
36110037SARM gem5 Developers                tid);
36210506SAli.Saidi@ARM.com
36310037SARM gem5 Developers        squashIt[tid] = instList[tid].end();
36410506SAli.Saidi@ARM.com
36510037SARM gem5 Developers        doneSquashing[tid] = true;
36610506SAli.Saidi@ARM.com        return;
36710037SARM gem5 Developers    }
36810506SAli.Saidi@ARM.com
36910037SARM gem5 Developers    bool robTailUpdate = false;
37010506SAli.Saidi@ARM.com
37110037SARM gem5 Developers    for (int numSquashed = 0;
37210506SAli.Saidi@ARM.com         numSquashed < squashWidth &&
37310037SARM gem5 Developers         squashIt[tid] != instList[tid].end() &&
37410506SAli.Saidi@ARM.com         (*squashIt[tid])->seqNum > squashedSeqNum[tid];
37510037SARM gem5 Developers         ++numSquashed)
37610506SAli.Saidi@ARM.com    {
37710037SARM gem5 Developers        DPRINTF(ROB, "[tid:%u]: Squashing instruction PC %#x, seq num %i.\n",
37810506SAli.Saidi@ARM.com                (*squashIt[tid])->threadNumber,
37910037SARM gem5 Developers                (*squashIt[tid])->readPC(),
38010506SAli.Saidi@ARM.com                (*squashIt[tid])->seqNum);
38110037SARM gem5 Developers
38210506SAli.Saidi@ARM.com        // Mark the instruction as squashed, and ready to commit so that
38310037SARM gem5 Developers        // it can drain out of the pipeline.
38410506SAli.Saidi@ARM.com        (*squashIt[tid])->setSquashed();
38510037SARM gem5 Developers
38610506SAli.Saidi@ARM.com        (*squashIt[tid])->setCanCommit();
38710037SARM gem5 Developers
38810506SAli.Saidi@ARM.com
38910037SARM gem5 Developers        if (squashIt[tid] == instList[tid].begin()) {
39010506SAli.Saidi@ARM.com            DPRINTF(ROB, "Reached head of instruction list while "
39110037SARM gem5 Developers                    "squashing.\n");
39210506SAli.Saidi@ARM.com
39310037SARM gem5 Developers            squashIt[tid] = instList[tid].end();
39410506SAli.Saidi@ARM.com
39510037SARM gem5 Developers            doneSquashing[tid] = true;
39610506SAli.Saidi@ARM.com
39710037SARM gem5 Developers            return;
39810506SAli.Saidi@ARM.com        }
39910037SARM gem5 Developers
40010506SAli.Saidi@ARM.com        InstIt tail_thread = instList[tid].end();
40110037SARM gem5 Developers        tail_thread--;
40210506SAli.Saidi@ARM.com
40310037SARM gem5 Developers        if ((*squashIt[tid]) == (*tail_thread))
40410506SAli.Saidi@ARM.com            robTailUpdate = true;
40510037SARM gem5 Developers
40610506SAli.Saidi@ARM.com        squashIt[tid]--;
40710037SARM gem5 Developers    }
40810506SAli.Saidi@ARM.com
40910037SARM gem5 Developers
41010506SAli.Saidi@ARM.com    // Check if ROB is done squashing.
41110037SARM gem5 Developers    if ((*squashIt[tid])->seqNum <= squashedSeqNum[tid]) {
41210506SAli.Saidi@ARM.com        DPRINTF(ROB, "[tid:%u]: Done squashing instructions.\n",
41310037SARM gem5 Developers                tid);
41410506SAli.Saidi@ARM.com
41510037SARM gem5 Developers        squashIt[tid] = instList[tid].end();
41610506SAli.Saidi@ARM.com
41710037SARM gem5 Developers        doneSquashing[tid] = true;
41810506SAli.Saidi@ARM.com    }
41910037SARM gem5 Developers
42010506SAli.Saidi@ARM.com    if (robTailUpdate) {
42110037SARM gem5 Developers        updateTail();
42210506SAli.Saidi@ARM.com    }
42310037SARM gem5 Developers}
42410506SAli.Saidi@ARM.com
42510037SARM gem5 Developers
42610506SAli.Saidi@ARM.comtemplate <class Impl>
42710037SARM gem5 Developersvoid
42810506SAli.Saidi@ARM.comROB<Impl>::updateHead()
42910037SARM gem5 Developers{
43010506SAli.Saidi@ARM.com    DynInstPtr head_inst;
43110037SARM gem5 Developers    InstSeqNum lowest_num = 0;
43210506SAli.Saidi@ARM.com    bool first_valid = true;
43310037SARM gem5 Developers
43410506SAli.Saidi@ARM.com    // @todo: set ActiveThreads through ROB or CPU
43510037SARM gem5 Developers    std::list<unsigned>::iterator threads = (*activeThreads).begin();
43610506SAli.Saidi@ARM.com
43710037SARM gem5 Developers    while (threads != (*activeThreads).end()) {
43810506SAli.Saidi@ARM.com        unsigned thread_num = *threads++;
43910037SARM gem5 Developers
44010506SAli.Saidi@ARM.com        if (instList[thread_num].empty())
44110037SARM gem5 Developers            continue;
44210506SAli.Saidi@ARM.com
44310037SARM gem5 Developers        if (first_valid) {
44410506SAli.Saidi@ARM.com            head = instList[thread_num].begin();
44510037SARM gem5 Developers            lowest_num = (*head)->seqNum;
44610506SAli.Saidi@ARM.com            first_valid = false;
44710037SARM gem5 Developers            continue;
44810506SAli.Saidi@ARM.com        }
44910037SARM gem5 Developers
45010506SAli.Saidi@ARM.com        InstIt head_thread = instList[thread_num].begin();
45110037SARM gem5 Developers
45210506SAli.Saidi@ARM.com        DynInstPtr head_inst = (*head_thread);
45310037SARM gem5 Developers
45410506SAli.Saidi@ARM.com        assert(head_inst != 0);
45510037SARM gem5 Developers
45610506SAli.Saidi@ARM.com        if (head_inst->seqNum < lowest_num) {
45710037SARM gem5 Developers            head = head_thread;
45810506SAli.Saidi@ARM.com            lowest_num = head_inst->seqNum;
45910037SARM gem5 Developers        }
46010506SAli.Saidi@ARM.com    }
46110037SARM gem5 Developers
46210506SAli.Saidi@ARM.com    if (first_valid) {
46310037SARM gem5 Developers        head = instList[0].end();
46410506SAli.Saidi@ARM.com    }
46510037SARM gem5 Developers
46610506SAli.Saidi@ARM.com}
46710037SARM gem5 Developers
46810506SAli.Saidi@ARM.comtemplate <class Impl>
46910037SARM gem5 Developersvoid
47010506SAli.Saidi@ARM.comROB<Impl>::updateTail()
47110037SARM gem5 Developers{
47210506SAli.Saidi@ARM.com    tail = instList[0].end();
47310037SARM gem5 Developers    bool first_valid = true;
47410506SAli.Saidi@ARM.com
47510037SARM gem5 Developers    std::list<unsigned>::iterator threads = (*activeThreads).begin();
47610506SAli.Saidi@ARM.com
47710037SARM gem5 Developers    while (threads != (*activeThreads).end()) {
47810506SAli.Saidi@ARM.com        unsigned tid = *threads++;
47910037SARM gem5 Developers
48010506SAli.Saidi@ARM.com        if (instList[tid].empty()) {
48110037SARM gem5 Developers            continue;
48210506SAli.Saidi@ARM.com        }
48310037SARM gem5 Developers
48410506SAli.Saidi@ARM.com        // If this is the first valid then assign w/out
48510037SARM gem5 Developers        // comparison
48610506SAli.Saidi@ARM.com        if (first_valid) {
48710037SARM gem5 Developers            tail = instList[tid].end();
48810506SAli.Saidi@ARM.com            tail--;
48910037SARM gem5 Developers            first_valid = false;
49010506SAli.Saidi@ARM.com            continue;
49110037SARM gem5 Developers        }
49210506SAli.Saidi@ARM.com
49310037SARM gem5 Developers        // Assign new tail if this thread's tail is younger
49410506SAli.Saidi@ARM.com        // than our current "tail high"
49510037SARM gem5 Developers        InstIt tail_thread = instList[tid].end();
49610506SAli.Saidi@ARM.com        tail_thread--;
49710037SARM gem5 Developers
49810506SAli.Saidi@ARM.com        if ((*tail_thread)->seqNum > (*tail)->seqNum) {
49910037SARM gem5 Developers            tail = tail_thread;
50010506SAli.Saidi@ARM.com        }
50110037SARM gem5 Developers    }
50210506SAli.Saidi@ARM.com}
50310037SARM gem5 Developers
50410506SAli.Saidi@ARM.com
50510037SARM gem5 Developerstemplate <class Impl>
50610506SAli.Saidi@ARM.comvoid
50710037SARM gem5 DevelopersROB<Impl>::squash(InstSeqNum squash_num,unsigned tid)
50810506SAli.Saidi@ARM.com{
50910037SARM gem5 Developers    if (isEmpty()) {
51010506SAli.Saidi@ARM.com        DPRINTF(ROB, "Does not need to squash due to being empty "
51110037SARM gem5 Developers                "[sn:%i]\n",
51210506SAli.Saidi@ARM.com                squash_num);
51310037SARM gem5 Developers
51410506SAli.Saidi@ARM.com        return;
51510037SARM gem5 Developers    }
51610506SAli.Saidi@ARM.com
51710037SARM gem5 Developers    DPRINTF(ROB, "Starting to squash within the ROB.\n");
51810506SAli.Saidi@ARM.com
51910037SARM gem5 Developers    robStatus[tid] = ROBSquashing;
52010506SAli.Saidi@ARM.com
52110037SARM gem5 Developers    doneSquashing[tid] = false;
52210506SAli.Saidi@ARM.com
52310037SARM gem5 Developers    squashedSeqNum[tid] = squash_num;
52410506SAli.Saidi@ARM.com
52510037SARM gem5 Developers    if (!instList[tid].empty()) {
52610506SAli.Saidi@ARM.com        InstIt tail_thread = instList[tid].end();
52710037SARM gem5 Developers        tail_thread--;
52810506SAli.Saidi@ARM.com
52910037SARM gem5 Developers        squashIt[tid] = tail_thread;
53010506SAli.Saidi@ARM.com
53110037SARM gem5 Developers        doSquash(tid);
53210506SAli.Saidi@ARM.com    }
53310037SARM gem5 Developers}
53410506SAli.Saidi@ARM.com/*
53510037SARM gem5 Developerstemplate <class Impl>
53610506SAli.Saidi@ARM.comtypename Impl::DynInstPtr
53710037SARM gem5 DevelopersROB<Impl>::readHeadInst()
53810506SAli.Saidi@ARM.com{
53910037SARM gem5 Developers    if (numInstsInROB != 0) {
54010506SAli.Saidi@ARM.com        assert((*head)->isInROB()==true);
54110037SARM gem5 Developers        return *head;
54210506SAli.Saidi@ARM.com    } else {
54310037SARM gem5 Developers        return dummyInst;
54410506SAli.Saidi@ARM.com    }
54510037SARM gem5 Developers}
54610506SAli.Saidi@ARM.com*/
54710037SARM gem5 Developers
54810506SAli.Saidi@ARM.comtemplate <class Impl>
54910037SARM gem5 Developerstypename Impl::DynInstPtr
55010506SAli.Saidi@ARM.comROB<Impl>::readHeadInst(unsigned tid)
55110037SARM gem5 Developers{
55210506SAli.Saidi@ARM.com    if (threadEntries[tid] != 0) {
55310037SARM gem5 Developers        InstIt head_thread = instList[tid].begin();
55410506SAli.Saidi@ARM.com
55510037SARM gem5 Developers        assert((*head_thread)->isInROB()==true);
55610506SAli.Saidi@ARM.com
55710037SARM gem5 Developers        return *head_thread;
55810506SAli.Saidi@ARM.com    } else {
55910037SARM gem5 Developers        return dummyInst;
56010506SAli.Saidi@ARM.com    }
56110037SARM gem5 Developers}
56210506SAli.Saidi@ARM.com
56310037SARM gem5 Developers/*
56410506SAli.Saidi@ARM.comtemplate <class Impl>
56510037SARM gem5 Developersuint64_t
56610506SAli.Saidi@ARM.comROB<Impl>::readHeadPC()
56710037SARM gem5 Developers{
56810506SAli.Saidi@ARM.com    //assert(numInstsInROB == countInsts());
56910037SARM gem5 Developers
57010506SAli.Saidi@ARM.com    DynInstPtr head_inst = *head;
57110037SARM gem5 Developers
57210506SAli.Saidi@ARM.com    return head_inst->readPC();
57310037SARM gem5 Developers}
57410506SAli.Saidi@ARM.com
57510037SARM gem5 Developerstemplate <class Impl>
57610506SAli.Saidi@ARM.comuint64_t
57710037SARM gem5 DevelopersROB<Impl>::readHeadPC(unsigned tid)
57810506SAli.Saidi@ARM.com{
57910037SARM gem5 Developers    //assert(numInstsInROB == countInsts());
58010506SAli.Saidi@ARM.com    InstIt head_thread = instList[tid].begin();
58110037SARM gem5 Developers
58210506SAli.Saidi@ARM.com    return (*head_thread)->readPC();
58310037SARM gem5 Developers}
58410506SAli.Saidi@ARM.com
58510037SARM gem5 Developers
58610506SAli.Saidi@ARM.comtemplate <class Impl>
58710037SARM gem5 Developersuint64_t
58810506SAli.Saidi@ARM.comROB<Impl>::readHeadNextPC()
58910037SARM gem5 Developers{
59010506SAli.Saidi@ARM.com    //assert(numInstsInROB == countInsts());
59110037SARM gem5 Developers
59210506SAli.Saidi@ARM.com    DynInstPtr head_inst = *head;
59310037SARM gem5 Developers
59410506SAli.Saidi@ARM.com    return head_inst->readNextPC();
59510037SARM gem5 Developers}
59610506SAli.Saidi@ARM.com
59710037SARM gem5 Developerstemplate <class Impl>
59810506SAli.Saidi@ARM.comuint64_t
59910037SARM gem5 DevelopersROB<Impl>::readHeadNextPC(unsigned tid)
60010506SAli.Saidi@ARM.com{
60110037SARM gem5 Developers    //assert(numInstsInROB == countInsts());
60210506SAli.Saidi@ARM.com    InstIt head_thread = instList[tid].begin();
60310037SARM gem5 Developers
60410506SAli.Saidi@ARM.com    return (*head_thread)->readNextPC();
60510037SARM gem5 Developers}
60610506SAli.Saidi@ARM.com
60710037SARM gem5 Developerstemplate <class Impl>
60810506SAli.Saidi@ARM.comInstSeqNum
60910037SARM gem5 DevelopersROB<Impl>::readHeadSeqNum()
61010506SAli.Saidi@ARM.com{
61110037SARM gem5 Developers    //assert(numInstsInROB == countInsts());
61210506SAli.Saidi@ARM.com    DynInstPtr head_inst = *head;
61310037SARM gem5 Developers
61410506SAli.Saidi@ARM.com    return head_inst->seqNum;
61510037SARM gem5 Developers}
61610506SAli.Saidi@ARM.com
61710037SARM gem5 Developerstemplate <class Impl>
61810506SAli.Saidi@ARM.comInstSeqNum
61910037SARM gem5 DevelopersROB<Impl>::readHeadSeqNum(unsigned tid)
62010506SAli.Saidi@ARM.com{
62110037SARM gem5 Developers    InstIt head_thread = instList[tid].begin();
62210506SAli.Saidi@ARM.com
62310037SARM gem5 Developers    return ((*head_thread)->seqNum);
62410506SAli.Saidi@ARM.com}
62510037SARM gem5 Developers
62610506SAli.Saidi@ARM.comtemplate <class Impl>
62710037SARM gem5 Developerstypename Impl::DynInstPtr
62810506SAli.Saidi@ARM.comROB<Impl>::readTailInst()
62910037SARM gem5 Developers{
63010506SAli.Saidi@ARM.com    //assert(numInstsInROB == countInsts());
63110037SARM gem5 Developers    //assert(tail != instList[0].end());
63210506SAli.Saidi@ARM.com
63310037SARM gem5 Developers    return (*tail);
63410506SAli.Saidi@ARM.com}
63510037SARM gem5 Developers*/
63610506SAli.Saidi@ARM.comtemplate <class Impl>
63710037SARM gem5 Developerstypename Impl::DynInstPtr
63810506SAli.Saidi@ARM.comROB<Impl>::readTailInst(unsigned tid)
63910037SARM gem5 Developers{
64010506SAli.Saidi@ARM.com    //assert(tail_thread[tid] != instList[tid].end());
64110037SARM gem5 Developers
64210506SAli.Saidi@ARM.com    InstIt tail_thread = instList[tid].end();
64310037SARM gem5 Developers    tail_thread--;
64410506SAli.Saidi@ARM.com
64510037SARM gem5 Developers    return *tail_thread;
64610506SAli.Saidi@ARM.com}
64710037SARM gem5 Developers
64810506SAli.Saidi@ARM.com/*
64910037SARM gem5 Developerstemplate <class Impl>
65010506SAli.Saidi@ARM.comuint64_t
65110037SARM gem5 DevelopersROB<Impl>::readTailPC()
65210506SAli.Saidi@ARM.com{
65310037SARM gem5 Developers    //assert(numInstsInROB == countInsts());
65410506SAli.Saidi@ARM.com
65510037SARM gem5 Developers    //assert(tail != instList[0].end());
65610506SAli.Saidi@ARM.com
65710037SARM gem5 Developers    return (*tail)->readPC();
65810506SAli.Saidi@ARM.com}
65910037SARM gem5 Developers
66010506SAli.Saidi@ARM.comtemplate <class Impl>
66110037SARM gem5 Developersuint64_t
66210506SAli.Saidi@ARM.comROB<Impl>::readTailPC(unsigned tid)
66310037SARM gem5 Developers{
66410506SAli.Saidi@ARM.com    //assert(tail_thread[tid] != instList[tid].end());
66510037SARM gem5 Developers
66610506SAli.Saidi@ARM.com    InstIt tail_thread = instList[tid].end();
66710037SARM gem5 Developers    tail_thread--;
66810506SAli.Saidi@ARM.com
66910037SARM gem5 Developers    return (*tail_thread)->readPC();
67010506SAli.Saidi@ARM.com}
67110037SARM gem5 Developers
67210506SAli.Saidi@ARM.comtemplate <class Impl>
67310037SARM gem5 DevelopersInstSeqNum
67410506SAli.Saidi@ARM.comROB<Impl>::readTailSeqNum()
67510037SARM gem5 Developers{
67610506SAli.Saidi@ARM.com    // Return the last sequence number that has not been squashed.  Other
67710037SARM gem5 Developers    // stages can use it to squash any instructions younger than the current
67810506SAli.Saidi@ARM.com    // tail.
67910037SARM gem5 Developers    return (*tail)->seqNum;
68010506SAli.Saidi@ARM.com}
68110037SARM gem5 Developers
68210506SAli.Saidi@ARM.comtemplate <class Impl>
68310037SARM gem5 DevelopersInstSeqNum
68410506SAli.Saidi@ARM.comROB<Impl>::readTailSeqNum(unsigned tid)
68510037SARM gem5 Developers{
68610506SAli.Saidi@ARM.com    // Return the last sequence number that has not been squashed.  Other
68710037SARM gem5 Developers    // stages can use it to squash any instructions younger than the current
68810506SAli.Saidi@ARM.com    // tail.
68910037SARM gem5 Developers    //    assert(tail_thread[tid] != instList[tid].end());
69010506SAli.Saidi@ARM.com
69110037SARM gem5 Developers    InstIt tail_thread = instList[tid].end();
69210506SAli.Saidi@ARM.com    tail_thread--;
69310037SARM gem5 Developers
69410506SAli.Saidi@ARM.com    return (*tail_thread)->seqNum;
69510037SARM gem5 Developers}
69610506SAli.Saidi@ARM.com*/
69710037SARM gem5 Developers