rob_impl.hh revision 14016
15132Sgblack@eecs.umich.edu/*
25132Sgblack@eecs.umich.edu * Copyright (c) 2012 ARM Limited
35132Sgblack@eecs.umich.edu * All rights reserved
45132Sgblack@eecs.umich.edu *
57087Snate@binkert.org * The license below extends only to copyright in the software and shall
67087Snate@binkert.org * not be construed as granting a license to any other intellectual
77087Snate@binkert.org * property including but not limited to intellectual property relating
87087Snate@binkert.org * to a hardware implementation of the functionality of the software
97087Snate@binkert.org * licensed hereunder.  You may use the software subject to the license
107087Snate@binkert.org * terms below provided that you ensure that this notice is replicated
117087Snate@binkert.org * unmodified and in its entirety in all distributions of the software,
127087Snate@binkert.org * modified or unmodified, in source code or in binary form.
135132Sgblack@eecs.umich.edu *
147087Snate@binkert.org * Copyright (c) 2004-2006 The Regents of The University of Michigan
157087Snate@binkert.org * All rights reserved.
167087Snate@binkert.org *
177087Snate@binkert.org * Redistribution and use in source and binary forms, with or without
187087Snate@binkert.org * modification, are permitted provided that the following conditions are
197087Snate@binkert.org * met: redistributions of source code must retain the above copyright
207087Snate@binkert.org * notice, this list of conditions and the following disclaimer;
217087Snate@binkert.org * redistributions in binary form must reproduce the above copyright
225132Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the
237087Snate@binkert.org * documentation and/or other materials provided with the distribution;
245132Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its
255132Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from
265132Sgblack@eecs.umich.edu * this software without specific prior written permission.
275132Sgblack@eecs.umich.edu *
285132Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
295132Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
305132Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
315132Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
325132Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
335132Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
345132Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
355132Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
365132Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
375132Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
385132Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
395132Sgblack@eecs.umich.edu *
4011793Sbrandon.potter@amd.com * Authors: Kevin Lim
4111793Sbrandon.potter@amd.com *          Korey Sewell
4211793Sbrandon.potter@amd.com */
438229Snate@binkert.org
445612Sgblack@eecs.umich.edu#ifndef __CPU_O3_ROB_IMPL_HH__
4511793Sbrandon.potter@amd.com#define __CPU_O3_ROB_IMPL_HH__
468229Snate@binkert.org
4711793Sbrandon.potter@amd.com#include <list>
485132Sgblack@eecs.umich.edu
495132Sgblack@eecs.umich.edu#include "base/logging.hh"
505132Sgblack@eecs.umich.edu#include "cpu/o3/rob.hh"
515299Sgblack@eecs.umich.edu#include "debug/Fetch.hh"
528706Sandreas.hansson@arm.com#include "debug/ROB.hh"
535132Sgblack@eecs.umich.edu#include "params/DerivO3CPU.hh"
545132Sgblack@eecs.umich.edu
555132Sgblack@eecs.umich.eduusing namespace std;
565299Sgblack@eecs.umich.edu
575299Sgblack@eecs.umich.edutemplate <class Impl>
585132Sgblack@eecs.umich.eduROB<Impl>::ROB(O3CPU *_cpu, DerivO3CPUParams *params)
595625Sgblack@eecs.umich.edu    : robPolicy(params->smtROBPolicy),
605625Sgblack@eecs.umich.edu      cpu(_cpu),
615625Sgblack@eecs.umich.edu      numEntries(params->numROBEntries),
625627Sgblack@eecs.umich.edu      squashWidth(params->squashWidth),
635627Sgblack@eecs.umich.edu      numInstsInROB(0),
647704Sgblack@eecs.umich.edu      numThreads(params->numThreads)
657704Sgblack@eecs.umich.edu{
665132Sgblack@eecs.umich.edu    //Figure out rob policy
6710554Salexandru.dutu@amd.com    if (robPolicy == SMTQueuePolicy::Dynamic) {
6810554Salexandru.dutu@amd.com        //Set Max Entries to Total ROB Capacity
696220Sgblack@eecs.umich.edu        for (ThreadID tid = 0; tid < numThreads; tid++) {
706220Sgblack@eecs.umich.edu            maxEntries[tid] = numEntries;
716220Sgblack@eecs.umich.edu        }
726220Sgblack@eecs.umich.edu
736220Sgblack@eecs.umich.edu    } else if (robPolicy == SMTQueuePolicy::Partitioned) {
746220Sgblack@eecs.umich.edu        DPRINTF(Fetch, "ROB sharing policy set to Partitioned\n");
756220Sgblack@eecs.umich.edu
766220Sgblack@eecs.umich.edu        //@todo:make work if part_amt doesnt divide evenly.
776220Sgblack@eecs.umich.edu        int part_amt = numEntries / numThreads;
786220Sgblack@eecs.umich.edu
796222Sgblack@eecs.umich.edu        //Divide ROB up evenly
806222Sgblack@eecs.umich.edu        for (ThreadID tid = 0; tid < numThreads; tid++) {
816222Sgblack@eecs.umich.edu            maxEntries[tid] = part_amt;
826222Sgblack@eecs.umich.edu        }
836222Sgblack@eecs.umich.edu
846222Sgblack@eecs.umich.edu    } else if (robPolicy == SMTQueuePolicy::Threshold) {
856222Sgblack@eecs.umich.edu        DPRINTF(Fetch, "ROB sharing policy set to Threshold\n");
866222Sgblack@eecs.umich.edu
876222Sgblack@eecs.umich.edu        int threshold =  params->smtROBThreshold;;
886222Sgblack@eecs.umich.edu
896220Sgblack@eecs.umich.edu        //Divide up by threshold amount
906220Sgblack@eecs.umich.edu        for (ThreadID tid = 0; tid < numThreads; tid++) {
916220Sgblack@eecs.umich.edu            maxEntries[tid] = threshold;
926222Sgblack@eecs.umich.edu        }
936220Sgblack@eecs.umich.edu    }
946222Sgblack@eecs.umich.edu
956220Sgblack@eecs.umich.edu    for (ThreadID tid = numThreads; tid < Impl::MaxThreads; tid++) {
966220Sgblack@eecs.umich.edu        maxEntries[tid] = 0;
976222Sgblack@eecs.umich.edu    }
986220Sgblack@eecs.umich.edu
996220Sgblack@eecs.umich.edu    resetState();
1006220Sgblack@eecs.umich.edu}
1016220Sgblack@eecs.umich.edu
1026222Sgblack@eecs.umich.edutemplate <class Impl>
1036220Sgblack@eecs.umich.eduvoid
1046220Sgblack@eecs.umich.eduROB<Impl>::resetState()
1056220Sgblack@eecs.umich.edu{
1066220Sgblack@eecs.umich.edu    for (ThreadID tid = 0; tid  < Impl::MaxThreads; tid++) {
1076220Sgblack@eecs.umich.edu        threadEntries[tid] = 0;
1086220Sgblack@eecs.umich.edu        squashIt[tid] = instList[tid].end();
1096220Sgblack@eecs.umich.edu        squashedSeqNum[tid] = 0;
1106220Sgblack@eecs.umich.edu        doneSquashing[tid] = true;
1116220Sgblack@eecs.umich.edu    }
1126220Sgblack@eecs.umich.edu    numInstsInROB = 0;
1135299Sgblack@eecs.umich.edu
1147532Ssteve.reinhardt@amd.com    // Initialize the "universal" ROB head & tail point to invalid
1155299Sgblack@eecs.umich.edu    // pointers
1167532Ssteve.reinhardt@amd.com    head = instList[0].end();
1177532Ssteve.reinhardt@amd.com    tail = instList[0].end();
1188958Sgblack@eecs.umich.edu}
1198958Sgblack@eecs.umich.edu
1208958Sgblack@eecs.umich.edutemplate <class Impl>
1218706Sandreas.hansson@arm.comstd::string
1228706Sandreas.hansson@arm.comROB<Impl>::name() const
1238706Sandreas.hansson@arm.com{
1246220Sgblack@eecs.umich.edu    return cpu->name() + ".rob";
1255299Sgblack@eecs.umich.edu}
1265299Sgblack@eecs.umich.edu
1275299Sgblack@eecs.umich.edutemplate <class Impl>
1285299Sgblack@eecs.umich.eduvoid
1295299Sgblack@eecs.umich.eduROB<Impl>::setActiveThreads(list<ThreadID> *at_ptr)
1305299Sgblack@eecs.umich.edu{
1315299Sgblack@eecs.umich.edu    DPRINTF(ROB, "Setting active threads list pointer.\n");
1325299Sgblack@eecs.umich.edu    activeThreads = at_ptr;
1335299Sgblack@eecs.umich.edu}
1345299Sgblack@eecs.umich.edu
1355299Sgblack@eecs.umich.edutemplate <class Impl>
1365299Sgblack@eecs.umich.eduvoid
1375299Sgblack@eecs.umich.eduROB<Impl>::drainSanityCheck() const
1385299Sgblack@eecs.umich.edu{
1395299Sgblack@eecs.umich.edu    for (ThreadID tid = 0; tid  < numThreads; tid++)
1405299Sgblack@eecs.umich.edu        assert(instList[tid].empty());
1415299Sgblack@eecs.umich.edu    assert(isEmpty());
1425299Sgblack@eecs.umich.edu}
1435299Sgblack@eecs.umich.edu
1445299Sgblack@eecs.umich.edutemplate <class Impl>
1455299Sgblack@eecs.umich.eduvoid
1465299Sgblack@eecs.umich.eduROB<Impl>::takeOverFrom()
1475299Sgblack@eecs.umich.edu{
1486220Sgblack@eecs.umich.edu    resetState();
1495299Sgblack@eecs.umich.edu}
1505299Sgblack@eecs.umich.edu
1518852Sandreas.hansson@arm.comtemplate <class Impl>
1528852Sandreas.hansson@arm.comvoid
1536220Sgblack@eecs.umich.eduROB<Impl>::resetEntries()
1545299Sgblack@eecs.umich.edu{
15510554Salexandru.dutu@amd.com    if (robPolicy != SMTQueuePolicy::Dynamic || numThreads > 1) {
15610554Salexandru.dutu@amd.com        auto active_threads = activeThreads->size();
15710554Salexandru.dutu@amd.com
15810554Salexandru.dutu@amd.com        list<ThreadID>::iterator threads = activeThreads->begin();
15910554Salexandru.dutu@amd.com        list<ThreadID>::iterator end = activeThreads->end();
16010554Salexandru.dutu@amd.com
16110554Salexandru.dutu@amd.com        while (threads != end) {
16210554Salexandru.dutu@amd.com            ThreadID tid = *threads++;
16310554Salexandru.dutu@amd.com
16410554Salexandru.dutu@amd.com            if (robPolicy == SMTQueuePolicy::Partitioned) {
16510554Salexandru.dutu@amd.com                maxEntries[tid] = numEntries / active_threads;
16610554Salexandru.dutu@amd.com            } else if (robPolicy == SMTQueuePolicy::Threshold &&
16710554Salexandru.dutu@amd.com                       active_threads == 1) {
16810554Salexandru.dutu@amd.com                maxEntries[tid] = numEntries;
16910554Salexandru.dutu@amd.com            }
1705299Sgblack@eecs.umich.edu        }
17110554Salexandru.dutu@amd.com    }
1726220Sgblack@eecs.umich.edu}
17310554Salexandru.dutu@amd.com
1745299Sgblack@eecs.umich.edutemplate <class Impl>
1755299Sgblack@eecs.umich.eduint
1765299Sgblack@eecs.umich.eduROB<Impl>::entryAmount(ThreadID num_threads)
1775299Sgblack@eecs.umich.edu{
1785299Sgblack@eecs.umich.edu    if (robPolicy == SMTQueuePolicy::Partitioned) {
1798852Sandreas.hansson@arm.com        return numEntries / num_threads;
1808852Sandreas.hansson@arm.com    } else {
1815299Sgblack@eecs.umich.edu        return 0;
1826220Sgblack@eecs.umich.edu    }
1836220Sgblack@eecs.umich.edu}
1846220Sgblack@eecs.umich.edu
1856220Sgblack@eecs.umich.edutemplate <class Impl>
1866220Sgblack@eecs.umich.eduint
1876220Sgblack@eecs.umich.eduROB<Impl>::countInsts()
1886220Sgblack@eecs.umich.edu{
1896220Sgblack@eecs.umich.edu    int total = 0;
19010554Salexandru.dutu@amd.com
1916220Sgblack@eecs.umich.edu    for (ThreadID tid = 0; tid < numThreads; tid++)
1928852Sandreas.hansson@arm.com        total += countInsts(tid);
1938852Sandreas.hansson@arm.com
1946220Sgblack@eecs.umich.edu    return total;
1956220Sgblack@eecs.umich.edu}
1966220Sgblack@eecs.umich.edu
1976712Snate@binkert.orgtemplate <class Impl>
1986220Sgblack@eecs.umich.edusize_t
1996220Sgblack@eecs.umich.eduROB<Impl>::countInsts(ThreadID tid)
2006220Sgblack@eecs.umich.edu{
2016220Sgblack@eecs.umich.edu    return instList[tid].size();
2026220Sgblack@eecs.umich.edu}
2036220Sgblack@eecs.umich.edu
2046220Sgblack@eecs.umich.edutemplate <class Impl>
2056220Sgblack@eecs.umich.eduvoid
2066220Sgblack@eecs.umich.eduROB<Impl>::insertInst(const DynInstPtr &inst)
2076220Sgblack@eecs.umich.edu{
2086220Sgblack@eecs.umich.edu    assert(inst);
2096220Sgblack@eecs.umich.edu
21010554Salexandru.dutu@amd.com    robWrites++;
2116220Sgblack@eecs.umich.edu
2128852Sandreas.hansson@arm.com    DPRINTF(ROB, "Adding inst PC %s to the ROB.\n", inst->pcState());
2138852Sandreas.hansson@arm.com
2146220Sgblack@eecs.umich.edu    assert(numInstsInROB != numEntries);
2156220Sgblack@eecs.umich.edu
2166220Sgblack@eecs.umich.edu    ThreadID tid = inst->threadNumber;
2176220Sgblack@eecs.umich.edu
2186220Sgblack@eecs.umich.edu    instList[tid].push_back(inst);
2196220Sgblack@eecs.umich.edu
2206220Sgblack@eecs.umich.edu    //Set Up head iterator if this is the 1st instruction in the ROB
2216220Sgblack@eecs.umich.edu    if (numInstsInROB == 0) {
2225299Sgblack@eecs.umich.edu        head = instList[tid].begin();
2235299Sgblack@eecs.umich.edu        assert((*head) == inst);
2245299Sgblack@eecs.umich.edu    }
2255299Sgblack@eecs.umich.edu
2265299Sgblack@eecs.umich.edu    //Must Decrement for iterator to actually be valid  since __.end()
2275299Sgblack@eecs.umich.edu    //actually points to 1 after the last inst
2285299Sgblack@eecs.umich.edu    tail = instList[tid].end();
2295299Sgblack@eecs.umich.edu    tail--;
2305299Sgblack@eecs.umich.edu
2315299Sgblack@eecs.umich.edu    inst->setInROB();
2325299Sgblack@eecs.umich.edu
2335299Sgblack@eecs.umich.edu    ++numInstsInROB;
2345299Sgblack@eecs.umich.edu    ++threadEntries[tid];
2355299Sgblack@eecs.umich.edu
2365299Sgblack@eecs.umich.edu    assert((*tail) == inst);
2375299Sgblack@eecs.umich.edu
2385299Sgblack@eecs.umich.edu    DPRINTF(ROB, "[tid:%i] Now has %d instructions.\n", tid, threadEntries[tid]);
2395299Sgblack@eecs.umich.edu}
2405299Sgblack@eecs.umich.edu
2415299Sgblack@eecs.umich.edutemplate <class Impl>
2428852Sandreas.hansson@arm.comvoid
2435299Sgblack@eecs.umich.eduROB<Impl>::retireHead(ThreadID tid)
2445299Sgblack@eecs.umich.edu{
2455299Sgblack@eecs.umich.edu    robWrites++;
2468852Sandreas.hansson@arm.com
2475299Sgblack@eecs.umich.edu    assert(numInstsInROB > 0);
2485299Sgblack@eecs.umich.edu
2495299Sgblack@eecs.umich.edu    // Get the head ROB instruction by copying it and remove it from the list
2505299Sgblack@eecs.umich.edu    InstIt head_it = instList[tid].begin();
2515299Sgblack@eecs.umich.edu
2525299Sgblack@eecs.umich.edu    DynInstPtr head_inst = std::move(*head_it);
2538852Sandreas.hansson@arm.com    instList[tid].erase(head_it);
2548852Sandreas.hansson@arm.com
2555299Sgblack@eecs.umich.edu    assert(head_inst->readyToCommit());
2565299Sgblack@eecs.umich.edu
2575299Sgblack@eecs.umich.edu    DPRINTF(ROB, "[tid:%i] Retiring head instruction, "
2585299Sgblack@eecs.umich.edu            "instruction PC %s, [sn:%llu]\n", tid, head_inst->pcState(),
2598852Sandreas.hansson@arm.com            head_inst->seqNum);
2608852Sandreas.hansson@arm.com
2615299Sgblack@eecs.umich.edu    --numInstsInROB;
2625299Sgblack@eecs.umich.edu    --threadEntries[tid];
2635299Sgblack@eecs.umich.edu
2645299Sgblack@eecs.umich.edu    head_inst->clearInROB();
2655299Sgblack@eecs.umich.edu    head_inst->setCommitted();
2665299Sgblack@eecs.umich.edu
2675299Sgblack@eecs.umich.edu    //Update "Global" Head of ROB
2685299Sgblack@eecs.umich.edu    updateHead();
2695299Sgblack@eecs.umich.edu
2705299Sgblack@eecs.umich.edu    // @todo: A special case is needed if the instruction being
2718852Sandreas.hansson@arm.com    // retired is the only instruction in the ROB; otherwise the tail
2728852Sandreas.hansson@arm.com    // iterator will become invalidated.
2735299Sgblack@eecs.umich.edu    cpu->removeFrontInst(head_inst);
2745299Sgblack@eecs.umich.edu}
2755299Sgblack@eecs.umich.edu
2765299Sgblack@eecs.umich.edutemplate <class Impl>
2775299Sgblack@eecs.umich.edubool
2785299Sgblack@eecs.umich.eduROB<Impl>::isHeadReady(ThreadID tid)
2795299Sgblack@eecs.umich.edu{
2806220Sgblack@eecs.umich.edu    robReads++;
2815299Sgblack@eecs.umich.edu    if (threadEntries[tid] != 0) {
2825299Sgblack@eecs.umich.edu        return instList[tid].front()->readyToCommit();
2836220Sgblack@eecs.umich.edu    }
2845299Sgblack@eecs.umich.edu
2855299Sgblack@eecs.umich.edu    return false;
2866220Sgblack@eecs.umich.edu}
2875299Sgblack@eecs.umich.edu
2886220Sgblack@eecs.umich.edutemplate <class Impl>
2895299Sgblack@eecs.umich.edubool
2905299Sgblack@eecs.umich.eduROB<Impl>::canCommit()
2916220Sgblack@eecs.umich.edu{
2925299Sgblack@eecs.umich.edu    //@todo: set ActiveThreads through ROB or CPU
2935299Sgblack@eecs.umich.edu    list<ThreadID>::iterator threads = activeThreads->begin();
2946220Sgblack@eecs.umich.edu    list<ThreadID>::iterator end = activeThreads->end();
2955299Sgblack@eecs.umich.edu
2966220Sgblack@eecs.umich.edu    while (threads != end) {
2975299Sgblack@eecs.umich.edu        ThreadID tid = *threads++;
2985299Sgblack@eecs.umich.edu
2996220Sgblack@eecs.umich.edu        if (isHeadReady(tid)) {
3006220Sgblack@eecs.umich.edu            return true;
3016220Sgblack@eecs.umich.edu        }
3026220Sgblack@eecs.umich.edu    }
3036220Sgblack@eecs.umich.edu
3046220Sgblack@eecs.umich.edu    return false;
3056220Sgblack@eecs.umich.edu}
3066220Sgblack@eecs.umich.edu
3076220Sgblack@eecs.umich.edutemplate <class Impl>
3085299Sgblack@eecs.umich.eduunsigned
3095299Sgblack@eecs.umich.eduROB<Impl>::numFreeEntries()
3105299Sgblack@eecs.umich.edu{
3116220Sgblack@eecs.umich.edu    return numEntries - numInstsInROB;
3125299Sgblack@eecs.umich.edu}
3137720Sgblack@eecs.umich.edu
3145299Sgblack@eecs.umich.edutemplate <class Impl>
3155299Sgblack@eecs.umich.eduunsigned
3165334Sgblack@eecs.umich.eduROB<Impl>::numFreeEntries(ThreadID tid)
3175615Sgblack@eecs.umich.edu{
3185625Sgblack@eecs.umich.edu    return maxEntries[tid] - threadEntries[tid];
3195615Sgblack@eecs.umich.edu}
3205334Sgblack@eecs.umich.edu
3215625Sgblack@eecs.umich.edutemplate <class Impl>
3225625Sgblack@eecs.umich.eduvoid
3235625Sgblack@eecs.umich.eduROB<Impl>::doSquash(ThreadID tid)
3245625Sgblack@eecs.umich.edu{
3255625Sgblack@eecs.umich.edu    robWrites++;
3265625Sgblack@eecs.umich.edu    DPRINTF(ROB, "[tid:%i] Squashing instructions until [sn:%llu].\n",
3275625Sgblack@eecs.umich.edu            tid, squashedSeqNum[tid]);
3285299Sgblack@eecs.umich.edu
3295299Sgblack@eecs.umich.edu    assert(squashIt[tid] != instList[tid].end());
3305334Sgblack@eecs.umich.edu
3315615Sgblack@eecs.umich.edu    if ((*squashIt[tid])->seqNum < squashedSeqNum[tid]) {
3325615Sgblack@eecs.umich.edu        DPRINTF(ROB, "[tid:%i] Done squashing instructions.\n",
3335334Sgblack@eecs.umich.edu                tid);
3345334Sgblack@eecs.umich.edu
3355334Sgblack@eecs.umich.edu        squashIt[tid] = instList[tid].end();
3365615Sgblack@eecs.umich.edu
3375615Sgblack@eecs.umich.edu        doneSquashing[tid] = true;
3385615Sgblack@eecs.umich.edu        return;
3395334Sgblack@eecs.umich.edu    }
3408706Sandreas.hansson@arm.com
3415615Sgblack@eecs.umich.edu    bool robTailUpdate = false;
3425615Sgblack@eecs.umich.edu
3435615Sgblack@eecs.umich.edu    for (int numSquashed = 0;
3445615Sgblack@eecs.umich.edu         numSquashed < squashWidth &&
3455615Sgblack@eecs.umich.edu         squashIt[tid] != instList[tid].end() &&
3465334Sgblack@eecs.umich.edu         (*squashIt[tid])->seqNum > squashedSeqNum[tid];
3475334Sgblack@eecs.umich.edu         ++numSquashed)
3485625Sgblack@eecs.umich.edu    {
3495625Sgblack@eecs.umich.edu        DPRINTF(ROB, "[tid:%i] Squashing instruction PC %s, seq num %i.\n",
3505625Sgblack@eecs.umich.edu                (*squashIt[tid])->threadNumber,
3515625Sgblack@eecs.umich.edu                (*squashIt[tid])->pcState(),
3525625Sgblack@eecs.umich.edu                (*squashIt[tid])->seqNum);
3535625Sgblack@eecs.umich.edu
3545625Sgblack@eecs.umich.edu        // Mark the instruction as squashed, and ready to commit so that
3555625Sgblack@eecs.umich.edu        // it can drain out of the pipeline.
3565625Sgblack@eecs.umich.edu        (*squashIt[tid])->setSquashed();
3575625Sgblack@eecs.umich.edu
3585625Sgblack@eecs.umich.edu        (*squashIt[tid])->setCanCommit();
3595625Sgblack@eecs.umich.edu
3605625Sgblack@eecs.umich.edu
3618706Sandreas.hansson@arm.com        if (squashIt[tid] == instList[tid].begin()) {
3625625Sgblack@eecs.umich.edu            DPRINTF(ROB, "Reached head of instruction list while "
3638706Sandreas.hansson@arm.com                    "squashing.\n");
3645625Sgblack@eecs.umich.edu
3655625Sgblack@eecs.umich.edu            squashIt[tid] = instList[tid].end();
3665625Sgblack@eecs.umich.edu
3675625Sgblack@eecs.umich.edu            doneSquashing[tid] = true;
3685625Sgblack@eecs.umich.edu
3695625Sgblack@eecs.umich.edu            return;
3705625Sgblack@eecs.umich.edu        }
3715625Sgblack@eecs.umich.edu
3725625Sgblack@eecs.umich.edu        InstIt tail_thread = instList[tid].end();
3735625Sgblack@eecs.umich.edu        tail_thread--;
3745334Sgblack@eecs.umich.edu
3755132Sgblack@eecs.umich.edu        if ((*squashIt[tid]) == (*tail_thread))
3765132Sgblack@eecs.umich.edu            robTailUpdate = true;
3775334Sgblack@eecs.umich.edu
3785132Sgblack@eecs.umich.edu        squashIt[tid]--;
3795132Sgblack@eecs.umich.edu    }
3805132Sgblack@eecs.umich.edu
3815132Sgblack@eecs.umich.edu
3825132Sgblack@eecs.umich.edu    // Check if ROB is done squashing.
3835132Sgblack@eecs.umich.edu    if ((*squashIt[tid])->seqNum <= squashedSeqNum[tid]) {
3845132Sgblack@eecs.umich.edu        DPRINTF(ROB, "[tid:%i] Done squashing instructions.\n",
385                tid);
386
387        squashIt[tid] = instList[tid].end();
388
389        doneSquashing[tid] = true;
390    }
391
392    if (robTailUpdate) {
393        updateTail();
394    }
395}
396
397
398template <class Impl>
399void
400ROB<Impl>::updateHead()
401{
402    InstSeqNum lowest_num = 0;
403    bool first_valid = true;
404
405    // @todo: set ActiveThreads through ROB or CPU
406    list<ThreadID>::iterator threads = activeThreads->begin();
407    list<ThreadID>::iterator end = activeThreads->end();
408
409    while (threads != end) {
410        ThreadID tid = *threads++;
411
412        if (instList[tid].empty())
413            continue;
414
415        if (first_valid) {
416            head = instList[tid].begin();
417            lowest_num = (*head)->seqNum;
418            first_valid = false;
419            continue;
420        }
421
422        InstIt head_thread = instList[tid].begin();
423
424        DynInstPtr head_inst = (*head_thread);
425
426        assert(head_inst != 0);
427
428        if (head_inst->seqNum < lowest_num) {
429            head = head_thread;
430            lowest_num = head_inst->seqNum;
431        }
432    }
433
434    if (first_valid) {
435        head = instList[0].end();
436    }
437
438}
439
440template <class Impl>
441void
442ROB<Impl>::updateTail()
443{
444    tail = instList[0].end();
445    bool first_valid = true;
446
447    list<ThreadID>::iterator threads = activeThreads->begin();
448    list<ThreadID>::iterator end = activeThreads->end();
449
450    while (threads != end) {
451        ThreadID tid = *threads++;
452
453        if (instList[tid].empty()) {
454            continue;
455        }
456
457        // If this is the first valid then assign w/out
458        // comparison
459        if (first_valid) {
460            tail = instList[tid].end();
461            tail--;
462            first_valid = false;
463            continue;
464        }
465
466        // Assign new tail if this thread's tail is younger
467        // than our current "tail high"
468        InstIt tail_thread = instList[tid].end();
469        tail_thread--;
470
471        if ((*tail_thread)->seqNum > (*tail)->seqNum) {
472            tail = tail_thread;
473        }
474    }
475}
476
477
478template <class Impl>
479void
480ROB<Impl>::squash(InstSeqNum squash_num, ThreadID tid)
481{
482    if (isEmpty(tid)) {
483        DPRINTF(ROB, "Does not need to squash due to being empty "
484                "[sn:%llu]\n",
485                squash_num);
486
487        return;
488    }
489
490    DPRINTF(ROB, "Starting to squash within the ROB.\n");
491
492    robStatus[tid] = ROBSquashing;
493
494    doneSquashing[tid] = false;
495
496    squashedSeqNum[tid] = squash_num;
497
498    if (!instList[tid].empty()) {
499        InstIt tail_thread = instList[tid].end();
500        tail_thread--;
501
502        squashIt[tid] = tail_thread;
503
504        doSquash(tid);
505    }
506}
507
508template <class Impl>
509const typename Impl::DynInstPtr&
510ROB<Impl>::readHeadInst(ThreadID tid)
511{
512    if (threadEntries[tid] != 0) {
513        InstIt head_thread = instList[tid].begin();
514
515        assert((*head_thread)->isInROB());
516
517        return *head_thread;
518    } else {
519        return dummyInst;
520    }
521}
522
523template <class Impl>
524typename Impl::DynInstPtr
525ROB<Impl>::readTailInst(ThreadID tid)
526{
527    InstIt tail_thread = instList[tid].end();
528    tail_thread--;
529
530    return *tail_thread;
531}
532
533template <class Impl>
534void
535ROB<Impl>::regStats()
536{
537    using namespace Stats;
538    robReads
539        .name(name() + ".rob_reads")
540        .desc("The number of ROB reads");
541
542    robWrites
543        .name(name() + ".rob_writes")
544        .desc("The number of ROB writes");
545}
546
547template <class Impl>
548typename Impl::DynInstPtr
549ROB<Impl>::findInst(ThreadID tid, InstSeqNum squash_inst)
550{
551    for (InstIt it = instList[tid].begin(); it != instList[tid].end(); it++) {
552        if ((*it)->seqNum == squash_inst) {
553            return *it;
554        }
555    }
556    return NULL;
557}
558
559#endif//__CPU_O3_ROB_IMPL_HH__
560