rob_impl.hh revision 10231:cb2e6950956d
16657Snate@binkert.org/*
26657Snate@binkert.org * Copyright (c) 2012 ARM Limited
36657Snate@binkert.org * All rights reserved
46657Snate@binkert.org *
56657Snate@binkert.org * The license below extends only to copyright in the software and shall
66657Snate@binkert.org * not be construed as granting a license to any other intellectual
76657Snate@binkert.org * property including but not limited to intellectual property relating
86657Snate@binkert.org * to a hardware implementation of the functionality of the software
96657Snate@binkert.org * licensed hereunder.  You may use the software subject to the license
106657Snate@binkert.org * terms below provided that you ensure that this notice is replicated
116657Snate@binkert.org * unmodified and in its entirety in all distributions of the software,
126657Snate@binkert.org * modified or unmodified, in source code or in binary form.
136657Snate@binkert.org *
146657Snate@binkert.org * Copyright (c) 2004-2006 The Regents of The University of Michigan
156657Snate@binkert.org * All rights reserved.
166657Snate@binkert.org *
176657Snate@binkert.org * Redistribution and use in source and binary forms, with or without
186657Snate@binkert.org * modification, are permitted provided that the following conditions are
196657Snate@binkert.org * met: redistributions of source code must retain the above copyright
206657Snate@binkert.org * notice, this list of conditions and the following disclaimer;
216657Snate@binkert.org * redistributions in binary form must reproduce the above copyright
226657Snate@binkert.org * notice, this list of conditions and the following disclaimer in the
236657Snate@binkert.org * documentation and/or other materials provided with the distribution;
246657Snate@binkert.org * neither the name of the copyright holders nor the names of its
256657Snate@binkert.org * contributors may be used to endorse or promote products derived from
266657Snate@binkert.org * this software without specific prior written permission.
276657Snate@binkert.org *
286999Snate@binkert.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
296657Snate@binkert.org * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
306657Snate@binkert.org * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
316657Snate@binkert.org * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
329302Snilay@cs.wisc.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
336657Snate@binkert.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
346657Snate@binkert.org * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
356657Snate@binkert.org * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
366657Snate@binkert.org * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
376657Snate@binkert.org * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
386657Snate@binkert.org * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
396657Snate@binkert.org *
406657Snate@binkert.org * Authors: Kevin Lim
416657Snate@binkert.org *          Korey Sewell
426657Snate@binkert.org */
436657Snate@binkert.org
446657Snate@binkert.org#ifndef __CPU_O3_ROB_IMPL_HH__
456657Snate@binkert.org#define __CPU_O3_ROB_IMPL_HH__
466657Snate@binkert.org
476657Snate@binkert.org#include <list>
486657Snate@binkert.org
496657Snate@binkert.org#include "cpu/o3/rob.hh"
506882SBrad.Beckmann@amd.com#include "debug/Fetch.hh"
516657Snate@binkert.org#include "debug/ROB.hh"
526657Snate@binkert.org#include "params/DerivO3CPU.hh"
536657Snate@binkert.org
546657Snate@binkert.orgusing namespace std;
556657Snate@binkert.org
566657Snate@binkert.orgtemplate <class Impl>
576657Snate@binkert.orgROB<Impl>::ROB(O3CPU *_cpu, DerivO3CPUParams *params)
586657Snate@binkert.org    : cpu(_cpu),
596657Snate@binkert.org      numEntries(params->numROBEntries),
606657Snate@binkert.org      squashWidth(params->squashWidth),
616657Snate@binkert.org      numInstsInROB(0),
626657Snate@binkert.org      numThreads(params->numThreads)
636657Snate@binkert.org{
646657Snate@binkert.org    std::string policy = params->smtROBPolicy;
656657Snate@binkert.org
666657Snate@binkert.org    //Convert string to lowercase
676657Snate@binkert.org    std::transform(policy.begin(), policy.end(), policy.begin(),
686657Snate@binkert.org                   (int(*)(int)) tolower);
696657Snate@binkert.org
7010228Snilay@cs.wisc.edu    //Figure out rob policy
716657Snate@binkert.org    if (policy == "dynamic") {
726657Snate@binkert.org        robPolicy = Dynamic;
7310228Snilay@cs.wisc.edu
746657Snate@binkert.org        //Set Max Entries to Total ROB Capacity
756657Snate@binkert.org        for (ThreadID tid = 0; tid < numThreads; tid++) {
766657Snate@binkert.org            maxEntries[tid] = numEntries;
776657Snate@binkert.org        }
786657Snate@binkert.org
796657Snate@binkert.org    } else if (policy == "partitioned") {
806657Snate@binkert.org        robPolicy = Partitioned;
816657Snate@binkert.org        DPRINTF(Fetch, "ROB sharing policy set to Partitioned\n");
826657Snate@binkert.org
836657Snate@binkert.org        //@todo:make work if part_amt doesnt divide evenly.
846657Snate@binkert.org        int part_amt = numEntries / numThreads;
856657Snate@binkert.org
866657Snate@binkert.org        //Divide ROB up evenly
876657Snate@binkert.org        for (ThreadID tid = 0; tid < numThreads; tid++) {
886657Snate@binkert.org            maxEntries[tid] = part_amt;
896657Snate@binkert.org        }
908086SBrad.Beckmann@amd.com
918086SBrad.Beckmann@amd.com    } else if (policy == "threshold") {
928086SBrad.Beckmann@amd.com        robPolicy = Threshold;
936657Snate@binkert.org        DPRINTF(Fetch, "ROB sharing policy set to Threshold\n");
946657Snate@binkert.org
956657Snate@binkert.org        int threshold =  params->smtROBThreshold;;
966657Snate@binkert.org
976657Snate@binkert.org        //Divide up by threshold amount
986657Snate@binkert.org        for (ThreadID tid = 0; tid < numThreads; tid++) {
996657Snate@binkert.org            maxEntries[tid] = threshold;
1006657Snate@binkert.org        }
1016657Snate@binkert.org    } else {
1026657Snate@binkert.org        assert(0 && "Invalid ROB Sharing Policy.Options Are:{Dynamic,"
1036657Snate@binkert.org                    "Partitioned, Threshold}");
1046657Snate@binkert.org    }
1056657Snate@binkert.org
1066657Snate@binkert.org    resetState();
1076657Snate@binkert.org}
1086657Snate@binkert.org
1096657Snate@binkert.orgtemplate <class Impl>
1106657Snate@binkert.orgvoid
1116657Snate@binkert.orgROB<Impl>::resetState()
1126657Snate@binkert.org{
1136657Snate@binkert.org    for (ThreadID tid = 0; tid  < numThreads; tid++) {
1146657Snate@binkert.org        doneSquashing[tid] = true;
1156657Snate@binkert.org        threadEntries[tid] = 0;
1166657Snate@binkert.org        squashIt[tid] = instList[tid].end();
1176657Snate@binkert.org        squashedSeqNum[tid] = 0;
1186657Snate@binkert.org    }
1196657Snate@binkert.org    numInstsInROB = 0;
1206657Snate@binkert.org
1216657Snate@binkert.org    // Initialize the "universal" ROB head & tail point to invalid
1226657Snate@binkert.org    // pointers
1236657Snate@binkert.org    head = instList[0].end();
1246657Snate@binkert.org    tail = instList[0].end();
1256657Snate@binkert.org}
1266657Snate@binkert.org
1276657Snate@binkert.orgtemplate <class Impl>
1286657Snate@binkert.orgstd::string
1299298Snilay@cs.wisc.eduROB<Impl>::name() const
1306657Snate@binkert.org{
1316657Snate@binkert.org    return cpu->name() + ".rob";
1326657Snate@binkert.org}
1336657Snate@binkert.org
1346657Snate@binkert.orgtemplate <class Impl>
1356657Snate@binkert.orgvoid
1369302Snilay@cs.wisc.eduROB<Impl>::setActiveThreads(list<ThreadID> *at_ptr)
1379302Snilay@cs.wisc.edu{
1389302Snilay@cs.wisc.edu    DPRINTF(ROB, "Setting active threads list pointer.\n");
1396657Snate@binkert.org    activeThreads = at_ptr;
1406657Snate@binkert.org}
1416657Snate@binkert.org
1426657Snate@binkert.orgtemplate <class Impl>
1436657Snate@binkert.orgvoid
1446657Snate@binkert.orgROB<Impl>::drainSanityCheck() const
1456657Snate@binkert.org{
1466657Snate@binkert.org    for (ThreadID tid = 0; tid  < numThreads; tid++)
1476882SBrad.Beckmann@amd.com        assert(instList[tid].empty());
1486882SBrad.Beckmann@amd.com    assert(isEmpty());
1496882SBrad.Beckmann@amd.com}
1508086SBrad.Beckmann@amd.com
1518086SBrad.Beckmann@amd.comtemplate <class Impl>
1528086SBrad.Beckmann@amd.comvoid
15310307Snilay@cs.wisc.eduROB<Impl>::takeOverFrom()
15410307Snilay@cs.wisc.edu{
1556657Snate@binkert.org    resetState();
1566657Snate@binkert.org}
1576657Snate@binkert.org
15810307Snilay@cs.wisc.edutemplate <class Impl>
1599298Snilay@cs.wisc.eduvoid
1609298Snilay@cs.wisc.eduROB<Impl>::resetEntries()
1619298Snilay@cs.wisc.edu{
1626657Snate@binkert.org    if (robPolicy != Dynamic || numThreads > 1) {
1636657Snate@binkert.org        int active_threads = activeThreads->size();
1646657Snate@binkert.org
1656657Snate@binkert.org        list<ThreadID>::iterator threads = activeThreads->begin();
1666657Snate@binkert.org        list<ThreadID>::iterator end = activeThreads->end();
1676657Snate@binkert.org
1686657Snate@binkert.org        while (threads != end) {
1696657Snate@binkert.org            ThreadID tid = *threads++;
1706657Snate@binkert.org
1716657Snate@binkert.org            if (robPolicy == Partitioned) {
1726657Snate@binkert.org                maxEntries[tid] = numEntries / active_threads;
1739219Spower.jg@gmail.com            } else if (robPolicy == Threshold && active_threads == 1) {
1746657Snate@binkert.org                maxEntries[tid] = numEntries;
1756657Snate@binkert.org            }
1766657Snate@binkert.org        }
1776657Snate@binkert.org    }
1786657Snate@binkert.org}
1796657Snate@binkert.org
1806657Snate@binkert.orgtemplate <class Impl>
1816657Snate@binkert.orgint
1826657Snate@binkert.orgROB<Impl>::entryAmount(ThreadID num_threads)
1836657Snate@binkert.org{
1846657Snate@binkert.org    if (robPolicy == Partitioned) {
1856657Snate@binkert.org        return numEntries / num_threads;
1866999Snate@binkert.org    } else {
1876657Snate@binkert.org        return 0;
1886657Snate@binkert.org    }
1896657Snate@binkert.org}
1906657Snate@binkert.org
1916657Snate@binkert.orgtemplate <class Impl>
1926657Snate@binkert.orgint
1936657Snate@binkert.orgROB<Impl>::countInsts()
1947007Snate@binkert.org{
1957007Snate@binkert.org    int total = 0;
1966657Snate@binkert.org
1977002Snate@binkert.org    for (ThreadID tid = 0; tid < numThreads; tid++)
1987002Snate@binkert.org        total += countInsts(tid);
1999466Snilay@cs.wisc.edu
2006657Snate@binkert.org    return total;
2016657Snate@binkert.org}
2026657Snate@binkert.org
2036657Snate@binkert.orgtemplate <class Impl>
2046657Snate@binkert.orgint
2056657Snate@binkert.orgROB<Impl>::countInsts(ThreadID tid)
2066657Snate@binkert.org{
2076657Snate@binkert.org    return instList[tid].size();
2086657Snate@binkert.org}
2096657Snate@binkert.org
2106657Snate@binkert.orgtemplate <class Impl>
2116657Snate@binkert.orgvoid
2127007Snate@binkert.orgROB<Impl>::insertInst(DynInstPtr &inst)
2137007Snate@binkert.org{
2146657Snate@binkert.org    assert(inst);
2159466Snilay@cs.wisc.edu
2166657Snate@binkert.org    robWrites++;
2176657Snate@binkert.org
2189466Snilay@cs.wisc.edu    DPRINTF(ROB, "Adding inst PC %s to the ROB.\n", inst->pcState());
2199508Snilay@cs.wisc.edu
2209466Snilay@cs.wisc.edu    assert(numInstsInROB != numEntries);
2219466Snilay@cs.wisc.edu
2229466Snilay@cs.wisc.edu    ThreadID tid = inst->threadNumber;
2236657Snate@binkert.org
2246657Snate@binkert.org    instList[tid].push_back(inst);
2256657Snate@binkert.org
2266657Snate@binkert.org    //Set Up head iterator if this is the 1st instruction in the ROB
2276657Snate@binkert.org    if (numInstsInROB == 0) {
2286657Snate@binkert.org        head = instList[tid].begin();
2296657Snate@binkert.org        assert((*head) == inst);
2306657Snate@binkert.org    }
2316657Snate@binkert.org
2326657Snate@binkert.org    //Must Decrement for iterator to actually be valid  since __.end()
2336657Snate@binkert.org    //actually points to 1 after the last inst
2346657Snate@binkert.org    tail = instList[tid].end();
2356657Snate@binkert.org    tail--;
2366657Snate@binkert.org
2376657Snate@binkert.org    inst->setInROB();
2386657Snate@binkert.org
2396657Snate@binkert.org    ++numInstsInROB;
2407453Snate@binkert.org    ++threadEntries[tid];
2417453Snate@binkert.org
2427453Snate@binkert.org    assert((*tail) == inst);
2437453Snate@binkert.org
2447453Snate@binkert.org    DPRINTF(ROB, "[tid:%i] Now has %d instructions.\n", tid, threadEntries[tid]);
2457453Snate@binkert.org}
2467453Snate@binkert.org
2477453Snate@binkert.orgtemplate <class Impl>
2487453Snate@binkert.orgvoid
2497453Snate@binkert.orgROB<Impl>::retireHead(ThreadID tid)
2507453Snate@binkert.org{
2517453Snate@binkert.org    robWrites++;
2527453Snate@binkert.org
2537453Snate@binkert.org    assert(numInstsInROB > 0);
2547453Snate@binkert.org
2557453Snate@binkert.org    // Get the head ROB instruction.
2567453Snate@binkert.org    InstIt head_it = instList[tid].begin();
2576657Snate@binkert.org
2586657Snate@binkert.org    DynInstPtr head_inst = (*head_it);
2596657Snate@binkert.org
2606657Snate@binkert.org    assert(head_inst->readyToCommit());
2619466Snilay@cs.wisc.edu
2626657Snate@binkert.org    DPRINTF(ROB, "[tid:%u]: Retiring head instruction, "
2639466Snilay@cs.wisc.edu            "instruction PC %s, [sn:%lli]\n", tid, head_inst->pcState(),
2649508Snilay@cs.wisc.edu            head_inst->seqNum);
2659466Snilay@cs.wisc.edu
2666657Snate@binkert.org    --numInstsInROB;
2676657Snate@binkert.org    --threadEntries[tid];
2686657Snate@binkert.org
2696657Snate@binkert.org    head_inst->clearInROB();
2709466Snilay@cs.wisc.edu    head_inst->setCommitted();
2719466Snilay@cs.wisc.edu
2729466Snilay@cs.wisc.edu    instList[tid].erase(head_it);
2739466Snilay@cs.wisc.edu
2746657Snate@binkert.org    //Update "Global" Head of ROB
2756657Snate@binkert.org    updateHead();
2766657Snate@binkert.org
2776657Snate@binkert.org    // @todo: A special case is needed if the instruction being
2786657Snate@binkert.org    // retired is the only instruction in the ROB; otherwise the tail
2796657Snate@binkert.org    // iterator will become invalidated.
2806657Snate@binkert.org    cpu->removeFrontInst(head_inst);
2816657Snate@binkert.org}
2826657Snate@binkert.org
2836657Snate@binkert.orgtemplate <class Impl>
2846657Snate@binkert.orgbool
2859466Snilay@cs.wisc.eduROB<Impl>::isHeadReady(ThreadID tid)
28610472Sandreas.hansson@arm.com{
28710472Sandreas.hansson@arm.com    robReads++;
28810472Sandreas.hansson@arm.com    if (threadEntries[tid] != 0) {
28910472Sandreas.hansson@arm.com        return instList[tid].front()->readyToCommit();
29010472Sandreas.hansson@arm.com    }
29110472Sandreas.hansson@arm.com
29210472Sandreas.hansson@arm.com    return false;
29310472Sandreas.hansson@arm.com}
29410472Sandreas.hansson@arm.com
29510472Sandreas.hansson@arm.comtemplate <class Impl>
2967453Snate@binkert.orgbool
2977007Snate@binkert.orgROB<Impl>::canCommit()
2987007Snate@binkert.org{
2997453Snate@binkert.org    //@todo: set ActiveThreads through ROB or CPU
3007007Snate@binkert.org    list<ThreadID>::iterator threads = activeThreads->begin();
3016657Snate@binkert.org    list<ThreadID>::iterator end = activeThreads->end();
3026657Snate@binkert.org
3036657Snate@binkert.org    while (threads != end) {
3046657Snate@binkert.org        ThreadID tid = *threads++;
3056657Snate@binkert.org
3066657Snate@binkert.org        if (isHeadReady(tid)) {
3076657Snate@binkert.org            return true;
3086657Snate@binkert.org        }
3096657Snate@binkert.org    }
3106657Snate@binkert.org
3117007Snate@binkert.org    return false;
3127007Snate@binkert.org}
3137007Snate@binkert.org
3147007Snate@binkert.orgtemplate <class Impl>
3157007Snate@binkert.orgunsigned
3166657Snate@binkert.orgROB<Impl>::numFreeEntries()
3176657Snate@binkert.org{
3186657Snate@binkert.org    return numEntries - numInstsInROB;
3196657Snate@binkert.org}
3206657Snate@binkert.org
3216657Snate@binkert.orgtemplate <class Impl>
3226657Snate@binkert.orgunsigned
3236657Snate@binkert.orgROB<Impl>::numFreeEntries(ThreadID tid)
3246657Snate@binkert.org{
3257007Snate@binkert.org    return maxEntries[tid] - threadEntries[tid];
3267007Snate@binkert.org}
3277007Snate@binkert.org
3287007Snate@binkert.orgtemplate <class Impl>
3297007Snate@binkert.orgvoid
3306657Snate@binkert.orgROB<Impl>::doSquash(ThreadID tid)
3316657Snate@binkert.org{
3326657Snate@binkert.org    robWrites++;
3336657Snate@binkert.org    DPRINTF(ROB, "[tid:%u]: Squashing instructions until [sn:%i].\n",
3346657Snate@binkert.org            tid, squashedSeqNum[tid]);
3356657Snate@binkert.org
3366657Snate@binkert.org    assert(squashIt[tid] != instList[tid].end());
3377007Snate@binkert.org
3387007Snate@binkert.org    if ((*squashIt[tid])->seqNum < squashedSeqNum[tid]) {
3397007Snate@binkert.org        DPRINTF(ROB, "[tid:%u]: Done squashing instructions.\n",
3407007Snate@binkert.org                tid);
3417007Snate@binkert.org
3426657Snate@binkert.org        squashIt[tid] = instList[tid].end();
3436657Snate@binkert.org
3447002Snate@binkert.org        doneSquashing[tid] = true;
3456657Snate@binkert.org        return;
3466657Snate@binkert.org    }
3476657Snate@binkert.org
3486657Snate@binkert.org    bool robTailUpdate = false;
3496657Snate@binkert.org
3506657Snate@binkert.org    for (int numSquashed = 0;
3516657Snate@binkert.org         numSquashed < squashWidth &&
3526657Snate@binkert.org         squashIt[tid] != instList[tid].end() &&
3536657Snate@binkert.org         (*squashIt[tid])->seqNum > squashedSeqNum[tid];
3546657Snate@binkert.org         ++numSquashed)
3556657Snate@binkert.org    {
3566657Snate@binkert.org        DPRINTF(ROB, "[tid:%u]: Squashing instruction PC %s, seq num %i.\n",
3576657Snate@binkert.org                (*squashIt[tid])->threadNumber,
3586657Snate@binkert.org                (*squashIt[tid])->pcState(),
3596657Snate@binkert.org                (*squashIt[tid])->seqNum);
3606657Snate@binkert.org
3616657Snate@binkert.org        // Mark the instruction as squashed, and ready to commit so that
3626657Snate@binkert.org        // it can drain out of the pipeline.
3636657Snate@binkert.org        (*squashIt[tid])->setSquashed();
3646657Snate@binkert.org
3656657Snate@binkert.org        (*squashIt[tid])->setCanCommit();
3667007Snate@binkert.org
3676657Snate@binkert.org
3687007Snate@binkert.org        if (squashIt[tid] == instList[tid].begin()) {
3696657Snate@binkert.org            DPRINTF(ROB, "Reached head of instruction list while "
37010307Snilay@cs.wisc.edu                    "squashing.\n");
37110307Snilay@cs.wisc.edu
37210307Snilay@cs.wisc.edu            squashIt[tid] = instList[tid].end();
3739298Snilay@cs.wisc.edu
3749298Snilay@cs.wisc.edu            doneSquashing[tid] = true;
3759298Snilay@cs.wisc.edu
3766657Snate@binkert.org            return;
3776657Snate@binkert.org        }
3786657Snate@binkert.org
3796657Snate@binkert.org        InstIt tail_thread = instList[tid].end();
3807055Snate@binkert.org        tail_thread--;
3817007Snate@binkert.org
3826657Snate@binkert.org        if ((*squashIt[tid]) == (*tail_thread))
3836657Snate@binkert.org            robTailUpdate = true;
3847002Snate@binkert.org
3856657Snate@binkert.org        squashIt[tid]--;
3866657Snate@binkert.org    }
3876657Snate@binkert.org
3887007Snate@binkert.org
3896657Snate@binkert.org    // Check if ROB is done squashing.
3906657Snate@binkert.org    if ((*squashIt[tid])->seqNum <= squashedSeqNum[tid]) {
3916657Snate@binkert.org        DPRINTF(ROB, "[tid:%u]: Done squashing instructions.\n",
3926657Snate@binkert.org                tid);
3936657Snate@binkert.org
3946999Snate@binkert.org        squashIt[tid] = instList[tid].end();
3956657Snate@binkert.org
3966657Snate@binkert.org        doneSquashing[tid] = true;
3976657Snate@binkert.org    }
3986657Snate@binkert.org
3996657Snate@binkert.org    if (robTailUpdate) {
4006657Snate@binkert.org        updateTail();
4016657Snate@binkert.org    }
4027002Snate@binkert.org}
40310472Sandreas.hansson@arm.com
4047002Snate@binkert.org
4056657Snate@binkert.orgtemplate <class Impl>
4069499Snilay@cs.wisc.eduvoid
4079499Snilay@cs.wisc.eduROB<Impl>::updateHead()
4087002Snate@binkert.org{
4097002Snate@binkert.org    InstSeqNum lowest_num = 0;
4106657Snate@binkert.org    bool first_valid = true;
4116657Snate@binkert.org
4126657Snate@binkert.org    // @todo: set ActiveThreads through ROB or CPU
4136657Snate@binkert.org    list<ThreadID>::iterator threads = activeThreads->begin();
4147007Snate@binkert.org    list<ThreadID>::iterator end = activeThreads->end();
4157007Snate@binkert.org
4166657Snate@binkert.org    while (threads != end) {
4176657Snate@binkert.org        ThreadID tid = *threads++;
4186657Snate@binkert.org
4196657Snate@binkert.org        if (instList[tid].empty())
4206657Snate@binkert.org            continue;
4216657Snate@binkert.org
4226657Snate@binkert.org        if (first_valid) {
4236657Snate@binkert.org            head = instList[tid].begin();
4246657Snate@binkert.org            lowest_num = (*head)->seqNum;
4256657Snate@binkert.org            first_valid = false;
4269206Snilay@cs.wisc.edu            continue;
4276657Snate@binkert.org        }
4286657Snate@binkert.org
4296657Snate@binkert.org        InstIt head_thread = instList[tid].begin();
4306657Snate@binkert.org
4316657Snate@binkert.org        DynInstPtr head_inst = (*head_thread);
4326657Snate@binkert.org
4336657Snate@binkert.org        assert(head_inst != 0);
43410307Snilay@cs.wisc.edu
43510307Snilay@cs.wisc.edu        if (head_inst->seqNum < lowest_num) {
43610307Snilay@cs.wisc.edu            head = head_thread;
4379298Snilay@cs.wisc.edu            lowest_num = head_inst->seqNum;
4386657Snate@binkert.org        }
4396657Snate@binkert.org    }
4406657Snate@binkert.org
4416999Snate@binkert.org    if (first_valid) {
4426657Snate@binkert.org        head = instList[0].end();
4436657Snate@binkert.org    }
4446657Snate@binkert.org
4456657Snate@binkert.org}
4466657Snate@binkert.org
4477007Snate@binkert.orgtemplate <class Impl>
4487007Snate@binkert.orgvoid
4497007Snate@binkert.orgROB<Impl>::updateTail()
4506657Snate@binkert.org{
4517002Snate@binkert.org    tail = instList[0].end();
4527002Snate@binkert.org    bool first_valid = true;
4537002Snate@binkert.org
4548086SBrad.Beckmann@amd.com    list<ThreadID>::iterator threads = activeThreads->begin();
4558086SBrad.Beckmann@amd.com    list<ThreadID>::iterator end = activeThreads->end();
4568086SBrad.Beckmann@amd.com
4578086SBrad.Beckmann@amd.com    while (threads != end) {
4588602Snilay@cs.wisc.edu        ThreadID tid = *threads++;
4598602Snilay@cs.wisc.edu
4608602Snilay@cs.wisc.edu        if (instList[tid].empty()) {
4618602Snilay@cs.wisc.edu            continue;
4628602Snilay@cs.wisc.edu        }
4638086SBrad.Beckmann@amd.com
4646657Snate@binkert.org        // If this is the first valid then assign w/out
4657007Snate@binkert.org        // comparison
4666657Snate@binkert.org        if (first_valid) {
4676657Snate@binkert.org            tail = instList[tid].end();
4686657Snate@binkert.org            tail--;
4696657Snate@binkert.org            first_valid = false;
4706657Snate@binkert.org            continue;
4716657Snate@binkert.org        }
4726657Snate@binkert.org
4736657Snate@binkert.org        // Assign new tail if this thread's tail is younger
4746657Snate@binkert.org        // than our current "tail high"
4756657Snate@binkert.org        InstIt tail_thread = instList[tid].end();
4766657Snate@binkert.org        tail_thread--;
4776862Sdrh5@cs.wisc.edu
4786862Sdrh5@cs.wisc.edu        if ((*tail_thread)->seqNum > (*tail)->seqNum) {
4796862Sdrh5@cs.wisc.edu            tail = tail_thread;
4806862Sdrh5@cs.wisc.edu        }
4816657Snate@binkert.org    }
4826657Snate@binkert.org}
4836657Snate@binkert.org
4846657Snate@binkert.org
4856657Snate@binkert.orgtemplate <class Impl>
4867007Snate@binkert.orgvoid
4877007Snate@binkert.orgROB<Impl>::squash(InstSeqNum squash_num, ThreadID tid)
4887002Snate@binkert.org{
4897007Snate@binkert.org    if (isEmpty(tid)) {
4907007Snate@binkert.org        DPRINTF(ROB, "Does not need to squash due to being empty "
4917002Snate@binkert.org                "[sn:%i]\n",
4927007Snate@binkert.org                squash_num);
4937007Snate@binkert.org
4946657Snate@binkert.org        return;
4956657Snate@binkert.org    }
4966657Snate@binkert.org
4976657Snate@binkert.org    DPRINTF(ROB, "Starting to squash within the ROB.\n");
4986657Snate@binkert.org
4996657Snate@binkert.org    robStatus[tid] = ROBSquashing;
5006657Snate@binkert.org
5016657Snate@binkert.org    doneSquashing[tid] = false;
5026657Snate@binkert.org
5036657Snate@binkert.org    squashedSeqNum[tid] = squash_num;
5046657Snate@binkert.org
5056657Snate@binkert.org    if (!instList[tid].empty()) {
5066657Snate@binkert.org        InstIt tail_thread = instList[tid].end();
5078602Snilay@cs.wisc.edu        tail_thread--;
5088602Snilay@cs.wisc.edu
5098602Snilay@cs.wisc.edu        squashIt[tid] = tail_thread;
5108602Snilay@cs.wisc.edu
5118602Snilay@cs.wisc.edu        doSquash(tid);
5128602Snilay@cs.wisc.edu    }
5138602Snilay@cs.wisc.edu}
5148602Snilay@cs.wisc.edu
5158602Snilay@cs.wisc.edutemplate <class Impl>
5168086SBrad.Beckmann@amd.comtypename Impl::DynInstPtr
5178086SBrad.Beckmann@amd.comROB<Impl>::readHeadInst(ThreadID tid)
5188086SBrad.Beckmann@amd.com{
5198086SBrad.Beckmann@amd.com    if (threadEntries[tid] != 0) {
5208086SBrad.Beckmann@amd.com        InstIt head_thread = instList[tid].begin();
5218086SBrad.Beckmann@amd.com
5228086SBrad.Beckmann@amd.com        assert((*head_thread)->isInROB());
5238086SBrad.Beckmann@amd.com
5246657Snate@binkert.org        return *head_thread;
5256657Snate@binkert.org    } else {
5267002Snate@binkert.org        return dummyInst;
5276657Snate@binkert.org    }
5287007Snate@binkert.org}
5296657Snate@binkert.org
5306657Snate@binkert.orgtemplate <class Impl>
5316657Snate@binkert.orgtypename Impl::DynInstPtr
5326657Snate@binkert.orgROB<Impl>::readTailInst(ThreadID tid)
5336657Snate@binkert.org{
5346999Snate@binkert.org    InstIt tail_thread = instList[tid].end();
5356657Snate@binkert.org    tail_thread--;
5366657Snate@binkert.org
5376657Snate@binkert.org    return *tail_thread;
5386657Snate@binkert.org}
5396657Snate@binkert.org
5406657Snate@binkert.orgtemplate <class Impl>
5417832Snate@binkert.orgvoid
5427002Snate@binkert.orgROB<Impl>::regStats()
5437002Snate@binkert.org{
5447002Snate@binkert.org    using namespace Stats;
5457805Snilay@cs.wisc.edu    robReads
5466657Snate@binkert.org        .name(name() + ".rob_reads")
5476657Snate@binkert.org        .desc("The number of ROB reads");
5487002Snate@binkert.org
5497002Snate@binkert.org    robWrites
5506657Snate@binkert.org        .name(name() + ".rob_writes")
5516657Snate@binkert.org        .desc("The number of ROB writes");
5528086SBrad.Beckmann@amd.com}
5538086SBrad.Beckmann@amd.com
5548086SBrad.Beckmann@amd.comtemplate <class Impl>
5558086SBrad.Beckmann@amd.comtypename Impl::DynInstPtr
5568086SBrad.Beckmann@amd.comROB<Impl>::findInst(ThreadID tid, InstSeqNum squash_inst)
5578086SBrad.Beckmann@amd.com{
5588086SBrad.Beckmann@amd.com    for (InstIt it = instList[tid].begin(); it != instList[tid].end(); it++) {
5598086SBrad.Beckmann@amd.com        if ((*it)->seqNum == squash_inst) {
5608086SBrad.Beckmann@amd.com            return *it;
5618086SBrad.Beckmann@amd.com        }
5628086SBrad.Beckmann@amd.com    }
5638086SBrad.Beckmann@amd.com    return NULL;
5648086SBrad.Beckmann@amd.com}
5658086SBrad.Beckmann@amd.com
5668086SBrad.Beckmann@amd.com#endif//__CPU_O3_ROB_IMPL_HH__
5678086SBrad.Beckmann@amd.com